oryx.debug.js 737 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510
  1. /**
  2. * @namespace Oryx name space for different utility methods
  3. * @name ORYX.Utils
  4. */
  5. if(!ORYX) var ORYX = {};
  6. ORYX.Utils = {
  7. /**
  8. * General helper method for parsing a param out of current location url
  9. * @example
  10. * // Current url in Browser => "http://oryx.org?param=value"
  11. * ORYX.Utils.getParamFromUrl("param") // => "value"
  12. * @param {Object} name
  13. */
  14. getParamFromUrl: function(name){
  15. name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
  16. var regexS = "[\\?&]" + name + "=([^&#]*)";
  17. var regex = new RegExp(regexS);
  18. var results = regex.exec(window.location.href);
  19. if (results == null) {
  20. return null;
  21. }
  22. else {
  23. return results[1];
  24. }
  25. },
  26. adjustLightness: function(){
  27. return arguments[0];
  28. },
  29. adjustGradient: function(gradient, reference){
  30. if (ORYX.CONFIG.DISABLE_GRADIENT && gradient){
  31. var col = reference.getAttributeNS(null, "stop-color") || "#ffffff";
  32. $A(gradient.getElementsByTagName("stop")).each(function(stop){
  33. if (stop == reference){ return; }
  34. stop.setAttributeNS(null, "stop-color", col);
  35. });
  36. }
  37. }
  38. }
  39. /*
  40. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  41. * License rights for this program may be obtained from Alfresco Software, Ltd.
  42. * pursuant to a written agreement and any use of this program without such an
  43. * agreement is prohibited.
  44. */
  45. /*
  46. * All code Copyright 2013 KIS Consultancy all rights reserved
  47. */
  48. XMLNS = {
  49. ATOM: "http://www.w3.org/2005/Atom",
  50. XHTML: "http://www.w3.org/1999/xhtml",
  51. ERDF: "http://purl.org/NET/erdf/profile",
  52. RDFS: "http://www.w3.org/2000/01/rdf-schema#",
  53. RDF: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
  54. RAZIEL: "http://b3mn.org/Raziel",
  55. SCHEMA: ""
  56. };
  57. //TODO kann kickstart sich vielleicht auch um die erzeugung von paketen/
  58. // namespaces k???mmern? z.b. requireNamespace("ORYX.Core.SVG");
  59. var Kickstart = {
  60. started: false,
  61. callbacks: [],
  62. alreadyLoaded: [],
  63. PATH: '',
  64. load: function() { Kickstart.kick(); },
  65. kick: function() {
  66. //console.profile("loading");
  67. if(!Kickstart.started) {
  68. Kickstart.started = true;
  69. Kickstart.callbacks.each(function(callback){
  70. // call the registered callback asynchronously.
  71. window.setTimeout(callback, 1);
  72. });
  73. }
  74. },
  75. register: function(callback) {
  76. //TODO Add some mutual exclusion between kick and register calls.
  77. with(Kickstart) {
  78. if(started) window.setTimeout(callback, 1);
  79. else Kickstart.callbacks.push(callback)
  80. }
  81. },
  82. /**
  83. * Loads a js, assuring that it has only been downloaded once.
  84. * @param {String} url the script to load.
  85. */
  86. require: function(url) {
  87. // if not already loaded, include it.
  88. if(Kickstart.alreadyLoaded.member(url))
  89. return false;
  90. return Kickstart.include(url);
  91. },
  92. /**
  93. * Loads a js, regardless of whether it has only been already downloaded.
  94. * @param {String} url the script to load.
  95. */
  96. include: function(url) {
  97. // prepare a script tag and place it in html head.
  98. var head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0];
  99. var s = document.createElementNS(XMLNS.XHTML, "script");
  100. s.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript');
  101. s.src = Kickstart.PATH + url;
  102. //TODO macht es sinn, dass neue skript als letztes kind in den head
  103. // einzubinden (stichwort reihenfolge der skript tags)?
  104. head.appendChild(s);
  105. // remember this url.
  106. Kickstart.alreadyLoaded.push(url);
  107. return true;
  108. }
  109. }
  110. // register kickstart as the new onload event listener on current window.
  111. // previous listener(s) are triggered to launch with kickstart.
  112. Event.observe(window, 'load', Kickstart.load);/*
  113. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  114. * License rights for this program may be obtained from Alfresco Software, Ltd.
  115. * pursuant to a written agreement and any use of this program without such an
  116. * agreement is prohibited.
  117. */
  118. /*
  119. * All code Copyright 2013 KIS Consultancy all rights reserved
  120. */
  121. var ERDF = {
  122. LITERAL: 0x01,
  123. RESOURCE: 0x02,
  124. DELIMITERS: ['.', '-'],
  125. HASH: '#',
  126. HYPHEN: "-",
  127. schemas: [],
  128. callback: undefined,
  129. log: undefined,
  130. init: function(callback) {
  131. // init logging.
  132. //ERDF.log = Log4js.getLogger("oryx");
  133. //ERDF.log.setLevel(Log4js.Level.ALL);
  134. //ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false));
  135. //if(ERDF.log.isTraceEnabled())
  136. // ERDF.log.trace("ERDF Parser is initialized.");
  137. // register callbacks and default schemas.
  138. ERDF.callback = callback;
  139. ERDF.registerSchema('schema', XMLNS.SCHEMA);
  140. ERDF.registerSchema('rdfs', XMLNS.RDFS);
  141. },
  142. run: function() {
  143. //if(ERDF.log.isTraceEnabled())
  144. // ERDF.log.trace("ERDF Parser is running.");
  145. // do the work.
  146. return ERDF._checkProfile() && ERDF.parse();
  147. },
  148. parse: function() {
  149. //(ERDF.log.isDebugEnabled())
  150. // ERDF.log.debug("Begin parsing document metadata.");
  151. // time measuring
  152. ERDF.__startTime = new Date();
  153. var bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body');
  154. var subject = {type: ERDF.RESOURCE, value: ''};
  155. var result = ERDF._parseDocumentMetadata() &&
  156. ERDF._parseFromTag(bodies[0], subject);
  157. // time measuring
  158. ERDF.__stopTime = new Date();
  159. var duration = (ERDF.__stopTime - ERDF.__startTime)/1000.;
  160. //alert('ERDF parsing took ' + duration + ' s.');
  161. return result;
  162. },
  163. _parseDocumentMetadata: function() {
  164. // get links from head element.
  165. var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');
  166. var links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link');
  167. var metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta');
  168. // process links first, since they could contain schema definitions.
  169. $A(links).each(function(link) {
  170. var properties = link.getAttribute('rel');
  171. var reversedProperties = link.getAttribute('rev');
  172. var value = link.getAttribute('href');
  173. ERDF._parseTriplesFrom(
  174. ERDF.RESOURCE, '',
  175. properties,
  176. ERDF.RESOURCE, value);
  177. ERDF._parseTriplesFrom(
  178. ERDF.RESOURCE, value,
  179. reversedProperties,
  180. ERDF.RESOURCE, '');
  181. });
  182. // continue with metas.
  183. $A(metas).each(function(meta) {
  184. var property = meta.getAttribute('name');
  185. var value = meta.getAttribute('content');
  186. ERDF._parseTriplesFrom(
  187. ERDF.RESOURCE, '',
  188. property,
  189. ERDF.LITERAL, value);
  190. });
  191. return true;
  192. },
  193. _parseFromTag: function(node, subject, depth) {
  194. // avoid parsing non-xhtml content.
  195. if(!node || !node.namespaceURI || node.namespaceURI != XMLNS.XHTML) { return; }
  196. // housekeeping.
  197. if(!depth) depth=0;
  198. var id = node.getAttribute('id');
  199. // some logging.
  200. //if(ERDF.log.isTraceEnabled())
  201. // ERDF.log.trace(">".times(depth) + " Parsing " + node.nodeName + " ("+node.nodeType+") for data on " +
  202. // ((subject.type == ERDF.RESOURCE) ? ('<' + subject.value + '>') : '') +
  203. // ((subject.type == ERDF.LITERAL) ? '"' + subject.value + '"' : ''));
  204. /* triple finding! */
  205. // in a-tags...
  206. if(node.nodeName.endsWith(':a') || node.nodeName == 'a') {
  207. var properties = node.getAttribute('rel');
  208. var reversedProperties = node.getAttribute('rev');
  209. var value = node.getAttribute('href');
  210. var title = node.getAttribute('title');
  211. var content = node.textContent;
  212. // rel triples
  213. ERDF._parseTriplesFrom(
  214. subject.type, subject.value,
  215. properties,
  216. ERDF.RESOURCE, value,
  217. function(triple) {
  218. var label = title? title : content;
  219. // label triples
  220. ERDF._parseTriplesFrom(
  221. triple.object.type, triple.object.value,
  222. 'rdfs.label',
  223. ERDF.LITERAL, label);
  224. });
  225. // rev triples
  226. ERDF._parseTriplesFrom(
  227. subject.type, subject.value,
  228. reversedProperties,
  229. ERDF.RESOURCE, '');
  230. // type triples
  231. ERDF._parseTypeTriplesFrom(
  232. subject.type, subject.value,
  233. properties);
  234. // in img-tags...
  235. } else if(node.nodeName.endsWith(':img') || node.nodeName == 'img') {
  236. var properties = node.getAttribute('class');
  237. var value = node.getAttribute('src');
  238. var alt = node.getAttribute('alt');
  239. ERDF._parseTriplesFrom(
  240. subject.type, subject.value,
  241. properties,
  242. ERDF.RESOURCE, value,
  243. function(triple) {
  244. var label = alt;
  245. // label triples
  246. ERDF._parseTriplesFrom(
  247. triple.object.type, triple.object.value,
  248. 'rdfs.label',
  249. ERDF.LITERAL, label);
  250. });
  251. }
  252. // in every tag
  253. var properties = node.getAttribute('class');
  254. var title = node.getAttribute('title');
  255. var content = node.textContent;
  256. var label = title ? title : content;
  257. // regular triples
  258. ERDF._parseTriplesFrom(
  259. subject.type, subject.value,
  260. properties,
  261. ERDF.LITERAL, label);
  262. if(id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH+id};
  263. // type triples
  264. ERDF._parseTypeTriplesFrom(
  265. subject.type, subject.value,
  266. properties);
  267. // parse all children that are element nodes.
  268. var children = node.childNodes;
  269. if(children) $A(children).each(function(_node) {
  270. if(_node.nodeType == _node.ELEMENT_NODE)
  271. ERDF._parseFromTag(_node, subject, depth+1); });
  272. },
  273. _parseTriplesFrom: function(subjectType, subject, properties,
  274. objectType, object, callback) {
  275. if(!properties) return;
  276. properties.toLowerCase().split(' ').each( function(property) {
  277. //if(ERDF.log.isTraceEnabled())
  278. // ERDF.log.trace("Going for property " + property);
  279. var schema = ERDF.schemas.find( function(schema) {
  280. return false || ERDF.DELIMITERS.find( function(delimiter) {
  281. return property.startsWith(schema.prefix + delimiter);
  282. });
  283. });
  284. if(schema && object) {
  285. property = property.substring(
  286. schema.prefix.length+1, property.length);
  287. var triple = ERDF.registerTriple(
  288. new ERDF.Resource(subject),
  289. {prefix: schema.prefix, name: property},
  290. (objectType == ERDF.RESOURCE) ?
  291. new ERDF.Resource(object) :
  292. new ERDF.Literal(object));
  293. if(callback) callback(triple);
  294. }
  295. });
  296. },
  297. _parseTypeTriplesFrom: function(subjectType, subject, properties, callback) {
  298. if(!properties) return;
  299. properties.toLowerCase().split(' ').each( function(property) {
  300. //if(ERDF.log.isTraceEnabled())
  301. // ERDF.log.trace("Going for property " + property);
  302. var schema = ERDF.schemas.find( function(schema) {
  303. return false || ERDF.DELIMITERS.find( function(delimiter) {
  304. return property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter);
  305. });
  306. });
  307. if(schema && subject) {
  308. property = property.substring(schema.prefix.length+2, property.length);
  309. var triple = ERDF.registerTriple(
  310. (subjectType == ERDF.RESOURCE) ?
  311. new ERDF.Resource(subject) :
  312. new ERDF.Literal(subject),
  313. {prefix: 'rdf', name: 'type'},
  314. new ERDF.Resource(schema.namespace+property));
  315. if(callback) callback(triple);
  316. }
  317. });
  318. },
  319. /**
  320. * Checks for ERDF profile declaration in head of document.
  321. */
  322. _checkProfile: function() {
  323. // get profiles from head element.
  324. var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');
  325. var profiles = heads[0].getAttribute("profile");
  326. var found = false;
  327. // if erdf profile is contained.
  328. if(profiles && profiles.split(" ").member(XMLNS.ERDF)) {
  329. // pass check.
  330. //if(ERDF.log.isTraceEnabled())
  331. // ERDF.log.trace("Found ERDF profile " + XMLNS.ERDF);
  332. return true;
  333. } else {
  334. // otherwise fail check.
  335. //if(ERDF.log.isFatalEnabled())
  336. // ERDF.log.fatal("No ERDF profile found.");
  337. return false;
  338. }
  339. },
  340. __stripHashes: function(s) {
  341. return (s && (typeof s.substring == 'function') && s.substring(0, 1)=='#') ? s.substring(1, s.length) : s;
  342. },
  343. registerSchema: function(prefix, namespace) {
  344. // TODO check whether already registered, if so, complain.
  345. ERDF.schemas.push({
  346. prefix: prefix,
  347. namespace: namespace
  348. });
  349. //if(ERDF.log.isDebugEnabled())
  350. // ERDF.log.debug("Prefix '"+prefix+"' for '"+namespace+"' registered.");
  351. },
  352. registerTriple: function(subject, predicate, object) {
  353. // if prefix is schema, this is a schema definition.
  354. if(predicate.prefix.toLowerCase() == 'schema')
  355. this.registerSchema(predicate.name, object.value);
  356. var triple = new ERDF.Triple(subject, predicate, object);
  357. ERDF.callback(triple);
  358. //if(ERDF.log.isInfoEnabled())
  359. // ERDF.log.info(triple)
  360. // return the registered triple.
  361. return triple;
  362. },
  363. __enhanceObject: function() {
  364. /* Resource state querying methods */
  365. this.isResource = function() {
  366. return this.type == ERDF.RESOURCE };
  367. this.isLocal = function() {
  368. return this.isResource() && this.value.startsWith('#') };
  369. this.isCurrentDocument = function() {
  370. return this.isResource() && (this.value == '') };
  371. /* Resource getter methods.*/
  372. this.getId = function() {
  373. return this.isLocal() ? ERDF.__stripHashes(this.value) : false; };
  374. /* Liiteral state querying methods */
  375. this.isLiteral = function() {
  376. return this.type == ERDF.LIITERAL };
  377. },
  378. serialize: function(literal) {
  379. if(!literal){
  380. return "";
  381. }else if(literal.constructor == String) {
  382. return literal;
  383. } else if(literal.constructor == Boolean) {
  384. return literal? 'true':'false';
  385. } else {
  386. return literal.toString();
  387. }
  388. }
  389. };
  390. ERDF.Triple = function(subject, predicate, object) {
  391. this.subject = subject;
  392. this.predicate = predicate;
  393. this.object = object;
  394. this.toString = function() {
  395. return "[ERDF.Triple] " +
  396. this.subject.toString() + ' ' +
  397. this.predicate.prefix + ':' + this.predicate.name + ' ' +
  398. this.object.toString();
  399. };
  400. };
  401. ERDF.Resource = function(uri) {
  402. this.type = ERDF.RESOURCE;
  403. this.value = uri;
  404. ERDF.__enhanceObject.apply(this);
  405. this.toString = function() {
  406. return '<' + this.value + '>';
  407. }
  408. };
  409. ERDF.Literal = function(literal) {
  410. this.type = ERDF.LITERAL;
  411. this.value = ERDF.serialize(literal);
  412. ERDF.__enhanceObject.apply(this);
  413. this.toString = function() {
  414. return '"' + this.value + '"';
  415. }
  416. };/*
  417. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  418. * License rights for this program may be obtained from Alfresco Software, Ltd.
  419. * pursuant to a written agreement and any use of this program without such an
  420. * agreement is prohibited.
  421. */
  422. /*
  423. * All code Copyright 2013 KIS Consultancy all rights reserved
  424. */
  425. /*
  426. * Save and triple generation behaviour. Use this area to configure
  427. * data management to your needs.
  428. */
  429. var USE_ASYNCHRONOUS_REQUESTS = true;
  430. var DISCARD_UNUSED_TRIPLES = true;
  431. var PREFER_SPANS_OVER_DIVS = true;
  432. var PREFER_TITLE_OVER_TEXTNODE = false;
  433. var RESOURCE_ID_PREFIX = 'resource';
  434. var SHOW_DEBUG_ALERTS_WHEN_SAVING = false;
  435. var SHOW_EXTENDED_DEBUG_INFORMATION = false;
  436. /*
  437. * Back end specific workarounds.
  438. */
  439. var USE_ARESS_WORKAROUNDS = true;
  440. /*
  441. * Data management constants. Do not change these, as they are used
  442. * both internally and externally to communicate on events and to identify
  443. * command object actions in triple production and embedding rules.
  444. */
  445. // Resource constants
  446. var RESOURCE_CREATED = 0x01;
  447. var RESOURCE_REMOVED = 0x02;
  448. var RESOURCE_SAVED = 0x04;
  449. var RESOURCE_RELOADED = 0x08;
  450. var RESOURCE_SYNCHRONIZED = 0x10;
  451. // Triple constants
  452. var TRIPLE_REMOVE = 0x01;
  453. var TRIPLE_ADD = 0x02;
  454. var TRIPLE_RELOAD = 0x04;
  455. var TRIPLE_SAVE = 0x08;
  456. var PROCESSDATA_REF = 'processdata';
  457. // HTTP status code constants
  458. //
  459. //// 2xx
  460. //const 200_OK = 'Ok';
  461. //const 201_CREATED = 'Created';
  462. //const 202_ACCEPTED = 'Accepted';
  463. //const 204_NO_CONTENT = 'No Content';
  464. //
  465. //// 3xx
  466. //const 301_MOVED_PERMANENTLY = 'Moved Permanently';
  467. //const 302_MOVED_TEMPORARILY = 'Moved Temporarily';
  468. //const 304_NOT_MODIFIED = 'Not Modified';
  469. //
  470. //// 4xx
  471. //const 400_BAD_REQUEST = 'Bad Request';
  472. //const 401_UNAUTHORIZED = 'Unauthorized';
  473. //const 403_FORBIDDEN = 'Forbidden';
  474. //const 404_NOT_FOUND = 'Not Found';
  475. //const 409_CONFLICT = 'Conflict';
  476. //
  477. //// 5xx
  478. //const 500_INTERNAL_SERVER_ERROR = 'Internal Server Error';
  479. //const 501_NOT_IMPLEMENTED = 'Not Implemented';
  480. //const 502_BAD_GATEWAY = 'Bad Gateway';
  481. //const 503_SERVICE_UNAVAILABLE = 'Service Unavailable';
  482. //
  483. /**
  484. * The Data Management object. Use this one when interacting with page internal
  485. * data. Initialize data management by DataManager.init();
  486. * @class DataManager
  487. */
  488. var DataManager = {
  489. /**
  490. * The init method should be called once in the DataManagers lifetime.
  491. * It causes the DataManager to initialize itself, the erdf parser, do all
  492. * neccessary registrations and configurations, to run the parser and
  493. * from then on deliver all resulting triples.
  494. * No parameters needed are needed in a call to this method.
  495. */
  496. init: function() {
  497. ERDF.init(DataManager._registerTriple);
  498. DataManager.__synclocal();
  499. },
  500. /**
  501. * This triple array is meant to be the whole knowledge of the DataManager.
  502. */
  503. _triples: [],
  504. /**
  505. * This method is meant for callback from erdf parsing. It is not to be
  506. * used in another way than to add triples to the triple store.
  507. * @param {Object} triple the triple to add to the triple store.
  508. */
  509. _registerTriple: function(triple) {
  510. DataManager._triples.push(triple)
  511. },
  512. /**
  513. * The __synclocal method is for internal usage only.
  514. * It performs synchronization with the local document, that is, the triple
  515. * store is adjustet to the content of the document, which could have been
  516. * changed by any other applications running on the same page.
  517. */
  518. __synclocal: function() {
  519. DataManager._triples = [];
  520. ERDF.run();
  521. },
  522. /**
  523. * Makes the shape passed into this method synchronize itself with the DOM.
  524. * This method returns the shapes resource object for further manipulation.
  525. * @param {Object} shape
  526. */
  527. __synchronizeShape: function(shape) {
  528. var r = ResourceManager.getResource(shape.resourceId);
  529. var serialize = shape.serialize();
  530. // store all serialize values
  531. serialize.each( function(ser) {
  532. var resource = (ser.type == 'resource');
  533. var _triple = new ERDF.Triple(
  534. new ERDF.Resource(shape.resourceId),
  535. {prefix: ser.prefix, name: ser.name},
  536. resource ?
  537. new ERDF.Resource(ser.value) :
  538. new ERDF.Literal(ser.value)
  539. );
  540. DataManager.setObject(_triple);
  541. });
  542. return r;
  543. },
  544. __storeShape: function(shape) {
  545. // first synchronize the shape,
  546. var resource = DataManager.__synchronizeShape(shape);
  547. // then save the synchronized dom.
  548. resource.save();
  549. },
  550. __forceExistance: function(shape) {
  551. if(!$(shape.resourceId)) {
  552. if(!$$('.' + PROCESSDATA_REF)[0])
  553. DataManager.graft(XMLNS.XHTML,
  554. document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
  555. // object is literal
  556. DataManager.graft(XMLNS.XHTML,
  557. $$('.' + PROCESSDATA_REF)[0], [
  558. 'div', {
  559. 'id': shape.resourceId,
  560. //This should be done in a more dynamic way!!!!!
  561. 'class': (shape instanceof ORYX.Core.Canvas) ? "-oryx-canvas" : undefined
  562. }
  563. ]);
  564. } else {
  565. var resource = $(shape.resourceId)
  566. var children = $A(resource.childNodes)
  567. children.each( function(child) {
  568. resource.removeChild(child);
  569. });
  570. };
  571. },
  572. __persistShape: function(shape) {
  573. // a shape serialization.
  574. var shapeData = shape.serialize();
  575. // initialize a triple array and construct a shape resource
  576. // to be used in triple generation.
  577. var triplesArray = [];
  578. var shapeResource = new ERDF.Resource(shape.resourceId);
  579. // remove all triples for this particular shape's resource
  580. DataManager.removeTriples( DataManager.query(
  581. shapeResource, undefined, undefined));
  582. // for each data set in the shape's serialization
  583. shapeData.each( function(data) {
  584. // construct a triple's value
  585. var value = (data.type == 'resource') ?
  586. new ERDF.Resource(data.value) :
  587. new ERDF.Literal(data.value);
  588. // construct triple and add it to the DOM.
  589. DataManager.addTriple( new ERDF.Triple(
  590. shapeResource,
  591. {prefix: data.prefix, name: data.name},
  592. value
  593. ));
  594. });
  595. },
  596. __persistDOM: function(facade) {
  597. // getChildShapes gets all shapes (nodes AND edges), deep flag
  598. // makes it return a flattened child hierarchy.
  599. var canvas = facade.getCanvas();
  600. var shapes = canvas.getChildShapes(true);
  601. var result = '';
  602. // persist all shapes.
  603. shapes.each( function(shape) {
  604. DataManager.__forceExistance(shape);
  605. });
  606. //DataManager.__synclocal();
  607. DataManager.__renderCanvas(facade);
  608. result += DataManager.serialize(
  609. $(ERDF.__stripHashes(facade.getCanvas().resourceId)), true);
  610. shapes.each( function(shape) {
  611. DataManager.__persistShape(shape);
  612. result += DataManager.serialize(
  613. $(ERDF.__stripHashes(shape.resourceId)), true);
  614. });
  615. //result += DataManager.__renderCanvas(facade);
  616. return result;
  617. },
  618. __renderCanvas: function(facade) {
  619. var canvas = facade.getCanvas();
  620. var stencilSets = facade.getStencilSets();
  621. var shapes = canvas.getChildShapes(true);
  622. DataManager.__forceExistance(canvas);
  623. DataManager.__persistShape(canvas);
  624. var shapeResource = new ERDF.Resource(canvas.resourceId);
  625. // remove all triples for this particular shape's resource
  626. DataManager.removeTriples( DataManager.query(
  627. shapeResource, undefined, undefined));
  628. DataManager.addTriple( new ERDF.Triple(
  629. shapeResource,
  630. {prefix: "oryx", name: "mode"},
  631. new ERDF.Literal("writable")
  632. ));
  633. DataManager.addTriple( new ERDF.Triple(
  634. shapeResource,
  635. {prefix: "oryx", name: "mode"},
  636. new ERDF.Literal("fullscreen")
  637. ));
  638. stencilSets.values().each(function(stencilset) {
  639. DataManager.addTriple( new ERDF.Triple(
  640. shapeResource,
  641. {prefix: "oryx", name: "stencilset"},
  642. new ERDF.Resource(stencilset.source().replace(/&/g, "%26"))
  643. ));
  644. DataManager.addTriple( new ERDF.Triple(
  645. shapeResource,
  646. {prefix: "oryx", name: "ssnamespace"},
  647. new ERDF.Resource(stencilset.namespace())
  648. ));
  649. stencilset.extensions().keys().each(function(extension) {
  650. DataManager.addTriple( new ERDF.Triple(
  651. shapeResource,
  652. {prefix: "oryx", name: "ssextension"},
  653. new ERDF.Literal(extension)
  654. ));
  655. });
  656. });
  657. shapes.each(function(shape) {
  658. DataManager.addTriple( new ERDF.Triple(
  659. shapeResource,
  660. {prefix: "oryx", name: "render"},
  661. new ERDF.Resource("#" + shape.resourceId)
  662. ));
  663. });
  664. },
  665. __counter: 0,
  666. __provideId: function() {
  667. while($(RESOURCE_ID_PREFIX+DataManager.__counter))
  668. DataManager.__counter++;
  669. return RESOURCE_ID_PREFIX+DataManager.__counter;
  670. },
  671. serializeDOM: function(facade) {
  672. return DataManager.__persistDOM(facade);
  673. },
  674. syncGlobal: function(facade) {
  675. return DataManager.__syncglobal(facade);
  676. },
  677. /**
  678. * This method is used to synchronize local DOM with remote resources.
  679. * Local changes are commited to the server, and remote changes are
  680. * performed to the local document.
  681. * @param {Object} facade The facade of the editor that holds certain
  682. * resource representations as shapes.
  683. */
  684. __syncglobal: function(facade) {
  685. // getChildShapes gets all shapes (nodes AND edges), deep flag
  686. // makes it return a flattened child hierarchy.
  687. var canvas = facade.getCanvas();
  688. var shapes = canvas.getChildShapes(true);
  689. // create dummy resource representations in the dom
  690. // for all shapes that were newly created.
  691. shapes.select( function(shape) {
  692. // select shapes without resource id.
  693. return !($(shape.resourceId));
  694. }).each( function(shape) {
  695. // create new resources for them.
  696. if(USE_ARESS_WORKAROUNDS) {
  697. /*
  698. * This is a workaround due to a bug in aress. Resources are
  699. * ignoring changes to raziel:type property once they are
  700. * created. As long as this is not fixed, the resource is now
  701. * being created using a randomly guessed id, this temporary id
  702. * is then used in references and the appropriate div is being
  703. * populated with properties.
  704. *
  705. * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT
  706. * TO IDS THAT ARE UNKNOWN TO THE BACK END.
  707. *
  708. * After the resource is actually created in aress, it gets an id
  709. * that is persistent. All shapes are then being populated with the
  710. * correct id references and stored on the server.
  711. *
  712. * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT
  713. * REGARDING THE ID REFERENCES AGAIN.
  714. */
  715. var razielType = shape.properties['raziel-type'];
  716. var div = '<div xmlns="http://www.w3.org/1999/xhtml">' +
  717. '<span class="raziel-type">'+razielType+'</span></div>';
  718. var r = ResourceManager.__createResource(div);
  719. shape.resourceId = r.id();
  720. } else {
  721. var r = ResourceManager.__createResource();
  722. shape.resourceId = r.id();
  723. }
  724. });
  725. shapes.each( function(shape) {
  726. // store all shapes.
  727. DataManager.__storeShape(shape);
  728. });
  729. },
  730. /**
  731. * This method serializes a single div into a string that satisfies the
  732. * client/server communication protocol. It ingnores all elements that have
  733. * an attribute named class that includes 'transient'.
  734. * @param {Object} node the element to serialize.
  735. * @param {Object} preserveNamespace whether to preserve the parent's
  736. * namespace. If you are not sure about namespaces, provide
  737. * just the element to be serialized.
  738. */
  739. serialize: function(node, preserveNamespace) {
  740. if (node.nodeType == node.ELEMENT_NODE) {
  741. // serialize an element node.
  742. var children = $A(node.childNodes);
  743. var attributes = $A(node.attributes);
  744. var clazz = new String(node.getAttribute('class'));
  745. var ignore = clazz.split(' ').member('transient');
  746. // ignore transients.
  747. if(ignore)
  748. return '';
  749. // start serialization.
  750. var result = '<' + node.nodeName;
  751. // preserve namespace?
  752. if(!preserveNamespace)
  753. result += ' xmlns="' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '" xmlns:oryx="http://oryx-editor.org"';
  754. // add all attributes.
  755. attributes.each(function(attribute) {
  756. result += ' ' + attribute.nodeName + '="' +
  757. attribute.nodeValue + '"';});
  758. // close if no children.
  759. if(children.length == 0)
  760. result += '/>';
  761. else {
  762. // serialize all children.
  763. result += '>';
  764. children.each(function(_node) {
  765. result += DataManager.serialize(_node, true)});
  766. result += '</' + node.nodeName + '>'
  767. }
  768. return result;
  769. } else if (node.nodeType == node.TEXT_NODE) {
  770. // serialize a text node.
  771. return node.nodeValue;
  772. }
  773. //TODO serialize cdata areas also.
  774. //TODO work on namespace awareness.
  775. },
  776. addTriple: function(triple) {
  777. // assert the subject is a resource
  778. if(!triple.subject.type == ERDF.LITERAL)
  779. throw 'Cannot add the triple ' + triple.toString() +
  780. ' because the subject is not a resource.'
  781. // get the element which represents this triple's subject.
  782. var elementId = ERDF.__stripHashes(triple.subject.value);
  783. var element = $(elementId);
  784. // assert the subject is inside this document.
  785. if(!element)
  786. throw 'Cannot add the triple ' + triple.toString() +
  787. ' because the subject "'+elementId+'" is not in the document.';
  788. if(triple.object.type == ERDF.LITERAL)
  789. // object is literal
  790. DataManager.graft(XMLNS.XHTML, element, [
  791. 'span', {'class': (triple.predicate.prefix + "-" +
  792. triple.predicate.name)}, triple.object.value.escapeHTML()
  793. ]);
  794. else {
  795. // object is resource
  796. DataManager.graft(XMLNS.XHTML, element, [
  797. 'a', {'rel': (triple.predicate.prefix + "-" +
  798. triple.predicate.name), 'href': triple.object.value}
  799. ]);
  800. }
  801. return true;
  802. },
  803. removeTriples: function(triples) {
  804. // alert('Removing ' +triples.length+' triples.');
  805. // from all the triples select those ...
  806. var removed = triples.select(
  807. function(triple) {
  808. // TODO remove also from triple store.
  809. // ... that were actually removed.
  810. return DataManager.__removeTriple(triple);
  811. });
  812. // sync and return removed triples.
  813. // DataManager.__synclocal();
  814. return removed;
  815. },
  816. removeTriple: function(triple) {
  817. // remember whether the triple was actually removed.
  818. var result = DataManager.__removeTriple(triple);
  819. // sync and return removed triples.
  820. // DataManager.__synclocal();
  821. return result;
  822. },
  823. __removeTriple: function(triple) {
  824. // assert the subject is a resource
  825. if(!triple.subject.type == ERDF.LITERAL)
  826. throw 'Cannot remove the triple ' + triple.toString() +
  827. ' because the subject is not a resource.';
  828. // get the element which represents this triple's subject.
  829. var elementId = ERDF.__stripHashes(triple.subject.value);
  830. var element = $(elementId);
  831. // assert the subject is inside this document.
  832. if(!element)
  833. throw 'Cannot remove the triple ' + triple.toString() +
  834. ' because the subject is not in the document.';
  835. if(triple.object.type == ERDF.LITERAL) {
  836. // continue searching actively for the triple.
  837. var result = DataManager.__removeTripleRecursively(triple, element);
  838. return result;
  839. }
  840. },
  841. __removeTripleRecursively: function(triple, continueFrom) {
  842. // return when this node is not an element node.
  843. if(continueFrom.nodeType != continueFrom.ELEMENT_NODE)
  844. return false;
  845. var classes = new String(continueFrom.getAttribute('class'));
  846. var children = $A(continueFrom.childNodes);
  847. if(classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) {
  848. var content = continueFrom.textContent;
  849. if( (triple.object.type == ERDF.LITERAL) &&
  850. (triple.object.value == content))
  851. continueFrom.parentNode.removeChild(continueFrom);
  852. return true;
  853. } else {
  854. children.each(function(_node) {
  855. DataManager.__removeTripleRecursively(triple, _node)});
  856. return false;
  857. }
  858. },
  859. /**
  860. * graft() function
  861. * Originally by Sean M. Burke from interglacial.com, altered for usage with
  862. * SVG and namespace (xmlns) support. Be sure you understand xmlns before
  863. * using this funtion, as it creates all grafted elements in the xmlns
  864. * provided by you and all element's attribures in default xmlns. If you
  865. * need to graft elements in a certain xmlns and wish to assign attributes
  866. * in both that and another xmlns, you will need to do stepwise grafting,
  867. * adding non-default attributes yourself or you'll have to enhance this
  868. * function. Latter, I would appreciate: martin???apfelfabrik.de
  869. * @param {Object} namespace The namespace in which
  870. * elements should be grafted.
  871. * @param {Object} parent The element that should contain the grafted
  872. * structure after the function returned.
  873. * @param {Object} t the crafting structure.
  874. * @param {Object} doc the document in which grafting is performed.
  875. */
  876. graft: function(namespace, parent, t, doc) {
  877. doc = (doc || (parent && parent.ownerDocument) || document);
  878. var e;
  879. if(t === undefined) {
  880. echo( "Can't graft an undefined value");
  881. } else if(t.constructor == String) {
  882. e = doc.createTextNode( t );
  883. } else {
  884. for(var i = 0; i < t.length; i++) {
  885. if( i === 0 && t[i].constructor == String ) {
  886. var snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i );
  887. if( snared ) {
  888. e = doc.createElementNS(namespace, snared[1]);
  889. e.setAttributeNS(null, 'class', snared[2] );
  890. continue;
  891. }
  892. snared = t[i].match( /^([a-z][a-z0-9]*)$/i );
  893. if( snared ) {
  894. e = doc.createElementNS(namespace, snared[1]); // but no class
  895. continue;
  896. }
  897. // Otherwise:
  898. e = doc.createElementNS(namespace, "span");
  899. e.setAttribute(null, "class", "namelessFromLOL" );
  900. }
  901. if( t[i] === undefined ) {
  902. echo("Can't graft an undefined value in a list!");
  903. } else if( t[i].constructor == String || t[i].constructor == Array) {
  904. this.graft(namespace, e, t[i], doc );
  905. } else if( t[i].constructor == Number ) {
  906. this.graft(namespace, e, t[i].toString(), doc );
  907. } else if( t[i].constructor == Object ) {
  908. // hash's properties => element's attributes
  909. for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }
  910. } else if( t[i].constructor == Boolean ) {
  911. this.graft(namespace, e, t[i] ? 'true' : 'false', doc );
  912. } else
  913. throw "Object " + t[i] + " is inscrutable as an graft arglet.";
  914. }
  915. }
  916. if(parent) parent.appendChild(e);
  917. return Element.extend(e); // return the topmost created node
  918. },
  919. setObject: function(triple) {
  920. /**
  921. * Erwartungen von Arvid an diese Funktion:
  922. * - Es existiert genau ein triple mit dem Subjekt und Praedikat,
  923. * das uebergeben wurde, und dieses haelt uebergebenes Objekt.
  924. */
  925. var triples = DataManager.query(
  926. triple.subject,
  927. triple.predicate,
  928. undefined
  929. );
  930. DataManager.removeTriples(triples);
  931. DataManager.addTriple(triple);
  932. return true;
  933. },
  934. query: function(subject, predicate, object) {
  935. /*
  936. * Typical triple.
  937. * {value: subject, type: subjectType},
  938. * {prefix: schema.prefix, name: property},
  939. * {value: object, type: objectType});
  940. */
  941. return DataManager._triples.select(function(triple) {
  942. var select = ((subject) ?
  943. (triple.subject.type == subject.type) &&
  944. (triple.subject.value == subject.value) : true);
  945. if(predicate) {
  946. select = select && ((predicate.prefix) ?
  947. (triple.predicate.prefix == predicate.prefix) : true);
  948. select = select && ((predicate.name) ?
  949. (triple.predicate.name == predicate.name) : true);
  950. }
  951. select = select && ((object) ?
  952. (triple.object.type == object.type) &&
  953. (triple.object.value == object.value) : true);
  954. return select;
  955. });
  956. }
  957. }
  958. Kickstart.register(DataManager.init);
  959. function assert(expr, m) { if(!expr) throw m; };
  960. function DMCommand(action, triple) {
  961. // store action and triple.
  962. this.action = action;
  963. this.triple = triple;
  964. this.toString = function() {
  965. return 'Command('+action+', '+triple+')';
  966. };
  967. }
  968. function DMCommandHandler(nextHandler) {
  969. /**
  970. * Private method to set the next handler in the Chain of Responsibility
  971. * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for
  972. * details).
  973. * @param {DMCommandHandler} handler The handler that is next in the chain.
  974. */
  975. this.__setNext = function(handler) {
  976. var _next = this.__next;
  977. this.__next = nextHandler;
  978. return _next ? _next : true;
  979. };
  980. this.__setNext(nextHandler);
  981. /**
  982. * Invokes the next handler. If there is no next handler, this method
  983. * returns false, otherwise it forwards the result of the handling.
  984. * @param {Object} command The command object to be processed.
  985. */
  986. this.__invokeNext = function(command) {
  987. return this.__next ? this.__next.handle(command) : false;
  988. };
  989. /**
  990. * Handles a command. The abstract method process() is called with the
  991. * command object that has been passed. If the process method catches the
  992. * command (returns true on completion), the handle() method returns true.
  993. * If the process() method doesn't catch the command, the next handler will
  994. * be invoked.
  995. * @param {Object} command The command object to be processed.
  996. */
  997. this.handle = function(command) {
  998. return this.process(command) ? true : this.__invokeNext(command);
  999. }
  1000. /**
  1001. * Empty process() method returning false. If javascript knew abstract
  1002. * class members, this would be one.
  1003. * @param {Object} command The command object to process.
  1004. */
  1005. this.process = function(command) { return false; };
  1006. };
  1007. /**
  1008. * This Handler manages the addition and the removal of meta elements in the
  1009. * head of the document.
  1010. * @param {DMCommandHandler} next The handler that is next in the chain.
  1011. */
  1012. function MetaTagHandler(next) {
  1013. DMCommandHandler.apply(this, [next]);
  1014. this.process = function(command) {
  1015. with(command.triple) {
  1016. /* assert prerequisites */
  1017. if( !(
  1018. (subject instanceof ERDF.Resource) &&
  1019. (subject.isCurrentDocument()) &&
  1020. (object instanceof ERDF.Literal)
  1021. )) return false;
  1022. }
  1023. };
  1024. };
  1025. var chain = new MetaTagHandler();
  1026. var command = new DMCommand(TRIPLE_ADD, new ERDF.Triple(
  1027. new ERDF.Resource(''),
  1028. 'rdf:tool',
  1029. new ERDF.Literal('')
  1030. ));
  1031. /*
  1032. if(chain.handle(command))
  1033. alert('Handled!');
  1034. */
  1035. ResourceManager = {
  1036. __corrupt: false,
  1037. __latelyCreatedResource: undefined,
  1038. __listeners: $H(),
  1039. __token: 1,
  1040. addListener: function(listener, mask) {
  1041. if(!(listener instanceof Function))
  1042. throw 'Resource event listener is not a function!';
  1043. if(!(mask))
  1044. throw 'Invalid mask for resource event listener registration.';
  1045. // construct controller and token.
  1046. var controller = {listener: listener, mask: mask};
  1047. var token = ResourceManager.__token++;
  1048. // add new listener.
  1049. ResourceManager.__listeners[token] = controller;
  1050. // return the token generated.
  1051. return token;
  1052. },
  1053. removeListener: function(token) {
  1054. // remove the listener with the token and return it.
  1055. return ResourceManager.__listners.remove(token);
  1056. },
  1057. __Event: function(action, resourceId) {
  1058. this.action = action;
  1059. this.resourceId = resourceId;
  1060. },
  1061. __dispatchEvent: function(event) {
  1062. // get all listeners. for each listener, ...
  1063. ResourceManager.__listeners.values().each(function(controller) {
  1064. // .. if listener subscribed to this type of event ...
  1065. if(event.action & controller.mask)
  1066. return controller.listener(event);
  1067. });
  1068. },
  1069. getResource: function(id) {
  1070. // get all possible resources for this.
  1071. id = ERDF.__stripHashes(id);
  1072. var resources = DataManager.query(
  1073. new ERDF.Resource('#'+id),
  1074. {prefix: 'raziel', name: 'entry'},
  1075. undefined
  1076. );
  1077. // check for consistency.
  1078. if((resources.length == 1) && (resources[0].object.isResource())) {
  1079. var entryUrl = resources[0].object.value;
  1080. return new ResourceManager.__Resource(id, entryUrl);
  1081. }
  1082. // else throw an error message.
  1083. throw ('Resource with id ' +id+ ' not recognized as such. ' +
  1084. ((resources.length > 1) ?
  1085. ' There is more than one raziel:entry URL.' :
  1086. ' There is no raziel:entry URL.'));
  1087. return false;
  1088. },
  1089. __createResource: function(alternativeDiv) {
  1090. var collectionUrls = DataManager.query(
  1091. new ERDF.Resource(''),
  1092. // TODO This will become raziel:collection in near future.
  1093. {prefix: 'raziel', name: 'collection'},
  1094. undefined
  1095. );
  1096. // check for consistency.
  1097. if( (collectionUrls.length == 1) &&
  1098. (collectionUrls[0].object.isResource())) {
  1099. // get the collection url.
  1100. var collectionUrl = collectionUrls[0].object.value;
  1101. var resource = undefined;
  1102. // if there is an old id, serialize the dummy div from there,
  1103. // otherwise create a dummy div on the fly.
  1104. var serialization = alternativeDiv? alternativeDiv :
  1105. '<div xmlns="http://www.w3.org/1999/xhtml"></div>';
  1106. ResourceManager.__request(
  1107. 'POST', collectionUrl, serialization,
  1108. // on success
  1109. function() {
  1110. // get div and id that have been generated by the server.
  1111. var response = (this.responseXML);
  1112. var div = response.childNodes[0];
  1113. var id = div.getAttribute('id');
  1114. // store div in DOM
  1115. if(!$$('.' + PROCESSDATA_REF)[0])
  1116. DataManager.graft(XMLNS.XHTML,
  1117. document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
  1118. $$('.' + PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));
  1119. // parse local erdf data once more.
  1120. DataManager.__synclocal();
  1121. // get new resource object.
  1122. resource = new ResourceManager.getResource(id);
  1123. // set up an action informing of the creation.
  1124. ResourceManager.__resourceActionSucceeded(
  1125. this, RESOURCE_CREATED, undefined);
  1126. },
  1127. function() { ResourceManager.__resourceActionFailed(
  1128. this, RESOURCE_CREATED, undefined);},
  1129. false
  1130. );
  1131. return resource;
  1132. }
  1133. // else
  1134. throw 'Could not create resource! raziel:collection URL is missing!';
  1135. return false;
  1136. },
  1137. __Resource: function(id, url) {
  1138. this.__id = id;
  1139. this.__url = url;
  1140. /*
  1141. * Process URL is no longer needed to refer to the shape element on the
  1142. * canvas. AReSS uses the id's to gather information on fireing
  1143. * behaviour now.
  1144. */
  1145. // // find the process url.
  1146. // var processUrl = undefined;
  1147. //
  1148. // var urls = DataManager.query(
  1149. // new ERDF.Resource('#'+this.__id),
  1150. // {prefix: 'raziel', name: 'process'},
  1151. // undefined
  1152. // );
  1153. //
  1154. // if(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'};
  1155. //
  1156. // urls.each( function(triple) {
  1157. //
  1158. // // if there are more urls, use the last one.
  1159. // processUrl = triple.object.value;
  1160. // });
  1161. //
  1162. // this.__processUrl = processUrl;
  1163. //
  1164. // // convenience function for getting the process url.
  1165. // this.processUrl = function() {
  1166. // return this.__processUrl;
  1167. // }
  1168. // convenience finction for getting the id.
  1169. this.id = function() {
  1170. return this.__id;
  1171. }
  1172. // convenience finction for getting the entry url.
  1173. this.url = function() {
  1174. return this.__url;
  1175. }
  1176. this.reload = function() {
  1177. var _url = this.__url;
  1178. var _id = this.__id;
  1179. ResourceManager.__request(
  1180. 'GET', _url, null,
  1181. function() { ResourceManager.__resourceActionSucceeded(
  1182. this, RESOURCE_RELOADED, _id); },
  1183. function() { ResourceManager.__resourceActionFailed(
  1184. this, RESURCE_RELOADED, _id); },
  1185. USE_ASYNCHRONOUS_REQUESTS
  1186. );
  1187. };
  1188. this.save = function(synchronize) {
  1189. var _url = this.__url;
  1190. var _id = this.__id;
  1191. data = DataManager.serialize($(_id));
  1192. ResourceManager.__request(
  1193. 'PUT', _url, data,
  1194. function() { ResourceManager.__resourceActionSucceeded(
  1195. this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); },
  1196. function() { ResourceManager.__resourceActionFailed(
  1197. this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); },
  1198. USE_ASYNCHRONOUS_REQUESTS
  1199. );
  1200. };
  1201. this.remove = function() {
  1202. var _url = this.__url;
  1203. var _id = this.__id;
  1204. ResourceManager.__request(
  1205. 'DELETE', _url, null,
  1206. function() { ResourceManager.__resourceActionSucceeded(
  1207. this, RESOURCE_REMOVED, _id); },
  1208. function() { ResourceManager.__resourceActionFailed(
  1209. this, RESOURCE_REMOVED, _id);},
  1210. USE_ASYNCHRONOUS_REQUESTS
  1211. );
  1212. };
  1213. },
  1214. request: function(url, requestOptions) {
  1215. var options = {
  1216. method: 'get',
  1217. asynchronous: true,
  1218. parameters: {}
  1219. };
  1220. Object.extend(options, requestOptions || {});
  1221. var params = Hash.toQueryString(options.parameters);
  1222. if (params)
  1223. url += (url.include('?') ? '&' : '?') + params;
  1224. return ResourceManager.__request(
  1225. options.method,
  1226. url,
  1227. options.data,
  1228. (options.onSuccess instanceof Function ? function() { options.onSuccess(this); } : undefined ),
  1229. (options.onFailure instanceof Function ? function() { options.onFailure(this); } : undefined ),
  1230. options.asynchronous && USE_ASYNCHRONOUS_REQUESTS,
  1231. options.headers);
  1232. },
  1233. __request: function(method, url, data, success, error, async, headers) {
  1234. // get a request object
  1235. var httpRequest = Try.these(
  1236. /* do the Mozilla/Safari/Opera stuff */
  1237. function() { return new XMLHttpRequest(); },
  1238. /* do the IE stuff */
  1239. function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
  1240. function() { return new ActiveXObject("Microsoft.XMLHTTP") }
  1241. );
  1242. // if there is no request object ...
  1243. if (!httpRequest) {
  1244. if(!this.__corrupt)
  1245. throw 'This browser does not provide any AJAX functionality. You will not be able to use the software provided with the page you are viewing. Please consider installing appropriate extensions.';
  1246. this.__corrupt = true;
  1247. return false;
  1248. }
  1249. if(success instanceof Function)
  1250. httpRequest.onload = success;
  1251. if(error instanceof Function) {
  1252. httpRequest.onerror = error;
  1253. }
  1254. var h = $H(headers)
  1255. h.keys().each(function(key) {
  1256. httpRequest.setRequestHeader(key, h[key]);
  1257. });
  1258. try {
  1259. if(SHOW_DEBUG_ALERTS_WHEN_SAVING)
  1260. alert(method + ' ' + url + '\n' +
  1261. SHOW_EXTENDED_DEBUG_INFORMATION ? data : '');
  1262. // TODO Remove synchronous calls to the server as soon as xenodot
  1263. // handles asynchronous requests without failure.
  1264. httpRequest.open(method, url, !async?false:true);
  1265. httpRequest.send(data);
  1266. } catch(e) {
  1267. return false;
  1268. }
  1269. return true;
  1270. },
  1271. __resourceActionSucceeded: function(transport, action, id) {
  1272. var status = transport.status;
  1273. var response = transport.responseText;
  1274. if(SHOW_DEBUG_ALERTS_WHEN_SAVING)
  1275. alert(status + ' ' + url + '\n' +
  1276. SHOW_EXTENDED_DEBUG_INFORMATION ? data : '');
  1277. // if the status code is not in 2xx, throw an error.
  1278. if(status >= 300)
  1279. throw 'The server responded with an error: ' + status + '\n' + (SHOW_EXTENDED_DEBUG_INFORMATION ? + data : 'If you need additional information here, including the data sent by the server, consider setting SHOW_EXTENDED_DEBUG_INFORMATION to true.');
  1280. switch(action) {
  1281. case RESOURCE_REMOVED:
  1282. // get div and id
  1283. var response = (transport.responseXML);
  1284. var div = response.childNodes[0];
  1285. var id = div.getAttribute('id');
  1286. // remove the resource from DOM
  1287. var localDiv = document.getElementById(id);
  1288. localDiv.parentNode.removeChild(localDiv);
  1289. break;
  1290. case RESOURCE_CREATED:
  1291. // nothing remains to be done.
  1292. break;
  1293. case RESOURCE_SAVED | RESOURCE_SYNCHRONIZED:
  1294. DataManager.__synclocal();
  1295. case RESOURCE_SAVED:
  1296. // nothing remains to be done.
  1297. break;
  1298. case RESOURCE_RELOADED:
  1299. // get div and id
  1300. var response = (transport.responseXML);
  1301. var div = response.childNodes[0];
  1302. var id = div.getAttribute('id');
  1303. // remove the local resource representation from DOM
  1304. var localDiv = document.getElementById(id)
  1305. localDiv.parentNode.removeChild(localDiv);
  1306. // store div in DOM
  1307. if(!$$(PROCESSDATA_REF)[0])
  1308. DataManager.graft(XMLNS.XHTML,
  1309. document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
  1310. $$(PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));
  1311. DataManager.__synclocal();
  1312. break;
  1313. default:
  1314. DataManager.__synclocal();
  1315. }
  1316. // dispatch to all listeners ...
  1317. ResourceManager.__dispatchEvent(
  1318. // ... an event describing the change that happened here.
  1319. new ResourceManager.__Event(action, id)
  1320. );
  1321. },
  1322. __resourceActionFailed: function(transport, action, id) {
  1323. throw "Fatal: Resource action failed. There is something horribly " +
  1324. "wrong with either the server, the transport protocol or your " +
  1325. "online status. Sure you're online?";
  1326. }
  1327. }/*
  1328. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  1329. * License rights for this program may be obtained from Alfresco Software, Ltd.
  1330. * pursuant to a written agreement and any use of this program without such an
  1331. * agreement is prohibited.
  1332. */
  1333. /*
  1334. * All code Copyright 2013 KIS Consultancy all rights reserved
  1335. */
  1336. /**
  1337. * The super class for all classes in ORYX. Adds some OOP feeling to javascript.
  1338. * See article "Object Oriented Super Class Method Calling with JavaScript" on
  1339. * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html
  1340. * for a documentation on this. Fairly good article that points out errors in
  1341. * Douglas Crockford's inheritance and super method calling approach.
  1342. * Worth reading.
  1343. * @class Clazz
  1344. */
  1345. var Clazz = function() {};
  1346. /**
  1347. * Empty constructor.
  1348. * @methodOf Clazz.prototype
  1349. */
  1350. Clazz.prototype.construct = function() {};
  1351. /**
  1352. * Can be used to build up inheritances of classes.
  1353. * @example
  1354. * var MyClass = Clazz.extend({
  1355. * construct: function(myParam){
  1356. * // Do sth.
  1357. * }
  1358. * });
  1359. * var MySubClass = MyClass.extend({
  1360. * construct: function(myParam){
  1361. * // Use this to call constructor of super class
  1362. * arguments.callee.$.construct.apply(this, arguments);
  1363. * // Do sth.
  1364. * }
  1365. * });
  1366. * @param {Object} def The definition of the new class.
  1367. */
  1368. Clazz.extend = function(def) {
  1369. var classDef = function() {
  1370. if (arguments[0] !== Clazz) { this.construct.apply(this, arguments); }
  1371. };
  1372. var proto = new this(Clazz);
  1373. var superClass = this.prototype;
  1374. for (var n in def) {
  1375. var item = def[n];
  1376. if (item instanceof Function) item.$ = superClass;
  1377. proto[n] = item;
  1378. }
  1379. classDef.prototype = proto;
  1380. //Give this new class the same static extend method
  1381. classDef.extend = this.extend;
  1382. return classDef;
  1383. };/*
  1384. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  1385. * License rights for this program may be obtained from Alfresco Software, Ltd.
  1386. * pursuant to a written agreement and any use of this program without such an
  1387. * agreement is prohibited.
  1388. */
  1389. /*
  1390. * All code Copyright 2013 KIS Consultancy all rights reserved
  1391. */
  1392. if(!ORYX) var ORYX = {};
  1393. if(!ORYX.CONFIG) ORYX.CONFIG = {};
  1394. /**
  1395. * This file contains URI constants that may be used for XMLHTTPRequests.
  1396. */
  1397. ORYX.CONFIG.ROOT_PATH = "editor/"; //TODO: Remove last slash!!
  1398. ORYX.CONFIG.EXPLORER_PATH = "explorer";
  1399. ORYX.CONFIG.LIBS_PATH = "libs";
  1400. /**
  1401. * Regular Config
  1402. */
  1403. ORYX.CONFIG.SERVER_HANDLER_ROOT = "service";
  1404. ORYX.CONFIG.SERVER_EDITOR_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor";
  1405. ORYX.CONFIG.SERVER_MODEL_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/model";
  1406. ORYX.CONFIG.STENCILSET_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_stencilset?embedsvg=true&url=true&namespace=";
  1407. ORYX.CONFIG.STENCIL_SETS_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_stencilset";
  1408. ORYX.CONFIG.PLUGINS_CONFIG = "editor-app/plugins.xml";
  1409. ORYX.CONFIG.SYNTAXCHECKER_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/syntaxchecker";
  1410. ORYX.CONFIG.DEPLOY_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/model/deploy";
  1411. ORYX.CONFIG.MODEL_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/models";
  1412. ORYX.CONFIG.FORM_FLOW_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/formflows";
  1413. ORYX.CONFIG.FORM_FLOW_IMAGE_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/formflow";
  1414. ORYX.CONFIG.FORM_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/forms";
  1415. ORYX.CONFIG.FORM_IMAGE_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/form";
  1416. ORYX.CONFIG.SUB_PROCESS_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/subprocesses";
  1417. ORYX.CONFIG.SUB_PROCESS_IMAGE_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/subprocess";
  1418. ORYX.CONFIG.TEST_SERVICE_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/service/";
  1419. ORYX.CONFIG.SERVICE_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/services";
  1420. ORYX.CONFIG.CONDITION_ELEMENT_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/conditionelements";
  1421. ORYX.CONFIG.VARIABLEDEF_ELEMENT_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/variabledefinitionelements";
  1422. ORYX.CONFIG.VALIDATOR_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/validators";
  1423. ORYX.CONFIG.SS_EXTENSIONS_FOLDER = ORYX.CONFIG.ROOT_PATH + "stencilsets/extensions/";
  1424. ORYX.CONFIG.SS_EXTENSIONS_CONFIG = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_ssextensions";
  1425. ORYX.CONFIG.ORYX_NEW_URL = "/new";
  1426. ORYX.CONFIG.BPMN_LAYOUTER = ORYX.CONFIG.ROOT_PATH + "bpmnlayouter";
  1427. ORYX.CONFIG.EXPRESSION_METADATA_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/expression-metadata";
  1428. ORYX.CONFIG.DATASOURCE_METADATA_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/datasource-metadata";/*
  1429. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  1430. * License rights for this program may be obtained from Alfresco Software, Ltd.
  1431. * pursuant to a written agreement and any use of this program without such an
  1432. * agreement is prohibited.
  1433. */
  1434. /*
  1435. * All code Copyright 2013 KIS Consultancy all rights reserved
  1436. */
  1437. if(!ORYX) var ORYX = {};
  1438. if(!ORYX.CONFIG) ORYX.CONFIG = {};
  1439. /**
  1440. * Signavio specific variables
  1441. */
  1442. ORYX.CONFIG.BACKEND_SWITCH = true;
  1443. ORYX.CONFIG.PANEL_LEFT_WIDTH = 250;
  1444. ORYX.CONFIG.PANEL_RIGHT_COLLAPSED = true;
  1445. ORYX.CONFIG.PANEL_RIGHT_WIDTH = 300;
  1446. ORYX.CONFIG.APPNAME = 'KISBPM';
  1447. ORYX.CONFIG.WEB_URL = ".";
  1448. ORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif';
  1449. /* Specify offset of header */
  1450. ORYX.CONFIG.OFFSET_HEADER = 61;
  1451. /* Show grid line while dragging */
  1452. ORYX.CONFIG.SHOW_GRIDLINE = true;
  1453. /* Editor-Mode */
  1454. ORYX.CONFIG.MODE_READONLY = "readonly";
  1455. ORYX.CONFIG.MODE_FULLSCREEN = "fullscreen";
  1456. ORYX.CONFIG.WINDOW_HEIGHT = 800;
  1457. ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false;
  1458. /* Plugins */
  1459. ORYX.CONFIG.PLUGINS_ENABLED = true;
  1460. ORYX.CONFIG.PLUGINS_FOLDER = "Plugins/";
  1461. ORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true;
  1462. /* Namespaces */
  1463. ORYX.CONFIG.NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
  1464. ORYX.CONFIG.NAMESPACE_SVG = "http://www.w3.org/2000/svg";
  1465. /* UI */
  1466. ORYX.CONFIG.CANVAS_WIDTH = 1200;
  1467. ORYX.CONFIG.CANVAS_HEIGHT = 1050;
  1468. ORYX.CONFIG.CANVAS_RESIZE_INTERVAL = 100;
  1469. ORYX.CONFIG.CANVAS_MIN_WIDTH = 800;
  1470. ORYX.CONFIG.CANVAS_MIN_HEIGHT = 300;
  1471. ORYX.CONFIG.SELECTED_AREA_PADDING = 4;
  1472. ORYX.CONFIG.CANVAS_BACKGROUND_COLOR = "none";
  1473. ORYX.CONFIG.GRID_DISTANCE = 30;
  1474. ORYX.CONFIG.GRID_ENABLED = true;
  1475. ORYX.CONFIG.ZOOM_OFFSET = 0.1;
  1476. ORYX.CONFIG.DEFAULT_SHAPE_MARGIN = 60;
  1477. ORYX.CONFIG.SCALERS_SIZE = 7;
  1478. ORYX.CONFIG.MINIMUM_SIZE = 20;
  1479. ORYX.CONFIG.MAXIMUM_SIZE = 10000;
  1480. ORYX.CONFIG.OFFSET_MAGNET = 15;
  1481. ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP = 8;
  1482. ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM = 8;
  1483. ORYX.CONFIG.OFFSET_EDGE_BOUNDS = 5;
  1484. ORYX.CONFIG.COPY_MOVE_OFFSET = 30;
  1485. ORYX.CONFIG.BORDER_OFFSET = 14;
  1486. ORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP = 20; // Updated so the form editor shows all elements at once
  1487. ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30;
  1488. ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45;
  1489. /* Shape-Menu Align */
  1490. ORYX.CONFIG.SHAPEMENU_RIGHT = "Oryx_Right";
  1491. ORYX.CONFIG.SHAPEMENU_BOTTOM = "Oryx_Bottom";
  1492. ORYX.CONFIG.SHAPEMENU_LEFT = "Oryx_Left";
  1493. ORYX.CONFIG.SHAPEMENU_TOP = "Oryx_Top";
  1494. /* Morph-Menu Item */
  1495. ORYX.CONFIG.MORPHITEM_DISABLED = "Oryx_MorphItem_disabled";
  1496. /* Property type names */
  1497. ORYX.CONFIG.TYPE_STRING = "string";
  1498. ORYX.CONFIG.TYPE_BOOLEAN = "boolean";
  1499. ORYX.CONFIG.TYPE_INTEGER = "integer";
  1500. ORYX.CONFIG.TYPE_FLOAT = "float";
  1501. ORYX.CONFIG.TYPE_COLOR = "color";
  1502. ORYX.CONFIG.TYPE_DATE = "date";
  1503. ORYX.CONFIG.TYPE_CHOICE = "choice";
  1504. ORYX.CONFIG.TYPE_URL = "url";
  1505. ORYX.CONFIG.TYPE_DIAGRAM_LINK = "diagramlink";
  1506. ORYX.CONFIG.TYPE_COMPLEX = "complex";
  1507. ORYX.CONFIG.TYPE_MULTIPLECOMPLEX = "multiplecomplex";
  1508. ORYX.CONFIG.TYPE_TEXT = "text";
  1509. ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE = "kisbpm-multiinstance";
  1510. ORYX.CONFIG.TYPE_MODEL_LINK = "modellink";
  1511. ORYX.CONFIG.TYPE_FORM_FLOW_LINK = "formflowlink";
  1512. ORYX.CONFIG.TYPE_FORM_LINK = "formlink";
  1513. ORYX.CONFIG.TYPE_SUB_PROCESS_LINK = "subprocesslink";
  1514. ORYX.CONFIG.TYPE_SERVICE_LINK = "servicelink";
  1515. ORYX.CONFIG.TYPE_CONDITIONS = "conditions";
  1516. ORYX.CONFIG.TYPE_VARIABLES = "variables";
  1517. ORYX.CONFIG.TYPE_LISTENER = "listener";
  1518. ORYX.CONFIG.TYPE_EPC_FREQ = "epcfrequency";
  1519. ORYX.CONFIG.TYPE_GLOSSARY_LINK = "glossarylink";
  1520. ORYX.CONFIG.TYPE_EXPRESSION = "expression";
  1521. ORYX.CONFIG.TYPE_DATASOURCE = "datasource";
  1522. ORYX.CONFIG.TYPE_DATASOURCE_MINIMAL = "datasource-minimal";
  1523. ORYX.CONFIG.TYPE_VALIDATORS = "validators";
  1524. /* Vertical line distance of multiline labels */
  1525. ORYX.CONFIG.LABEL_LINE_DISTANCE = 2;
  1526. ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT = 12;
  1527. /* Open Morph Menu with Hover */
  1528. ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false;
  1529. /* Editor constants come here */
  1530. ORYX.CONFIG.EDITOR_ALIGN_BOTTOM = 0x01;
  1531. ORYX.CONFIG.EDITOR_ALIGN_MIDDLE = 0x02;
  1532. ORYX.CONFIG.EDITOR_ALIGN_TOP = 0x04;
  1533. ORYX.CONFIG.EDITOR_ALIGN_LEFT = 0x08;
  1534. ORYX.CONFIG.EDITOR_ALIGN_CENTER = 0x10;
  1535. ORYX.CONFIG.EDITOR_ALIGN_RIGHT = 0x20;
  1536. ORYX.CONFIG.EDITOR_ALIGN_SIZE = 0x30;
  1537. /* Event types */
  1538. ORYX.CONFIG.EVENT_MOUSEDOWN = "mousedown";
  1539. ORYX.CONFIG.EVENT_MOUSEUP = "mouseup";
  1540. ORYX.CONFIG.EVENT_MOUSEOVER = "mouseover";
  1541. ORYX.CONFIG.EVENT_MOUSEOUT = "mouseout";
  1542. ORYX.CONFIG.EVENT_MOUSEMOVE = "mousemove";
  1543. ORYX.CONFIG.EVENT_DBLCLICK = "dblclick";
  1544. ORYX.CONFIG.EVENT_KEYDOWN = "keydown";
  1545. ORYX.CONFIG.EVENT_KEYUP = "keyup";
  1546. ORYX.CONFIG.EVENT_LOADED = "editorloaded";
  1547. ORYX.CONFIG.EVENT_SAVED = "editorSaved";
  1548. ORYX.CONFIG.EVENT_EXECUTE_COMMANDS = "executeCommands";
  1549. ORYX.CONFIG.EVENT_STENCIL_SET_LOADED = "stencilSetLoaded";
  1550. ORYX.CONFIG.EVENT_SELECTION_CHANGED = "selectionchanged";
  1551. ORYX.CONFIG.EVENT_SHAPEADDED = "shapeadded";
  1552. ORYX.CONFIG.EVENT_SHAPEREMOVED = "shaperemoved";
  1553. ORYX.CONFIG.EVENT_PROPERTY_CHANGED = "propertyChanged";
  1554. ORYX.CONFIG.EVENT_DRAGDROP_START = "dragdrop.start";
  1555. ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE = "shape.menu.close";
  1556. ORYX.CONFIG.EVENT_DRAGDROP_END = "dragdrop.end";
  1557. ORYX.CONFIG.EVENT_RESIZE_START = "resize.start";
  1558. ORYX.CONFIG.EVENT_RESIZE_END = "resize.end";
  1559. ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED = "dragDocker.docked";
  1560. ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW = "highlight.showHighlight";
  1561. ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE = "highlight.hideHighlight";
  1562. ORYX.CONFIG.EVENT_LOADING_ENABLE = "loading.enable";
  1563. ORYX.CONFIG.EVENT_LOADING_DISABLE = "loading.disable";
  1564. ORYX.CONFIG.EVENT_LOADING_STATUS = "loading.status";
  1565. ORYX.CONFIG.EVENT_OVERLAY_SHOW = "overlay.show";
  1566. ORYX.CONFIG.EVENT_OVERLAY_HIDE = "overlay.hide";
  1567. ORYX.CONFIG.EVENT_ARRANGEMENT_TOP = "arrangement.setToTop";
  1568. ORYX.CONFIG.EVENT_ARRANGEMENT_BACK = "arrangement.setToBack";
  1569. ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD = "arrangement.setForward";
  1570. ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD = "arrangement.setBackward";
  1571. ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED = "propertyWindow.propertyChanged";
  1572. ORYX.CONFIG.EVENT_LAYOUT_ROWS = "layout.rows";
  1573. ORYX.CONFIG.EVENT_LAYOUT_BPEL = "layout.BPEL";
  1574. ORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL = "layout.BPEL.vertical";
  1575. ORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL = "layout.BPEL.horizontal";
  1576. ORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = "layout.BPEL.singlechild";
  1577. ORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE = "layout.BPEL.autoresize";
  1578. ORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT = "autolayout.layout";
  1579. ORYX.CONFIG.EVENT_UNDO_EXECUTE = "undo.execute";
  1580. ORYX.CONFIG.EVENT_UNDO_ROLLBACK = "undo.rollback";
  1581. ORYX.CONFIG.EVENT_BUTTON_UPDATE = "toolbar.button.update";
  1582. ORYX.CONFIG.EVENT_LAYOUT = "layout.dolayout";
  1583. ORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = "glossary.link.edit";
  1584. ORYX.CONFIG.EVENT_GLOSSARY_SHOW = "glossary.show.info";
  1585. ORYX.CONFIG.EVENT_GLOSSARY_NEW = "glossary.show.new";
  1586. ORYX.CONFIG.EVENT_DOCKERDRAG = "dragTheDocker";
  1587. ORYX.CONFIG.EVENT_CANVAS_SCROLL = "canvas.scroll";
  1588. ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW = "propertywindow.show";
  1589. ORYX.CONFIG.EVENT_ABOUT_TO_SAVE = "file.aboutToSave";
  1590. /* Selection Shapes Highlights */
  1591. ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE = 5;
  1592. ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR = "#4444FF";
  1593. ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR2 = "#9999FF";
  1594. ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_CORNER = "corner";
  1595. ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE = "rectangle";
  1596. ORYX.CONFIG.SELECTION_VALID_COLOR = "#00FF00";
  1597. ORYX.CONFIG.SELECTION_INVALID_COLOR = "#FF0000";
  1598. ORYX.CONFIG.DOCKER_DOCKED_COLOR = "#00FF00";
  1599. ORYX.CONFIG.DOCKER_UNDOCKED_COLOR = "#FF0000";
  1600. ORYX.CONFIG.DOCKER_SNAP_OFFSET = 10;
  1601. /* Copy & Paste */
  1602. ORYX.CONFIG.EDIT_OFFSET_PASTE = 10;
  1603. /* Key-Codes */
  1604. ORYX.CONFIG.KEY_CODE_X = 88;
  1605. ORYX.CONFIG.KEY_CODE_C = 67;
  1606. ORYX.CONFIG.KEY_CODE_V = 86;
  1607. ORYX.CONFIG.KEY_CODE_DELETE = 46;
  1608. ORYX.CONFIG.KEY_CODE_META = 224;
  1609. ORYX.CONFIG.KEY_CODE_BACKSPACE = 8;
  1610. ORYX.CONFIG.KEY_CODE_LEFT = 37;
  1611. ORYX.CONFIG.KEY_CODE_RIGHT = 39;
  1612. ORYX.CONFIG.KEY_CODE_UP = 38;
  1613. ORYX.CONFIG.KEY_CODE_DOWN = 40;
  1614. // TODO Determine where the lowercase constants are still used and remove them from here.
  1615. ORYX.CONFIG.KEY_Code_enter = 12;
  1616. ORYX.CONFIG.KEY_Code_left = 37;
  1617. ORYX.CONFIG.KEY_Code_right = 39;
  1618. ORYX.CONFIG.KEY_Code_top = 38;
  1619. ORYX.CONFIG.KEY_Code_bottom = 40;
  1620. /* Supported Meta Keys */
  1621. ORYX.CONFIG.META_KEY_META_CTRL = "metactrl";
  1622. ORYX.CONFIG.META_KEY_ALT = "alt";
  1623. ORYX.CONFIG.META_KEY_SHIFT = "shift";
  1624. /* Key Actions */
  1625. ORYX.CONFIG.KEY_ACTION_DOWN = "down";
  1626. ORYX.CONFIG.KEY_ACTION_UP = "up";
  1627. /* Form Rowlayouting */
  1628. ORYX.CONFIG.FORM_ROW_WIDTH = 350;
  1629. ORYX.CONFIG.FORM_GROUP_MARGIN = 5;
  1630. ORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT = 100;
  1631. /* Form element types */
  1632. ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX = 'http://b3mn.org/stencilset/xforms';
  1633. ORYX.CONFIG.FORM_ELEMENT_TYPE_ROOT = 'http://b3mn.org/stencilset/xforms#XForm';
  1634. ORYX.CONFIG.FORM_ELEMENT_TYPE_GROUP = 'http://b3mn.org/stencilset/xforms#Group';
  1635. ORYX.CONFIG.FORM_ELEMENT_TYPE_REPEATING_GROUP = 'http://b3mn.org/stencilset/xforms#RepeatingGroup';
  1636. ORYX.CONFIG.FORM_ELEMENT_TYPE_LABEL_FIELD = 'http://b3mn.org/stencilset/xforms#LabelField';
  1637. /*
  1638. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  1639. * License rights for this program may be obtained from Alfresco Software, Ltd.
  1640. * pursuant to a written agreement and any use of this program without such an
  1641. * agreement is prohibited.
  1642. */
  1643. /*
  1644. * All code Copyright 2013 KIS Consultancy all rights reserved
  1645. */
  1646. function printf() {
  1647. var result = arguments[0];
  1648. for (var i=1; i<arguments.length; i++)
  1649. result = result.replace('%' + (i-1), arguments[i]);
  1650. return result;
  1651. }
  1652. // oryx constants.
  1653. var ORYX_LOGLEVEL_TRACE = 5;
  1654. var ORYX_LOGLEVEL_DEBUG = 4;
  1655. var ORYX_LOGLEVEL_INFO = 3;
  1656. var ORYX_LOGLEVEL_WARN = 2;
  1657. var ORYX_LOGLEVEL_ERROR = 1;
  1658. var ORYX_LOGLEVEL_FATAL = 0;
  1659. var ORYX_LOGLEVEL = 3;
  1660. var ORYX_CONFIGURATION_DELAY = 100;
  1661. var ORYX_CONFIGURATION_WAIT_ATTEMPTS = 10;
  1662. if(!ORYX) var ORYX = {};
  1663. ORYX = Object.extend(ORYX, {
  1664. //set the path in the config.js file!!!!
  1665. PATH: ORYX.CONFIG.ROOT_PATH,
  1666. //CONFIGURATION: "config.js",
  1667. URLS: [],
  1668. alreadyLoaded: [],
  1669. configrationRetries: 0,
  1670. Version: '0.1.1',
  1671. availablePlugins: [],
  1672. /**
  1673. * The ORYX.Log logger.
  1674. */
  1675. Log: {
  1676. __appenders: [
  1677. {
  1678. append: function(message) {
  1679. if(typeof(console) !== "undefined" && console.log !== undefined) {
  1680. console.log(message);
  1681. }
  1682. }
  1683. }
  1684. ],
  1685. trace: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_TRACE)
  1686. ORYX.Log.__log('TRACE', arguments); },
  1687. debug: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_DEBUG)
  1688. ORYX.Log.__log('DEBUG', arguments); },
  1689. info: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_INFO)
  1690. ORYX.Log.__log('INFO', arguments); },
  1691. warn: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_WARN)
  1692. ORYX.Log.__log('WARN', arguments); },
  1693. error: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_ERROR)
  1694. ORYX.Log.__log('ERROR', arguments); },
  1695. fatal: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_FATAL)
  1696. ORYX.Log.__log('FATAL', arguments); },
  1697. __log: function(prefix, messageParts) {
  1698. messageParts[0] = (new Date()).getTime() + " "
  1699. + prefix + " " + messageParts[0];
  1700. var message = printf.apply(null, messageParts);
  1701. ORYX.Log.__appenders.each(function(appender) {
  1702. appender.append(message);
  1703. });
  1704. },
  1705. addAppender: function(appender) {
  1706. ORYX.Log.__appenders.push(appender);
  1707. }
  1708. },
  1709. /**
  1710. * First bootstrapping layer. The Oryx loading procedure begins. In this
  1711. * step, all preliminaries that are not in the responsibility of Oryx to be
  1712. * met have to be checked here, such as the existance of the prototpe
  1713. * library in the current execution environment. After that, the second
  1714. * bootstrapping layer is being invoked. Failing to ensure that any
  1715. * preliminary condition is not met has to fail with an error.
  1716. */
  1717. load: function() {
  1718. ORYX.Log.debug("Oryx begins loading procedure.");
  1719. // check for prototype
  1720. if( (typeof Prototype=='undefined') ||
  1721. (typeof Element == 'undefined') ||
  1722. (typeof Element.Methods=='undefined') ||
  1723. parseFloat(Prototype.Version.split(".")[0] + "." +
  1724. Prototype.Version.split(".")[1]) < 1.5)
  1725. throw("Application requires the Prototype JavaScript framework >= 1.5.3");
  1726. ORYX.Log.debug("Prototype > 1.5 found.");
  1727. // continue loading.
  1728. ORYX._load();
  1729. },
  1730. /**
  1731. * Second bootstrapping layer. The oryx configuration is checked. When not
  1732. * yet loaded, config.js is being requested from the server. A repeated
  1733. * error in retrieving the configuration will result in an error to be
  1734. * thrown after a certain time of retries. Once the configuration is there,
  1735. * all urls that are registered with oryx loading are being requested from
  1736. * the server. Once everything is loaded, the third layer is being invoked.
  1737. */
  1738. _load: function() {
  1739. /*
  1740. // if configuration not there already,
  1741. if(!(ORYX.CONFIG)) {
  1742. // if this is the first attempt...
  1743. if(ORYX.configrationRetries == 0) {
  1744. // get the path and filename.
  1745. var configuration = ORYX.PATH + ORYX.CONFIGURATION;
  1746. ORYX.Log.debug("Configuration not found, loading from '%0'.",
  1747. configuration);
  1748. // require configuration file.
  1749. Kickstart.require(configuration);
  1750. // else if attempts exceeded ...
  1751. } else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) {
  1752. throw "Tried to get configuration" +
  1753. ORYX_CONFIGURATION_WAIT_ATTEMPTS +
  1754. " times from '" + configuration + "'. Giving up."
  1755. } else if(ORYX.configrationRetries > 0){
  1756. // point out how many attempts are left...
  1757. ORYX.Log.debug("Waiting once more (%0 attempts left)",
  1758. (ORYX_CONFIGURATION_WAIT_ATTEMPTS -
  1759. ORYX.configrationRetries));
  1760. }
  1761. // any case: continue in a moment with increased retry count.
  1762. ORYX.configrationRetries++;
  1763. window.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY);
  1764. return;
  1765. }
  1766. ORYX.Log.info("Configuration loaded.");
  1767. // load necessary scripts.
  1768. ORYX.URLS.each(function(url) {
  1769. ORYX.Log.debug("Requireing '%0'", url);
  1770. Kickstart.require(ORYX.PATH + url) });
  1771. */
  1772. // configurate logging and load plugins.
  1773. ORYX.loadPlugins();
  1774. },
  1775. /**
  1776. * Third bootstrapping layer. This is where first the plugin coniguration
  1777. * file is loaded into oryx, analyzed, and where all plugins are being
  1778. * requested by the server. Afterwards, all editor instances will be
  1779. * initialized.
  1780. */
  1781. loadPlugins: function() {
  1782. // load plugins if enabled.
  1783. if(ORYX.CONFIG.PLUGINS_ENABLED)
  1784. ORYX._loadPlugins()
  1785. else
  1786. ORYX.Log.warn("Ignoring plugins, loading Core only.");
  1787. // init the editor instances.
  1788. init();
  1789. },
  1790. _loadPlugins: function() {
  1791. // load plugin configuration file.
  1792. var source = ORYX.CONFIG.PLUGINS_CONFIG;
  1793. ORYX.Log.debug("Loading plugin configuration from '%0'.", source);
  1794. new Ajax.Request(source, {
  1795. asynchronous: false,
  1796. method: 'get',
  1797. onSuccess: function(result) {
  1798. /*
  1799. * This is the method that is being called when the plugin
  1800. * configuration was successfully loaded from the server. The
  1801. * file has to be processed and the contents need to be
  1802. * considered for further plugin requireation.
  1803. */
  1804. ORYX.Log.info("Plugin configuration file loaded.");
  1805. // get plugins.xml content
  1806. var resultXml = result.responseXML;
  1807. // TODO: Describe how properties are handled.
  1808. // Get the globale Properties
  1809. var globalProperties = [];
  1810. var preferences = $A(resultXml.getElementsByTagName("properties"));
  1811. preferences.each( function(p) {
  1812. var props = $A(p.childNodes);
  1813. props.each( function(prop) {
  1814. var property = new Hash();
  1815. // get all attributes from the node and set to global properties
  1816. var attributes = $A(prop.attributes)
  1817. attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});
  1818. if(attributes.length > 0) { globalProperties.push(property) };
  1819. });
  1820. });
  1821. // TODO Why are we using XML if we don't respect structure anyway?
  1822. // for each plugin element in the configuration..
  1823. var plugin = resultXml.getElementsByTagName("plugin");
  1824. $A(plugin).each( function(node) {
  1825. // get all element's attributes.
  1826. // TODO: What about: var pluginData = $H(node.attributes) !?
  1827. var pluginData = new Hash();
  1828. $A(node.attributes).each( function(attr){
  1829. pluginData[attr.nodeName] = attr.nodeValue});
  1830. // ensure there's a name attribute.
  1831. if(!pluginData['name']) {
  1832. ORYX.Log.error("A plugin is not providing a name. Ingnoring this plugin.");
  1833. return;
  1834. }
  1835. // ensure there's a source attribute.
  1836. if(!pluginData['source']) {
  1837. ORYX.Log.error("Plugin with name '%0' doesn't provide a source attribute.", pluginData['name']);
  1838. return;
  1839. }
  1840. // Get all private Properties
  1841. var propertyNodes = node.getElementsByTagName("property");
  1842. var properties = [];
  1843. $A(propertyNodes).each(function(prop) {
  1844. var property = new Hash();
  1845. // Get all Attributes from the Node
  1846. var attributes = $A(prop.attributes)
  1847. attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});
  1848. if(attributes.length > 0) { properties.push(property) };
  1849. });
  1850. // Set all Global-Properties to the Properties
  1851. properties = properties.concat(globalProperties);
  1852. // Set Properties to Plugin-Data
  1853. pluginData['properties'] = properties;
  1854. // Get the RequieredNodes
  1855. var requireNodes = node.getElementsByTagName("requires");
  1856. var requires;
  1857. $A(requireNodes).each(function(req) {
  1858. var namespace = $A(req.attributes).find(function(attr){ return attr.name == "namespace"})
  1859. if( namespace && namespace.nodeValue ){
  1860. if( !requires ){
  1861. requires = {namespaces:[]}
  1862. }
  1863. requires.namespaces.push(namespace.nodeValue)
  1864. }
  1865. });
  1866. // Set Requires to the Plugin-Data, if there is one
  1867. if( requires ){
  1868. pluginData['requires'] = requires;
  1869. }
  1870. // Get the RequieredNodes
  1871. var notUsesInNodes = node.getElementsByTagName("notUsesIn");
  1872. var notUsesIn;
  1873. $A(notUsesInNodes).each(function(not) {
  1874. var namespace = $A(not.attributes).find(function(attr){ return attr.name == "namespace"})
  1875. if( namespace && namespace.nodeValue ){
  1876. if( !notUsesIn ){
  1877. notUsesIn = {namespaces:[]}
  1878. }
  1879. notUsesIn.namespaces.push(namespace.nodeValue)
  1880. }
  1881. });
  1882. // Set Requires to the Plugin-Data, if there is one
  1883. if( notUsesIn ){
  1884. pluginData['notUsesIn'] = notUsesIn;
  1885. }
  1886. var url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source'];
  1887. ORYX.Log.debug("Requireing '%0'", url);
  1888. // Add the Script-Tag to the Site
  1889. //Kickstart.require(url);
  1890. ORYX.Log.info("Plugin '%0' successfully loaded.", pluginData['name']);
  1891. // Add the Plugin-Data to all available Plugins
  1892. ORYX.availablePlugins.push(pluginData);
  1893. });
  1894. },
  1895. onFailure:this._loadPluginsOnFails
  1896. });
  1897. },
  1898. _loadPluginsOnFails: function(result) {
  1899. ORYX.Log.error("Plugin configuration file not available.");
  1900. }
  1901. });
  1902. /*
  1903. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  1904. * License rights for this program may be obtained from Alfresco Software, Ltd.
  1905. * pursuant to a written agreement and any use of this program without such an
  1906. * agreement is prohibited.
  1907. */
  1908. /*
  1909. * All code Copyright 2013 KIS Consultancy all rights reserved
  1910. */
  1911. /**
  1912. * Init namespaces
  1913. */
  1914. if(!ORYX) {var ORYX = {};}
  1915. if(!ORYX.Core) {ORYX.Core = {};}
  1916. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  1917. /**
  1918. * EditPathHandler
  1919. *
  1920. * Edit SVG paths' coordinates according to specified from-to movement and
  1921. * horizontal and vertical scaling factors.
  1922. * The resulting path's d attribute is stored in instance variable d.
  1923. *
  1924. * @constructor
  1925. */
  1926. ORYX.Core.SVG.EditPathHandler = Clazz.extend({
  1927. construct: function() {
  1928. arguments.callee.$.construct.apply(this, arguments);
  1929. this.x = 0;
  1930. this.y = 0;
  1931. this.oldX = 0;
  1932. this.oldY = 0;
  1933. this.deltaWidth = 1;
  1934. this.deltaHeight = 1;
  1935. this.d = "";
  1936. },
  1937. /**
  1938. * init
  1939. *
  1940. * @param {float} x Target point's x-coordinate
  1941. * @param {float} y Target point's y-coordinate
  1942. * @param {float} oldX Reference point's x-coordinate
  1943. * @param {float} oldY Reference point's y-coordinate
  1944. * @param {float} deltaWidth Horizontal scaling factor
  1945. * @param {float} deltaHeight Vertical scaling factor
  1946. */
  1947. init: function(x, y, oldX, oldY, deltaWidth, deltaHeight) {
  1948. this.x = x;
  1949. this.y = y;
  1950. this.oldX = oldX;
  1951. this.oldY = oldY;
  1952. this.deltaWidth = deltaWidth;
  1953. this.deltaHeight = deltaHeight;
  1954. this.d = "";
  1955. },
  1956. /**
  1957. * editPointsAbs
  1958. *
  1959. * @param {Array} points Array of absolutePoints
  1960. */
  1961. editPointsAbs: function(points) {
  1962. if(points instanceof Array) {
  1963. var newPoints = [];
  1964. var x, y;
  1965. for(var i = 0; i < points.length; i++) {
  1966. x = (parseFloat(points[i]) - this.oldX)*this.deltaWidth + this.x;
  1967. i++;
  1968. y = (parseFloat(points[i]) - this.oldY)*this.deltaHeight + this.y;
  1969. newPoints.push(x);
  1970. newPoints.push(y);
  1971. }
  1972. return newPoints;
  1973. } else {
  1974. //TODO error
  1975. }
  1976. },
  1977. /**
  1978. * editPointsRel
  1979. *
  1980. * @param {Array} points Array of absolutePoints
  1981. */
  1982. editPointsRel: function(points) {
  1983. if(points instanceof Array) {
  1984. var newPoints = [];
  1985. var x, y;
  1986. for(var i = 0; i < points.length; i++) {
  1987. x = parseFloat(points[i])*this.deltaWidth;
  1988. i++;
  1989. y = parseFloat(points[i])*this.deltaHeight;
  1990. newPoints.push(x);
  1991. newPoints.push(y);
  1992. }
  1993. return newPoints;
  1994. } else {
  1995. //TODO error
  1996. }
  1997. },
  1998. /**
  1999. * arcAbs - A
  2000. *
  2001. * @param {Number} rx
  2002. * @param {Number} ry
  2003. * @param {Number} xAxisRotation
  2004. * @param {Boolean} largeArcFlag
  2005. * @param {Boolean} sweepFlag
  2006. * @param {Number} x
  2007. * @param {Number} y
  2008. */
  2009. arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2010. var pointsAbs = this.editPointsAbs([x, y]);
  2011. var pointsRel = this.editPointsRel([rx, ry]);
  2012. this.d = this.d.concat(" A" + pointsRel[0] + " " + pointsRel[1] +
  2013. " " + xAxisRotation + " " + largeArcFlag +
  2014. " " + sweepFlag + " " + pointsAbs[0] + " " +
  2015. pointsAbs[1] + " ");
  2016. },
  2017. /**
  2018. * arcRel - a
  2019. *
  2020. * @param {Number} rx
  2021. * @param {Number} ry
  2022. * @param {Number} xAxisRotation
  2023. * @param {Boolean} largeArcFlag
  2024. * @param {Boolean} sweepFlag
  2025. * @param {Number} x
  2026. * @param {Number} y
  2027. */
  2028. arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2029. var pointsRel = this.editPointsRel([rx, ry, x, y]);
  2030. this.d = this.d.concat(" a" + pointsRel[0] + " " + pointsRel[1] +
  2031. " " + xAxisRotation + " " + largeArcFlag +
  2032. " " + sweepFlag + " " + pointsRel[2] + " " +
  2033. pointsRel[3] + " ");
  2034. },
  2035. /**
  2036. * curvetoCubicAbs - C
  2037. *
  2038. * @param {Number} x1
  2039. * @param {Number} y1
  2040. * @param {Number} x2
  2041. * @param {Number} y2
  2042. * @param {Number} x
  2043. * @param {Number} y
  2044. */
  2045. curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
  2046. var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]);
  2047. this.d = this.d.concat(" C" + pointsAbs[0] + " " + pointsAbs[1] +
  2048. " " + pointsAbs[2] + " " + pointsAbs[3] +
  2049. " " + pointsAbs[4] + " " + pointsAbs[5] + " ");
  2050. },
  2051. /**
  2052. * curvetoCubicRel - c
  2053. *
  2054. * @param {Number} x1
  2055. * @param {Number} y1
  2056. * @param {Number} x2
  2057. * @param {Number} y2
  2058. * @param {Number} x
  2059. * @param {Number} y
  2060. */
  2061. curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
  2062. var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]);
  2063. this.d = this.d.concat(" c" + pointsRel[0] + " " + pointsRel[1] +
  2064. " " + pointsRel[2] + " " + pointsRel[3] +
  2065. " " + pointsRel[4] + " " + pointsRel[5] + " ");
  2066. },
  2067. /**
  2068. * linetoHorizontalAbs - H
  2069. *
  2070. * @param {Number} x
  2071. */
  2072. linetoHorizontalAbs: function(x) {
  2073. var pointsAbs = this.editPointsAbs([x, 0]);
  2074. this.d = this.d.concat(" H" + pointsAbs[0] + " ");
  2075. },
  2076. /**
  2077. * linetoHorizontalRel - h
  2078. *
  2079. * @param {Number} x
  2080. */
  2081. linetoHorizontalRel: function(x) {
  2082. var pointsRel = this.editPointsRel([x, 0]);
  2083. this.d = this.d.concat(" h" + pointsRel[0] + " ");
  2084. },
  2085. /**
  2086. * linetoAbs - L
  2087. *
  2088. * @param {Number} x
  2089. * @param {Number} y
  2090. */
  2091. linetoAbs: function(x, y) {
  2092. var pointsAbs = this.editPointsAbs([x, y]);
  2093. this.d = this.d.concat(" L" + pointsAbs[0] + " " + pointsAbs[1] + " ");
  2094. },
  2095. /**
  2096. * linetoRel - l
  2097. *
  2098. * @param {Number} x
  2099. * @param {Number} y
  2100. */
  2101. linetoRel: function(x, y) {
  2102. var pointsRel = this.editPointsRel([x, y]);
  2103. this.d = this.d.concat(" l" + pointsRel[0] + " " + pointsRel[1] + " ");
  2104. },
  2105. /**
  2106. * movetoAbs - M
  2107. *
  2108. * @param {Number} x
  2109. * @param {Number} y
  2110. */
  2111. movetoAbs: function(x, y) {
  2112. var pointsAbs = this.editPointsAbs([x, y]);
  2113. this.d = this.d.concat(" M" + pointsAbs[0] + " " + pointsAbs[1] + " ");
  2114. },
  2115. /**
  2116. * movetoRel - m
  2117. *
  2118. * @param {Number} x
  2119. * @param {Number} y
  2120. */
  2121. movetoRel: function(x, y) {
  2122. var pointsRel;
  2123. if(this.d === "") {
  2124. pointsRel = this.editPointsAbs([x, y]);
  2125. } else {
  2126. pointsRel = this.editPointsRel([x, y]);
  2127. }
  2128. this.d = this.d.concat(" m" + pointsRel[0] + " " + pointsRel[1] + " ");
  2129. },
  2130. /**
  2131. * curvetoQuadraticAbs - Q
  2132. *
  2133. * @param {Number} x1
  2134. * @param {Number} y1
  2135. * @param {Number} x
  2136. * @param {Number} y
  2137. */
  2138. curvetoQuadraticAbs: function(x1, y1, x, y) {
  2139. var pointsAbs = this.editPointsAbs([x1, y1, x, y]);
  2140. this.d = this.d.concat(" Q" + pointsAbs[0] + " " + pointsAbs[1] + " " +
  2141. pointsAbs[2] + " " + pointsAbs[3] + " ");
  2142. },
  2143. /**
  2144. * curvetoQuadraticRel - q
  2145. *
  2146. * @param {Number} x1
  2147. * @param {Number} y1
  2148. * @param {Number} x
  2149. * @param {Number} y
  2150. */
  2151. curvetoQuadraticRel: function(x1, y1, x, y) {
  2152. var pointsRel = this.editPointsRel([x1, y1, x, y]);
  2153. this.d = this.d.concat(" q" + pointsRel[0] + " " + pointsRel[1] + " " +
  2154. pointsRel[2] + " " + pointsRel[3] + " ");
  2155. },
  2156. /**
  2157. * curvetoCubicSmoothAbs - S
  2158. *
  2159. * @param {Number} x2
  2160. * @param {Number} y2
  2161. * @param {Number} x
  2162. * @param {Number} y
  2163. */
  2164. curvetoCubicSmoothAbs: function(x2, y2, x, y) {
  2165. var pointsAbs = this.editPointsAbs([x2, y2, x, y]);
  2166. this.d = this.d.concat(" S" + pointsAbs[0] + " " + pointsAbs[1] + " " +
  2167. pointsAbs[2] + " " + pointsAbs[3] + " ");
  2168. },
  2169. /**
  2170. * curvetoCubicSmoothRel - s
  2171. *
  2172. * @param {Number} x2
  2173. * @param {Number} y2
  2174. * @param {Number} x
  2175. * @param {Number} y
  2176. */
  2177. curvetoCubicSmoothRel: function(x2, y2, x, y) {
  2178. var pointsRel = this.editPointsRel([x2, y2, x, y]);
  2179. this.d = this.d.concat(" s" + pointsRel[0] + " " + pointsRel[1] + " " +
  2180. pointsRel[2] + " " + pointsRel[3] + " ");
  2181. },
  2182. /**
  2183. * curvetoQuadraticSmoothAbs - T
  2184. *
  2185. * @param {Number} x
  2186. * @param {Number} y
  2187. */
  2188. curvetoQuadraticSmoothAbs: function(x, y) {
  2189. var pointsAbs = this.editPointsAbs([x, y]);
  2190. this.d = this.d.concat(" T" + pointsAbs[0] + " " + pointsAbs[1] + " ");
  2191. },
  2192. /**
  2193. * curvetoQuadraticSmoothRel - t
  2194. *
  2195. * @param {Number} x
  2196. * @param {Number} y
  2197. */
  2198. curvetoQuadraticSmoothRel: function(x, y) {
  2199. var pointsRel = this.editPointsRel([x, y]);
  2200. this.d = this.d.concat(" t" + pointsRel[0] + " " + pointsRel[1] + " ");
  2201. },
  2202. /**
  2203. * linetoVerticalAbs - V
  2204. *
  2205. * @param {Number} y
  2206. */
  2207. linetoVerticalAbs: function(y) {
  2208. var pointsAbs = this.editPointsAbs([0, y]);
  2209. this.d = this.d.concat(" V" + pointsAbs[1] + " ");
  2210. },
  2211. /**
  2212. * linetoVerticalRel - v
  2213. *
  2214. * @param {Number} y
  2215. */
  2216. linetoVerticalRel: function(y) {
  2217. var pointsRel = this.editPointsRel([0, y]);
  2218. this.d = this.d.concat(" v" + pointsRel[1] + " ");
  2219. },
  2220. /**
  2221. * closePath - z or Z
  2222. */
  2223. closePath: function() {
  2224. this.d = this.d.concat(" z");
  2225. }
  2226. });/*
  2227. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  2228. * License rights for this program may be obtained from Alfresco Software, Ltd.
  2229. * pursuant to a written agreement and any use of this program without such an
  2230. * agreement is prohibited.
  2231. */
  2232. /*
  2233. * All code Copyright 2013 KIS Consultancy all rights reserved
  2234. */
  2235. /**
  2236. * Init namespaces
  2237. */
  2238. if(!ORYX) {var ORYX = {};}
  2239. if(!ORYX.Core) {ORYX.Core = {};}
  2240. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  2241. /**
  2242. * MinMaxPathHandler
  2243. *
  2244. * Determine the minimum and maximum of a SVG path's absolute coordinates.
  2245. * For relative coordinates the absolute value is computed for consideration.
  2246. * The values are stored in attributes minX, minY, maxX, and maxY.
  2247. *
  2248. * @constructor
  2249. */
  2250. ORYX.Core.SVG.MinMaxPathHandler = Clazz.extend({
  2251. construct: function() {
  2252. arguments.callee.$.construct.apply(this, arguments);
  2253. this.minX = undefined;
  2254. this.minY = undefined;
  2255. this.maxX = undefined;
  2256. this.maxY = undefined;
  2257. this._lastAbsX = undefined;
  2258. this._lastAbsY = undefined;
  2259. },
  2260. /**
  2261. * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY
  2262. *
  2263. * @param {Array} points Array of absolutePoints
  2264. */
  2265. calculateMinMax: function(points) {
  2266. if(points instanceof Array) {
  2267. var x, y;
  2268. for(var i = 0; i < points.length; i++) {
  2269. x = parseFloat(points[i]);
  2270. i++;
  2271. y = parseFloat(points[i]);
  2272. this.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x;
  2273. this.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x;
  2274. this.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y;
  2275. this.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y;
  2276. this._lastAbsX = x;
  2277. this._lastAbsY = y;
  2278. }
  2279. } else {
  2280. //TODO error
  2281. }
  2282. },
  2283. /**
  2284. * arcAbs - A
  2285. *
  2286. * @param {Number} rx
  2287. * @param {Number} ry
  2288. * @param {Number} xAxisRotation
  2289. * @param {Boolean} largeArcFlag
  2290. * @param {Boolean} sweepFlag
  2291. * @param {Number} x
  2292. * @param {Number} y
  2293. */
  2294. arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2295. this.calculateMinMax([x, y]);
  2296. },
  2297. /**
  2298. * arcRel - a
  2299. *
  2300. * @param {Number} rx
  2301. * @param {Number} ry
  2302. * @param {Number} xAxisRotation
  2303. * @param {Boolean} largeArcFlag
  2304. * @param {Boolean} sweepFlag
  2305. * @param {Number} x
  2306. * @param {Number} y
  2307. */
  2308. arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2309. this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
  2310. },
  2311. /**
  2312. * curvetoCubicAbs - C
  2313. *
  2314. * @param {Number} x1
  2315. * @param {Number} y1
  2316. * @param {Number} x2
  2317. * @param {Number} y2
  2318. * @param {Number} x
  2319. * @param {Number} y
  2320. */
  2321. curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
  2322. this.calculateMinMax([x1, y1, x2, y2, x, y]);
  2323. },
  2324. /**
  2325. * curvetoCubicRel - c
  2326. *
  2327. * @param {Number} x1
  2328. * @param {Number} y1
  2329. * @param {Number} x2
  2330. * @param {Number} y2
  2331. * @param {Number} x
  2332. * @param {Number} y
  2333. */
  2334. curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
  2335. this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1,
  2336. this._lastAbsX + x2, this._lastAbsY + y2,
  2337. this._lastAbsX + x, this._lastAbsY + y]);
  2338. },
  2339. /**
  2340. * linetoHorizontalAbs - H
  2341. *
  2342. * @param {Number} x
  2343. */
  2344. linetoHorizontalAbs: function(x) {
  2345. this.calculateMinMax([x, this._lastAbsY]);
  2346. },
  2347. /**
  2348. * linetoHorizontalRel - h
  2349. *
  2350. * @param {Number} x
  2351. */
  2352. linetoHorizontalRel: function(x) {
  2353. this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]);
  2354. },
  2355. /**
  2356. * linetoAbs - L
  2357. *
  2358. * @param {Number} x
  2359. * @param {Number} y
  2360. */
  2361. linetoAbs: function(x, y) {
  2362. this.calculateMinMax([x, y]);
  2363. },
  2364. /**
  2365. * linetoRel - l
  2366. *
  2367. * @param {Number} x
  2368. * @param {Number} y
  2369. */
  2370. linetoRel: function(x, y) {
  2371. this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
  2372. },
  2373. /**
  2374. * movetoAbs - M
  2375. *
  2376. * @param {Number} x
  2377. * @param {Number} y
  2378. */
  2379. movetoAbs: function(x, y) {
  2380. this.calculateMinMax([x, y]);
  2381. },
  2382. /**
  2383. * movetoRel - m
  2384. *
  2385. * @param {Number} x
  2386. * @param {Number} y
  2387. */
  2388. movetoRel: function(x, y) {
  2389. if(this._lastAbsX && this._lastAbsY) {
  2390. this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
  2391. } else {
  2392. this.calculateMinMax([x, y]);
  2393. }
  2394. },
  2395. /**
  2396. * curvetoQuadraticAbs - Q
  2397. *
  2398. * @param {Number} x1
  2399. * @param {Number} y1
  2400. * @param {Number} x
  2401. * @param {Number} y
  2402. */
  2403. curvetoQuadraticAbs: function(x1, y1, x, y) {
  2404. this.calculateMinMax([x1, y1, x, y]);
  2405. },
  2406. /**
  2407. * curvetoQuadraticRel - q
  2408. *
  2409. * @param {Number} x1
  2410. * @param {Number} y1
  2411. * @param {Number} x
  2412. * @param {Number} y
  2413. */
  2414. curvetoQuadraticRel: function(x1, y1, x, y) {
  2415. this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]);
  2416. },
  2417. /**
  2418. * curvetoCubicSmoothAbs - S
  2419. *
  2420. * @param {Number} x2
  2421. * @param {Number} y2
  2422. * @param {Number} x
  2423. * @param {Number} y
  2424. */
  2425. curvetoCubicSmoothAbs: function(x2, y2, x, y) {
  2426. this.calculateMinMax([x2, y2, x, y]);
  2427. },
  2428. /**
  2429. * curvetoCubicSmoothRel - s
  2430. *
  2431. * @param {Number} x2
  2432. * @param {Number} y2
  2433. * @param {Number} x
  2434. * @param {Number} y
  2435. */
  2436. curvetoCubicSmoothRel: function(x2, y2, x, y) {
  2437. this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]);
  2438. },
  2439. /**
  2440. * curvetoQuadraticSmoothAbs - T
  2441. *
  2442. * @param {Number} x
  2443. * @param {Number} y
  2444. */
  2445. curvetoQuadraticSmoothAbs: function(x, y) {
  2446. this.calculateMinMax([x, y]);
  2447. },
  2448. /**
  2449. * curvetoQuadraticSmoothRel - t
  2450. *
  2451. * @param {Number} x
  2452. * @param {Number} y
  2453. */
  2454. curvetoQuadraticSmoothRel: function(x, y) {
  2455. this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
  2456. },
  2457. /**
  2458. * linetoVerticalAbs - V
  2459. *
  2460. * @param {Number} y
  2461. */
  2462. linetoVerticalAbs: function(y) {
  2463. this.calculateMinMax([this._lastAbsX, y]);
  2464. },
  2465. /**
  2466. * linetoVerticalRel - v
  2467. *
  2468. * @param {Number} y
  2469. */
  2470. linetoVerticalRel: function(y) {
  2471. this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]);
  2472. },
  2473. /**
  2474. * closePath - z or Z
  2475. */
  2476. closePath: function() {
  2477. return;// do nothing
  2478. }
  2479. });/*
  2480. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  2481. * License rights for this program may be obtained from Alfresco Software, Ltd.
  2482. * pursuant to a written agreement and any use of this program without such an
  2483. * agreement is prohibited.
  2484. */
  2485. /*
  2486. * All code Copyright 2013 KIS Consultancy all rights reserved
  2487. */
  2488. /**
  2489. * Init namespaces
  2490. */
  2491. if(!ORYX) {var ORYX = {};}
  2492. if(!ORYX.Core) {ORYX.Core = {};}
  2493. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  2494. /**
  2495. * PathHandler
  2496. *
  2497. * Determine absolute points of a SVG path. The coordinates are stored
  2498. * sequentially in the attribute points (x-coordinates at even indices,
  2499. * y-coordinates at odd indices).
  2500. *
  2501. * @constructor
  2502. */
  2503. ORYX.Core.SVG.PointsPathHandler = Clazz.extend({
  2504. construct: function() {
  2505. arguments.callee.$.construct.apply(this, arguments);
  2506. this.points = [];
  2507. this._lastAbsX = undefined;
  2508. this._lastAbsY = undefined;
  2509. },
  2510. /**
  2511. * addPoints
  2512. *
  2513. * @param {Array} points Array of absolutePoints
  2514. */
  2515. addPoints: function(points) {
  2516. if(points instanceof Array) {
  2517. var x, y;
  2518. for(var i = 0; i < points.length; i++) {
  2519. x = parseFloat(points[i]);
  2520. i++;
  2521. y = parseFloat(points[i]);
  2522. this.points.push(x);
  2523. this.points.push(y);
  2524. //this.points.push({x:x, y:y});
  2525. this._lastAbsX = x;
  2526. this._lastAbsY = y;
  2527. }
  2528. } else {
  2529. //TODO error
  2530. }
  2531. },
  2532. /**
  2533. * arcAbs - A
  2534. *
  2535. * @param {Number} rx
  2536. * @param {Number} ry
  2537. * @param {Number} xAxisRotation
  2538. * @param {Boolean} largeArcFlag
  2539. * @param {Boolean} sweepFlag
  2540. * @param {Number} x
  2541. * @param {Number} y
  2542. */
  2543. arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2544. this.addPoints([x, y]);
  2545. },
  2546. /**
  2547. * arcRel - a
  2548. *
  2549. * @param {Number} rx
  2550. * @param {Number} ry
  2551. * @param {Number} xAxisRotation
  2552. * @param {Boolean} largeArcFlag
  2553. * @param {Boolean} sweepFlag
  2554. * @param {Number} x
  2555. * @param {Number} y
  2556. */
  2557. arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
  2558. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2559. },
  2560. /**
  2561. * curvetoCubicAbs - C
  2562. *
  2563. * @param {Number} x1
  2564. * @param {Number} y1
  2565. * @param {Number} x2
  2566. * @param {Number} y2
  2567. * @param {Number} x
  2568. * @param {Number} y
  2569. */
  2570. curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
  2571. this.addPoints([x, y]);
  2572. },
  2573. /**
  2574. * curvetoCubicRel - c
  2575. *
  2576. * @param {Number} x1
  2577. * @param {Number} y1
  2578. * @param {Number} x2
  2579. * @param {Number} y2
  2580. * @param {Number} x
  2581. * @param {Number} y
  2582. */
  2583. curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
  2584. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2585. },
  2586. /**
  2587. * linetoHorizontalAbs - H
  2588. *
  2589. * @param {Number} x
  2590. */
  2591. linetoHorizontalAbs: function(x) {
  2592. this.addPoints([x, this._lastAbsY]);
  2593. },
  2594. /**
  2595. * linetoHorizontalRel - h
  2596. *
  2597. * @param {Number} x
  2598. */
  2599. linetoHorizontalRel: function(x) {
  2600. this.addPoints([this._lastAbsX + x, this._lastAbsY]);
  2601. },
  2602. /**
  2603. * linetoAbs - L
  2604. *
  2605. * @param {Number} x
  2606. * @param {Number} y
  2607. */
  2608. linetoAbs: function(x, y) {
  2609. this.addPoints([x, y]);
  2610. },
  2611. /**
  2612. * linetoRel - l
  2613. *
  2614. * @param {Number} x
  2615. * @param {Number} y
  2616. */
  2617. linetoRel: function(x, y) {
  2618. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2619. },
  2620. /**
  2621. * movetoAbs - M
  2622. *
  2623. * @param {Number} x
  2624. * @param {Number} y
  2625. */
  2626. movetoAbs: function(x, y) {
  2627. this.addPoints([x, y]);
  2628. },
  2629. /**
  2630. * movetoRel - m
  2631. *
  2632. * @param {Number} x
  2633. * @param {Number} y
  2634. */
  2635. movetoRel: function(x, y) {
  2636. if(this._lastAbsX && this._lastAbsY) {
  2637. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2638. } else {
  2639. this.addPoints([x, y]);
  2640. }
  2641. },
  2642. /**
  2643. * curvetoQuadraticAbs - Q
  2644. *
  2645. * @param {Number} x1
  2646. * @param {Number} y1
  2647. * @param {Number} x
  2648. * @param {Number} y
  2649. */
  2650. curvetoQuadraticAbs: function(x1, y1, x, y) {
  2651. this.addPoints([x, y]);
  2652. },
  2653. /**
  2654. * curvetoQuadraticRel - q
  2655. *
  2656. * @param {Number} x1
  2657. * @param {Number} y1
  2658. * @param {Number} x
  2659. * @param {Number} y
  2660. */
  2661. curvetoQuadraticRel: function(x1, y1, x, y) {
  2662. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2663. },
  2664. /**
  2665. * curvetoCubicSmoothAbs - S
  2666. *
  2667. * @param {Number} x2
  2668. * @param {Number} y2
  2669. * @param {Number} x
  2670. * @param {Number} y
  2671. */
  2672. curvetoCubicSmoothAbs: function(x2, y2, x, y) {
  2673. this.addPoints([x, y]);
  2674. },
  2675. /**
  2676. * curvetoCubicSmoothRel - s
  2677. *
  2678. * @param {Number} x2
  2679. * @param {Number} y2
  2680. * @param {Number} x
  2681. * @param {Number} y
  2682. */
  2683. curvetoCubicSmoothRel: function(x2, y2, x, y) {
  2684. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2685. },
  2686. /**
  2687. * curvetoQuadraticSmoothAbs - T
  2688. *
  2689. * @param {Number} x
  2690. * @param {Number} y
  2691. */
  2692. curvetoQuadraticSmoothAbs: function(x, y) {
  2693. this.addPoints([x, y]);
  2694. },
  2695. /**
  2696. * curvetoQuadraticSmoothRel - t
  2697. *
  2698. * @param {Number} x
  2699. * @param {Number} y
  2700. */
  2701. curvetoQuadraticSmoothRel: function(x, y) {
  2702. this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
  2703. },
  2704. /**
  2705. * linetoVerticalAbs - V
  2706. *
  2707. * @param {Number} y
  2708. */
  2709. linetoVerticalAbs: function(y) {
  2710. this.addPoints([this._lastAbsX, y]);
  2711. },
  2712. /**
  2713. * linetoVerticalRel - v
  2714. *
  2715. * @param {Number} y
  2716. */
  2717. linetoVerticalRel: function(y) {
  2718. this.addPoints([this._lastAbsX, this._lastAbsY + y]);
  2719. },
  2720. /**
  2721. * closePath - z or Z
  2722. */
  2723. closePath: function() {
  2724. return;// do nothing
  2725. }
  2726. });/*
  2727. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  2728. * License rights for this program may be obtained from Alfresco Software, Ltd.
  2729. * pursuant to a written agreement and any use of this program without such an
  2730. * agreement is prohibited.
  2731. */
  2732. /*
  2733. * All code Copyright 2013 KIS Consultancy all rights reserved
  2734. */
  2735. /**
  2736. *
  2737. * Config variables
  2738. */
  2739. NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
  2740. NAMESPACE_SVG = "http://www.w3.org/2000/svg/";
  2741. /**
  2742. * @classDescription This class wraps the manipulation of a SVG marker.
  2743. * @namespace ORYX.Core.SVG
  2744. * uses Inheritance (Clazz)
  2745. * uses Prototype 1.5.0
  2746. *
  2747. */
  2748. /**
  2749. * Init package
  2750. */
  2751. if(!ORYX) {var ORYX = {};}
  2752. if(!ORYX.Core) {ORYX.Core = {};}
  2753. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  2754. ORYX.Core.SVG.SVGMarker = Clazz.extend({
  2755. /**
  2756. * Constructor
  2757. * @param markerElement {SVGMarkerElement}
  2758. */
  2759. construct: function(markerElement) {
  2760. arguments.callee.$.construct.apply(this, arguments);
  2761. this.id = undefined;
  2762. this.element = markerElement;
  2763. this.refX = undefined;
  2764. this.refY = undefined;
  2765. this.markerWidth = undefined;
  2766. this.markerHeight = undefined;
  2767. this.oldRefX = undefined;
  2768. this.oldRefY = undefined;
  2769. this.oldMarkerWidth = undefined;
  2770. this.oldMarkerHeight = undefined;
  2771. this.optional = false;
  2772. this.enabled = true;
  2773. this.minimumLength = undefined;
  2774. this.resize = false;
  2775. this.svgShapes = [];
  2776. this._init(); //initialisation of all the properties declared above.
  2777. },
  2778. /**
  2779. * Initializes the values that are defined in the constructor.
  2780. */
  2781. _init: function() {
  2782. //check if this.element is a SVGMarkerElement
  2783. if(!( this.element == "[object SVGMarkerElement]")) {
  2784. throw "SVGMarker: Argument is not an instance of SVGMarkerElement.";
  2785. }
  2786. this.id = this.element.getAttributeNS(null, "id");
  2787. //init svg marker attributes
  2788. var refXValue = this.element.getAttributeNS(null, "refX");
  2789. if(refXValue) {
  2790. this.refX = parseFloat(refXValue);
  2791. } else {
  2792. this.refX = 0;
  2793. }
  2794. var refYValue = this.element.getAttributeNS(null, "refY");
  2795. if(refYValue) {
  2796. this.refY = parseFloat(refYValue);
  2797. } else {
  2798. this.refY = 0;
  2799. }
  2800. var markerWidthValue = this.element.getAttributeNS(null, "markerWidth");
  2801. if(markerWidthValue) {
  2802. this.markerWidth = parseFloat(markerWidthValue);
  2803. } else {
  2804. this.markerWidth = 3;
  2805. }
  2806. var markerHeightValue = this.element.getAttributeNS(null, "markerHeight");
  2807. if(markerHeightValue) {
  2808. this.markerHeight = parseFloat(markerHeightValue);
  2809. } else {
  2810. this.markerHeight = 3;
  2811. }
  2812. this.oldRefX = this.refX;
  2813. this.oldRefY = this.refY;
  2814. this.oldMarkerWidth = this.markerWidth;
  2815. this.oldMarkerHeight = this.markerHeight;
  2816. //init oryx attributes
  2817. var optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "optional");
  2818. if(optionalAttr) {
  2819. optionalAttr = optionalAttr.strip();
  2820. this.optional = (optionalAttr.toLowerCase() === "yes");
  2821. } else {
  2822. this.optional = false;
  2823. }
  2824. var enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "enabled");
  2825. if(enabledAttr) {
  2826. enabledAttr = enabledAttr.strip();
  2827. this.enabled = !(enabledAttr.toLowerCase() === "no");
  2828. } else {
  2829. this.enabled = true;
  2830. }
  2831. var minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "minimumLength");
  2832. if(minLengthAttr) {
  2833. this.minimumLength = parseFloat(minLengthAttr);
  2834. }
  2835. var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize");
  2836. if(resizeAttr) {
  2837. resizeAttr = resizeAttr.strip();
  2838. this.resize = (resizeAttr.toLowerCase() === "yes");
  2839. } else {
  2840. this.resize = false;
  2841. }
  2842. //init SVGShape objects
  2843. //this.svgShapes = this._getSVGShapes(this.element);
  2844. },
  2845. /**
  2846. *
  2847. */
  2848. _getSVGShapes: function(svgElement) {
  2849. if(svgElement.hasChildNodes) {
  2850. var svgShapes = [];
  2851. var me = this;
  2852. $A(svgElement.childNodes).each(function(svgChild) {
  2853. try {
  2854. var svgShape = new ORYX.Core.SVG.SVGShape(svgChild);
  2855. svgShapes.push(svgShape);
  2856. } catch (e) {
  2857. svgShapes = svgShapes.concat(me._getSVGShapes(svgChild));
  2858. }
  2859. });
  2860. return svgShapes;
  2861. }
  2862. },
  2863. /**
  2864. * Writes the changed values into the SVG marker.
  2865. */
  2866. update: function() {
  2867. //TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt!
  2868. // //update marker attributes
  2869. // if(this.refX != this.oldRefX) {
  2870. // this.element.setAttributeNS(null, "refX", this.refX);
  2871. // }
  2872. // if(this.refY != this.oldRefY) {
  2873. // this.element.setAttributeNS(null, "refY", this.refY);
  2874. // }
  2875. // if(this.markerWidth != this.oldMarkerWidth) {
  2876. // this.element.setAttributeNS(null, "markerWidth", this.markerWidth);
  2877. // }
  2878. // if(this.markerHeight != this.oldMarkerHeight) {
  2879. // this.element.setAttributeNS(null, "markerHeight", this.markerHeight);
  2880. // }
  2881. //
  2882. // //update SVGShape objects
  2883. // var widthDelta = this.markerWidth / this.oldMarkerWidth;
  2884. // var heightDelta = this.markerHeight / this.oldMarkerHeight;
  2885. // if(widthDelta != 1 && heightDelta != 1) {
  2886. // this.svgShapes.each(function(svgShape) {
  2887. //
  2888. // });
  2889. // }
  2890. //update old values to prepare the next update
  2891. this.oldRefX = this.refX;
  2892. this.oldRefY = this.refY;
  2893. this.oldMarkerWidth = this.markerWidth;
  2894. this.oldMarkerHeight = this.markerHeight;
  2895. },
  2896. toString: function() { return (this.element) ? "SVGMarker " + this.element.id : "SVGMarker " + this.element;}
  2897. });/*
  2898. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  2899. * License rights for this program may be obtained from Alfresco Software, Ltd.
  2900. * pursuant to a written agreement and any use of this program without such an
  2901. * agreement is prohibited.
  2902. */
  2903. /*
  2904. * All code Copyright 2013 KIS Consultancy all rights reserved
  2905. */
  2906. /**
  2907. *
  2908. * Config variables
  2909. */
  2910. NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
  2911. NAMESPACE_SVG = "http://www.w3.org/2000/svg/";
  2912. /**
  2913. * @classDescription This class wraps the manipulation of a SVG basic shape or a path.
  2914. * @namespace ORYX.Core.SVG
  2915. * uses Inheritance (Clazz)
  2916. * uses Prototype 1.5.0
  2917. * uses PathParser by Kevin Lindsey (http://kevlindev.com/)
  2918. * uses MinMaxPathHandler
  2919. * uses EditPathHandler
  2920. *
  2921. */
  2922. //init package
  2923. if(!ORYX) {var ORYX = {};}
  2924. if(!ORYX.Core) {ORYX.Core = {};}
  2925. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  2926. ORYX.Core.SVG.SVGShape = Clazz.extend({
  2927. /**
  2928. * Constructor
  2929. * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path.
  2930. */
  2931. construct: function(svgElem) {
  2932. arguments.callee.$.construct.apply(this, arguments);
  2933. this.type;
  2934. this.element = svgElem;
  2935. this.x = undefined;
  2936. this.y = undefined;
  2937. this.width = undefined;
  2938. this.height = undefined;
  2939. this.oldX = undefined;
  2940. this.oldY = undefined;
  2941. this.oldWidth = undefined;
  2942. this.oldHeight = undefined;
  2943. this.radiusX = undefined;
  2944. this.radiusY = undefined;
  2945. this.isHorizontallyResizable = false;
  2946. this.isVerticallyResizable = false;
  2947. //this.anchors = [];
  2948. this.anchorLeft = false;
  2949. this.anchorRight = false;
  2950. this.anchorTop = false;
  2951. this.anchorBottom = false;
  2952. //attributes of path elements of edge objects
  2953. this.allowDockers = true;
  2954. this.resizeMarkerMid = false;
  2955. this.editPathParser;
  2956. this.editPathHandler;
  2957. this.init(); //initialisation of all the properties declared above.
  2958. },
  2959. /**
  2960. * Initializes the values that are defined in the constructor.
  2961. */
  2962. init: function() {
  2963. /**initialize position and size*/
  2964. if(ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) {
  2965. this.type = "Rect";
  2966. var xAttr = this.element.getAttributeNS(null, "x");
  2967. if(xAttr) {
  2968. this.oldX = parseFloat(xAttr);
  2969. } else {
  2970. throw "Missing attribute in element " + this.element;
  2971. }
  2972. var yAttr = this.element.getAttributeNS(null, "y");
  2973. if(yAttr) {
  2974. this.oldY = parseFloat(yAttr);
  2975. } else {
  2976. throw "Missing attribute in element " + this.element;
  2977. }
  2978. var widthAttr = this.element.getAttributeNS(null, "width");
  2979. if(widthAttr) {
  2980. this.oldWidth = parseFloat(widthAttr);
  2981. } else {
  2982. throw "Missing attribute in element " + this.element;
  2983. }
  2984. var heightAttr = this.element.getAttributeNS(null, "height");
  2985. if(heightAttr) {
  2986. this.oldHeight = parseFloat(heightAttr);
  2987. } else {
  2988. throw "Missing attribute in element " + this.element;
  2989. }
  2990. } else if(ORYX.Editor.checkClassType(this.element, SVGCircleElement)) {
  2991. this.type = "Circle";
  2992. var cx = undefined;
  2993. var cy = undefined;
  2994. //var r = undefined;
  2995. var cxAttr = this.element.getAttributeNS(null, "cx");
  2996. if(cxAttr) {
  2997. cx = parseFloat(cxAttr);
  2998. } else {
  2999. throw "Missing attribute in element " + this.element;
  3000. }
  3001. var cyAttr = this.element.getAttributeNS(null, "cy");
  3002. if(cyAttr) {
  3003. cy = parseFloat(cyAttr);
  3004. } else {
  3005. throw "Missing attribute in element " + this.element;
  3006. }
  3007. var rAttr = this.element.getAttributeNS(null, "r");
  3008. if(rAttr) {
  3009. //r = parseFloat(rAttr);
  3010. this.radiusX = parseFloat(rAttr);
  3011. } else {
  3012. throw "Missing attribute in element " + this.element;
  3013. }
  3014. this.oldX = cx - this.radiusX;
  3015. this.oldY = cy - this.radiusX;
  3016. this.oldWidth = 2*this.radiusX;
  3017. this.oldHeight = 2*this.radiusX;
  3018. } else if(ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) {
  3019. this.type = "Ellipse";
  3020. var cx = undefined;
  3021. var cy = undefined;
  3022. //var rx = undefined;
  3023. //var ry = undefined;
  3024. var cxAttr = this.element.getAttributeNS(null, "cx");
  3025. if(cxAttr) {
  3026. cx = parseFloat(cxAttr);
  3027. } else {
  3028. throw "Missing attribute in element " + this.element;
  3029. }
  3030. var cyAttr = this.element.getAttributeNS(null, "cy");
  3031. if(cyAttr) {
  3032. cy = parseFloat(cyAttr);
  3033. } else {
  3034. throw "Missing attribute in element " + this.element;
  3035. }
  3036. var rxAttr = this.element.getAttributeNS(null, "rx");
  3037. if(rxAttr) {
  3038. this.radiusX = parseFloat(rxAttr);
  3039. } else {
  3040. throw "Missing attribute in element " + this.element;
  3041. }
  3042. var ryAttr = this.element.getAttributeNS(null, "ry");
  3043. if(ryAttr) {
  3044. this.radiusY = parseFloat(ryAttr);
  3045. } else {
  3046. throw "Missing attribute in element " + this.element;
  3047. }
  3048. this.oldX = cx - this.radiusX;
  3049. this.oldY = cy - this.radiusY;
  3050. this.oldWidth = 2*this.radiusX;
  3051. this.oldHeight = 2*this.radiusY;
  3052. } else if(ORYX.Editor.checkClassType(this.element, SVGLineElement)) {
  3053. this.type = "Line";
  3054. var x1 = undefined;
  3055. var y1 = undefined;
  3056. var x2 = undefined;
  3057. var y2 = undefined;
  3058. var x1Attr = this.element.getAttributeNS(null, "x1");
  3059. if(x1Attr) {
  3060. x1 = parseFloat(x1Attr);
  3061. } else {
  3062. throw "Missing attribute in element " + this.element;
  3063. }
  3064. var y1Attr = this.element.getAttributeNS(null, "y1");
  3065. if(y1Attr) {
  3066. y1 = parseFloat(y1Attr);
  3067. } else {
  3068. throw "Missing attribute in element " + this.element;
  3069. }
  3070. var x2Attr = this.element.getAttributeNS(null, "x2");
  3071. if(x2Attr) {
  3072. x2 = parseFloat(x2Attr);
  3073. } else {
  3074. throw "Missing attribute in element " + this.element;
  3075. }
  3076. var y2Attr = this.element.getAttributeNS(null, "y2");
  3077. if(y2Attr) {
  3078. y2 = parseFloat(y2Attr);
  3079. } else {
  3080. throw "Missing attribute in element " + this.element;
  3081. }
  3082. this.oldX = Math.min(x1,x2);
  3083. this.oldY = Math.min(y1,y2);
  3084. this.oldWidth = Math.abs(x1-x2);
  3085. this.oldHeight = Math.abs(y1-y2);
  3086. } else if(ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) {
  3087. this.type = "Polyline";
  3088. var pointsArray = [];
  3089. if (this.element.points&&this.element.points.numberOfItems){
  3090. for(var i=0, size=this.element.points.numberOfItems; i<size; i++){
  3091. pointsArray.push(this.element.points.getItem(i).x)
  3092. pointsArray.push(this.element.points.getItem(i).y)
  3093. }
  3094. } else {
  3095. var points = this.element.getAttributeNS(null, "points");
  3096. if(points) {
  3097. points = points.replace(/,/g , " ");
  3098. pointsArray = points.split(" ");
  3099. pointsArray = pointsArray.without("");
  3100. } else {
  3101. throw "Missing attribute in element " + this.element;
  3102. }
  3103. }
  3104. if(pointsArray && pointsArray.length && pointsArray.length > 1) {
  3105. var minX = parseFloat(pointsArray[0]);
  3106. var minY = parseFloat(pointsArray[1]);
  3107. var maxX = parseFloat(pointsArray[0]);
  3108. var maxY = parseFloat(pointsArray[1]);
  3109. for(var i = 0; i < pointsArray.length; i++) {
  3110. minX = Math.min(minX, parseFloat(pointsArray[i]));
  3111. maxX = Math.max(maxX, parseFloat(pointsArray[i]));
  3112. i++;
  3113. minY = Math.min(minY, parseFloat(pointsArray[i]));
  3114. maxY = Math.max(maxY, parseFloat(pointsArray[i]));
  3115. }
  3116. this.oldX = minX;
  3117. this.oldY = minY;
  3118. this.oldWidth = maxX-minX;
  3119. this.oldHeight = maxY-minY;
  3120. } else {
  3121. throw "Missing attribute in element " + this.element;
  3122. }
  3123. } else if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {
  3124. this.type = "Path";
  3125. this.editPathParser = new PathParser();
  3126. this.editPathHandler = new ORYX.Core.SVG.EditPathHandler();
  3127. this.editPathParser.setHandler(this.editPathHandler);
  3128. var parser = new PathParser();
  3129. var handler = new ORYX.Core.SVG.MinMaxPathHandler();
  3130. parser.setHandler(handler);
  3131. parser.parsePath(this.element);
  3132. this.oldX = handler.minX;
  3133. this.oldY = handler.minY;
  3134. this.oldWidth = handler.maxX - handler.minX;
  3135. this.oldHeight = handler.maxY - handler.minY;
  3136. delete parser;
  3137. delete handler;
  3138. } else {
  3139. throw "Element is not a shape.";
  3140. }
  3141. /** initialize attributes of oryx namespace */
  3142. //resize
  3143. var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize");
  3144. if(resizeAttr) {
  3145. resizeAttr = resizeAttr.toLowerCase();
  3146. if(resizeAttr.match(/horizontal/)) {
  3147. this.isHorizontallyResizable = true;
  3148. } else {
  3149. this.isHorizontallyResizable = false;
  3150. }
  3151. if(resizeAttr.match(/vertical/)) {
  3152. this.isVerticallyResizable = true;
  3153. } else {
  3154. this.isVerticallyResizable = false;
  3155. }
  3156. } else {
  3157. this.isHorizontallyResizable = false;
  3158. this.isVerticallyResizable = false;
  3159. }
  3160. //anchors
  3161. var anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "anchors");
  3162. if(anchorAttr) {
  3163. anchorAttr = anchorAttr.replace("/,/g", " ");
  3164. var anchors = anchorAttr.split(" ").without("");
  3165. for(var i = 0; i < anchors.length; i++) {
  3166. switch(anchors[i].toLowerCase()) {
  3167. case "left":
  3168. this.anchorLeft = true;
  3169. break;
  3170. case "right":
  3171. this.anchorRight = true;
  3172. break;
  3173. case "top":
  3174. this.anchorTop = true;
  3175. break;
  3176. case "bottom":
  3177. this.anchorBottom = true;
  3178. break;
  3179. }
  3180. }
  3181. }
  3182. //allowDockers and resizeMarkerMid
  3183. if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {
  3184. var allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "allowDockers");
  3185. if(allowDockersAttr) {
  3186. if(allowDockersAttr.toLowerCase() === "no") {
  3187. this.allowDockers = false;
  3188. } else {
  3189. this.allowDockers = true;
  3190. }
  3191. }
  3192. var resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resizeMarker-mid");
  3193. if(resizeMarkerMidAttr) {
  3194. if(resizeMarkerMidAttr.toLowerCase() === "yes") {
  3195. this.resizeMarkerMid = true;
  3196. } else {
  3197. this.resizeMarkerMid = false;
  3198. }
  3199. }
  3200. }
  3201. this.x = this.oldX;
  3202. this.y = this.oldY;
  3203. this.width = this.oldWidth;
  3204. this.height = this.oldHeight;
  3205. },
  3206. /**
  3207. * Writes the changed values into the SVG element.
  3208. */
  3209. update: function() {
  3210. if(this.x !== this.oldX || this.y !== this.oldY || this.width !== this.oldWidth || this.height !== this.oldHeight) {
  3211. switch(this.type) {
  3212. case "Rect":
  3213. if(this.x !== this.oldX) this.element.setAttributeNS(null, "x", this.x);
  3214. if(this.y !== this.oldY) this.element.setAttributeNS(null, "y", this.y);
  3215. if(this.width !== this.oldWidth) this.element.setAttributeNS(null, "width", this.width);
  3216. if(this.height !== this.oldHeight) this.element.setAttributeNS(null, "height", this.height);
  3217. break;
  3218. case "Circle":
  3219. //calculate the radius
  3220. //var r;
  3221. // if(this.width/this.oldWidth <= this.height/this.oldHeight) {
  3222. // this.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0;
  3223. // } else {
  3224. this.radiusX = ((this.width < this.height) ? this.width : this.height)/2.0;
  3225. //}
  3226. this.element.setAttributeNS(null, "cx", this.x + this.width/2.0);
  3227. this.element.setAttributeNS(null, "cy", this.y + this.height/2.0);
  3228. this.element.setAttributeNS(null, "r", this.radiusX);
  3229. break;
  3230. case "Ellipse":
  3231. this.radiusX = this.width/2;
  3232. this.radiusY = this.height/2;
  3233. this.element.setAttributeNS(null, "cx", this.x + this.radiusX);
  3234. this.element.setAttributeNS(null, "cy", this.y + this.radiusY);
  3235. this.element.setAttributeNS(null, "rx", this.radiusX);
  3236. this.element.setAttributeNS(null, "ry", this.radiusY);
  3237. break;
  3238. case "Line":
  3239. if(this.x !== this.oldX)
  3240. this.element.setAttributeNS(null, "x1", this.x);
  3241. if(this.y !== this.oldY)
  3242. this.element.setAttributeNS(null, "y1", this.y);
  3243. if(this.x !== this.oldX || this.width !== this.oldWidth)
  3244. this.element.setAttributeNS(null, "x2", this.x + this.width);
  3245. if(this.y !== this.oldY || this.height !== this.oldHeight)
  3246. this.element.setAttributeNS(null, "y2", this.y + this.height);
  3247. break;
  3248. case "Polyline":
  3249. var points = this.element.getAttributeNS(null, "points");
  3250. if(points) {
  3251. points = points.replace(/,/g, " ").split(" ").without("");
  3252. if(points && points.length && points.length > 1) {
  3253. //TODO what if oldWidth == 0?
  3254. var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;
  3255. var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;
  3256. var updatedPoints = "";
  3257. for(var i = 0; i < points.length; i++) {
  3258. var x = (parseFloat(points[i])-this.oldX)*widthDelta + this.x;
  3259. i++;
  3260. var y = (parseFloat(points[i])-this.oldY)*heightDelta + this.y;
  3261. updatedPoints += x + " " + y + " ";
  3262. }
  3263. this.element.setAttributeNS(null, "points", updatedPoints);
  3264. } else {
  3265. //TODO error
  3266. }
  3267. } else {
  3268. //TODO error
  3269. }
  3270. break;
  3271. case "Path":
  3272. //calculate scaling delta
  3273. //TODO what if oldWidth == 0?
  3274. var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;
  3275. var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;
  3276. //use path parser to edit each point of the path
  3277. this.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta);
  3278. this.editPathParser.parsePath(this.element);
  3279. //change d attribute of path
  3280. this.element.setAttributeNS(null, "d", this.editPathHandler.d);
  3281. break;
  3282. }
  3283. this.oldX = this.x;
  3284. this.oldY = this.y;
  3285. this.oldWidth = this.width;
  3286. this.oldHeight = this.height;
  3287. }
  3288. // Remove cached variables
  3289. delete this.visible;
  3290. delete this.handler;
  3291. },
  3292. isPointIncluded: function(pointX, pointY) {
  3293. // Check if there are the right arguments and if the node is visible
  3294. if(!pointX || !pointY || !this.isVisible()) {
  3295. return false;
  3296. }
  3297. switch(this.type) {
  3298. case "Rect":
  3299. return (pointX >= this.x && pointX <= this.x + this.width &&
  3300. pointY >= this.y && pointY <= this.y+this.height);
  3301. break;
  3302. case "Circle":
  3303. //calculate the radius
  3304. // var r;
  3305. // if(this.width/this.oldWidth <= this.height/this.oldHeight) {
  3306. // r = ((this.width > this.height) ? this.width : this.height)/2.0;
  3307. // } else {
  3308. // r = ((this.width < this.height) ? this.width : this.height)/2.0;
  3309. // }
  3310. return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width/2.0, this.y + this.height/2.0, this.radiusX, this.radiusX);
  3311. break;
  3312. case "Ellipse":
  3313. return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY);
  3314. break;
  3315. case "Line":
  3316. return ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height);
  3317. break;
  3318. case "Polyline":
  3319. var points = this.element.getAttributeNS(null, "points");
  3320. if(points) {
  3321. points = points.replace(/,/g , " ").split(" ").without("");
  3322. points = points.collect(function(n) {
  3323. return parseFloat(n);
  3324. });
  3325. return ORYX.Core.Math.isPointInPolygone(pointX, pointY, points);
  3326. } else {
  3327. return false;
  3328. }
  3329. break;
  3330. case "Path":
  3331. // Cache Path handler
  3332. if (!this.handler) {
  3333. var parser = new PathParser();
  3334. this.handler = new ORYX.Core.SVG.PointsPathHandler();
  3335. parser.setHandler(this.handler);
  3336. parser.parsePath(this.element);
  3337. }
  3338. return ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points);
  3339. break;
  3340. default:
  3341. return false;
  3342. }
  3343. },
  3344. /**
  3345. * Returns true if the element is visible
  3346. * @param {SVGElement} elem
  3347. * @return boolean
  3348. */
  3349. isVisible: function(elem) {
  3350. if (this.visible !== undefined){
  3351. return this.visible;
  3352. }
  3353. if (!elem) {
  3354. elem = this.element;
  3355. }
  3356. var hasOwnerSVG = false;
  3357. try {
  3358. hasOwnerSVG = !!elem.ownerSVGElement;
  3359. } catch(e){}
  3360. // Is SVG context
  3361. if ( hasOwnerSVG ) {
  3362. // IF G-Element
  3363. if (ORYX.Editor.checkClassType(elem, SVGGElement)) {
  3364. if (elem.className && elem.className.baseVal == "me") {
  3365. this.visible = true;
  3366. return this.visible;
  3367. }
  3368. }
  3369. // Check if fill or stroke is set
  3370. var fill = elem.getAttributeNS(null, "fill");
  3371. var stroke = elem.getAttributeNS(null, "stroke");
  3372. if (fill && fill == "none" && stroke && stroke == "none") {
  3373. this.visible = false;
  3374. } else {
  3375. // Check if displayed
  3376. var attr = elem.getAttributeNS(null, "display");
  3377. if(!attr)
  3378. this.visible = this.isVisible(elem.parentNode);
  3379. else if (attr == "none")
  3380. this.visible = false;
  3381. else
  3382. this.visible = true;
  3383. }
  3384. } else {
  3385. this.visible = true;
  3386. }
  3387. return this.visible;
  3388. },
  3389. toString: function() { return (this.element) ? "SVGShape " + this.element.id : "SVGShape " + this.element;}
  3390. });/*
  3391. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  3392. * License rights for this program may be obtained from Alfresco Software, Ltd.
  3393. * pursuant to a written agreement and any use of this program without such an
  3394. * agreement is prohibited.
  3395. */
  3396. /*
  3397. * All code Copyright 2013 KIS Consultancy all rights reserved
  3398. */
  3399. /**
  3400. * Init namespaces
  3401. */
  3402. if(!ORYX) {var ORYX = {};}
  3403. if(!ORYX.Core) {ORYX.Core = {};}
  3404. if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
  3405. /**
  3406. * @classDescription Class for adding text to a shape.
  3407. *
  3408. */
  3409. ORYX.Core.SVG.Label = Clazz.extend({
  3410. _characterSets:[
  3411. "%W",
  3412. "@",
  3413. "m",
  3414. "wDGMOQ?????#+=<>~^",
  3415. "ABCHKNRSUVXZ??????????&",
  3416. "bdghnopqux???????????ETY1234567890?????_????${}*????`???????????",
  3417. "aeksvyz?????FLP????????????????",
  3418. "c-",
  3419. "rtJ\"/()[]:;!|\\",
  3420. "fjI., ",
  3421. "'",
  3422. "il"
  3423. ],
  3424. _characterSetValues:[15,14,13,11,10,9,8,7,6,5,4,3],
  3425. /**
  3426. * Constructor
  3427. * @param options {Object} :
  3428. * textElement
  3429. *
  3430. */
  3431. construct: function(options) {
  3432. arguments.callee.$.construct.apply(this, arguments);
  3433. if(!options.textElement) {
  3434. throw "Label: No parameter textElement."
  3435. } else if (!ORYX.Editor.checkClassType( options.textElement, SVGTextElement ) ) {
  3436. throw "Label: Parameter textElement is not an SVGTextElement."
  3437. }
  3438. this.invisibleRenderPoint = -5000;
  3439. this.node = options.textElement;
  3440. this.node.setAttributeNS(null, 'stroke-width', '0pt');
  3441. this.node.setAttributeNS(null, 'letter-spacing', '-0.01px');
  3442. this.shapeId = options.shapeId;
  3443. this.id;
  3444. this.fitToElemId;
  3445. this.edgePosition;
  3446. this.x;
  3447. this.y;
  3448. this.oldX;
  3449. this.oldY;
  3450. this.isVisible = true;
  3451. this._text;
  3452. this._verticalAlign;
  3453. this._horizontalAlign;
  3454. this._rotate;
  3455. this._rotationPoint;
  3456. //this.anchors = [];
  3457. this.anchorLeft;
  3458. this.anchorRight;
  3459. this.anchorTop;
  3460. this.anchorBottom;
  3461. this._isChanged = true;
  3462. //if the text element already has an id, don't change it.
  3463. var _id = this.node.getAttributeNS(null, 'id');
  3464. if(_id) {
  3465. this.id = _id;
  3466. }
  3467. //initialization
  3468. //set referenced element the text is fit to
  3469. this.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem');
  3470. if(this.fitToElemId)
  3471. this.fitToElemId = this.shapeId + this.fitToElemId;
  3472. //set alignment
  3473. var alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align');
  3474. if(alignValues) {
  3475. alignValues = alignValues.replace(/,/g, " ");
  3476. alignValues = alignValues.split(" ");
  3477. alignValues = alignValues.without("");
  3478. alignValues.each((function(alignValue) {
  3479. switch (alignValue) {
  3480. case 'top':
  3481. case 'middle':
  3482. case 'bottom':
  3483. if(!this._verticalAlign){this._originVerticalAlign = this._verticalAlign = alignValue;}
  3484. break;
  3485. case 'left':
  3486. case 'center':
  3487. case 'right':
  3488. if(!this._horizontalAlign){this._originHorizontalAlign = this._horizontalAlign = alignValue;}
  3489. break;
  3490. }
  3491. }).bind(this));
  3492. }
  3493. //set edge position (only in case the label belongs to an edge)
  3494. this.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition');
  3495. if(this.edgePosition) {
  3496. this.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase();
  3497. }
  3498. //get offset top
  3499. this.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP;
  3500. if(this.offsetTop) {
  3501. this.offsetTop = parseInt(this.offsetTop);
  3502. }
  3503. //get offset top
  3504. this.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM;
  3505. if(this.offsetBottom) {
  3506. this.offsetBottom = parseInt(this.offsetBottom);
  3507. }
  3508. //set rotation
  3509. var rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate');
  3510. if(rotateValue) {
  3511. try {
  3512. this._rotate = parseFloat(rotateValue);
  3513. } catch (e) {
  3514. this._rotate = 0;
  3515. }
  3516. } else {
  3517. this._rotate = 0;
  3518. }
  3519. //anchors
  3520. var anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
  3521. if(anchorAttr) {
  3522. anchorAttr = anchorAttr.replace("/,/g", " ");
  3523. var anchors = anchorAttr.split(" ").without("");
  3524. for(var i = 0; i < anchors.length; i++) {
  3525. switch(anchors[i].toLowerCase()) {
  3526. case "left":
  3527. this.originAnchorLeft = this.anchorLeft = true;
  3528. break;
  3529. case "right":
  3530. this.originAnchorRight = this.anchorRight = true;
  3531. break;
  3532. case "top":
  3533. this.originAnchorTop = this.anchorTop = true;
  3534. break;
  3535. case "bottom":
  3536. this.originAnchorBottom = this.anchorBottom = true;
  3537. break;
  3538. }
  3539. }
  3540. }
  3541. //if no alignment defined, set default alignment
  3542. if(!this._verticalAlign) { this._verticalAlign = 'bottom'; }
  3543. if(!this._horizontalAlign) { this._horizontalAlign = 'left'; }
  3544. var xValue = this.node.getAttributeNS(null, 'x');
  3545. if(xValue) {
  3546. this.oldX = this.x = parseFloat(xValue);
  3547. } else {
  3548. //TODO error
  3549. }
  3550. var yValue = this.node.getAttributeNS(null, 'y');
  3551. if(yValue) {
  3552. this.oldY = this.y = parseFloat(yValue);
  3553. } else {
  3554. //TODO error
  3555. }
  3556. //set initial text
  3557. this.text(this.node.textContent);
  3558. },
  3559. /**
  3560. * Reset the anchor position to the original value
  3561. * which was specified in the stencil set
  3562. *
  3563. */
  3564. resetAnchorPosition: function(){
  3565. this.anchorLeft = this.originAnchorLeft || false;
  3566. this.anchorRight = this.originAnchorRight || false;
  3567. this.anchorTop = this.originAnchorTop || false;
  3568. this.anchorBottom = this.originAnchorBottom || false;
  3569. },
  3570. isOriginAnchorLeft: function(){ return this.originAnchorLeft || false; },
  3571. isOriginAnchorRight: function(){ return this.originAnchorRight || false; },
  3572. isOriginAnchorTop: function(){ return this.originAnchorTop || false; },
  3573. isOriginAnchorBottom: function(){ return this.originAnchorBottom || false; },
  3574. isAnchorLeft: function(){ return this.anchorLeft || false; },
  3575. isAnchorRight: function(){ return this.anchorRight || false; },
  3576. isAnchorTop: function(){ return this.anchorTop || false; },
  3577. isAnchorBottom: function(){ return this.anchorBottom || false; },
  3578. /**
  3579. * Returns the x coordinate
  3580. * @return {number}
  3581. */
  3582. getX: function(){
  3583. try {
  3584. var x = this.node.x.baseVal.getItem(0).value;
  3585. switch(this.horizontalAlign()){
  3586. case "left": return x;
  3587. case "center": return x - (this.getWidth()/2);
  3588. case "right": return x - this.getWidth();
  3589. }
  3590. return this.node.getBBox().x;
  3591. } catch(e){
  3592. return this.x;
  3593. }
  3594. },
  3595. setX: function(x){
  3596. if (this.position)
  3597. this.position.x = x;
  3598. else
  3599. this.setOriginX(x);
  3600. },
  3601. /**
  3602. * Returns the y coordinate
  3603. * @return {number}
  3604. */
  3605. getY: function(){
  3606. try {
  3607. return this.node.getBBox().y;
  3608. } catch(e){
  3609. return this.y;
  3610. }
  3611. },
  3612. setY: function(y){
  3613. if (this.position)
  3614. this.position.y = y;
  3615. else
  3616. this.setOriginY(y);
  3617. },
  3618. setOriginX: function(x){
  3619. this.x = x;
  3620. },
  3621. setOriginY: function(y){
  3622. this.y = y;
  3623. },
  3624. /**
  3625. * Returns the width of the label
  3626. * @return {number}
  3627. */
  3628. getWidth: function(){
  3629. try {
  3630. try {
  3631. var width, cn = this.node.childNodes;
  3632. if (cn.length == 0) {
  3633. width = this.node.getBBox().width;
  3634. } else {
  3635. for (var i = 0, size = cn.length; i < size; ++i) {
  3636. var w = cn[i].getComputedTextLength();
  3637. if ("undefined" == typeof width || width < w) {
  3638. width = w;
  3639. }
  3640. }
  3641. }
  3642. return width+(width%2==0?0:1);
  3643. } catch (ee) {
  3644. return this.node.getBBox().width;
  3645. }
  3646. } catch(e){
  3647. return 0;
  3648. }
  3649. },
  3650. getOriginUpperLeft: function(){
  3651. var x = this.x, y = this.y;
  3652. switch (this._horizontalAlign){
  3653. case 'center' :
  3654. x -= this.getWidth()/2;
  3655. break;
  3656. case 'right' :
  3657. x -= this.getWidth();
  3658. break;
  3659. }
  3660. switch (this._verticalAlign){
  3661. case 'middle' :
  3662. y -= this.getHeight()/2;
  3663. break;
  3664. case 'bottom' :
  3665. y -= this.getHeight();
  3666. break;
  3667. }
  3668. return {x:x, y:y};
  3669. },
  3670. /**
  3671. * Returns the height of the label
  3672. * @return {number}
  3673. */
  3674. getHeight: function(){
  3675. try {
  3676. return this.node.getBBox().height;
  3677. } catch(e){
  3678. return 0;
  3679. }
  3680. },
  3681. /**
  3682. * Returns the relative center position of the label
  3683. * to its parent shape.
  3684. * @return {Object}
  3685. */
  3686. getCenter: function(){
  3687. var up = {x: this.getX(), y: this.getY()};
  3688. up.x += this.getWidth()/2;
  3689. up.y += this.getHeight()/2;
  3690. return up;
  3691. },
  3692. /**
  3693. * Sets the position of a label relative to the parent.
  3694. * @param {Object} position
  3695. */
  3696. setPosition: function(position){
  3697. if (!position || position.x === undefined || position.y === undefined) {
  3698. delete this.position;
  3699. } else {
  3700. this.position = position;
  3701. }
  3702. if (this.position){
  3703. delete this._referencePoint;
  3704. delete this.edgePosition;
  3705. }
  3706. this._isChanged = true;
  3707. this.update();
  3708. },
  3709. /**
  3710. * Return the position
  3711. */
  3712. getPosition: function(){
  3713. return this.position;
  3714. },
  3715. setReferencePoint: function(ref){
  3716. if (ref) {
  3717. this._referencePoint = ref;
  3718. } else {
  3719. delete this._referencePoint;
  3720. }
  3721. if (this._referencePoint){
  3722. delete this.position;
  3723. }
  3724. },
  3725. getReferencePoint: function(){
  3726. return this._referencePoint || undefined;
  3727. },
  3728. changed: function() {
  3729. this._isChanged = true;
  3730. },
  3731. /**
  3732. * Register a callback which will be called if the label
  3733. * was rendered.
  3734. * @param {Object} fn
  3735. */
  3736. registerOnChange: function(fn){
  3737. if (!this.changeCallbacks){
  3738. this.changeCallbacks = [];
  3739. }
  3740. if (fn instanceof Function && !this.changeCallbacks.include(fn)){
  3741. this.changeCallbacks.push(fn);
  3742. }
  3743. },
  3744. /**
  3745. * Unregister the callback for changes.
  3746. * @param {Object} fn
  3747. */
  3748. unregisterOnChange: function(fn){
  3749. if (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)){
  3750. this.changeCallbacks = this.changeCallbacks.without(fn);
  3751. }
  3752. },
  3753. /**
  3754. * Returns TRUE if the labe is currently in
  3755. * the update mechanism.
  3756. * @return {Boolean}
  3757. */
  3758. isUpdating: function(){
  3759. return !!this._isUpdating;
  3760. },
  3761. getOriginEdgePosition: function(){
  3762. return this.originEdgePosition;
  3763. },
  3764. /**
  3765. * Returns the edgeposition.
  3766. *
  3767. * @return {String} "starttop", "startmiddle", "startbottom",
  3768. * "midtop", "midbottom", "endtop", "endbottom" or null
  3769. */
  3770. getEdgePosition: function(){
  3771. return this.edgePosition || null;
  3772. },
  3773. /**
  3774. * Set the edge position, must be one of the valid
  3775. * edge positions (see getEdgePosition).
  3776. * Removes the reference point and the absolute position as well.
  3777. *
  3778. * @param {Object} position
  3779. */
  3780. setEdgePosition: function(position){
  3781. if (["starttop", "startmiddle", "startbottom",
  3782. "midtop", "midbottom", "endtop", "endbottom"].include(position)){
  3783. this.edgePosition = position;
  3784. delete this.position;
  3785. delete this._referencePoint;
  3786. } else {
  3787. delete this.edgePosition;
  3788. }
  3789. },
  3790. /**
  3791. * Update the SVG text element.
  3792. */
  3793. update: function(force) {
  3794. var x = this.x, y = this.y;
  3795. if (this.position){
  3796. x = this.position.x;
  3797. y = this.position.y;
  3798. }
  3799. x = Math.floor(x); y = Math.floor(y);
  3800. if(this._isChanged || x !== this.oldX || y !== this.oldY || force === true) {
  3801. if (this.isVisible) {
  3802. this._isChanged = false;
  3803. this._isUpdating = true;
  3804. this.node.setAttributeNS(null, 'x', x);
  3805. this.node.setAttributeNS(null, 'y', y);
  3806. this.node.removeAttributeNS(null, "fill-opacity");
  3807. //this.node.setAttributeNS(null, 'font-size', this._fontSize);
  3808. //this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + " " + this._verticalAlign);
  3809. this.oldX = x;
  3810. this.oldY = y;
  3811. //set rotation
  3812. if (!this.position && !this.getReferencePoint()) {
  3813. if (this._rotate !== undefined) {
  3814. if (this._rotationPoint)
  3815. this.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(this._rotationPoint.x) + ' ' + Math.floor(this._rotationPoint.y) + ')');
  3816. else
  3817. this.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(x) + ' ' + Math.floor(y) + ')');
  3818. }
  3819. } else {
  3820. this.node.removeAttributeNS(null, 'transform');
  3821. }
  3822. var textLines = this._text.split("\n");
  3823. while (textLines.last() == "")
  3824. textLines.pop();
  3825. if (this.node.ownerDocument) {
  3826. // Only reset the tspans if the text
  3827. // has changed or has to be wrapped
  3828. if (this.fitToElemId || this._textHasChanged){
  3829. this.node.textContent = ""; // Remove content
  3830. textLines.each((function(textLine, index){
  3831. var tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
  3832. tspan.textContent = textLine.trim();
  3833. if (this.fitToElemId) {
  3834. tspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);
  3835. tspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);
  3836. }
  3837. /*
  3838. * Chrome's getBBox() method fails, if a text node contains an empty tspan element.
  3839. * So, we add a whitespace to such a tspan element.
  3840. */
  3841. if(tspan.textContent === "") {
  3842. tspan.textContent = " ";
  3843. }
  3844. //append tspan to text node
  3845. this.node.appendChild(tspan);
  3846. }).bind(this));
  3847. delete this._textHasChanged;
  3848. delete this.indices;
  3849. }
  3850. //Work around for Mozilla bug 293581
  3851. if (this.isVisible && this.fitToElemId) {
  3852. this.node.setAttributeNS(null, 'visibility', 'hidden');
  3853. }
  3854. if (this.fitToElemId) {
  3855. window.setTimeout(this._checkFittingToReferencedElem.bind(this), 0);
  3856. //this._checkFittingToReferencedElem();
  3857. } else {
  3858. window.setTimeout(this._positionText.bind(this), 0);
  3859. //this._positionText();
  3860. }
  3861. }
  3862. } else {
  3863. this.node.textContent = "";
  3864. //this.node.setAttributeNS(null, "fill-opacity", "0.2");
  3865. }
  3866. }
  3867. },
  3868. _checkFittingToReferencedElem: function() {
  3869. try {
  3870. var tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'));
  3871. //only do this in firefox 3. all other browsers do not support word wrapping!!!!!
  3872. //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) {
  3873. var newtspans = [];
  3874. var refNode = this.node.ownerDocument.getElementById(this.fitToElemId);
  3875. if (refNode) {
  3876. var refbb = refNode.getBBox();
  3877. var fontSize = this.getFontSize();
  3878. for (var j = 0; j < tspans.length; j++) {
  3879. var tspan = tspans[j];
  3880. var textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize);
  3881. var refBoxLength = (this._rotate != 0
  3882. && this._rotate % 180 != 0
  3883. && this._rotate % 90 == 0 ?
  3884. refbb.height : refbb.width);
  3885. if (textLength > refBoxLength) {
  3886. var startIndex = 0;
  3887. var lastSeperatorIndex = 0;
  3888. var numOfChars = this.getTrimmedTextLength(tspan.textContent);
  3889. for (var i = 0; i < numOfChars; i++) {
  3890. var sslength = this._getRenderedTextLength(tspan, startIndex, i-startIndex, fontSize);
  3891. if (sslength > refBoxLength - 2) {
  3892. var newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
  3893. if (lastSeperatorIndex <= startIndex) {
  3894. lastSeperatorIndex = (i == 0) ? i : i-1;
  3895. newtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim();
  3896. //lastSeperatorIndex = i;
  3897. }
  3898. else {
  3899. newtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim();
  3900. }
  3901. newtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);
  3902. newtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);
  3903. //insert tspan to text node
  3904. //this.node.insertBefore(newtspan, tspan);
  3905. newtspans.push(newtspan);
  3906. startIndex = lastSeperatorIndex;
  3907. }
  3908. else {
  3909. var curChar = tspan.textContent.charAt(i);
  3910. if (curChar == ' ' ||
  3911. curChar == '-' ||
  3912. curChar == "." ||
  3913. curChar == "," ||
  3914. curChar == ";" ||
  3915. curChar == ":") {
  3916. lastSeperatorIndex = i;
  3917. }
  3918. }
  3919. }
  3920. tspan.textContent = tspan.textContent.slice(startIndex).trim();
  3921. }
  3922. newtspans.push(tspan);
  3923. }
  3924. while (this.node.hasChildNodes())
  3925. this.node.removeChild(this.node.childNodes[0]);
  3926. while (newtspans.length > 0) {
  3927. this.node.appendChild(newtspans.shift());
  3928. }
  3929. }
  3930. //}
  3931. } catch (e) {
  3932. ORYX.Log.fatal("Error " + e);
  3933. }
  3934. window.setTimeout(this._positionText.bind(this), 0);
  3935. //this._positionText();
  3936. },
  3937. /**
  3938. * This is a work around method for Mozilla bug 293581.
  3939. * Before the method getComputedTextLength works, the text has to be rendered.
  3940. */
  3941. _positionText: function() {
  3942. try {
  3943. var tspans = this.node.childNodes;
  3944. var fontSize = this.getFontSize(this.node);
  3945. var invalidTSpans = [];
  3946. var x = this.x, y = this.y;
  3947. if (this.position){
  3948. x = this.position.x;
  3949. y = this.position.y;
  3950. }
  3951. x = Math.floor(x); y = Math.floor(y);
  3952. var i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called
  3953. var is =(this.indices || $R(0,tspans.length-1).toArray());
  3954. var length = is.length;
  3955. is.each((function(index){
  3956. if ("undefined" == typeof index){
  3957. return;
  3958. }
  3959. var tspan = tspans[i++];
  3960. if(tspan.textContent.trim() === "") {
  3961. invalidTSpans.push(tspan);
  3962. } else {
  3963. //set vertical position
  3964. var dy = 0;
  3965. switch (this._verticalAlign) {
  3966. case 'bottom':
  3967. dy = -(length - index - 1) * (fontSize);
  3968. break;
  3969. case 'middle':
  3970. dy = -(length / 2.0 - index - 1) * (fontSize);
  3971. dy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2;
  3972. break;
  3973. case 'top':
  3974. dy = index * (fontSize);
  3975. dy += fontSize;
  3976. break;
  3977. }
  3978. tspan.setAttributeNS(null, 'dy', Math.floor(dy));
  3979. tspan.setAttributeNS(null, 'x', x);
  3980. tspan.setAttributeNS(null, 'y', y);
  3981. indic.push(index);
  3982. }
  3983. }).bind(this));
  3984. indic.length = tspans.length;
  3985. this.indices = this.indices || indic;
  3986. invalidTSpans.each(function(tspan) {
  3987. this.node.removeChild(tspan)
  3988. }.bind(this));
  3989. //set horizontal alignment
  3990. switch (this._horizontalAlign) {
  3991. case 'left':
  3992. this.node.setAttributeNS(null, 'text-anchor', 'start');
  3993. break;
  3994. case 'center':
  3995. this.node.setAttributeNS(null, 'text-anchor', 'middle');
  3996. break;
  3997. case 'right':
  3998. this.node.setAttributeNS(null, 'text-anchor', 'end');
  3999. break;
  4000. }
  4001. } catch(e) {
  4002. //console.log(e);
  4003. this._isChanged = true;
  4004. }
  4005. if(this.isVisible) {
  4006. this.node.removeAttributeNS(null, 'visibility');
  4007. }
  4008. // Finished
  4009. delete this._isUpdating;
  4010. // Raise change event
  4011. (this.changeCallbacks||[]).each(function(fn){
  4012. fn.apply(fn);
  4013. })
  4014. },
  4015. /**
  4016. * Returns the text length of the text content of an SVG tspan element.
  4017. * For all browsers but Firefox 3 the values are estimated.
  4018. * @param {TSpanSVGElement} tspan
  4019. * @param {int} startIndex Optional, for sub strings
  4020. * @param {int} endIndex Optional, for sub strings
  4021. */
  4022. _getRenderedTextLength: function(tspan, startIndex, endIndex, fontSize) {
  4023. //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {
  4024. if(startIndex === undefined) {
  4025. //test string: abcdefghijklmnopqrstuvwxyz????????????????,.-#+ 1234567890?????ABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*???????????????!"????$%&/()=?[]{}|<>'~????`\^?????????@?????????????????
  4026. // for(var i = 0; i < tspan.textContent.length; i++) {
  4027. // console.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0));
  4028. // }
  4029. return tspan.getComputedTextLength();
  4030. } else {
  4031. return tspan.getSubStringLength(startIndex, endIndex);
  4032. }
  4033. /*} else {
  4034. if(startIndex === undefined) {
  4035. return this._estimateTextWidth(tspan.textContent, fontSize);
  4036. } else {
  4037. return this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize);
  4038. }
  4039. }*/
  4040. },
  4041. /**
  4042. * Estimates the text width for a string.
  4043. * Used for word wrapping in all browser but FF3.
  4044. * @param {Object} text
  4045. */
  4046. _estimateTextWidth: function(text, fontSize) {
  4047. var sum = 0.0;
  4048. for(var i = 0; i < text.length; i++) {
  4049. sum += this._estimateCharacterWidth(text.charAt(i));
  4050. }
  4051. return sum*(fontSize/14.0);
  4052. },
  4053. /**
  4054. * Estimates the width of a single character for font size 14.
  4055. * Used for word wrapping in all browser but FF3.
  4056. * @param {Object} character
  4057. */
  4058. _estimateCharacterWidth: function(character) {
  4059. for(var i = 0; i < this._characterSets.length; i++) {
  4060. if(this._characterSets[i].indexOf(character) >= 0) {
  4061. return this._characterSetValues[i];
  4062. }
  4063. }
  4064. return 9;
  4065. },
  4066. getReferencedElementWidth: function() {
  4067. var refNode = this.node.ownerDocument.getElementById(this.fitToElemId);
  4068. if(refNode) {
  4069. var refbb = refNode.getBBox();
  4070. if(refbb) {
  4071. return (this._rotate != 0
  4072. && this._rotate % 180 != 0
  4073. && this._rotate % 90 == 0 ?
  4074. refbb.height : refbb.width);
  4075. }
  4076. }
  4077. return undefined;
  4078. },
  4079. /**
  4080. * If no parameter is provided, this method returns the current text.
  4081. * @param text {String} Optional. Replaces the old text with this one.
  4082. */
  4083. text: function() {
  4084. switch (arguments.length) {
  4085. case 0:
  4086. return this._text
  4087. break;
  4088. case 1:
  4089. var oldText = this._text;
  4090. if(arguments[0]) {
  4091. // Filter out multiple spaces to fix issue in chrome for line-wrapping
  4092. this._text = arguments[0].toString();
  4093. if(this._text != null && this._text != undefined) {
  4094. this._text = this._text.replace(/ {2,}/g,' ');
  4095. }
  4096. } else {
  4097. this._text = "";
  4098. }
  4099. if(oldText !== this._text) {
  4100. this._isChanged = true;
  4101. this._textHasChanged = true;
  4102. }
  4103. break;
  4104. default:
  4105. //TODO error
  4106. break;
  4107. }
  4108. },
  4109. getOriginVerticalAlign: function(){
  4110. return this._originVerticalAlign;
  4111. },
  4112. verticalAlign: function() {
  4113. switch(arguments.length) {
  4114. case 0:
  4115. return this._verticalAlign;
  4116. case 1:
  4117. if(['top', 'middle', 'bottom'].member(arguments[0])) {
  4118. var oldValue = this._verticalAlign;
  4119. this._verticalAlign = arguments[0];
  4120. if(this._verticalAlign !== oldValue) {
  4121. this._isChanged = true;
  4122. }
  4123. }
  4124. break;
  4125. default:
  4126. //TODO error
  4127. break;
  4128. }
  4129. },
  4130. getOriginHorizontalAlign: function(){
  4131. return this._originHorizontalAlign;
  4132. },
  4133. horizontalAlign: function() {
  4134. switch(arguments.length) {
  4135. case 0:
  4136. return this._horizontalAlign;
  4137. case 1:
  4138. if(['left', 'center', 'right'].member(arguments[0])) {
  4139. var oldValue = this._horizontalAlign;
  4140. this._horizontalAlign = arguments[0];
  4141. if(this._horizontalAlign !== oldValue) {
  4142. this._isChanged = true;
  4143. }
  4144. }
  4145. break;
  4146. default:
  4147. //TODO error
  4148. break;
  4149. }
  4150. },
  4151. rotate: function() {
  4152. switch(arguments.length) {
  4153. case 0:
  4154. return this._rotate;
  4155. case 1:
  4156. if (this._rotate != arguments[0]) {
  4157. this._rotate = arguments[0];
  4158. this._rotationPoint = undefined;
  4159. this._isChanged = true;
  4160. }
  4161. case 2:
  4162. if(this._rotate != arguments[0] ||
  4163. !this._rotationPoint ||
  4164. this._rotationPoint.x != arguments[1].x ||
  4165. this._rotationPoint.y != arguments[1].y) {
  4166. this._rotate = arguments[0];
  4167. this._rotationPoint = arguments[1];
  4168. this._isChanged = true;
  4169. }
  4170. }
  4171. },
  4172. hide: function() {
  4173. if(this.isVisible) {
  4174. this.isVisible = false;
  4175. this._isChanged = true;
  4176. }
  4177. },
  4178. show: function() {
  4179. if(!this.isVisible) {
  4180. this.isVisible = true;
  4181. this._isChanged = true;
  4182. // Since text is removed from the tspan when "hidden", mark
  4183. // the text as changed to get it redrawn
  4184. this._textHasChanged = true;
  4185. }
  4186. },
  4187. /**
  4188. * iterates parent nodes till it finds a SVG font-size
  4189. * attribute.
  4190. * @param {SVGElement} node
  4191. */
  4192. getInheritedFontSize: function(node) {
  4193. if(!node || !node.getAttributeNS)
  4194. return;
  4195. var attr = node.getAttributeNS(null, "font-size");
  4196. if(attr) {
  4197. return parseFloat(attr);
  4198. } else if(!ORYX.Editor.checkClassType(node, SVGSVGElement)) {
  4199. return this.getInheritedFontSize(node.parentNode);
  4200. }
  4201. },
  4202. getFontSize: function(node) {
  4203. var tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
  4204. //trying to get an inherited font-size attribute
  4205. //NO CSS CONSIDERED!
  4206. var fontSize = this.getInheritedFontSize(this.node);
  4207. if (!fontSize) {
  4208. //because this only works in firefox 3, all other browser use the default line height
  4209. if (tspans[0] && /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {
  4210. fontSize = tspans[0].getExtentOfChar(0).height;
  4211. }
  4212. else {
  4213. fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;
  4214. }
  4215. //handling of unsupported method in webkit
  4216. if (fontSize <= 0) {
  4217. fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;
  4218. }
  4219. }
  4220. if(fontSize)
  4221. this.node.setAttribute("oryx:fontSize", fontSize);
  4222. return fontSize;
  4223. },
  4224. /**
  4225. * Get trimmed text length for use with
  4226. * getExtentOfChar and getSubStringLength.
  4227. * @param {String} text
  4228. */
  4229. getTrimmedTextLength: function(text) {
  4230. text = text.strip().gsub(' ', ' ');
  4231. var oldLength;
  4232. do {
  4233. oldLength = text.length;
  4234. text = text.gsub(' ', ' ');
  4235. } while (oldLength > text.length);
  4236. return text.length;
  4237. },
  4238. /**
  4239. * Returns the offset from
  4240. * edge to the label which is
  4241. * positioned under the edge
  4242. * @return {int}
  4243. */
  4244. getOffsetBottom: function(){
  4245. return this.offsetBottom;
  4246. },
  4247. /**
  4248. * Returns the offset from
  4249. * edge to the label which is
  4250. * positioned over the edge
  4251. * @return {int}
  4252. */
  4253. getOffsetTop: function(){
  4254. return this.offsetTop;
  4255. },
  4256. /**
  4257. *
  4258. * @param {Object} obj
  4259. */
  4260. deserialize: function(obj, shape){
  4261. if (obj && "undefined" != typeof obj.x && "undefined" != typeof obj.y){
  4262. this.setPosition({x:obj.x, y:obj.y});
  4263. if ("undefined" != typeof obj.distance){
  4264. var from = shape.dockers[obj.from];
  4265. var to = shape.dockers[obj.to];
  4266. if (from && to){
  4267. this.setReferencePoint({
  4268. dirty : true,
  4269. distance : obj.distance,
  4270. intersection : {x: obj.x, y: obj.y},
  4271. orientation : obj.orientation,
  4272. segment: {
  4273. from: from,
  4274. fromIndex: obj.from,
  4275. fromPosition: from.bounds.center(),
  4276. to: to,
  4277. toIndex: obj.to,
  4278. toPosition: to.bounds.center()
  4279. }
  4280. })
  4281. }
  4282. }
  4283. if (obj.left) this.anchorLeft = true;
  4284. if (obj.right) this.anchorRight = true;
  4285. if (obj.top) this.anchorTop = true;
  4286. if (obj.bottom) this.anchorBottom = true;
  4287. if (obj.valign) this.verticalAlign(obj.valign);
  4288. if (obj.align) this.horizontalAlign(obj.align);
  4289. } else if (obj && "undefined" != typeof obj.edge){
  4290. this.setEdgePosition(obj.edge);
  4291. }
  4292. },
  4293. /**
  4294. *
  4295. * @return {Object}
  4296. */
  4297. serialize: function(){
  4298. // On edge position
  4299. if (this.getEdgePosition()){
  4300. if (this.getOriginEdgePosition() !== this.getEdgePosition()){
  4301. return {edge: this.getEdgePosition()};
  4302. } else {
  4303. return null;
  4304. }
  4305. }
  4306. // On self defined position
  4307. if (this.position){
  4308. var pos = {x: this.position.x, y: this.position.y};
  4309. if (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()){
  4310. pos.left = true;
  4311. }
  4312. if (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()){
  4313. pos.right = true;
  4314. }
  4315. if (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()){
  4316. pos.top = true;
  4317. }
  4318. if (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()){
  4319. pos.bottom = true;
  4320. }
  4321. if (this.getOriginVerticalAlign() !== this.verticalAlign()){
  4322. pos.valign = this.verticalAlign();
  4323. }
  4324. if (this.getOriginHorizontalAlign() !== this.horizontalAlign()){
  4325. pos.align = this.horizontalAlign();
  4326. }
  4327. return pos;
  4328. }
  4329. // On reference point which is interesting for edges
  4330. if (this.getReferencePoint()){
  4331. var ref = this.getReferencePoint();
  4332. return {
  4333. distance : ref.distance,
  4334. x : ref.intersection.x,
  4335. y : ref.intersection.y,
  4336. from : ref.segment.fromIndex,
  4337. to : ref.segment.toIndex,
  4338. orientation : ref.orientation,
  4339. valign : this.verticalAlign(),
  4340. align : this.horizontalAlign()
  4341. }
  4342. }
  4343. return null;
  4344. },
  4345. toString: function() { return "Label " + this.id }
  4346. });/*
  4347. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  4348. * License rights for this program may be obtained from Alfresco Software, Ltd.
  4349. * pursuant to a written agreement and any use of this program without such an
  4350. * agreement is prohibited.
  4351. */
  4352. /*
  4353. * All code Copyright 2013 KIS Consultancy all rights reserved
  4354. */
  4355. /**
  4356. * Init namespaces
  4357. */
  4358. if(!ORYX) {var ORYX = {};}
  4359. if(!ORYX.Core) {ORYX.Core = {};}
  4360. if(!ORYX.Core.Math) {ORYX.Core.Math = {};}
  4361. /**
  4362. * Calculate the middle point between two given points
  4363. * @param {x:double, y:double} point1
  4364. * @param {x:double, y:double} point2
  4365. * @return the middle point
  4366. */
  4367. ORYX.Core.Math.midPoint = function(point1, point2) {
  4368. return {
  4369. x: (point1.x + point2.x) / 2.0,
  4370. y: (point1.y + point2.y) / 2.0
  4371. }
  4372. }
  4373. /**
  4374. * Returns a TRUE if the point is over a line (defined by
  4375. * point1 and point 2). In Addition a threshold can be set,
  4376. * which defines the weight of those line.
  4377. *
  4378. * @param {int} pointX - Point X
  4379. * @param {int} pointY - Point Y
  4380. * @param {int} lPoint1X - Line first Point X
  4381. * @param {int} lPoint1Y - Line first Point Y
  4382. * @param {int} lPoint2X - Line second Point X
  4383. * @param {int} lPoint2Y - Line second Point y
  4384. * @param {int} offset {optional} - maximal distance to line
  4385. * @class ORYX.Core.Math.prototype
  4386. */
  4387. ORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) {
  4388. offset = offset ? Math.abs(offset) : 1;
  4389. // Check if the edge is vertical
  4390. if(Math.abs(lPoint1X-lPoint2X)<=offset && Math.abs(pointX-lPoint1X)<=offset && pointY-Math.max(lPoint1Y, lPoint2Y)<=offset && Math.min(lPoint1Y, lPoint2Y)-pointY<=offset) {
  4391. return true
  4392. }
  4393. // Check if the edge is horizontal
  4394. if(Math.abs(lPoint1Y-lPoint2Y)<=offset && Math.abs(pointY-lPoint1Y)<=offset && pointX-Math.max(lPoint1X, lPoint2X)<=offset && Math.min(lPoint1X, lPoint2X)-pointX<=offset) {
  4395. return true
  4396. }
  4397. if(pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) {
  4398. return false
  4399. }
  4400. if(pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) {
  4401. return false
  4402. }
  4403. var s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X);
  4404. return Math.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset
  4405. }
  4406. /**
  4407. * Get a boolean if the point is in the polygone
  4408. *
  4409. */
  4410. ORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) {
  4411. if(cx === undefined || cy === undefined || rx === undefined || ry === undefined) {
  4412. throw "ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY"
  4413. }
  4414. var tx = (pointX - cx) / rx;
  4415. var ty = (pointY - cy) / ry;
  4416. return tx * tx + ty * ty < 1.0;
  4417. }
  4418. /**
  4419. * Get a boolean if the point is in the polygone
  4420. * @param {int} pointX
  4421. * @param {int} pointY
  4422. * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...)
  4423. */
  4424. ORYX.Core.Math.isPointInPolygone = function(pointX, pointY, polygone){
  4425. if (arguments.length < 3) {
  4426. throw "ORYX.Core.Math.isPointInPolygone needs two arguments"
  4427. }
  4428. var lastIndex = polygone.length-1;
  4429. if (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) {
  4430. polygone.push(polygone[0]);
  4431. polygone.push(polygone[1]);
  4432. }
  4433. var crossings = 0;
  4434. var x1, y1, x2, y2, d;
  4435. for (var i = 0; i < polygone.length - 3; ) {
  4436. x1=polygone[i];
  4437. y1=polygone[++i];
  4438. x2=polygone[++i];
  4439. y2=polygone[i+1];
  4440. d=(pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1);
  4441. if ((y1 >= pointY) != (y2 >= pointY)) {
  4442. crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0;
  4443. }
  4444. if (!d && Math.min(x1,x2) <= pointX && pointX <= Math.max(x1,x2)
  4445. && Math.min(y1,y2) <= pointY && pointY <= Math.max(y1,y2)) {
  4446. return true;
  4447. }
  4448. }
  4449. return (crossings%2)?true:false;
  4450. }
  4451. /**
  4452. * Calculates the distance between a point and a line. It is also testable, if
  4453. * the distance orthogonal to the line, matches the segment of the line.
  4454. *
  4455. * @param {float} lineP1
  4456. * The starting point of the line segment
  4457. * @param {float} lineP2
  4458. * The end point of the line segment
  4459. * @param {Point} point
  4460. * The point to calculate the distance to.
  4461. * @param {boolean} toSegmentOnly
  4462. * Flag to signal if only the segment of the line shell be evaluated.
  4463. */
  4464. ORYX.Core.Math.distancePointLinie = function(
  4465. lineP1,
  4466. lineP2,
  4467. point,
  4468. toSegmentOnly) {
  4469. var intersectionPoint =
  4470. ORYX.Core.Math.getPointOfIntersectionPointLine(lineP1,
  4471. lineP2,
  4472. point,
  4473. toSegmentOnly);
  4474. if(!intersectionPoint) {
  4475. return null;
  4476. }
  4477. return ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint);
  4478. };
  4479. /**
  4480. * Calculates the distance between two points.
  4481. *
  4482. * @param {point} point1
  4483. * @param {point} point2
  4484. */
  4485. ORYX.Core.Math.getDistancePointToPoint = function(point1, point2) {
  4486. return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
  4487. };
  4488. /**
  4489. * Calculates the relative distance of a point which is between two other points.
  4490. *
  4491. * @param {point} between1
  4492. * @param {point} between2
  4493. * @param {point} point
  4494. */
  4495. ORYX.Core.Math.getDistanceBetweenTwoPoints = function(between1, between2, point) {
  4496. return ORYX.Core.Math.getDistancePointToPoint(point, between1) /
  4497. ORYX.Core.Math.getDistancePointToPoint(between1, between2);
  4498. };
  4499. /**
  4500. * Returns true, if the point is of the left hand
  4501. * side of the regarding the line.
  4502. *
  4503. * @param {point} lineP1 Line first point
  4504. * @param {point} lineP2 Line second point
  4505. * @param {point} point
  4506. */
  4507. ORYX.Core.Math.pointIsLeftOfLine = function(lineP1, lineP2, point){
  4508. var vec1 = ORYX.Core.Math.getVector(lineP1, lineP2);
  4509. var vec2 = ORYX.Core.Math.getVector(lineP1, point);
  4510. // if the cross produkt is more than 0
  4511. return ((vec1.x*vec2.y) - (vec2.x*vec1.y)) > 0
  4512. };
  4513. /**
  4514. * Calculates the a point which is relatively between two other points.
  4515. *
  4516. * @param {point} point1
  4517. * @param {point} point2
  4518. * @param {number} relative Relative which is between 0 and 1
  4519. */
  4520. ORYX.Core.Math.getPointBetweenTwoPoints = function(point1, point2, relative) {
  4521. relative = Math.max(Math.min(relative || 0, 1), 0);
  4522. if (relative === 0){
  4523. return point1;
  4524. } else if (relative === 1){
  4525. return point2;
  4526. }
  4527. return {
  4528. x: point1.x + ((point2.x - point1.x) * relative),
  4529. y: point1.y + ((point2.y - point1.y) * relative)
  4530. }
  4531. };
  4532. /**
  4533. * Returns the vector of the both points
  4534. *
  4535. * @param {point} point1
  4536. * @param {point} point2
  4537. */
  4538. ORYX.Core.Math.getVector = function(point1, point2){
  4539. return {
  4540. x: point2.x - point1.x,
  4541. y: point2.y - point1.y
  4542. }
  4543. }
  4544. /**
  4545. * Returns the an identity vector of the given vector,
  4546. * which has the length ot one.
  4547. *
  4548. * @param {point} vector
  4549. * or
  4550. * @param {point} point1
  4551. * @param {point} point2
  4552. */
  4553. ORYX.Core.Math.getIdentityVector = function(vector){
  4554. if (arguments.length == 2){
  4555. vector = ORYX.Core.Math.getVector(arguments[0], arguments[1]);
  4556. }
  4557. var length = Math.sqrt((vector.x*vector.x)+(vector.y*vector.y))
  4558. return {
  4559. x: vector.x / (length || 1),
  4560. y: vector.y / (length || 1)
  4561. }
  4562. }
  4563. ORYX.Core.Math.getOrthogonalIdentityVector = function(point1, point2){
  4564. var vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2);
  4565. return {
  4566. x: vec.y,
  4567. y: -vec.x
  4568. }
  4569. }
  4570. /**
  4571. * Returns the intersection point of a line and a point that defines a line
  4572. * orthogonal to the given line.
  4573. *
  4574. * @param {float} lineP1
  4575. * The starting point of the line segment
  4576. * @param {float} lineP2
  4577. * The end point of the line segment
  4578. * @param {Point} point
  4579. * The point to calculate the distance to.
  4580. * @param {boolean} onSegmentOnly
  4581. * Flag to signal if only the segment of the line shell be evaluated.
  4582. */
  4583. ORYX.Core.Math.getPointOfIntersectionPointLine = function(
  4584. lineP1,
  4585. lineP2,
  4586. point,
  4587. onSegmentOnly) {
  4588. /*
  4589. * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0
  4590. * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)??
  4591. */
  4592. var denominator = Math.pow(lineP2.x - lineP1.x, 2)
  4593. + Math.pow(lineP2.y - lineP1.y, 2);
  4594. if(denominator == 0) {
  4595. return undefined;
  4596. }
  4597. var u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x)
  4598. + (point.y - lineP1.y) * (lineP2.y - lineP1.y))
  4599. / denominator;
  4600. if(onSegmentOnly) {
  4601. if (!(0 <= u && u <= 1)) {
  4602. return undefined;
  4603. }
  4604. }
  4605. pointOfIntersection = new Object();
  4606. pointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x);
  4607. pointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y);
  4608. return pointOfIntersection;
  4609. };
  4610. /**
  4611. * Translated the point with the given matrix.
  4612. * @param {Point} point
  4613. * @param {Matrix} matrix
  4614. * @return {Object} Includes x, y
  4615. */
  4616. ORYX.Core.Math.getTranslatedPoint = function(point, matrix){
  4617. var x = matrix.a*point.x+matrix.c*point.y+matrix.e*1;
  4618. var y = matrix.b*point.x+matrix.d*point.y+matrix.f*1;
  4619. return {x:x, y:y}
  4620. }
  4621. /**
  4622. * Returns the inverse matrix of the given SVG transformation matrix
  4623. * @param {SVGTransformationMatrix} matrix
  4624. * @return {Matrix}
  4625. */
  4626. ORYX.Core.Math.getInverseMatrix = function(matrix){
  4627. var det = ORYX.Core.Math.getDeterminant(matrix), m = matrix;
  4628. // +- -+
  4629. // | a c e |
  4630. // | b d f |
  4631. // | 0 0 1 |
  4632. // +- -+
  4633. return {
  4634. a: det * ((m.d*1)-(m.f*0)),
  4635. b: det * ((m.f*0)-(m.b*1)),
  4636. c: det * ((m.e*0)-(m.c*1)),
  4637. d: det * ((m.a*1)-(m.e*0)),
  4638. e: det * ((m.c*m.f)-(m.e*m.d)),
  4639. f: det * ((m.e*m.b)-(m.a*m.f))
  4640. }
  4641. }
  4642. /**
  4643. * Returns the determinant of the svg transformation matrix
  4644. * @param {SVGTranformationMatrix} matrix
  4645. * @return {Number}
  4646. *
  4647. */
  4648. ORYX.Core.Math.getDeterminant = function(m){
  4649. // a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32
  4650. return (m.a*m.d*1)+(m.c*m.f*0)+(m.e*m.b*0)-(m.e*m.d*0)-(m.c*m.b*1)-(m.a*m.f*0);
  4651. }
  4652. /**
  4653. * Returns the bounding box of the given node. Translates the
  4654. * origin bounding box with the tranlation matrix.
  4655. * @param {SVGElement} node
  4656. * @return {Object} Includes x, y, width, height
  4657. */
  4658. ORYX.Core.Math.getTranslatedBoundingBox = function(node){
  4659. var matrix = node.getCTM();
  4660. var bb = node.getBBox();
  4661. var ul = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y}, matrix);
  4662. var ll = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y+bb.height}, matrix);
  4663. var ur = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y}, matrix);
  4664. var lr = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y+bb.height}, matrix);
  4665. var minPoint = {
  4666. x: Math.min(ul.x, ll.x, ur.x, lr.x),
  4667. y: Math.min(ul.y, ll.y, ur.y, lr.y)
  4668. }
  4669. var maxPoint = {
  4670. x: Math.max(ul.x, ll.x, ur.x, lr.x),
  4671. y: Math.max(ul.y, ll.y, ur.y, lr.y)
  4672. }
  4673. return {
  4674. x: minPoint.x,
  4675. y: minPoint.y,
  4676. width: maxPoint.x - minPoint.x,
  4677. height: maxPoint.y - minPoint.y
  4678. }
  4679. };
  4680. /**
  4681. * Returns the angle of the given line, which is representated by the two points
  4682. * @param {Point} p1
  4683. * @param {Point} p2
  4684. * @return {Number} 0 <= x <= 359.99999
  4685. */
  4686. ORYX.Core.Math.getAngle = function(p1, p2){
  4687. if(p1.x == p2.x && p1.y == p2.y)
  4688. return 0;
  4689. var angle = Math.asin(Math.sqrt(Math.pow(p1.y-p2.y, 2))
  4690. /(Math.sqrt(Math.pow(p2.x-p1.x, 2)+Math.pow(p1.y-p2.y, 2))))
  4691. *180/Math.PI;
  4692. if(p2.x >= p1.x && p2.y <= p1.y)
  4693. return angle;
  4694. else if(p2.x < p1.x && p2.y <= p1.y)
  4695. return 180 - angle;
  4696. else if(p2.x < p1.x && p2.y > p1.y)
  4697. return 180 + angle;
  4698. else
  4699. return 360 - angle;
  4700. };
  4701. /**
  4702. * Implementation of the cohen-sutherland algorithm
  4703. */
  4704. new function(){
  4705. var RIGHT = 2, TOP = 8, BOTTOM = 4, LEFT = 1;
  4706. function computeOutCode (x, y, xmin, ymin, xmax, ymax) {
  4707. var code = 0;
  4708. if (y > ymax)
  4709. code |= TOP;
  4710. else if (y < ymin)
  4711. code |= BOTTOM;
  4712. if (x > xmax)
  4713. code |= RIGHT;
  4714. else if (x < xmin)
  4715. code |= LEFT;
  4716. return code;
  4717. }
  4718. /**
  4719. * Returns TRUE if the rectangle is over the edge and has intersection points or includes it
  4720. * @param {Object} x1 Point A of the line
  4721. * @param {Object} y1
  4722. * @param {Object} x2 Point B of the line
  4723. * @param {Object} y2
  4724. * @param {Object} xmin Point A of the rectangle
  4725. * @param {Object} ymin
  4726. * @param {Object} xmax Point B of the rectangle
  4727. * @param {Object} ymax
  4728. */
  4729. ORYX.Core.Math.isRectOverLine = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){
  4730. return !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments);
  4731. }
  4732. /**
  4733. * Returns the clipped line on the given rectangle. If there is
  4734. * no intersection, it will return NULL.
  4735. *
  4736. * @param {Object} x1 Point A of the line
  4737. * @param {Object} y1
  4738. * @param {Object} x2 Point B of the line
  4739. * @param {Object} y2
  4740. * @param {Object} xmin Point A of the rectangle
  4741. * @param {Object} ymin
  4742. * @param {Object} xmax Point B of the rectangle
  4743. * @param {Object} ymax
  4744. */
  4745. ORYX.Core.Math.clipLineOnRect = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){
  4746. //Outcodes for P0, P1, and whatever point lies outside the clip rectangle
  4747. var outcode0, outcode1, outcodeOut, hhh = 0;
  4748. var accept = false, done = false;
  4749. //compute outcodes
  4750. outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax);
  4751. outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax);
  4752. do {
  4753. if ((outcode0 | outcode1) == 0 ){
  4754. accept = true;
  4755. done = true;
  4756. } else if ( (outcode0 & outcode1) > 0 ) {
  4757. done = true;
  4758. } else {
  4759. //failed both tests, so calculate the line segment to clip
  4760. //from an outside point to an intersection with clip edge
  4761. var x = 0, y = 0;
  4762. //At least one endpoint is outside the clip rectangle; pick it.
  4763. outcodeOut = outcode0 != 0 ? outcode0: outcode1;
  4764. //Now find the intersection point;
  4765. //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0)
  4766. if ( (outcodeOut & TOP) > 0 ) {
  4767. x = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1);
  4768. y = ymax;
  4769. } else if ((outcodeOut & BOTTOM) > 0 ) {
  4770. x = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1);
  4771. y = ymin;
  4772. } else if ((outcodeOut & RIGHT)> 0) {
  4773. y = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1);
  4774. x = xmax;
  4775. } else if ((outcodeOut & LEFT) > 0) {
  4776. y = y1 + (y2 - y1) * (xmin - x1)/(x2 - x1);
  4777. x = xmin;
  4778. }
  4779. //Now we move outside point to intersection point to clip
  4780. //and get ready for next pass.
  4781. if (outcodeOut == outcode0) {
  4782. x1 = x;
  4783. y1 = y;
  4784. outcode0 = computeOutCode (x1, y1, xmin, ymin, xmax, ymax);
  4785. } else {
  4786. x2 = x;
  4787. y2 = y;
  4788. outcode1 = computeOutCode (x2, y2, xmin, ymin, xmax, ymax);
  4789. }
  4790. }
  4791. hhh ++;
  4792. } while (done != true && hhh < 5000);
  4793. if(accept) {
  4794. return {a:{x:x1, y:y1}, b:{x:x2, y:y2}};
  4795. }
  4796. return null;
  4797. }
  4798. }();
  4799. /*
  4800. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  4801. * License rights for this program may be obtained from Alfresco Software, Ltd.
  4802. * pursuant to a written agreement and any use of this program without such an
  4803. * agreement is prohibited.
  4804. */
  4805. /*
  4806. * All code Copyright 2013 KIS Consultancy all rights reserved
  4807. */
  4808. /**
  4809. * Init namespace
  4810. */
  4811. if(!ORYX) {var ORYX = {};}
  4812. if(!ORYX.Core) {ORYX.Core = {};}
  4813. if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
  4814. /**
  4815. * Class Stencil
  4816. * uses Prototpye 1.5.0
  4817. * uses Inheritance
  4818. *
  4819. * This class represents one stencil of a stencil set.
  4820. */
  4821. ORYX.Core.StencilSet.Stencil = {
  4822. /**
  4823. * Constructor
  4824. */
  4825. construct: function(jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) {
  4826. arguments.callee.$.construct.apply(this, arguments); // super();
  4827. // check arguments and set defaults.
  4828. if(!jsonStencil) throw "Stencilset seems corrupt.";
  4829. if(!namespace) throw "Stencil does not provide namespace.";
  4830. if(!source) throw "Stencil does not provide SVG source.";
  4831. if(!stencilSet) throw "Fatal internal error loading stencilset.";
  4832. //if(!propertyPackages) throw "Fatal internal error loading stencilset.";
  4833. this._source = source;
  4834. this._jsonStencil = jsonStencil;
  4835. this._stencilSet = stencilSet;
  4836. this._namespace = namespace;
  4837. this._propertyPackages = propertyPackages;
  4838. if(defaultPosition && !this._jsonStencil.position)
  4839. this._jsonStencil.position = defaultPosition;
  4840. this._view;
  4841. this._properties = new Hash();
  4842. // check stencil consistency and set defaults.
  4843. /*with(this._jsonStencil) {
  4844. if(!type) throw "Stencil does not provide type.";
  4845. if((type != "edge") && (type != "node"))
  4846. throw "Stencil type must be 'edge' or 'node'.";
  4847. if(!id || id == "") throw "Stencil does not provide valid id.";
  4848. if(!title || title == "")
  4849. throw "Stencil does not provide title";
  4850. if(!description) { description = ""; };
  4851. if(!groups) { groups = []; }
  4852. if(!roles) { roles = []; }
  4853. // add id of stencil to its roles
  4854. roles.push(id);
  4855. }*/
  4856. //init all JSON values
  4857. if(!this._jsonStencil.type || !(this._jsonStencil.type === "edge" || this._jsonStencil.type === "node")) {
  4858. throw "ORYX.Core.StencilSet.Stencil(construct): Type is not defined.";
  4859. }
  4860. if(!this._jsonStencil.id || this._jsonStencil.id === "") {
  4861. throw "ORYX.Core.StencilSet.Stencil(construct): Id is not defined.";
  4862. }
  4863. if(!this._jsonStencil.title || this._jsonStencil.title === "") {
  4864. throw "ORYX.Core.StencilSet.Stencil(construct): Title is not defined.";
  4865. }
  4866. if(!this._jsonStencil.description) { this._jsonStencil.description = ""; };
  4867. if(!this._jsonStencil.groups) { this._jsonStencil.groups = []; }
  4868. if(!this._jsonStencil.roles) { this._jsonStencil.roles = []; }
  4869. //add id of stencil to its roles
  4870. this._jsonStencil.roles.push(this._jsonStencil.id);
  4871. //prepend namespace to each role
  4872. this._jsonStencil.roles.each((function(role, index) {
  4873. this._jsonStencil.roles[index] = namespace + role;
  4874. }).bind(this));
  4875. //delete duplicate roles
  4876. this._jsonStencil.roles = this._jsonStencil.roles.uniq();
  4877. //make id unique by prepending namespace of stencil set
  4878. this._jsonStencil.id = namespace + this._jsonStencil.id;
  4879. this.postProcessProperties();
  4880. // init serialize callback
  4881. if(!this._jsonStencil.serialize) {
  4882. this._jsonStencil.serialize = {};
  4883. //this._jsonStencil.serialize = function(shape, data) { return data;};
  4884. }
  4885. // init deserialize callback
  4886. if(!this._jsonStencil.deserialize) {
  4887. this._jsonStencil.deserialize = {};
  4888. //this._jsonStencil.deserialize = function(shape, data) { return data;};
  4889. }
  4890. // init layout callback
  4891. if(!this._jsonStencil.layout) {
  4892. this._jsonStencil.layout = []
  4893. //this._jsonStencil.layout = function() {return true;}
  4894. }
  4895. //TODO does not work correctly, if the url does not exist
  4896. //How to guarantee that the view is loaded correctly before leaving the constructor???
  4897. var url = source + "view/" + jsonStencil.view;
  4898. // override content type when this is webkit.
  4899. if(this._jsonStencil.view.trim().match(/</)) {
  4900. var parser = new DOMParser();
  4901. var xml = parser.parseFromString( this._jsonStencil.view ,"text/xml");
  4902. //check if result is a SVG document
  4903. if( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {
  4904. this._view = xml.documentElement;
  4905. } else {
  4906. throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document."
  4907. }
  4908. } else {
  4909. new Ajax.Request(
  4910. url, {
  4911. asynchronous:false, method:'get',
  4912. onSuccess:this._loadSVGOnSuccess.bind(this),
  4913. onFailure:this._loadSVGOnFailure.bind(this)
  4914. });
  4915. }
  4916. },
  4917. postProcessProperties: function() {
  4918. // init property packages
  4919. if(this._jsonStencil.propertyPackages && this._jsonStencil.propertyPackages instanceof Array) {
  4920. this._jsonStencil.propertyPackages.each((function(ppId) {
  4921. var pp = this._propertyPackages[ppId];
  4922. if(pp) {
  4923. pp.each((function(prop){
  4924. var oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);
  4925. this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
  4926. }).bind(this));
  4927. }
  4928. }).bind(this));
  4929. }
  4930. // init properties
  4931. if(this._jsonStencil.properties && this._jsonStencil.properties instanceof Array) {
  4932. this._jsonStencil.properties.each((function(prop) {
  4933. var oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);
  4934. this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
  4935. }).bind(this));
  4936. }
  4937. },
  4938. /**
  4939. * @param {ORYX.Core.StencilSet.Stencil} stencil
  4940. * @return {Boolean} True, if stencil has the same namespace and type.
  4941. */
  4942. equals: function(stencil) {
  4943. return (this.id() === stencil.id());
  4944. },
  4945. stencilSet: function() {
  4946. return this._stencilSet;
  4947. },
  4948. type: function() {
  4949. return this._jsonStencil.type;
  4950. },
  4951. namespace: function() {
  4952. return this._namespace;
  4953. },
  4954. id: function() {
  4955. return this._jsonStencil.id;
  4956. },
  4957. idWithoutNs: function(){
  4958. return this.id().replace(this.namespace(),"");
  4959. },
  4960. title: function() {
  4961. return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "title");
  4962. },
  4963. description: function() {
  4964. return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "description");
  4965. },
  4966. groups: function() {
  4967. return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "groups");
  4968. },
  4969. position: function() {
  4970. return (isNaN(this._jsonStencil.position) ? 0 : this._jsonStencil.position);
  4971. },
  4972. view: function() {
  4973. return this._view.cloneNode(true) || this._view;
  4974. },
  4975. icon: function() {
  4976. return this._jsonStencil.icon;
  4977. },
  4978. fixedAspectRatio: function() {
  4979. return this._jsonStencil.fixedAspectRatio === true;
  4980. },
  4981. hasMultipleRepositoryEntries: function() {
  4982. return (this.getRepositoryEntries().length > 0);
  4983. },
  4984. getRepositoryEntries: function() {
  4985. return (this._jsonStencil.repositoryEntries) ?
  4986. $A(this._jsonStencil.repositoryEntries) : $A([]);
  4987. },
  4988. properties: function() {
  4989. return this._properties.values();
  4990. },
  4991. property: function(id) {
  4992. return this._properties[id];
  4993. },
  4994. roles: function() {
  4995. return this._jsonStencil.roles;
  4996. },
  4997. defaultAlign: function() {
  4998. if(!this._jsonStencil.defaultAlign)
  4999. return "east";
  5000. return this._jsonStencil.defaultAlign;
  5001. },
  5002. serialize: function(shape, data) {
  5003. return this._jsonStencil.serialize;
  5004. //return this._jsonStencil.serialize(shape, data);
  5005. },
  5006. deserialize: function(shape, data) {
  5007. return this._jsonStencil.deserialize;
  5008. //return this._jsonStencil.deserialize(shape, data);
  5009. },
  5010. // in which case is targetShape used?
  5011. // layout: function(shape, targetShape) {
  5012. // return this._jsonStencil.layout(shape, targetShape);
  5013. // },
  5014. // layout property to store events for layouting in plugins
  5015. layout: function(shape) {
  5016. return this._jsonStencil.layout
  5017. },
  5018. addProperty: function(property, namespace) {
  5019. if(property && namespace) {
  5020. var oProp = new ORYX.Core.StencilSet.Property(property, namespace, this);
  5021. this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
  5022. }
  5023. },
  5024. removeProperty: function(propertyId) {
  5025. if(propertyId) {
  5026. var oProp = this._properties.values().find(function(prop) {
  5027. return (propertyId == prop.id());
  5028. });
  5029. if(oProp)
  5030. delete this._properties[oProp.prefix() + "-" + oProp.id()];
  5031. }
  5032. },
  5033. _loadSVGOnSuccess: function(result) {
  5034. var xml = null;
  5035. /*
  5036. * We want to get a dom object for the requested file. Unfortunately,
  5037. * safari has some issues here. this is meant as a fallback for all
  5038. * browsers that don't recognize the svg mimetype as XML but support
  5039. * data: urls on Ajax calls.
  5040. */
  5041. // responseXML != undefined.
  5042. // if(!(result.responseXML))
  5043. // get the dom by data: url.
  5044. // xml = _evenMoreEvilHack(result.responseText, 'text/xml');
  5045. // else
  5046. // get it the usual way.
  5047. xml = result.responseXML;
  5048. //check if result is a SVG document
  5049. if( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {
  5050. this._view = xml.documentElement;
  5051. } else {
  5052. throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document."
  5053. }
  5054. },
  5055. _loadSVGOnFailure: function(result) {
  5056. throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed."
  5057. },
  5058. toString: function() { return "Stencil " + this.title() + " (" + this.id() + ")"; }
  5059. };
  5060. ORYX.Core.StencilSet.Stencil = Clazz.extend(ORYX.Core.StencilSet.Stencil);
  5061. /**
  5062. * Transform a string into an xml document, the Safari way, as long as
  5063. * the nightlies are broken. Even more evil version.
  5064. * @param {Object} str
  5065. * @param {Object} contentType
  5066. */
  5067. function _evenMoreEvilHack(str, contentType) {
  5068. /*
  5069. * This even more evil hack was taken from
  5070. * http://web-graphics.com/mtarchive/001606.php#chatty004999
  5071. */
  5072. if (window.ActiveXObject) {
  5073. var d = new ActiveXObject("MSXML.DomDocument");
  5074. d.loadXML(str);
  5075. return d;
  5076. } else if (window.XMLHttpRequest) {
  5077. var req = new XMLHttpRequest;
  5078. req.open("GET", "data:" + (contentType || "application/xml") +
  5079. ";charset=utf-8," + encodeURIComponent(str), false);
  5080. if (req.overrideMimeType) {
  5081. req.overrideMimeType(contentType);
  5082. }
  5083. req.send(null);
  5084. return req.responseXML;
  5085. }
  5086. }
  5087. /**
  5088. * Transform a string into an xml document, the Safari way, as long as
  5089. * the nightlies are broken.
  5090. * @param {Object} result the xml document object.
  5091. */
  5092. function _evilSafariHack(serializedXML) {
  5093. /*
  5094. * The Dave way. Taken from:
  5095. * http://web-graphics.com/mtarchive/001606.php
  5096. *
  5097. * There is another possibility to parse XML in Safari, by implementing
  5098. * the DOMParser in javascript. However, in the latest nightlies of
  5099. * WebKit, DOMParser is already available, but still buggy. So, this is
  5100. * the best compromise for the time being.
  5101. */
  5102. var xml = serializedXML;
  5103. var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xml);
  5104. var dom = null;
  5105. // your standard AJAX stuff
  5106. var req = new XMLHttpRequest();
  5107. req.open("GET", url);
  5108. req.onload = function() { dom = req.responseXML; }
  5109. req.send(null);
  5110. return dom;
  5111. }
  5112. /*
  5113. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  5114. * License rights for this program may be obtained from Alfresco Software, Ltd.
  5115. * pursuant to a written agreement and any use of this program without such an
  5116. * agreement is prohibited.
  5117. */
  5118. /*
  5119. * All code Copyright 2013 KIS Consultancy all rights reserved
  5120. */
  5121. /**
  5122. * Init namespace
  5123. */
  5124. if (!ORYX) {
  5125. var ORYX = {};
  5126. }
  5127. if (!ORYX.Core) {
  5128. ORYX.Core = {};
  5129. }
  5130. if (!ORYX.Core.StencilSet) {
  5131. ORYX.Core.StencilSet = {};
  5132. }
  5133. /**
  5134. * Class Property
  5135. * uses Prototpye 1.5.0
  5136. * uses Inheritance
  5137. */
  5138. ORYX.Core.StencilSet.Property = Clazz.extend({
  5139. /**
  5140. * Constructor
  5141. */
  5142. construct: function(jsonProp, namespace, stencil){
  5143. arguments.callee.$.construct.apply(this, arguments);
  5144. this._jsonProp = jsonProp || ORYX.Log.error("Parameter jsonProp is not defined.");
  5145. this._namespace = namespace || ORYX.Log.error("Parameter namespace is not defined.");
  5146. this._stencil = stencil || ORYX.Log.error("Parameter stencil is not defined.");
  5147. this._items = {};
  5148. this._complexItems = {};
  5149. // Flag to indicate whether or not the property should be hidden
  5150. // This can be for example when the stencil set is upgraded, but the model
  5151. // has a value for that specific property filled in which we still want to show.
  5152. // If the value is missing, the property can simply be not shown.
  5153. this._hidden = false;
  5154. jsonProp.id = jsonProp.id || ORYX.Log.error("ORYX.Core.StencilSet.Property(construct): Id is not defined.");
  5155. jsonProp.id = jsonProp.id.toLowerCase();
  5156. if (!jsonProp.type) {
  5157. ORYX.Log.info("Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.", stencil, jsonProp.id);
  5158. jsonProp.type = "string";
  5159. }
  5160. else {
  5161. jsonProp.type = jsonProp.type.toLowerCase();
  5162. }
  5163. jsonProp.prefix = jsonProp.prefix || "oryx";
  5164. jsonProp.title = jsonProp.title || "";
  5165. jsonProp.value = jsonProp.value || "";
  5166. jsonProp.description = jsonProp.description || "";
  5167. jsonProp.readonly = jsonProp.readonly || false;
  5168. jsonProp.optional = jsonProp.optional !== false;
  5169. //init refToView
  5170. if (this._jsonProp.refToView) {
  5171. if (!(this._jsonProp.refToView instanceof Array)) {
  5172. this._jsonProp.refToView = [this._jsonProp.refToView];
  5173. }
  5174. }
  5175. else {
  5176. this._jsonProp.refToView = [];
  5177. }
  5178. var globalMin = this.getMinForType(jsonProp.type);
  5179. if (jsonProp.min === undefined || jsonProp.min === null) {
  5180. jsonProp.min =globalMin;
  5181. } else if (jsonProp.min < globalMin) {
  5182. jsonProp.min = globalMin;
  5183. }
  5184. var globalMax = this.getMaxForType(jsonProp.type);
  5185. if (jsonProp.max === undefined || jsonProp.max === null) {
  5186. jsonProp.max = globalMax;
  5187. } else if (jsonProp.max > globalMax) {
  5188. jsonProp.min = globalMax;
  5189. }
  5190. if (!jsonProp.fillOpacity) {
  5191. jsonProp.fillOpacity = false;
  5192. }
  5193. if ("number" != typeof jsonProp.lightness) {
  5194. jsonProp.lightness = 1;
  5195. } else {
  5196. jsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness));
  5197. }
  5198. if (!jsonProp.strokeOpacity) {
  5199. jsonProp.strokeOpacity = false;
  5200. }
  5201. if (jsonProp.length === undefined || jsonProp.length === null) {
  5202. jsonProp.length = Number.MAX_VALUE;
  5203. }
  5204. if (!jsonProp.wrapLines) {
  5205. jsonProp.wrapLines = false;
  5206. }
  5207. if (!jsonProp.dateFormat) {
  5208. jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || "m/d/y";
  5209. }
  5210. if (!jsonProp.fill) {
  5211. jsonProp.fill = false;
  5212. }
  5213. if (!jsonProp.stroke) {
  5214. jsonProp.stroke = false;
  5215. }
  5216. if(!jsonProp.inverseBoolean) {
  5217. jsonProp.inverseBoolean = false;
  5218. }
  5219. if(!jsonProp.directlyEditable && jsonProp.directlyEditable != false) {
  5220. jsonProp.directlyEditable = true;
  5221. }
  5222. if(jsonProp.visible !== false) {
  5223. jsonProp.visible = true;
  5224. }
  5225. if(jsonProp.isList !== true) {
  5226. jsonProp.isList = false;
  5227. if(!jsonProp.list || !(jsonProp.list instanceof Array)) {
  5228. jsonProp.list = [];
  5229. }
  5230. }
  5231. if(!jsonProp.category) {
  5232. if (jsonProp.popular) {
  5233. jsonProp.category = "popular";
  5234. } else {
  5235. jsonProp.category = "others";
  5236. }
  5237. }
  5238. if(!jsonProp.alwaysAppearInMultiselect) {
  5239. jsonProp.alwaysAppearInMultiselect = false;
  5240. }
  5241. if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) {
  5242. if (jsonProp.items && jsonProp.items instanceof Array) {
  5243. jsonProp.items.each((function(jsonItem){
  5244. // why is the item's value used as the key???
  5245. this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this);
  5246. }).bind(this));
  5247. }
  5248. else {
  5249. throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
  5250. }
  5251. // extended by Kerstin (start)
  5252. }
  5253. else
  5254. if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) {
  5255. if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) {
  5256. jsonProp.complexItems.each((function(jsonComplexItem){
  5257. this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this);
  5258. }).bind(this));
  5259. }
  5260. }
  5261. // extended by Kerstin (end)
  5262. },
  5263. getMinForType : function(type) {
  5264. if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {
  5265. return -Math.pow(2,31)
  5266. } else {
  5267. return -Number.MAX_VALUE+1;
  5268. }
  5269. },
  5270. getMaxForType : function(type) {
  5271. if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {
  5272. return Math.pow(2,31)-1
  5273. } else {
  5274. return Number.MAX_VALUE;
  5275. }
  5276. },
  5277. /**
  5278. * @param {ORYX.Core.StencilSet.Property} property
  5279. * @return {Boolean} True, if property has the same namespace and id.
  5280. */
  5281. equals: function(property){
  5282. return (this._namespace === property.namespace() &&
  5283. this.id() === property.id()) ? true : false;
  5284. },
  5285. namespace: function(){
  5286. return this._namespace;
  5287. },
  5288. stencil: function(){
  5289. return this._stencil;
  5290. },
  5291. id: function(){
  5292. return this._jsonProp.id;
  5293. },
  5294. prefix: function(){
  5295. return this._jsonProp.prefix;
  5296. },
  5297. type: function(){
  5298. return this._jsonProp.type;
  5299. },
  5300. inverseBoolean: function() {
  5301. return this._jsonProp.inverseBoolean;
  5302. },
  5303. category: function() {
  5304. return this._jsonProp.category;
  5305. },
  5306. setCategory: function(value) {
  5307. this._jsonProp.category = value;
  5308. },
  5309. directlyEditable: function() {
  5310. return this._jsonProp.directlyEditable;
  5311. },
  5312. visible: function() {
  5313. return this._jsonProp.visible;
  5314. },
  5315. title: function(){
  5316. return ORYX.Core.StencilSet.getTranslation(this._jsonProp, "title");
  5317. },
  5318. value: function(){
  5319. return this._jsonProp.value;
  5320. },
  5321. readonly: function(){
  5322. return this._jsonProp.readonly;
  5323. },
  5324. optional: function(){
  5325. return this._jsonProp.optional;
  5326. },
  5327. description: function(){
  5328. return ORYX.Core.StencilSet.getTranslation(this._jsonProp, "description");
  5329. },
  5330. /**
  5331. * An optional link to a SVG element so that the property affects the
  5332. * graphical representation of the stencil.
  5333. */
  5334. refToView: function(){
  5335. return this._jsonProp.refToView;
  5336. },
  5337. /**
  5338. * If type is integer or float, min is the lower bounds of value.
  5339. */
  5340. min: function(){
  5341. return this._jsonProp.min;
  5342. },
  5343. /**
  5344. * If type ist integer or float, max is the upper bounds of value.
  5345. */
  5346. max: function(){
  5347. return this._jsonProp.max;
  5348. },
  5349. /**
  5350. * If type is float, this method returns if the fill-opacity property should
  5351. * be set.
  5352. * @return {Boolean}
  5353. */
  5354. fillOpacity: function(){
  5355. return this._jsonProp.fillOpacity;
  5356. },
  5357. /**
  5358. * If type is float, this method returns if the stroke-opacity property should
  5359. * be set.
  5360. * @return {Boolean}
  5361. */
  5362. strokeOpacity: function(){
  5363. return this._jsonProp.strokeOpacity;
  5364. },
  5365. /**
  5366. * If type is string or richtext, length is the maximum length of the text.
  5367. * TODO how long can a string be.
  5368. */
  5369. length: function(){
  5370. return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE;
  5371. },
  5372. wrapLines: function(){
  5373. return this._jsonProp.wrapLines;
  5374. },
  5375. /**
  5376. * If type is date, dateFormat specifies the format of the date. The format
  5377. * specification of the ext library is used:
  5378. *
  5379. * Format Output Description
  5380. * ------ ---------- --------------------------------------------------------------
  5381. * d 10 Day of the month, 2 digits with leading zeros
  5382. * D Wed A textual representation of a day, three letters
  5383. * j 10 Day of the month without leading zeros
  5384. * l Wednesday A full textual representation of the day of the week
  5385. * S th English ordinal day of month suffix, 2 chars (use with j)
  5386. * w 3 Numeric representation of the day of the week
  5387. * z 9 The julian date, or day of the year (0-365)
  5388. * W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
  5389. * F January A full textual representation of the month
  5390. * m 01 Numeric representation of a month, with leading zeros
  5391. * M Jan Month name abbreviation, three letters
  5392. * n 1 Numeric representation of a month, without leading zeros
  5393. * t 31 Number of days in the given month
  5394. * L 0 Whether its a leap year (1 if it is a leap year, else 0)
  5395. * Y 2007 A full numeric representation of a year, 4 digits
  5396. * y 07 A two digit representation of a year
  5397. * a pm Lowercase Ante meridiem and Post meridiem
  5398. * A PM Uppercase Ante meridiem and Post meridiem
  5399. * g 3 12-hour format of an hour without leading zeros
  5400. * G 15 24-hour format of an hour without leading zeros
  5401. * h 03 12-hour format of an hour with leading zeros
  5402. * H 15 24-hour format of an hour with leading zeros
  5403. * i 05 Minutes with leading zeros
  5404. * s 01 Seconds, with leading zeros
  5405. * O -0600 Difference to Greenwich time (GMT) in hours
  5406. * T CST Timezone setting of the machine running the code
  5407. * Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
  5408. *
  5409. * Example:
  5410. * F j, Y, g:i a -> January 10, 2007, 3:05 pm
  5411. */
  5412. dateFormat: function(){
  5413. return this._jsonProp.dateFormat;
  5414. },
  5415. /**
  5416. * If type is color, this method returns if the fill property should
  5417. * be set.
  5418. * @return {Boolean}
  5419. */
  5420. fill: function(){
  5421. return this._jsonProp.fill;
  5422. },
  5423. /**
  5424. * Lightness defines the satiation of the color
  5425. * 0 is the pure color
  5426. * 1 is white
  5427. * @return {Integer} lightness
  5428. */
  5429. lightness: function(){
  5430. return this._jsonProp.lightness;
  5431. },
  5432. /**
  5433. * If type is color, this method returns if the stroke property should
  5434. * be set.
  5435. * @return {Boolean}
  5436. */
  5437. stroke: function(){
  5438. return this._jsonProp.stroke;
  5439. },
  5440. /**
  5441. * If type is choice, items is a hash map with all alternative values
  5442. * (PropertyItem objects) with id as keys.
  5443. */
  5444. items: function(){
  5445. return $H(this._items).values();
  5446. },
  5447. item: function(value){
  5448. if (value) {
  5449. return this._items[value.toLowerCase()];
  5450. } else {
  5451. return null;
  5452. }
  5453. },
  5454. toString: function(){
  5455. return "Property " + this.title() + " (" + this.id() + ")";
  5456. },
  5457. complexItems: function(){
  5458. return $H(this._complexItems).values();
  5459. },
  5460. complexItem: function(id){
  5461. if(id) {
  5462. return this._complexItems[id.toLowerCase()];
  5463. } else {
  5464. return null;
  5465. }
  5466. },
  5467. complexAttributeToView: function(){
  5468. return this._jsonProp.complexAttributeToView || "";
  5469. },
  5470. isList: function() {
  5471. return !!this._jsonProp.isList;
  5472. },
  5473. getListItems: function() {
  5474. return this._jsonProp.list;
  5475. },
  5476. /**
  5477. * If type is glossary link, the
  5478. * type of category can be defined where
  5479. * the link only can go to.
  5480. * @return {String} The glossary category id
  5481. */
  5482. linkableType: function(){
  5483. return this._jsonProp.linkableType || "";
  5484. },
  5485. alwaysAppearInMultiselect : function() {
  5486. return this._jsonProp.alwaysAppearInMultiselect;
  5487. },
  5488. popular: function() {
  5489. return this._jsonProp.popular || false;
  5490. },
  5491. setPopular: function() {
  5492. this._jsonProp.popular = true;
  5493. },
  5494. hide: function() {
  5495. this._hidden = true;
  5496. },
  5497. isHidden: function() {
  5498. return this._hidden;
  5499. }
  5500. });
  5501. /*
  5502. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  5503. * License rights for this program may be obtained from Alfresco Software, Ltd.
  5504. * pursuant to a written agreement and any use of this program without such an
  5505. * agreement is prohibited.
  5506. */
  5507. /*
  5508. * All code Copyright 2013 KIS Consultancy all rights reserved
  5509. */
  5510. /**
  5511. * Init namespace
  5512. */
  5513. if(!ORYX) {var ORYX = {};}
  5514. if(!ORYX.Core) {ORYX.Core = {};}
  5515. if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
  5516. /**
  5517. * Class Stencil
  5518. * uses Prototpye 1.5.0
  5519. * uses Inheritance
  5520. */
  5521. ORYX.Core.StencilSet.PropertyItem = Clazz.extend({
  5522. /**
  5523. * Constructor
  5524. */
  5525. construct: function(jsonItem, namespace, property) {
  5526. arguments.callee.$.construct.apply(this, arguments);
  5527. if(!jsonItem) {
  5528. throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined.";
  5529. }
  5530. if(!namespace) {
  5531. throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined.";
  5532. }
  5533. if(!property) {
  5534. throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined.";
  5535. }
  5536. this._jsonItem = jsonItem;
  5537. this._namespace = namespace;
  5538. this._property = property;
  5539. //init all values
  5540. if(!jsonItem.value) {
  5541. throw "ORYX.Core.StencilSet.PropertyItem(construct): Value is not defined.";
  5542. }
  5543. if(this._jsonItem.refToView) {
  5544. if(!(this._jsonItem.refToView instanceof Array)) {
  5545. this._jsonItem.refToView = [this._jsonItem.refToView];
  5546. }
  5547. } else {
  5548. this._jsonItem.refToView = [];
  5549. }
  5550. },
  5551. /**
  5552. * @param {ORYX.Core.StencilSet.PropertyItem} item
  5553. * @return {Boolean} True, if item has the same namespace and id.
  5554. */
  5555. equals: function(item) {
  5556. return (this.property().equals(item.property()) &&
  5557. this.value() === item.value());
  5558. },
  5559. namespace: function() {
  5560. return this._namespace;
  5561. },
  5562. property: function() {
  5563. return this._property;
  5564. },
  5565. value: function() {
  5566. return this._jsonItem.value;
  5567. },
  5568. title: function() {
  5569. return ORYX.Core.StencilSet.getTranslation(this._jsonItem, "title");
  5570. },
  5571. refToView: function() {
  5572. return this._jsonItem.refToView;
  5573. },
  5574. icon: function() {
  5575. return (this._jsonItem.icon) ? this.property().stencil()._source + "icons/" + this._jsonItem.icon : "";
  5576. },
  5577. toString: function() { return "PropertyItem " + this.property() + " (" + this.value() + ")"; }
  5578. });/*
  5579. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  5580. * License rights for this program may be obtained from Alfresco Software, Ltd.
  5581. * pursuant to a written agreement and any use of this program without such an
  5582. * agreement is prohibited.
  5583. */
  5584. /*
  5585. * All code Copyright 2013 KIS Consultancy all rights reserved
  5586. */
  5587. /**
  5588. * Init namespaces
  5589. */
  5590. if(!ORYX) {var ORYX = {};}
  5591. if(!ORYX.Core) {ORYX.Core = {};}
  5592. if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
  5593. /**
  5594. * Class Stencil
  5595. * uses Prototpye 1.5.0
  5596. * uses Inheritance
  5597. */
  5598. ORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({
  5599. /**
  5600. * Constructor
  5601. */
  5602. construct: function(jsonItem, namespace, property) {
  5603. arguments.callee.$.construct.apply(this, arguments);
  5604. if(!jsonItem) {
  5605. throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined.";
  5606. }
  5607. if(!namespace) {
  5608. throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined.";
  5609. }
  5610. if(!property) {
  5611. throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined.";
  5612. }
  5613. this._jsonItem = jsonItem;
  5614. this._namespace = namespace;
  5615. this._property = property;
  5616. this._items = new Hash();
  5617. this._complexItems = new Hash();
  5618. //init all values
  5619. if(!jsonItem.name) {
  5620. throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined.";
  5621. }
  5622. if(!jsonItem.type) {
  5623. throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined.";
  5624. } else {
  5625. jsonItem.type = jsonItem.type.toLowerCase();
  5626. }
  5627. if(jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) {
  5628. if(jsonItem.items && jsonItem.items instanceof Array) {
  5629. jsonItem.items.each((function(item) {
  5630. this._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this);
  5631. }).bind(this));
  5632. } else {
  5633. throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
  5634. }
  5635. } else if(jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) {
  5636. if(jsonItem.complexItems && jsonItem.complexItems instanceof Array) {
  5637. jsonItem.complexItems.each((function(complexItem) {
  5638. this._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this);
  5639. }).bind(this));
  5640. } else {
  5641. throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
  5642. }
  5643. }
  5644. },
  5645. /**
  5646. * @param {ORYX.Core.StencilSet.PropertyItem} item
  5647. * @return {Boolean} True, if item has the same namespace and id.
  5648. */
  5649. equals: function(item) {
  5650. return (this.property().equals(item.property()) &&
  5651. this.name() === item.name());
  5652. },
  5653. namespace: function() {
  5654. return this._namespace;
  5655. },
  5656. property: function() {
  5657. return this._property;
  5658. },
  5659. name: function() {
  5660. return ORYX.Core.StencilSet.getTranslation(this._jsonItem, "name");
  5661. },
  5662. id: function() {
  5663. return this._jsonItem.id;
  5664. },
  5665. type: function() {
  5666. return this._jsonItem.type;
  5667. },
  5668. optional: function() {
  5669. return this._jsonItem.optional;
  5670. },
  5671. width: function() {
  5672. return this._jsonItem.width;
  5673. },
  5674. value: function() {
  5675. return this._jsonItem.value;
  5676. },
  5677. items: function() {
  5678. return this._items.values();
  5679. },
  5680. complexItems: function() {
  5681. return this._complexItems.values();
  5682. },
  5683. disable: function() {
  5684. return this._jsonItem.disable;
  5685. }
  5686. });/*
  5687. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  5688. * License rights for this program may be obtained from Alfresco Software, Ltd.
  5689. * pursuant to a written agreement and any use of this program without such an
  5690. * agreement is prohibited.
  5691. */
  5692. /*
  5693. * All code Copyright 2013 KIS Consultancy all rights reserved
  5694. */
  5695. /**
  5696. * Init namespaces
  5697. */
  5698. if(!ORYX) {var ORYX = {};}
  5699. if(!ORYX.Core) {ORYX.Core = {};}
  5700. if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
  5701. /**
  5702. * Class Rules uses Prototpye 1.5.0 uses Inheritance
  5703. *
  5704. * This class implements the API to check the stencil sets' rules.
  5705. */
  5706. ORYX.Core.StencilSet.Rules = {
  5707. /**
  5708. * Constructor
  5709. */
  5710. construct: function() {
  5711. arguments.callee.$.construct.apply(this, arguments);
  5712. this._stencilSets = [];
  5713. this._stencils = [];
  5714. this._containerStencils = [];
  5715. this._cachedConnectSET = new Hash();
  5716. this._cachedConnectSE = new Hash();
  5717. this._cachedConnectTE = new Hash();
  5718. this._cachedCardSE = new Hash();
  5719. this._cachedCardTE = new Hash();
  5720. this._cachedContainPC = new Hash();
  5721. this._cachedMorphRS = new Hash();
  5722. this._connectionRules = new Hash();
  5723. this._cardinalityRules = new Hash();
  5724. this._containmentRules = new Hash();
  5725. this._morphingRules = new Hash();
  5726. this._layoutRules = new Hash();
  5727. },
  5728. /**
  5729. * Call this method to initialize the rules for a stencil set and all of its
  5730. * active extensions.
  5731. *
  5732. * @param {Object}
  5733. * stencilSet
  5734. */
  5735. initializeRules: function(stencilSet) {
  5736. var existingSS = this._stencilSets.find(function(ss) {
  5737. return (ss.namespace() == stencilSet.namespace());
  5738. });
  5739. if (existingSS) {
  5740. // reinitialize all rules
  5741. var stencilsets = this._stencilSets.clone();
  5742. stencilsets = stencilsets.without(existingSS);
  5743. stencilsets.push(stencilSet);
  5744. this._stencilSets = [];
  5745. this._stencils = [];
  5746. this._containerStencils = [];
  5747. this._cachedConnectSET = new Hash();
  5748. this._cachedConnectSE = new Hash();
  5749. this._cachedConnectTE = new Hash();
  5750. this._cachedCardSE = new Hash();
  5751. this._cachedCardTE = new Hash();
  5752. this._cachedContainPC = new Hash();
  5753. this._cachedMorphRS = new Hash();
  5754. this._connectionRules = new Hash();
  5755. this._cardinalityRules = new Hash();
  5756. this._containmentRules = new Hash();
  5757. this._morphingRules = new Hash();
  5758. this._layoutRules = new Hash();
  5759. stencilsets.each(function(ss){
  5760. this.initializeRules(ss);
  5761. }.bind(this));
  5762. return;
  5763. }
  5764. else {
  5765. this._stencilSets.push(stencilSet);
  5766. var jsonRules = new Hash(stencilSet.jsonRules());
  5767. var namespace = stencilSet.namespace();
  5768. var stencils = stencilSet.stencils();
  5769. stencilSet.extensions().values().each(function(extension) {
  5770. if(extension.rules) {
  5771. if(extension.rules.connectionRules)
  5772. jsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules);
  5773. if(extension.rules.cardinalityRules)
  5774. jsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules);
  5775. if(extension.rules.containmentRules)
  5776. jsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules);
  5777. if(extension.rules.morphingRules)
  5778. jsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules);
  5779. }
  5780. if(extension.stencils)
  5781. stencils = stencils.concat(extension.stencils);
  5782. });
  5783. this._stencils = this._stencils.concat(stencilSet.stencils());
  5784. // init connection rules
  5785. var cr = this._connectionRules;
  5786. if (jsonRules.connectionRules) {
  5787. jsonRules.connectionRules.each((function(rules){
  5788. if (this._isRoleOfOtherNamespace(rules.role)) {
  5789. if (!cr[rules.role]) {
  5790. cr[rules.role] = new Hash();
  5791. }
  5792. }
  5793. else {
  5794. if (!cr[namespace + rules.role])
  5795. cr[namespace + rules.role] = new Hash();
  5796. }
  5797. rules.connects.each((function(connect){
  5798. var toRoles = [];
  5799. if (connect.to) {
  5800. if (!(connect.to instanceof Array)) {
  5801. connect.to = [connect.to];
  5802. }
  5803. connect.to.each((function(to){
  5804. if (this._isRoleOfOtherNamespace(to)) {
  5805. toRoles.push(to);
  5806. }
  5807. else {
  5808. toRoles.push(namespace + to);
  5809. }
  5810. }).bind(this));
  5811. }
  5812. var role, from;
  5813. if (this._isRoleOfOtherNamespace(rules.role))
  5814. role = rules.role;
  5815. else
  5816. role = namespace + rules.role;
  5817. if (this._isRoleOfOtherNamespace(connect.from))
  5818. from = connect.from;
  5819. else
  5820. from = namespace + connect.from;
  5821. if (!cr[role][from])
  5822. cr[role][from] = toRoles;
  5823. else
  5824. cr[role][from] = cr[role][from].concat(toRoles);
  5825. }).bind(this));
  5826. }).bind(this));
  5827. }
  5828. // init cardinality rules
  5829. var cardr = this._cardinalityRules;
  5830. if (jsonRules.cardinalityRules) {
  5831. jsonRules.cardinalityRules.each((function(rules){
  5832. var cardrKey;
  5833. if (this._isRoleOfOtherNamespace(rules.role)) {
  5834. cardrKey = rules.role;
  5835. }
  5836. else {
  5837. cardrKey = namespace + rules.role;
  5838. }
  5839. if (!cardr[cardrKey]) {
  5840. cardr[cardrKey] = {};
  5841. for (i in rules) {
  5842. cardr[cardrKey][i] = rules[i];
  5843. }
  5844. }
  5845. var oe = new Hash();
  5846. if (rules.outgoingEdges) {
  5847. rules.outgoingEdges.each((function(rule){
  5848. if (this._isRoleOfOtherNamespace(rule.role)) {
  5849. oe[rule.role] = rule;
  5850. }
  5851. else {
  5852. oe[namespace + rule.role] = rule;
  5853. }
  5854. }).bind(this));
  5855. }
  5856. cardr[cardrKey].outgoingEdges = oe;
  5857. var ie = new Hash();
  5858. if (rules.incomingEdges) {
  5859. rules.incomingEdges.each((function(rule){
  5860. if (this._isRoleOfOtherNamespace(rule.role)) {
  5861. ie[rule.role] = rule;
  5862. }
  5863. else {
  5864. ie[namespace + rule.role] = rule;
  5865. }
  5866. }).bind(this));
  5867. }
  5868. cardr[cardrKey].incomingEdges = ie;
  5869. }).bind(this));
  5870. }
  5871. // init containment rules
  5872. var conr = this._containmentRules;
  5873. if (jsonRules.containmentRules) {
  5874. jsonRules.containmentRules.each((function(rules){
  5875. var conrKey;
  5876. if (this._isRoleOfOtherNamespace(rules.role)) {
  5877. conrKey = rules.role;
  5878. }
  5879. else {
  5880. this._containerStencils.push(namespace + rules.role);
  5881. conrKey = namespace + rules.role;
  5882. }
  5883. if (!conr[conrKey]) {
  5884. conr[conrKey] = [];
  5885. }
  5886. (rules.contains||[]).each((function(containRole){
  5887. if (this._isRoleOfOtherNamespace(containRole)) {
  5888. conr[conrKey].push(containRole);
  5889. }
  5890. else {
  5891. conr[conrKey].push(namespace + containRole);
  5892. }
  5893. }).bind(this));
  5894. }).bind(this));
  5895. }
  5896. // init morphing rules
  5897. var morphr = this._morphingRules;
  5898. if (jsonRules.morphingRules) {
  5899. jsonRules.morphingRules.each((function(rules){
  5900. var morphrKey;
  5901. if (this._isRoleOfOtherNamespace(rules.role)) {
  5902. morphrKey = rules.role;
  5903. }
  5904. else {
  5905. morphrKey = namespace + rules.role;
  5906. }
  5907. if (!morphr[morphrKey]) {
  5908. morphr[morphrKey] = [];
  5909. }
  5910. if(!rules.preserveBounds) {
  5911. rules.preserveBounds = false;
  5912. }
  5913. rules.baseMorphs.each((function(baseMorphStencilId){
  5914. var morphStencil = this._getStencilById(namespace + baseMorphStencilId);
  5915. if(morphStencil) {
  5916. morphr[morphrKey].push(morphStencil);
  5917. }
  5918. }).bind(this));
  5919. }).bind(this));
  5920. }
  5921. // init layouting rules
  5922. var layoutRules = this._layoutRules;
  5923. if (jsonRules.layoutRules) {
  5924. var getDirections = function(o){
  5925. return {
  5926. "edgeRole":o.edgeRole||undefined,
  5927. "t": o["t"]||1,
  5928. "r": o["r"]||1,
  5929. "b": o["b"]||1,
  5930. "l": o["l"]||1
  5931. }
  5932. }
  5933. jsonRules.layoutRules.each(function(rules){
  5934. var layoutKey;
  5935. if (this._isRoleOfOtherNamespace(rules.role)) {
  5936. layoutKey = rules.role;
  5937. }
  5938. else {
  5939. layoutKey = namespace + rules.role;
  5940. }
  5941. if (!layoutRules[layoutKey]) {
  5942. layoutRules[layoutKey] = {};
  5943. }
  5944. if (rules["in"]){
  5945. layoutRules[layoutKey]["in"] = getDirections(rules["in"]);
  5946. }
  5947. if (rules["ins"]){
  5948. layoutRules[layoutKey]["ins"] = (rules["ins"]||[]).map(function(e){ return getDirections(e) })
  5949. }
  5950. if (rules["out"]) {
  5951. layoutRules[layoutKey]["out"] = getDirections(rules["out"]);
  5952. }
  5953. if (rules["outs"]){
  5954. layoutRules[layoutKey]["outs"] = (rules["outs"]||[]).map(function(e){ return getDirections(e) })
  5955. }
  5956. }.bind(this));
  5957. }
  5958. }
  5959. },
  5960. _getStencilById: function(id) {
  5961. return this._stencils.find(function(stencil) {
  5962. return stencil.id()==id;
  5963. });
  5964. },
  5965. _cacheConnect: function(args) {
  5966. result = this._canConnect(args);
  5967. if (args.sourceStencil && args.targetStencil) {
  5968. var source = this._cachedConnectSET[args.sourceStencil.id()];
  5969. if(!source) {
  5970. source = new Hash();
  5971. this._cachedConnectSET[args.sourceStencil.id()] = source;
  5972. }
  5973. var edge = source[args.edgeStencil.id()];
  5974. if(!edge) {
  5975. edge = new Hash();
  5976. source[args.edgeStencil.id()] = edge;
  5977. }
  5978. edge[args.targetStencil.id()] = result;
  5979. } else if (args.sourceStencil) {
  5980. var source = this._cachedConnectSE[args.sourceStencil.id()];
  5981. if(!source) {
  5982. source = new Hash();
  5983. this._cachedConnectSE[args.sourceStencil.id()] = source;
  5984. }
  5985. source[args.edgeStencil.id()] = result;
  5986. } else {
  5987. var target = this._cachedConnectTE[args.targetStencil.id()];
  5988. if(!target) {
  5989. target = new Hash();
  5990. this._cachedConnectTE[args.targetStencil.id()] = target;
  5991. }
  5992. target[args.edgeStencil.id()] = result;
  5993. }
  5994. return result;
  5995. },
  5996. _cacheCard: function(args) {
  5997. if(args.sourceStencil) {
  5998. var source = this._cachedCardSE[args.sourceStencil.id()]
  5999. if(!source) {
  6000. source = new Hash();
  6001. this._cachedCardSE[args.sourceStencil.id()] = source;
  6002. }
  6003. var max = this._getMaximumNumberOfOutgoingEdge(args);
  6004. if(max == undefined)
  6005. max = -1;
  6006. source[args.edgeStencil.id()] = max;
  6007. }
  6008. if(args.targetStencil) {
  6009. var target = this._cachedCardTE[args.targetStencil.id()]
  6010. if(!target) {
  6011. target = new Hash();
  6012. this._cachedCardTE[args.targetStencil.id()] = target;
  6013. }
  6014. var max = this._getMaximumNumberOfIncomingEdge(args);
  6015. if(max == undefined)
  6016. max = -1;
  6017. target[args.edgeStencil.id()] = max;
  6018. }
  6019. },
  6020. _cacheContain: function(args) {
  6021. var result = [this._canContain(args),
  6022. this._getMaximumOccurrence(args.containingStencil, args.containedStencil)]
  6023. if(result[1] == undefined)
  6024. result[1] = -1;
  6025. var children = this._cachedContainPC[args.containingStencil.id()];
  6026. if(!children) {
  6027. children = new Hash();
  6028. this._cachedContainPC[args.containingStencil.id()] = children;
  6029. }
  6030. children[args.containedStencil.id()] = result;
  6031. return result;
  6032. },
  6033. /**
  6034. * Returns all stencils belonging to a morph group. (calculation result is
  6035. * cached)
  6036. */
  6037. _cacheMorph: function(role) {
  6038. var morphs = this._cachedMorphRS[role];
  6039. if(!morphs) {
  6040. morphs = [];
  6041. if(this._morphingRules.keys().include(role)) {
  6042. morphs = this._stencils.select(function(stencil) {
  6043. return stencil.roles().include(role);
  6044. });
  6045. }
  6046. this._cachedMorphRS[role] = morphs;
  6047. }
  6048. return morphs;
  6049. },
  6050. /** Begin connection rules' methods */
  6051. /**
  6052. *
  6053. * @param {Object}
  6054. * args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined
  6055. * sourceShape: ORYX.Core.Shape | undefined
  6056. *
  6057. * At least sourceStencil or sourceShape has to be specified
  6058. *
  6059. * @return {Array} Array of stencils of edges that can be outgoing edges of
  6060. * the source.
  6061. */
  6062. outgoingEdgeStencils: function(args) {
  6063. // check arguments
  6064. if(!args.sourceShape && !args.sourceStencil) {
  6065. return [];
  6066. }
  6067. // init arguments
  6068. if(args.sourceShape) {
  6069. args.sourceStencil = args.sourceShape.getStencil();
  6070. }
  6071. var _edges = [];
  6072. // test each edge, if it can connect to source
  6073. this._stencils.each((function(stencil) {
  6074. if(stencil.type() === "edge") {
  6075. var newArgs = Object.clone(args);
  6076. newArgs.edgeStencil = stencil;
  6077. if(this.canConnect(newArgs)) {
  6078. _edges.push(stencil);
  6079. }
  6080. }
  6081. }).bind(this));
  6082. return _edges;
  6083. },
  6084. /**
  6085. *
  6086. * @param {Object}
  6087. * args targetStencil: ORYX.Core.StencilSet.Stencil | undefined
  6088. * targetShape: ORYX.Core.Shape | undefined
  6089. *
  6090. * At least targetStencil or targetShape has to be specified
  6091. *
  6092. * @return {Array} Array of stencils of edges that can be incoming edges of
  6093. * the target.
  6094. */
  6095. incomingEdgeStencils: function(args) {
  6096. // check arguments
  6097. if(!args.targetShape && !args.targetStencil) {
  6098. return [];
  6099. }
  6100. // init arguments
  6101. if(args.targetShape) {
  6102. args.targetStencil = args.targetShape.getStencil();
  6103. }
  6104. var _edges = [];
  6105. // test each edge, if it can connect to source
  6106. this._stencils.each((function(stencil) {
  6107. if(stencil.type() === "edge") {
  6108. var newArgs = Object.clone(args);
  6109. newArgs.edgeStencil = stencil;
  6110. if(this.canConnect(newArgs)) {
  6111. _edges.push(stencil);
  6112. }
  6113. }
  6114. }).bind(this));
  6115. return _edges;
  6116. },
  6117. /**
  6118. *
  6119. * @param {Object}
  6120. * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined
  6121. * edgeShape: ORYX.Core.Edge | undefined targetStencil:
  6122. * ORYX.Core.StencilSet.Stencil | undefined targetShape:
  6123. * ORYX.Core.Node | undefined
  6124. *
  6125. * At least edgeStencil or edgeShape has to be specified!!!
  6126. *
  6127. * @return {Array} Returns an array of stencils that can be source of the
  6128. * specified edge.
  6129. */
  6130. sourceStencils: function(args) {
  6131. // check arguments
  6132. if(!args ||
  6133. !args.edgeShape && !args.edgeStencil) {
  6134. return [];
  6135. }
  6136. // init arguments
  6137. if(args.targetShape) {
  6138. args.targetStencil = args.targetShape.getStencil();
  6139. }
  6140. if(args.edgeShape) {
  6141. args.edgeStencil = args.edgeShape.getStencil();
  6142. }
  6143. var _sources = [];
  6144. // check each stencil, if it can be a source
  6145. this._stencils.each((function(stencil) {
  6146. var newArgs = Object.clone(args);
  6147. newArgs.sourceStencil = stencil;
  6148. if(this.canConnect(newArgs)) {
  6149. _sources.push(stencil);
  6150. }
  6151. }).bind(this));
  6152. return _sources;
  6153. },
  6154. /**
  6155. *
  6156. * @param {Object}
  6157. * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined
  6158. * edgeShape: ORYX.Core.Edge | undefined sourceStencil:
  6159. * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
  6160. * ORYX.Core.Node | undefined
  6161. *
  6162. * At least edgeStencil or edgeShape has to be specified!!!
  6163. *
  6164. * @return {Array} Returns an array of stencils that can be target of the
  6165. * specified edge.
  6166. */
  6167. targetStencils: function(args) {
  6168. // check arguments
  6169. if(!args ||
  6170. !args.edgeShape && !args.edgeStencil) {
  6171. return [];
  6172. }
  6173. // init arguments
  6174. if(args.sourceShape) {
  6175. args.sourceStencil = args.sourceShape.getStencil();
  6176. }
  6177. if(args.edgeShape) {
  6178. args.edgeStencil = args.edgeShape.getStencil();
  6179. }
  6180. var _targets = [];
  6181. // check stencil, if it can be a target
  6182. this._stencils.each((function(stencil) {
  6183. var newArgs = Object.clone(args);
  6184. newArgs.targetStencil = stencil;
  6185. if(this.canConnect(newArgs)) {
  6186. _targets.push(stencil);
  6187. }
  6188. }).bind(this));
  6189. return _targets;
  6190. },
  6191. /**
  6192. *
  6193. * @param {Object}
  6194. * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:
  6195. * ORYX.Core.Edge |undefined sourceStencil:
  6196. * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
  6197. * ORYX.Core.Node |undefined targetStencil:
  6198. * ORYX.Core.StencilSet.Stencil | undefined targetShape:
  6199. * ORYX.Core.Node |undefined
  6200. *
  6201. * At least source or target has to be specified!!!
  6202. *
  6203. * @return {Boolean} Returns, if the edge can connect source and target.
  6204. */
  6205. canConnect: function(args) {
  6206. // check arguments
  6207. if(!args ||
  6208. (!args.sourceShape && !args.sourceStencil &&
  6209. !args.targetShape && !args.targetStencil) ||
  6210. !args.edgeShape && !args.edgeStencil) {
  6211. return false;
  6212. }
  6213. // init arguments
  6214. if(args.sourceShape) {
  6215. args.sourceStencil = args.sourceShape.getStencil();
  6216. }
  6217. if(args.targetShape) {
  6218. args.targetStencil = args.targetShape.getStencil();
  6219. }
  6220. if(args.edgeShape) {
  6221. args.edgeStencil = args.edgeShape.getStencil();
  6222. }
  6223. var result;
  6224. if(args.sourceStencil && args.targetStencil) {
  6225. var source = this._cachedConnectSET[args.sourceStencil.id()];
  6226. if(!source)
  6227. result = this._cacheConnect(args);
  6228. else {
  6229. var edge = source[args.edgeStencil.id()];
  6230. if(!edge)
  6231. result = this._cacheConnect(args);
  6232. else {
  6233. var target = edge[args.targetStencil.id()];
  6234. if(target == undefined)
  6235. result = this._cacheConnect(args);
  6236. else
  6237. result = target;
  6238. }
  6239. }
  6240. } else if (args.sourceStencil) {
  6241. var source = this._cachedConnectSE[args.sourceStencil.id()];
  6242. if(!source)
  6243. result = this._cacheConnect(args);
  6244. else {
  6245. var edge = source[args.edgeStencil.id()];
  6246. if(edge == undefined)
  6247. result = this._cacheConnect(args);
  6248. else
  6249. result = edge;
  6250. }
  6251. } else { // args.targetStencil
  6252. var target = this._cachedConnectTE[args.targetStencil.id()];
  6253. if(!target)
  6254. result = this._cacheConnect(args);
  6255. else {
  6256. var edge = target[args.edgeStencil.id()];
  6257. if(edge == undefined)
  6258. result = this._cacheConnect(args);
  6259. else
  6260. result = edge;
  6261. }
  6262. }
  6263. // check cardinality
  6264. if (result) {
  6265. if(args.sourceShape) {
  6266. var source = this._cachedCardSE[args.sourceStencil.id()];
  6267. if(!source) {
  6268. this._cacheCard(args);
  6269. source = this._cachedCardSE[args.sourceStencil.id()];
  6270. }
  6271. var max = source[args.edgeStencil.id()];
  6272. if(max == undefined) {
  6273. this._cacheCard(args);
  6274. }
  6275. max = source[args.edgeStencil.id()];
  6276. if(max != -1) {
  6277. result = args.sourceShape.getOutgoingShapes().all(function(cs) {
  6278. if((cs.getStencil().id() === args.edgeStencil.id()) &&
  6279. ((args.edgeShape) ? cs !== args.edgeShape : true)) {
  6280. max--;
  6281. return (max > 0) ? true : false;
  6282. } else {
  6283. return true;
  6284. }
  6285. });
  6286. }
  6287. }
  6288. if (args.targetShape) {
  6289. var target = this._cachedCardTE[args.targetStencil.id()];
  6290. if(!target) {
  6291. this._cacheCard(args);
  6292. target = this._cachedCardTE[args.targetStencil.id()];
  6293. }
  6294. var max = target[args.edgeStencil.id()];
  6295. if(max == undefined) {
  6296. this._cacheCard(args);
  6297. }
  6298. max = target[args.edgeStencil.id()];
  6299. if(max != -1) {
  6300. result = args.targetShape.getIncomingShapes().all(function(cs){
  6301. if ((cs.getStencil().id() === args.edgeStencil.id()) &&
  6302. ((args.edgeShape) ? cs !== args.edgeShape : true)) {
  6303. max--;
  6304. return (max > 0) ? true : false;
  6305. }
  6306. else {
  6307. return true;
  6308. }
  6309. });
  6310. }
  6311. }
  6312. }
  6313. return result;
  6314. },
  6315. /**
  6316. *
  6317. * @param {Object}
  6318. * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:
  6319. * ORYX.Core.Edge |undefined sourceStencil:
  6320. * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
  6321. * ORYX.Core.Node |undefined targetStencil:
  6322. * ORYX.Core.StencilSet.Stencil | undefined targetShape:
  6323. * ORYX.Core.Node |undefined
  6324. *
  6325. * At least source or target has to be specified!!!
  6326. *
  6327. * @return {Boolean} Returns, if the edge can connect source and target.
  6328. */
  6329. _canConnect: function(args) {
  6330. // check arguments
  6331. if(!args ||
  6332. (!args.sourceShape && !args.sourceStencil &&
  6333. !args.targetShape && !args.targetStencil) ||
  6334. !args.edgeShape && !args.edgeStencil) {
  6335. return false;
  6336. }
  6337. // init arguments
  6338. if(args.sourceShape) {
  6339. args.sourceStencil = args.sourceShape.getStencil();
  6340. }
  6341. if(args.targetShape) {
  6342. args.targetStencil = args.targetShape.getStencil();
  6343. }
  6344. if(args.edgeShape) {
  6345. args.edgeStencil = args.edgeShape.getStencil();
  6346. }
  6347. // 1. check connection rules
  6348. var resultCR;
  6349. // get all connection rules for this edge
  6350. var edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil);
  6351. // check connection rules, if the source can be connected to the target
  6352. // with the specified edge.
  6353. if(edgeRules.keys().length === 0) {
  6354. resultCR = false;
  6355. } else {
  6356. if(args.sourceStencil) {
  6357. resultCR = args.sourceStencil.roles().any(function(sourceRole) {
  6358. var targetRoles = edgeRules[sourceRole];
  6359. if(!targetRoles) {return false;}
  6360. if(args.targetStencil) {
  6361. return (targetRoles.any(function(targetRole) {
  6362. return args.targetStencil.roles().member(targetRole);
  6363. }));
  6364. } else {
  6365. return true;
  6366. }
  6367. });
  6368. } else { // !args.sourceStencil -> there is args.targetStencil
  6369. resultCR = edgeRules.values().any(function(targetRoles) {
  6370. return args.targetStencil.roles().any(function(targetRole) {
  6371. return targetRoles.member(targetRole);
  6372. });
  6373. });
  6374. }
  6375. }
  6376. return resultCR;
  6377. },
  6378. /** End connection rules' methods */
  6379. /** Begin containment rules' methods */
  6380. isContainer: function(shape) {
  6381. return this._containerStencils.member(shape.getStencil().id());
  6382. },
  6383. /**
  6384. *
  6385. * @param {Object}
  6386. * args containingStencil: ORYX.Core.StencilSet.Stencil
  6387. * containingShape: ORYX.Core.AbstractShape containedStencil:
  6388. * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape
  6389. */
  6390. canContain: function(args) {
  6391. if(!args ||
  6392. !args.containingStencil && !args.containingShape ||
  6393. !args.containedStencil && !args.containedShape) {
  6394. return false;
  6395. }
  6396. // init arguments
  6397. if(args.containedShape) {
  6398. args.containedStencil = args.containedShape.getStencil();
  6399. }
  6400. if(args.containingShape) {
  6401. args.containingStencil = args.containingShape.getStencil();
  6402. }
  6403. //if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge')
  6404. // return false;
  6405. if(args.containedStencil.type() == 'edge')
  6406. return false;
  6407. var childValues;
  6408. var parent = this._cachedContainPC[args.containingStencil.id()];
  6409. if(!parent)
  6410. childValues = this._cacheContain(args);
  6411. else {
  6412. childValues = parent[args.containedStencil.id()];
  6413. if(!childValues)
  6414. childValues = this._cacheContain(args);
  6415. }
  6416. if(!childValues[0])
  6417. return false;
  6418. else if (childValues[1] == -1)
  6419. return true;
  6420. else {
  6421. if(args.containingShape) {
  6422. var max = childValues[1];
  6423. return args.containingShape.getChildShapes(false).all(function(as) {
  6424. if(as.getStencil().id() === args.containedStencil.id()) {
  6425. max--;
  6426. return (max > 0) ? true : false;
  6427. } else {
  6428. return true;
  6429. }
  6430. });
  6431. } else {
  6432. return true;
  6433. }
  6434. }
  6435. },
  6436. /**
  6437. *
  6438. * @param {Object}
  6439. * args containingStencil: ORYX.Core.StencilSet.Stencil
  6440. * containingShape: ORYX.Core.AbstractShape containedStencil:
  6441. * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape
  6442. */
  6443. _canContain: function(args) {
  6444. if(!args ||
  6445. !args.containingStencil && !args.containingShape ||
  6446. !args.containedStencil && !args.containedShape) {
  6447. return false;
  6448. }
  6449. // init arguments
  6450. if(args.containedShape) {
  6451. args.containedStencil = args.containedShape.getStencil();
  6452. }
  6453. if(args.containingShape) {
  6454. args.containingStencil = args.containingShape.getStencil();
  6455. }
  6456. // if(args.containingShape) {
  6457. // if(args.containingShape instanceof ORYX.Core.Edge) {
  6458. // // edges cannot contain other shapes
  6459. // return false;
  6460. // }
  6461. // }
  6462. var result;
  6463. // check containment rules
  6464. result = args.containingStencil.roles().any((function(role) {
  6465. var roles = this._containmentRules[role];
  6466. if(roles) {
  6467. return roles.any(function(role) {
  6468. return args.containedStencil.roles().member(role);
  6469. });
  6470. } else {
  6471. return false;
  6472. }
  6473. }).bind(this));
  6474. return result;
  6475. },
  6476. /** End containment rules' methods */
  6477. /** Begin morphing rules' methods */
  6478. /**
  6479. *
  6480. * @param {Object}
  6481. * args
  6482. * stencil: ORYX.Core.StencilSet.Stencil | undefined
  6483. * shape: ORYX.Core.Shape | undefined
  6484. *
  6485. * At least stencil or shape has to be specified
  6486. *
  6487. * @return {Array} Array of stencils that the passed stencil/shape can be
  6488. * transformed to (including the current stencil itself)
  6489. */
  6490. morphStencils: function(args) {
  6491. // check arguments
  6492. if(!args.stencil && !args.shape) {
  6493. return [];
  6494. }
  6495. // init arguments
  6496. if(args.shape) {
  6497. args.stencil = args.shape.getStencil();
  6498. }
  6499. var _morphStencils = [];
  6500. args.stencil.roles().each(function(role) {
  6501. this._cacheMorph(role).each(function(stencil) {
  6502. _morphStencils.push(stencil);
  6503. })
  6504. }.bind(this));
  6505. var baseMorphs = this.baseMorphs();
  6506. // BaseMorphs should be in the front of the array
  6507. _morphStencils = _morphStencils.uniq().sort(function(a,b){ return baseMorphs.include(a)&&!baseMorphs.include(b) ? -1 : (baseMorphs.include(b)&&!baseMorphs.include(a) ? 1 : 0)})
  6508. return _morphStencils;
  6509. },
  6510. /**
  6511. * @return {Array} An array of all base morph stencils
  6512. */
  6513. baseMorphs: function() {
  6514. var _baseMorphs = [];
  6515. this._morphingRules.each(function(pair) {
  6516. pair.value.each(function(baseMorph) {
  6517. _baseMorphs.push(baseMorph);
  6518. });
  6519. });
  6520. return _baseMorphs;
  6521. },
  6522. /**
  6523. * Returns true if there are morphing rules defines
  6524. * @return {boolean}
  6525. */
  6526. containsMorphingRules: function(){
  6527. return this._stencilSets.any(function(ss){ return !!ss.jsonRules().morphingRules});
  6528. },
  6529. /**
  6530. *
  6531. * @param {Object}
  6532. * args
  6533. * sourceStencil:
  6534. * ORYX.Core.StencilSet.Stencil | undefined
  6535. * sourceShape:
  6536. * ORYX.Core.Node |undefined
  6537. * targetStencil:
  6538. * ORYX.Core.StencilSet.Stencil | undefined
  6539. * targetShape:
  6540. * ORYX.Core.Node |undefined
  6541. *
  6542. *
  6543. * @return {Stencil} Returns, the stencil for the connecting edge
  6544. * or null if connection is not possible
  6545. */
  6546. connectMorph: function(args) {
  6547. // check arguments
  6548. if(!args ||
  6549. (!args.sourceShape && !args.sourceStencil &&
  6550. !args.targetShape && !args.targetStencil)) {
  6551. return false;
  6552. }
  6553. // init arguments
  6554. if(args.sourceShape) {
  6555. args.sourceStencil = args.sourceShape.getStencil();
  6556. }
  6557. if(args.targetShape) {
  6558. args.targetStencil = args.targetShape.getStencil();
  6559. }
  6560. var incoming = this.incomingEdgeStencils(args);
  6561. var outgoing = this.outgoingEdgeStencils(args);
  6562. var edgeStencils = incoming.select(function(e) { return outgoing.member(e); }); // intersection of sets
  6563. var baseEdgeStencils = this.baseMorphs().select(function(e) { return edgeStencils.member(e); }); // again: intersection of sets
  6564. if(baseEdgeStencils.size()>0)
  6565. return baseEdgeStencils[0]; // return any of the possible base morphs
  6566. else if(edgeStencils.size()>0)
  6567. return edgeStencils[0]; // return any of the possible stencils
  6568. return null; //connection not possible
  6569. },
  6570. /**
  6571. * Return true if the stencil should be located in the shape menu
  6572. * @param {ORYX.Core.StencilSet.Stencil} morph
  6573. * @return {Boolean} Returns true if the morphs in the morph group of the
  6574. * specified morph shall be displayed in the shape menu
  6575. */
  6576. showInShapeMenu: function(stencil) {
  6577. return this._stencilSets.any(function(ss){
  6578. return ss.jsonRules().morphingRules
  6579. .any(function(r){
  6580. return stencil.roles().include(ss.namespace() + r.role)
  6581. && r.showInShapeMenu !== false;
  6582. })
  6583. });
  6584. },
  6585. preserveBounds: function(stencil) {
  6586. return this._stencilSets.any(function(ss) {
  6587. return ss.jsonRules().morphingRules.any(function(r) {
  6588. return stencil.roles().include(ss.namespace() + r.role)
  6589. && r.preserveBounds;
  6590. })
  6591. })
  6592. },
  6593. /** End morphing rules' methods */
  6594. /** Begin layouting rules' methods */
  6595. /**
  6596. * Returns a set on "in" and "out" layouting rules for a given shape
  6597. * @param {Object} shape
  6598. * @param {Object} edgeShape (Optional)
  6599. * @return {Object} "in" and "out" with a default value of {"t":1, "r":1, "b":1, "r":1} if not specified in the json
  6600. */
  6601. getLayoutingRules : function(shape, edgeShape){
  6602. if (!shape||!(shape instanceof ORYX.Core.Shape)){ return }
  6603. var layout = {"in":{},"out":{}};
  6604. var parseValues = function(o, v){
  6605. if (o && o[v]){
  6606. ["t","r","b","l"].each(function(d){
  6607. layout[v][d]=Math.max(o[v][d],layout[v][d]||0);
  6608. });
  6609. }
  6610. if (o && o[v+"s"] instanceof Array){
  6611. ["t","r","b","l"].each(function(d){
  6612. var defaultRule = o[v+"s"].find(function(e){ return !e.edgeRole });
  6613. var edgeRule;
  6614. if (edgeShape instanceof ORYX.Core.Edge) {
  6615. edgeRule = o[v + "s"].find(function(e){return this._hasRole(edgeShape, e.edgeRole) }.bind(this));
  6616. }
  6617. layout[v][d]=Math.max(edgeRule?edgeRule[d]:defaultRule[d],layout[v][d]||0);
  6618. }.bind(this));
  6619. }
  6620. }.bind(this)
  6621. // For each role
  6622. shape.getStencil().roles().each(function(role) {
  6623. // check if there are layout information
  6624. if (this._layoutRules[role]){
  6625. // if so, parse those information to the 'layout' variable
  6626. parseValues(this._layoutRules[role], "in");
  6627. parseValues(this._layoutRules[role], "out");
  6628. }
  6629. }.bind(this));
  6630. // Make sure, that every attribute has an value,
  6631. // otherwise set 1
  6632. ["in","out"].each(function(v){
  6633. ["t","r","b","l"].each(function(d){
  6634. layout[v][d]=layout[v][d]!==undefined?layout[v][d]:1;
  6635. });
  6636. })
  6637. return layout;
  6638. },
  6639. /** End layouting rules' methods */
  6640. /** Helper methods */
  6641. /**
  6642. * Checks wether a shape contains the given role or the role is equal the stencil id
  6643. * @param {ORYX.Core.Shape} shape
  6644. * @param {String} role
  6645. */
  6646. _hasRole: function(shape, role){
  6647. if (!(shape instanceof ORYX.Core.Shape)||!role){ return }
  6648. var isRole = shape.getStencil().roles().any(function(r){ return r == role});
  6649. return isRole || shape.getStencil().id() == (shape.getStencil().namespace()+role);
  6650. },
  6651. /**
  6652. *
  6653. * @param {String}
  6654. * role
  6655. *
  6656. * @return {Array} Returns an array of stencils that can act as role.
  6657. */
  6658. _stencilsWithRole: function(role) {
  6659. return this._stencils.findAll(function(stencil) {
  6660. return (stencil.roles().member(role)) ? true : false;
  6661. });
  6662. },
  6663. /**
  6664. *
  6665. * @param {String}
  6666. * role
  6667. *
  6668. * @return {Array} Returns an array of stencils that can act as role and
  6669. * have the type 'edge'.
  6670. */
  6671. _edgesWithRole: function(role) {
  6672. return this._stencils.findAll(function(stencil) {
  6673. return (stencil.roles().member(role) && stencil.type() === "edge") ? true : false;
  6674. });
  6675. },
  6676. /**
  6677. *
  6678. * @param {String}
  6679. * role
  6680. *
  6681. * @return {Array} Returns an array of stencils that can act as role and
  6682. * have the type 'node'.
  6683. */
  6684. _nodesWithRole: function(role) {
  6685. return this._stencils.findAll(function(stencil) {
  6686. return (stencil.roles().member(role) && stencil.type() === "node") ? true : false;
  6687. });
  6688. },
  6689. /**
  6690. *
  6691. * @param {ORYX.Core.StencilSet.Stencil}
  6692. * parent
  6693. * @param {ORYX.Core.StencilSet.Stencil}
  6694. * child
  6695. *
  6696. * @returns {Boolean} Returns the maximum occurrence of shapes of the
  6697. * stencil's type inside the parent.
  6698. */
  6699. _getMaximumOccurrence: function(parent, child) {
  6700. var max;
  6701. child.roles().each((function(role) {
  6702. var cardRule = this._cardinalityRules[role];
  6703. if(cardRule && cardRule.maximumOccurrence) {
  6704. if(max) {
  6705. max = Math.min(max, cardRule.maximumOccurrence);
  6706. } else {
  6707. max = cardRule.maximumOccurrence;
  6708. }
  6709. }
  6710. }).bind(this));
  6711. return max;
  6712. },
  6713. /**
  6714. *
  6715. * @param {Object}
  6716. * args sourceStencil: ORYX.Core.Node edgeStencil:
  6717. * ORYX.Core.StencilSet.Stencil
  6718. *
  6719. * @return {Boolean} Returns, the maximum number of outgoing edges of the
  6720. * type specified by edgeStencil of the sourceShape.
  6721. */
  6722. _getMaximumNumberOfOutgoingEdge: function(args) {
  6723. if(!args ||
  6724. !args.sourceStencil ||
  6725. !args.edgeStencil) {
  6726. return false;
  6727. }
  6728. var max;
  6729. args.sourceStencil.roles().each((function(role) {
  6730. var cardRule = this._cardinalityRules[role];
  6731. if(cardRule && cardRule.outgoingEdges) {
  6732. args.edgeStencil.roles().each(function(edgeRole) {
  6733. var oe = cardRule.outgoingEdges[edgeRole];
  6734. if(oe && oe.maximum) {
  6735. if(max) {
  6736. max = Math.min(max, oe.maximum);
  6737. } else {
  6738. max = oe.maximum;
  6739. }
  6740. }
  6741. });
  6742. }
  6743. }).bind(this));
  6744. return max;
  6745. },
  6746. /**
  6747. *
  6748. * @param {Object}
  6749. * args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil:
  6750. * ORYX.Core.StencilSet.Stencil
  6751. *
  6752. * @return {Boolean} Returns the maximum number of incoming edges of the
  6753. * type specified by edgeStencil of the targetShape.
  6754. */
  6755. _getMaximumNumberOfIncomingEdge: function(args) {
  6756. if(!args ||
  6757. !args.targetStencil ||
  6758. !args.edgeStencil) {
  6759. return false;
  6760. }
  6761. var max;
  6762. args.targetStencil.roles().each((function(role) {
  6763. var cardRule = this._cardinalityRules[role];
  6764. if(cardRule && cardRule.incomingEdges) {
  6765. args.edgeStencil.roles().each(function(edgeRole) {
  6766. var ie = cardRule.incomingEdges[edgeRole];
  6767. if(ie && ie.maximum) {
  6768. if(max) {
  6769. max = Math.min(max, ie.maximum);
  6770. } else {
  6771. max = ie.maximum;
  6772. }
  6773. }
  6774. });
  6775. }
  6776. }).bind(this));
  6777. return max;
  6778. },
  6779. /**
  6780. *
  6781. * @param {ORYX.Core.StencilSet.Stencil}
  6782. * edgeStencil
  6783. *
  6784. * @return {Hash} Returns a hash map of all connection rules for
  6785. * edgeStencil.
  6786. */
  6787. _getConnectionRulesOfEdgeStencil: function(edgeStencil) {
  6788. var edgeRules = new Hash();
  6789. edgeStencil.roles().each((function(role) {
  6790. if(this._connectionRules[role]) {
  6791. this._connectionRules[role].each(function(cr) {
  6792. if(edgeRules[cr.key]) {
  6793. edgeRules[cr.key] = edgeRules[cr.key].concat(cr.value);
  6794. } else {
  6795. edgeRules[cr.key] = cr.value;
  6796. }
  6797. });
  6798. }
  6799. }).bind(this));
  6800. return edgeRules;
  6801. },
  6802. _isRoleOfOtherNamespace: function(role) {
  6803. return (role.indexOf("#") > 0);
  6804. },
  6805. toString: function() { return "Rules"; }
  6806. }
  6807. ORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules);
  6808. /*
  6809. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  6810. * License rights for this program may be obtained from Alfresco Software, Ltd.
  6811. * pursuant to a written agreement and any use of this program without such an
  6812. * agreement is prohibited.
  6813. */
  6814. /*
  6815. * All code Copyright 2013 KIS Consultancy all rights reserved
  6816. */
  6817. /**
  6818. * Init namespace
  6819. */
  6820. if (!ORYX) {
  6821. var ORYX = {};
  6822. }
  6823. if (!ORYX.Core) {
  6824. ORYX.Core = {};
  6825. }
  6826. if (!ORYX.Core.StencilSet) {
  6827. ORYX.Core.StencilSet = {};
  6828. }
  6829. /**
  6830. * This class represents a stencil set. It offers methods for accessing
  6831. * the attributes of the stencil set description JSON file and the stencil set's
  6832. * stencils.
  6833. */
  6834. ORYX.Core.StencilSet.StencilSet = Clazz.extend({
  6835. /**
  6836. * Constructor
  6837. * @param source {URL} A reference to the stencil set specification.
  6838. *
  6839. */
  6840. construct: function(source, modelMetaData, editorId){
  6841. arguments.callee.$.construct.apply(this, arguments);
  6842. if (!source) {
  6843. throw "ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined.";
  6844. }
  6845. if (source.endsWith("/")) {
  6846. source = source.substr(0, source.length - 1);
  6847. }
  6848. this._extensions = new Hash();
  6849. this._source = source;
  6850. this._baseUrl = source.substring(0, source.lastIndexOf("/") + 1);
  6851. this._jsonObject = {};
  6852. this._stencils = new Hash();
  6853. this._availableStencils = new Hash();
  6854. if(ORYX.CONFIG.BACKEND_SWITCH) {
  6855. this._baseUrl = "editor/stencilsets/bpmn2.0/";
  6856. this._source = "stencilsets/bpmn2.0/bpmn2.0.json";
  6857. new Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(), {
  6858. asynchronous: false,
  6859. method: 'get',
  6860. onSuccess: this._init.bind(this),
  6861. onFailure: this._cancelInit.bind(this)
  6862. });
  6863. } else {
  6864. new Ajax.Request(source, {
  6865. asynchronous: false,
  6866. method: 'get',
  6867. onSuccess: this._init.bind(this),
  6868. onFailure: this._cancelInit.bind(this)
  6869. });
  6870. }
  6871. if (this.errornous)
  6872. throw "Loading stencil set " + source + " failed.";
  6873. },
  6874. /**
  6875. * Finds a root stencil in this stencil set. There may be many of these. If
  6876. * there are, the first one found will be used. In Firefox, this is the
  6877. * topmost definition in the stencil set description file.
  6878. */
  6879. findRootStencilName: function(){
  6880. // find any stencil that may be root.
  6881. var rootStencil = this._stencils.values().find(function(stencil){
  6882. return stencil._jsonStencil.mayBeRoot
  6883. });
  6884. // if there is none, just guess the first.
  6885. if (!rootStencil) {
  6886. ORYX.Log.warn("Did not find any stencil that may be root. Taking a guess.");
  6887. rootStencil = this._stencils.values()[0];
  6888. }
  6889. // return its id.
  6890. return rootStencil.id();
  6891. },
  6892. /**
  6893. * @param {ORYX.Core.StencilSet.StencilSet} stencilSet
  6894. * @return {Boolean} True, if stencil set has the same namespace.
  6895. */
  6896. equals: function(stencilSet){
  6897. return (this.namespace() === stencilSet.namespace());
  6898. },
  6899. /**
  6900. *
  6901. * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils
  6902. * that could be (in)direct child of that stencil.
  6903. */
  6904. stencils: function(rootStencil, rules, sortByGroup){
  6905. if(rootStencil && rules) {
  6906. var stencils = this._availableStencils.values();
  6907. var containers = [rootStencil];
  6908. var checkedContainers = [];
  6909. var result = [];
  6910. while (containers.size() > 0) {
  6911. var container = containers.pop();
  6912. checkedContainers.push(container);
  6913. var children = stencils.findAll(function(stencil){
  6914. var args = {
  6915. containingStencil: container,
  6916. containedStencil: stencil
  6917. };
  6918. return rules.canContain(args);
  6919. });
  6920. for(var i = 0; i < children.size(); i++) {
  6921. if (!checkedContainers.member(children[i])) {
  6922. containers.push(children[i]);
  6923. }
  6924. }
  6925. result = result.concat(children).uniq();
  6926. }
  6927. // Sort the result to the origin order
  6928. result = result.sortBy(function(stencil) {
  6929. return stencils.indexOf(stencil);
  6930. });
  6931. if(sortByGroup) {
  6932. result = result.sortBy(function(stencil) {
  6933. return stencil.groups().first();
  6934. });
  6935. }
  6936. var edges = stencils.findAll(function(stencil) {
  6937. return stencil.type() == "edge";
  6938. });
  6939. result = result.concat(edges);
  6940. return result;
  6941. } else {
  6942. if(sortByGroup) {
  6943. return this._availableStencils.values().sortBy(function(stencil) {
  6944. return stencil.groups().first();
  6945. });
  6946. } else {
  6947. return this._availableStencils.values();
  6948. }
  6949. }
  6950. },
  6951. nodes: function(){
  6952. return this._availableStencils.values().findAll(function(stencil){
  6953. return (stencil.type() === 'node')
  6954. });
  6955. },
  6956. edges: function(){
  6957. return this._availableStencils.values().findAll(function(stencil){
  6958. return (stencil.type() === 'edge')
  6959. });
  6960. },
  6961. stencil: function(id){
  6962. return this._stencils[id];
  6963. },
  6964. title: function(){
  6965. return ORYX.Core.StencilSet.getTranslation(this._jsonObject, "title");
  6966. },
  6967. description: function(){
  6968. return ORYX.Core.StencilSet.getTranslation(this._jsonObject, "description");
  6969. },
  6970. namespace: function(){
  6971. return this._jsonObject ? this._jsonObject.namespace : null;
  6972. },
  6973. jsonRules: function(){
  6974. return this._jsonObject ? this._jsonObject.rules : null;
  6975. },
  6976. source: function(){
  6977. return this._source;
  6978. },
  6979. extensions: function() {
  6980. return this._extensions;
  6981. },
  6982. addExtension: function(url) {
  6983. new Ajax.Request(url, {
  6984. method: 'GET',
  6985. asynchronous: false,
  6986. onSuccess: (function(transport) {
  6987. this.addExtensionDirectly(transport.responseText);
  6988. }).bind(this),
  6989. onFailure: (function(transport) {
  6990. ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport);
  6991. }).bind(this),
  6992. onException: (function(transport) {
  6993. ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport);
  6994. }).bind(this)
  6995. });
  6996. },
  6997. addExtensionDirectly: function(str){
  6998. try {
  6999. eval("var jsonExtension = " + str);
  7000. if(!(jsonExtension["extends"].endsWith("#")))
  7001. jsonExtension["extends"] += "#";
  7002. if(jsonExtension["extends"] == this.namespace()) {
  7003. this._extensions[jsonExtension.namespace] = jsonExtension;
  7004. var defaultPosition = this._stencils.keys().size();
  7005. //load new stencils
  7006. if(jsonExtension.stencils) {
  7007. $A(jsonExtension.stencils).each(function(stencil) {
  7008. defaultPosition++;
  7009. var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition);
  7010. this._stencils[oStencil.id()] = oStencil;
  7011. this._availableStencils[oStencil.id()] = oStencil;
  7012. }.bind(this));
  7013. }
  7014. //load additional properties
  7015. if (jsonExtension.properties) {
  7016. var stencils = this._stencils.values();
  7017. stencils.each(function(stencil){
  7018. var roles = stencil.roles();
  7019. jsonExtension.properties.each(function(prop){
  7020. prop.roles.any(function(role){
  7021. role = jsonExtension["extends"] + role;
  7022. if (roles.member(role)) {
  7023. prop.properties.each(function(property){
  7024. stencil.addProperty(property, jsonExtension.namespace);
  7025. });
  7026. return true;
  7027. }
  7028. else
  7029. return false;
  7030. })
  7031. })
  7032. }.bind(this));
  7033. }
  7034. //remove stencil properties
  7035. if(jsonExtension.removeproperties) {
  7036. jsonExtension.removeproperties.each(function(remprop) {
  7037. var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil);
  7038. if(stencil) {
  7039. remprop.properties.each(function(propId) {
  7040. stencil.removeProperty(propId);
  7041. });
  7042. }
  7043. }.bind(this));
  7044. }
  7045. //remove stencils
  7046. if(jsonExtension.removestencils) {
  7047. $A(jsonExtension.removestencils).each(function(remstencil) {
  7048. delete this._availableStencils[jsonExtension["extends"] + remstencil];
  7049. }.bind(this));
  7050. }
  7051. }
  7052. } catch (e) {
  7053. ORYX.Log.debug("StencilSet.addExtension: Something went wrong when initialising the stencil set extension. " + e);
  7054. }
  7055. },
  7056. removeExtension: function(namespace) {
  7057. var jsonExtension = this._extensions[namespace];
  7058. if(jsonExtension) {
  7059. //unload extension's stencils
  7060. if(jsonExtension.stencils) {
  7061. $A(jsonExtension.stencils).each(function(stencil) {
  7062. var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this);
  7063. delete this._stencils[oStencil.id()]; // maybe not ??
  7064. delete this._availableStencils[oStencil.id()];
  7065. }.bind(this));
  7066. }
  7067. //unload extension's properties
  7068. if (jsonExtension.properties) {
  7069. var stencils = this._stencils.values();
  7070. stencils.each(function(stencil){
  7071. var roles = stencil.roles();
  7072. jsonExtension.properties.each(function(prop){
  7073. prop.roles.any(function(role){
  7074. role = jsonExtension["extends"] + role;
  7075. if (roles.member(role)) {
  7076. prop.properties.each(function(property){
  7077. stencil.removeProperty(property.id);
  7078. });
  7079. return true;
  7080. }
  7081. else
  7082. return false;
  7083. })
  7084. })
  7085. }.bind(this));
  7086. }
  7087. //restore removed stencil properties
  7088. if(jsonExtension.removeproperties) {
  7089. jsonExtension.removeproperties.each(function(remprop) {
  7090. var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil);
  7091. if(stencil) {
  7092. var stencilJson = $A(this._jsonObject.stencils).find(function(s) { return s.id == stencil.id() });
  7093. remprop.properties.each(function(propId) {
  7094. var propertyJson = $A(stencilJson.properties).find(function(p) { return p.id == propId });
  7095. stencil.addProperty(propertyJson, this.namespace());
  7096. }.bind(this));
  7097. }
  7098. }.bind(this));
  7099. }
  7100. //restore removed stencils
  7101. if(jsonExtension.removestencils) {
  7102. $A(jsonExtension.removestencils).each(function(remstencil) {
  7103. var sId = jsonExtension["extends"] + remstencil;
  7104. this._availableStencils[sId] = this._stencils[sId];
  7105. }.bind(this));
  7106. }
  7107. }
  7108. delete this._extensions[namespace];
  7109. },
  7110. __handleStencilset: function(response){
  7111. try {
  7112. // using eval instead of prototype's parsing,
  7113. // since there are functions in this JSON.
  7114. eval("this._jsonObject =" + response.responseText);
  7115. }
  7116. catch (e) {
  7117. throw "Stenciset corrupt: " + e;
  7118. }
  7119. // assert it was parsed.
  7120. if (!this._jsonObject) {
  7121. throw "Error evaluating stencilset. It may be corrupt.";
  7122. }
  7123. with (this._jsonObject) {
  7124. // assert there is a namespace.
  7125. if (!namespace || namespace === "")
  7126. throw "Namespace definition missing in stencilset.";
  7127. if (!(stencils instanceof Array))
  7128. throw "Stencilset corrupt.";
  7129. // assert namespace ends with '#'.
  7130. if (!namespace.endsWith("#"))
  7131. namespace = namespace + "#";
  7132. // assert title and description are strings.
  7133. if (!title)
  7134. title = "";
  7135. if (!description)
  7136. description = "";
  7137. }
  7138. },
  7139. /**
  7140. * This method is called when the HTTP request to get the requested stencil
  7141. * set succeeds. The response is supposed to be a JSON representation
  7142. * according to the stencil set specification.
  7143. * @param {Object} response The JSON representation according to the
  7144. * stencil set specification.
  7145. */
  7146. _init: function(response){
  7147. // init and check consistency.
  7148. this.__handleStencilset(response);
  7149. var pps = new Hash();
  7150. // init property packages
  7151. if(this._jsonObject.propertyPackages) {
  7152. $A(this._jsonObject.propertyPackages).each((function(pp) {
  7153. pps[pp.name] = pp.properties;
  7154. }).bind(this));
  7155. }
  7156. var defaultPosition = 0;
  7157. // init each stencil
  7158. $A(this._jsonObject.stencils).each((function(stencil){
  7159. defaultPosition++;
  7160. // instantiate normally.
  7161. var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition);
  7162. this._stencils[oStencil.id()] = oStencil;
  7163. this._availableStencils[oStencil.id()] = oStencil;
  7164. }).bind(this));
  7165. },
  7166. _cancelInit: function(response){
  7167. this.errornous = true;
  7168. },
  7169. toString: function(){
  7170. return "StencilSet " + this.title() + " (" + this.namespace() + ")";
  7171. }
  7172. });
  7173. /*
  7174. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  7175. * License rights for this program may be obtained from Alfresco Software, Ltd.
  7176. * pursuant to a written agreement and any use of this program without such an
  7177. * agreement is prohibited.
  7178. */
  7179. /*
  7180. * All code Copyright 2013 KIS Consultancy all rights reserved
  7181. */
  7182. /**
  7183. * Init namespace
  7184. */
  7185. if(!ORYX) {var ORYX = {};}
  7186. if(!ORYX.Core) {ORYX.Core = {};}
  7187. if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
  7188. /**
  7189. * Class StencilSets
  7190. * uses Prototpye 1.5.0
  7191. * uses Inheritance
  7192. *
  7193. * Singleton
  7194. */
  7195. //storage for loaded stencil sets by namespace
  7196. ORYX.Core.StencilSet._stencilSetsByNamespace = new Hash();
  7197. //storage for stencil sets by url
  7198. ORYX.Core.StencilSet._stencilSetsByUrl = new Hash();
  7199. //storage for stencil set namespaces by editor instances
  7200. ORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash();
  7201. //storage for rules by editor instances
  7202. ORYX.Core.StencilSet._rulesByEditorInstance = new Hash();
  7203. /**
  7204. *
  7205. * @param {String} editorId
  7206. *
  7207. * @return {Hash} Returns a hash map with all stencil sets that are loaded by
  7208. * the editor with the editorId.
  7209. */
  7210. ORYX.Core.StencilSet.stencilSets = function(editorId) {
  7211. var stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId];
  7212. var stencilSets = new Hash();
  7213. if(stencilSetNSs) {
  7214. stencilSetNSs.each(function(stencilSetNS) {
  7215. var stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS)
  7216. stencilSets[stencilSet.namespace()] = stencilSet;
  7217. });
  7218. }
  7219. return stencilSets;
  7220. };
  7221. /**
  7222. *
  7223. * @param {String} namespace
  7224. *
  7225. * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified
  7226. * namespace.
  7227. *
  7228. * The method can handle namespace strings like
  7229. * http://www.example.org/stencilset
  7230. * http://www.example.org/stencilset#
  7231. * http://www.example.org/stencilset#ANode
  7232. */
  7233. ORYX.Core.StencilSet.stencilSet = function(namespace) {
  7234. ORYX.Log.trace("Getting stencil set %0", namespace);
  7235. var splitted = namespace.split("#", 1);
  7236. if(splitted.length === 1) {
  7237. ORYX.Log.trace("Getting stencil set %0", splitted[0]);
  7238. return ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + "#"];
  7239. } else {
  7240. return undefined;
  7241. }
  7242. };
  7243. /**
  7244. *
  7245. * @param {String} id
  7246. *
  7247. * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id.
  7248. *
  7249. * The id must be unique and contains the namespace of the stencil's stencil set.
  7250. * e.g. http://www.example.org/stencilset#ANode
  7251. */
  7252. ORYX.Core.StencilSet.stencil = function(id) {
  7253. ORYX.Log.trace("Getting stencil for %0", id);
  7254. var ss = ORYX.Core.StencilSet.stencilSet(id);
  7255. if(ss) {
  7256. return ss.stencil(id);
  7257. } else {
  7258. ORYX.Log.trace("Cannot fild stencil for %0", id);
  7259. return undefined;
  7260. }
  7261. };
  7262. /**
  7263. *
  7264. * @param {String} editorId
  7265. *
  7266. * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor
  7267. * specified by its editor id.
  7268. */
  7269. ORYX.Core.StencilSet.rules = function(editorId) {
  7270. if(!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {
  7271. ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules();
  7272. }
  7273. return ORYX.Core.StencilSet._rulesByEditorInstance[editorId];
  7274. };
  7275. /**
  7276. *
  7277. * @param {String} url
  7278. * @param {String} editorId
  7279. *
  7280. * Loads a stencil set from url, if it is not already loaded.
  7281. * It also stores which editor instance loads the stencil set and
  7282. * initializes the Rules object for the editor instance.
  7283. */
  7284. ORYX.Core.StencilSet.loadStencilSet = function(url, modelMetaData, editorId) {
  7285. // Alfresco: disable cache, because stencil sets are now flexible
  7286. //var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url];
  7287. //if(!stencilSet) {
  7288. //load stencil set
  7289. stencilSet = new ORYX.Core.StencilSet.StencilSet(url, modelMetaData, editorId);
  7290. //store stencil set
  7291. ORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet;
  7292. //store stencil set by url
  7293. ORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet;
  7294. //}
  7295. var namespace = stencilSet.namespace();
  7296. //store which editorInstance loads the stencil set
  7297. if(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) {
  7298. ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace);
  7299. } else {
  7300. ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace];
  7301. }
  7302. //store the rules for the editor instance
  7303. if(ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {
  7304. ORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet);
  7305. } else {
  7306. var rules = new ORYX.Core.StencilSet.Rules();
  7307. rules.initializeRules(stencilSet);
  7308. ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules;
  7309. }
  7310. };
  7311. /**
  7312. * Returns the translation of an attribute in jsonObject specified by its name
  7313. * according to navigator.language
  7314. */
  7315. ORYX.Core.StencilSet.getTranslation = function(jsonObject, name) {
  7316. var lang = ORYX.I18N.Language.toLowerCase();
  7317. var result = jsonObject[name + "_" + lang];
  7318. if(result)
  7319. return result;
  7320. result = jsonObject[name + "_" + lang.substr(0, 2)];
  7321. if(result)
  7322. return result;
  7323. return jsonObject[name];
  7324. };
  7325. /*
  7326. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  7327. * License rights for this program may be obtained from Alfresco Software, Ltd.
  7328. * pursuant to a written agreement and any use of this program without such an
  7329. * agreement is prohibited.
  7330. */
  7331. /*
  7332. * All code Copyright 2013 KIS Consultancy all rights reserved
  7333. */
  7334. /**
  7335. * Init namespaces
  7336. */
  7337. if(!ORYX) {var ORYX = {};}
  7338. if(!ORYX.Core) {ORYX.Core = {};}
  7339. /**
  7340. * @classDescription With Bounds you can set and get position and size of UIObjects.
  7341. */
  7342. ORYX.Core.Command = Clazz.extend({
  7343. /**
  7344. * Constructor
  7345. */
  7346. construct: function() {
  7347. },
  7348. execute: function(){
  7349. throw "Command.execute() has to be implemented!"
  7350. },
  7351. rollback: function(){
  7352. throw "Command.rollback() has to be implemented!"
  7353. }
  7354. });/*
  7355. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  7356. * License rights for this program may be obtained from Alfresco Software, Ltd.
  7357. * pursuant to a written agreement and any use of this program without such an
  7358. * agreement is prohibited.
  7359. */
  7360. /*
  7361. * All code Copyright 2013 KIS Consultancy all rights reserved
  7362. */
  7363. /**
  7364. * Init namespaces
  7365. */
  7366. if(!ORYX) {var ORYX = {};}
  7367. if(!ORYX.Core) {ORYX.Core = {};}
  7368. /**
  7369. * @classDescription With Bounds you can set and get position and size of UIObjects.
  7370. */
  7371. ORYX.Core.Bounds = {
  7372. /**
  7373. * Constructor
  7374. */
  7375. construct: function() {
  7376. this._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this));
  7377. this.a = {};
  7378. this.b = {};
  7379. this.set.apply(this, arguments);
  7380. this.suspendChange = false;
  7381. this.changedWhileSuspend = false;
  7382. },
  7383. /**
  7384. * Calls all registered callbacks.
  7385. */
  7386. _changed: function(sizeChanged) {
  7387. if(!this.suspendChange) {
  7388. this._changedCallbacks.each(function(callback) {
  7389. callback(this, sizeChanged);
  7390. }.bind(this));
  7391. this.changedWhileSuspend = false;
  7392. } else
  7393. this.changedWhileSuspend = true;
  7394. },
  7395. /**
  7396. * Registers a callback that is called, if the bounds changes.
  7397. * @param callback {Function} The callback function.
  7398. */
  7399. registerCallback: function(callback) {
  7400. if(!this._changedCallbacks.member(callback)) {
  7401. this._changedCallbacks.push(callback);
  7402. }
  7403. },
  7404. /**
  7405. * Unregisters a callback.
  7406. * @param callback {Function} The callback function.
  7407. */
  7408. unregisterCallback: function(callback) {
  7409. this._changedCallbacks = this._changedCallbacks.without(callback);
  7410. },
  7411. /**
  7412. * Sets position and size of the shape dependent of four coordinates
  7413. * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});)
  7414. * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});).
  7415. */
  7416. set: function() {
  7417. var changed = false;
  7418. switch (arguments.length) {
  7419. case 1:
  7420. if(this.a.x !== arguments[0].a.x) {
  7421. changed = true;
  7422. this.a.x = arguments[0].a.x;
  7423. }
  7424. if(this.a.y !== arguments[0].a.y) {
  7425. changed = true;
  7426. this.a.y = arguments[0].a.y;
  7427. }
  7428. if(this.b.x !== arguments[0].b.x) {
  7429. changed = true;
  7430. this.b.x = arguments[0].b.x;
  7431. }
  7432. if(this.b.y !== arguments[0].b.y) {
  7433. changed = true;
  7434. this.b.y = arguments[0].b.y;
  7435. }
  7436. break;
  7437. case 2:
  7438. var ax = Math.min(arguments[0].x, arguments[1].x);
  7439. var ay = Math.min(arguments[0].y, arguments[1].y);
  7440. var bx = Math.max(arguments[0].x, arguments[1].x);
  7441. var by = Math.max(arguments[0].y, arguments[1].y);
  7442. if(this.a.x !== ax) {
  7443. changed = true;
  7444. this.a.x = ax;
  7445. }
  7446. if(this.a.y !== ay) {
  7447. changed = true;
  7448. this.a.y = ay;
  7449. }
  7450. if(this.b.x !== bx) {
  7451. changed = true;
  7452. this.b.x = bx;
  7453. }
  7454. if(this.b.y !== by) {
  7455. changed = true;
  7456. this.b.y = by;
  7457. }
  7458. break;
  7459. case 4:
  7460. var ax = Math.min(arguments[0], arguments[2]);
  7461. var ay = Math.min(arguments[1], arguments[3]);
  7462. var bx = Math.max(arguments[0], arguments[2]);
  7463. var by = Math.max(arguments[1], arguments[3]);
  7464. if(this.a.x !== ax) {
  7465. changed = true;
  7466. this.a.x = ax;
  7467. }
  7468. if(this.a.y !== ay) {
  7469. changed = true;
  7470. this.a.y = ay;
  7471. }
  7472. if(this.b.x !== bx) {
  7473. changed = true;
  7474. this.b.x = bx;
  7475. }
  7476. if(this.b.y !== by) {
  7477. changed = true;
  7478. this.b.y = by;
  7479. }
  7480. break;
  7481. }
  7482. if(changed) {
  7483. this._changed(true);
  7484. }
  7485. },
  7486. /**
  7487. * Moves the bounds so that the point p will be the new upper left corner.
  7488. * @param {Point} p
  7489. * or
  7490. * @param {Number} x
  7491. * @param {Number} y
  7492. */
  7493. moveTo: function() {
  7494. var currentPosition = this.upperLeft();
  7495. switch (arguments.length) {
  7496. case 1:
  7497. this.moveBy({
  7498. x: arguments[0].x - currentPosition.x,
  7499. y: arguments[0].y - currentPosition.y
  7500. });
  7501. break;
  7502. case 2:
  7503. this.moveBy({
  7504. x: arguments[0] - currentPosition.x,
  7505. y: arguments[1] - currentPosition.y
  7506. });
  7507. break;
  7508. default:
  7509. //TODO error
  7510. }
  7511. },
  7512. /**
  7513. * Moves the bounds relatively by p.
  7514. * @param {Point} p
  7515. * or
  7516. * @param {Number} x
  7517. * @param {Number} y
  7518. *
  7519. */
  7520. moveBy: function() {
  7521. var changed = false;
  7522. switch (arguments.length) {
  7523. case 1:
  7524. var p = arguments[0];
  7525. if(p.x !== 0 || p.y !== 0) {
  7526. changed = true;
  7527. this.a.x += p.x;
  7528. this.b.x += p.x;
  7529. this.a.y += p.y;
  7530. this.b.y += p.y;
  7531. }
  7532. break;
  7533. case 2:
  7534. var x = arguments[0];
  7535. var y = arguments[1];
  7536. if(x !== 0 || y !== 0) {
  7537. changed = true;
  7538. this.a.x += x;
  7539. this.b.x += x;
  7540. this.a.y += y;
  7541. this.b.y += y;
  7542. }
  7543. break;
  7544. default:
  7545. //TODO error
  7546. }
  7547. if(changed) {
  7548. this._changed();
  7549. }
  7550. },
  7551. /***
  7552. * Includes the bounds b into the current bounds.
  7553. * @param {Bounds} b
  7554. */
  7555. include: function(b) {
  7556. if( (this.a.x === undefined) && (this.a.y === undefined) &&
  7557. (this.b.x === undefined) && (this.b.y === undefined)) {
  7558. return b;
  7559. };
  7560. var cx = Math.min(this.a.x,b.a.x);
  7561. var cy = Math.min(this.a.y,b.a.y);
  7562. var dx = Math.max(this.b.x,b.b.x);
  7563. var dy = Math.max(this.b.y,b.b.y);
  7564. this.set(cx, cy, dx, dy);
  7565. },
  7566. /**
  7567. * Relatively extends the bounds by p.
  7568. * @param {Point} p
  7569. */
  7570. extend: function(p) {
  7571. if(p.x !== 0 || p.y !== 0) {
  7572. // this is over cross for the case that a and b have same coordinates.
  7573. //((this.a.x > this.b.x) ? this.a : this.b).x += p.x;
  7574. //((this.b.y > this.a.y) ? this.b : this.a).y += p.y;
  7575. this.b.x += p.x;
  7576. this.b.y += p.y;
  7577. this._changed(true);
  7578. }
  7579. },
  7580. /**
  7581. * Widens the scope of the bounds by x.
  7582. * @param {Number} x
  7583. */
  7584. widen: function(x) {
  7585. if (x !== 0) {
  7586. this.suspendChange = true;
  7587. this.moveBy({x: -x, y: -x});
  7588. this.extend({x: 2*x, y: 2*x});
  7589. this.suspendChange = false;
  7590. if(this.changedWhileSuspend) {
  7591. this._changed(true);
  7592. }
  7593. }
  7594. },
  7595. /**
  7596. * Returns the upper left corner's point regardless of the
  7597. * bound delimiter points.
  7598. */
  7599. upperLeft: function() {
  7600. var result = {};
  7601. result.x = this.a.x;
  7602. result.y = this.a.y;
  7603. return result;
  7604. },
  7605. /**
  7606. * Returns the lower Right left corner's point regardless of the
  7607. * bound delimiter points.
  7608. */
  7609. lowerRight: function() {
  7610. var result = {};
  7611. result.x = this.b.x;
  7612. result.y = this.b.y;
  7613. return result;
  7614. },
  7615. /**
  7616. * @return {Number} Width of bounds.
  7617. */
  7618. width: function() {
  7619. return this.b.x - this.a.x;
  7620. },
  7621. /**
  7622. * @return {Number} Height of bounds.
  7623. */
  7624. height: function() {
  7625. return this.b.y - this.a.y;
  7626. },
  7627. /**
  7628. * @return {Point} The center point of this bounds.
  7629. */
  7630. center: function() {
  7631. var center = {};
  7632. center.x =(this.a.x + this.b.x)/2.0;
  7633. center.y =(this.a.y + this.b.y)/2.0;
  7634. return center;
  7635. },
  7636. /**
  7637. * @return {Point} The center point of this bounds relative to upperLeft.
  7638. */
  7639. midPoint: function() {
  7640. var midpoint = {};
  7641. midpoint.x = (this.b.x - this.a.x)/2.0;
  7642. midpoint.y = (this.b.y - this.a.y)/2.0;
  7643. return midpoint;
  7644. },
  7645. /**
  7646. * Moves the center point of this bounds to the new position.
  7647. * @param p {Point}
  7648. * or
  7649. * @param x {Number}
  7650. * @param y {Number}
  7651. */
  7652. centerMoveTo: function() {
  7653. var currentPosition = this.center();
  7654. switch (arguments.length) {
  7655. case 1:
  7656. this.moveBy(arguments[0].x - currentPosition.x,
  7657. arguments[0].y - currentPosition.y);
  7658. break;
  7659. case 2:
  7660. this.moveBy(arguments[0] - currentPosition.x,
  7661. arguments[1] - currentPosition.y);
  7662. break;
  7663. }
  7664. },
  7665. isIncluded: function(point, offset) {
  7666. var pointX, pointY, offset;
  7667. // Get the the two Points
  7668. switch(arguments.length) {
  7669. case 1:
  7670. pointX = arguments[0].x;
  7671. pointY = arguments[0].y;
  7672. offset = 0;
  7673. break;
  7674. case 2:
  7675. if(arguments[0].x && arguments[0].y) {
  7676. pointX = arguments[0].x;
  7677. pointY = arguments[0].y;
  7678. offset = Math.abs(arguments[1]);
  7679. } else {
  7680. pointX = arguments[0];
  7681. pointY = arguments[1];
  7682. offset = 0;
  7683. }
  7684. break;
  7685. case 3:
  7686. pointX = arguments[0];
  7687. pointY = arguments[1];
  7688. offset = Math.abs(arguments[2]);
  7689. break;
  7690. default:
  7691. throw "isIncluded needs one, two or three arguments";
  7692. }
  7693. var ul = this.upperLeft();
  7694. var lr = this.lowerRight();
  7695. if(pointX >= ul.x - offset
  7696. && pointX <= lr.x + offset && pointY >= ul.y - offset
  7697. && pointY <= lr.y + offset)
  7698. return true;
  7699. else
  7700. return false;
  7701. },
  7702. /**
  7703. * @return {Bounds} A copy of this bounds.
  7704. */
  7705. clone: function() {
  7706. //Returns a new bounds object without the callback
  7707. // references of the original bounds
  7708. return new ORYX.Core.Bounds(this);
  7709. },
  7710. toString: function() {
  7711. return "( "+this.a.x+" | "+this.a.y+" )/( "+this.b.x+" | "+this.b.y+" )";
  7712. },
  7713. serializeForERDF: function() {
  7714. return this.a.x+","+this.a.y+","+this.b.x+","+this.b.y;
  7715. }
  7716. };
  7717. ORYX.Core.Bounds = Clazz.extend(ORYX.Core.Bounds);/*
  7718. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  7719. * License rights for this program may be obtained from Alfresco Software, Ltd.
  7720. * pursuant to a written agreement and any use of this program without such an
  7721. * agreement is prohibited.
  7722. */
  7723. /*
  7724. * All code Copyright 2013 KIS Consultancy all rights reserved
  7725. */
  7726. /**
  7727. * Init namespaces
  7728. */
  7729. if(!ORYX) {var ORYX = {};}
  7730. if(!ORYX.Core) {ORYX.Core = {};}
  7731. /**
  7732. * @classDescription Abstract base class for all objects that have a graphical representation
  7733. * within the editor.
  7734. * @extends Clazz
  7735. */
  7736. ORYX.Core.UIObject = {
  7737. /**
  7738. * Constructor of the UIObject class.
  7739. */
  7740. construct: function(options) {
  7741. this.isChanged = true; //Flag, if UIObject has been changed since last update.
  7742. this.isResized = true;
  7743. this.isVisible = true; //Flag, if UIObject's display attribute is set to 'inherit' or 'none'
  7744. this.isSelectable = false; //Flag, if UIObject is selectable.
  7745. this.isResizable = false; //Flag, if UIObject is resizable.
  7746. this.isMovable = false; //Flag, if UIObject is movable.
  7747. this.id = ORYX.Editor.provideId(); //get unique id
  7748. this.parent = undefined; //parent is defined, if this object is added to another uiObject.
  7749. this.node = undefined; //this is a reference to the SVG representation, either locally or in DOM.
  7750. this.children = []; //array for all add uiObjects
  7751. this.bounds = new ORYX.Core.Bounds(); //bounds with undefined values
  7752. this._changedCallback = this._changed.bind(this); //callback reference for calling _changed
  7753. this.bounds.registerCallback(this._changedCallback); //set callback in bounds
  7754. if(options && options.eventHandlerCallback) {
  7755. this.eventHandlerCallback = options.eventHandlerCallback;
  7756. }
  7757. },
  7758. /**
  7759. * Sets isChanged flag to true. Callback for the bounds object.
  7760. */
  7761. _changed: function(bounds, isResized) {
  7762. this.isChanged = true;
  7763. if(this.bounds == bounds)
  7764. this.isResized = isResized || this.isResized;
  7765. },
  7766. /**
  7767. * If something changed, this method calls the refresh method that must be implemented by subclasses.
  7768. */
  7769. update: function() {
  7770. if(this.isChanged) {
  7771. this.refresh();
  7772. this.isChanged = false;
  7773. //call update of all children
  7774. this.children.each(function(value) {
  7775. value.update();
  7776. });
  7777. }
  7778. },
  7779. /**
  7780. * Is called in update method, if isChanged is set to true. Sub classes should call the super class method.
  7781. */
  7782. refresh: function() {
  7783. },
  7784. /**
  7785. * @return {Array} Array of all child UIObjects.
  7786. */
  7787. getChildren: function() {
  7788. return this.children.clone();
  7789. },
  7790. /**
  7791. * @return {Array} Array of all parent UIObjects.
  7792. */
  7793. getParents: function(){
  7794. var parents = [];
  7795. var parent = this.parent;
  7796. while(parent){
  7797. parents.push(parent);
  7798. parent = parent.parent;
  7799. }
  7800. return parents;
  7801. },
  7802. /**
  7803. * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE.
  7804. * @param {UIObject} parent
  7805. * @return {Boolean}
  7806. */
  7807. isParent: function(parent){
  7808. var cparent = this;
  7809. while(cparent){
  7810. if (cparent === parent){
  7811. return true;
  7812. }
  7813. cparent = cparent.parent;
  7814. }
  7815. return false;
  7816. },
  7817. /**
  7818. * @return {String} Id of this UIObject
  7819. */
  7820. getId: function() {
  7821. return this.id;
  7822. },
  7823. /**
  7824. * Method for accessing child uiObjects by id.
  7825. * @param {String} id
  7826. * @param {Boolean} deep
  7827. *
  7828. * @return {UIObject} If found, it returns the UIObject with id.
  7829. */
  7830. getChildById: function(id, deep) {
  7831. return this.children.find(function(uiObj) {
  7832. if(uiObj.getId() === id) {
  7833. return uiObj;
  7834. } else {
  7835. if(deep) {
  7836. var obj = uiObj.getChildById(id, deep);
  7837. if(obj) {
  7838. return obj;
  7839. }
  7840. }
  7841. }
  7842. });
  7843. },
  7844. /**
  7845. * Adds an UIObject to this UIObject and sets the parent of the
  7846. * added UIObject. It is also added to the SVG representation of this
  7847. * UIObject.
  7848. * @param {UIObject} uiObject
  7849. */
  7850. add: function(uiObject) {
  7851. //add uiObject, if it is not already a child of this object
  7852. if (!(this.children.member(uiObject))) {
  7853. //if uiObject is child of another parent, remove it from that parent.
  7854. if(uiObject.parent) {
  7855. uiObject.remove(uiObject);
  7856. }
  7857. //add uiObject to children
  7858. this.children.push(uiObject);
  7859. //set parent reference
  7860. uiObject.parent = this;
  7861. //add uiObject.node to this.node
  7862. uiObject.node = this.node.appendChild(uiObject.node);
  7863. //register callback to get informed, if child is changed
  7864. uiObject.bounds.registerCallback(this._changedCallback);
  7865. //uiObject.update();
  7866. } else {
  7867. ORYX.Log.info("add: ORYX.Core.UIObject is already a child of this object.");
  7868. }
  7869. },
  7870. /**
  7871. * Removes UIObject from this UIObject. The SVG representation will also
  7872. * be removed from this UIObject's SVG representation.
  7873. * @param {UIObject} uiObject
  7874. */
  7875. remove: function(uiObject) {
  7876. //if uiObject is a child of this object, remove it.
  7877. if (this.children.member(uiObject)) {
  7878. //remove uiObject from children
  7879. this.children = this._uiObjects.without(uiObject);
  7880. //delete parent reference of uiObject
  7881. uiObject.parent = undefined;
  7882. //delete uiObject.node from this.node
  7883. uiObject.node = this.node.removeChild(uiObject.node);
  7884. //unregister callback to get informed, if child is changed
  7885. uiObject.bounds.unregisterCallback(this._changedCallback);
  7886. } else {
  7887. ORYX.Log.info("remove: ORYX.Core.UIObject is not a child of this object.");
  7888. }
  7889. },
  7890. /**
  7891. * Calculates absolute bounds of this UIObject.
  7892. */
  7893. absoluteBounds: function() {
  7894. if(this.parent) {
  7895. var absUL = this.absoluteXY();
  7896. return new ORYX.Core.Bounds(absUL.x, absUL.y,
  7897. absUL.x + this.bounds.width(),
  7898. absUL.y + this.bounds.height());
  7899. } else {
  7900. return this.bounds.clone();
  7901. }
  7902. },
  7903. /**
  7904. * @return {Point} The absolute position of this UIObject.
  7905. */
  7906. absoluteXY: function() {
  7907. if(this.parent) {
  7908. var pXY = this.parent.absoluteXY();
  7909. var result = {};
  7910. result.x = pXY.x + this.bounds.upperLeft().x;
  7911. result.y = pXY.y + this.bounds.upperLeft().y;
  7912. return result;
  7913. } else {
  7914. var result = {};
  7915. result.x = this.bounds.upperLeft().x;
  7916. result.y = this.bounds.upperLeft().y;
  7917. return result;
  7918. }
  7919. },
  7920. /**
  7921. * @return {Point} The absolute position from the Center of this UIObject.
  7922. */
  7923. absoluteCenterXY: function() {
  7924. if(this.parent) {
  7925. var pXY = this.parent.absoluteXY();
  7926. var result = {};
  7927. result.x = pXY.x + this.bounds.center().x;
  7928. result.y = pXY.y + this.bounds.center().y;
  7929. return result;
  7930. } else {
  7931. var result = {};
  7932. result.x = this.bounds.center().x;
  7933. result.y = this.bounds.center().y;
  7934. return result;
  7935. }
  7936. },
  7937. /**
  7938. * Hides this UIObject and all its children.
  7939. */
  7940. hide: function() {
  7941. this.node.setAttributeNS(null, 'display', 'none');
  7942. this.isVisible = false;
  7943. this.children.each(function(uiObj) {
  7944. uiObj.hide();
  7945. });
  7946. },
  7947. /**
  7948. * Enables visibility of this UIObject and all its children.
  7949. */
  7950. show: function() {
  7951. this.node.setAttributeNS(null, 'display', 'inherit');
  7952. this.isVisible = true;
  7953. this.children.each(function(uiObj) {
  7954. uiObj.show();
  7955. });
  7956. },
  7957. addEventHandlers: function(node) {
  7958. node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false);
  7959. node.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false);
  7960. node.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false);
  7961. node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false);
  7962. node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false);
  7963. node.addEventListener('click', this._delegateEvent.bind(this), false);
  7964. node.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false);
  7965. },
  7966. _delegateEvent: function(event) {
  7967. if(this.eventHandlerCallback) {
  7968. this.eventHandlerCallback(event, this);
  7969. }
  7970. },
  7971. toString: function() { return "UIObject " + this.id }
  7972. };
  7973. ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/*
  7974. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  7975. * License rights for this program may be obtained from Alfresco Software, Ltd.
  7976. * pursuant to a written agreement and any use of this program without such an
  7977. * agreement is prohibited.
  7978. */
  7979. /*
  7980. * All code Copyright 2013 KIS Consultancy all rights reserved
  7981. */
  7982. /**
  7983. * Init namespaces
  7984. */
  7985. if(!ORYX) {var ORYX = {};}
  7986. if(!ORYX.Core) {ORYX.Core = {};}
  7987. /**
  7988. * Top Level uiobject.
  7989. * @class ORYX.Core.AbstractShape
  7990. * @extends ORYX.Core.UIObject
  7991. */
  7992. ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(
  7993. /** @lends ORYX.Core.AbstractShape.prototype */
  7994. {
  7995. /**
  7996. * Constructor
  7997. */
  7998. construct: function(options, stencil, facade) {
  7999. arguments.callee.$.construct.apply(this, arguments);
  8000. this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM
  8001. // stencil reference
  8002. this._stencil = stencil;
  8003. // if the stencil defines a super stencil that should be used for its instances, set it.
  8004. if (this._stencil._jsonStencil.superId){
  8005. stencilId = this._stencil.id()
  8006. superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId;
  8007. stencilSet = this._stencil.stencilSet();
  8008. this._stencil = stencilSet.stencil(superStencilId);
  8009. }
  8010. //Hash map for all properties. Only stores the values of the properties.
  8011. this.properties = new Hash();
  8012. this.propertiesChanged = new Hash();
  8013. // List of properties which are not included in the stencilset,
  8014. // but which gets (de)serialized
  8015. this.hiddenProperties = new Hash();
  8016. //Initialization of property map and initial value.
  8017. this._stencil.properties().each((function(property) {
  8018. var key = property.prefix() + "-" + property.id();
  8019. this.properties[key] = property.value();
  8020. this.propertiesChanged[key] = true;
  8021. }).bind(this));
  8022. // if super stencil was defined, also regard stencil's properties:
  8023. if (stencil._jsonStencil.superId) {
  8024. stencil.properties().each((function(property) {
  8025. var key = property.prefix() + "-" + property.id();
  8026. var value = property.value();
  8027. var oldValue = this.properties[key];
  8028. this.properties[key] = value;
  8029. this.propertiesChanged[key] = true;
  8030. // Raise an event, to show that the property has changed
  8031. // required for plugins like processLink.js
  8032. //window.setTimeout( function(){
  8033. this._delegateEvent({
  8034. type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
  8035. name : key,
  8036. value : value,
  8037. oldValue: oldValue
  8038. });
  8039. //}.bind(this), 10)
  8040. }).bind(this));
  8041. }
  8042. },
  8043. layout: function() {
  8044. },
  8045. /**
  8046. * Returns the stencil object specifiing the type of the shape.
  8047. */
  8048. getStencil: function() {
  8049. return this._stencil;
  8050. },
  8051. /**
  8052. *
  8053. * @param {Object} resourceId
  8054. */
  8055. getChildShapeByResourceId: function(resourceId) {
  8056. resourceId = ERDF.__stripHashes(resourceId);
  8057. return this.getChildShapes(true).find(function(shape) {
  8058. return shape.resourceId == resourceId
  8059. });
  8060. },
  8061. /**
  8062. *
  8063. * @param {Object} deep
  8064. * @param {Object} iterator
  8065. */
  8066. getChildShapes: function(deep, iterator) {
  8067. var result = [];
  8068. this.children.each(function(uiObject) {
  8069. if(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {
  8070. if(iterator) {
  8071. iterator(uiObject);
  8072. }
  8073. result.push(uiObject);
  8074. if(deep) {
  8075. result = result.concat(uiObject.getChildShapes(deep, iterator));
  8076. }
  8077. }
  8078. });
  8079. return result;
  8080. },
  8081. /**
  8082. * @param {Object} shape
  8083. * @return {boolean} true if any of shape's childs is given shape
  8084. */
  8085. hasChildShape: function(shape){
  8086. return this.getChildShapes().any(function(child){
  8087. return (child === shape) || child.hasChildShape(shape);
  8088. });
  8089. },
  8090. /**
  8091. *
  8092. * @param {Object} deep
  8093. * @param {Object} iterator
  8094. */
  8095. getChildNodes: function(deep, iterator) {
  8096. var result = [];
  8097. this.children.each(function(uiObject) {
  8098. if(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {
  8099. if(iterator) {
  8100. iterator(uiObject);
  8101. }
  8102. result.push(uiObject);
  8103. }
  8104. if(uiObject instanceof ORYX.Core.Shape) {
  8105. if(deep) {
  8106. result = result.concat(uiObject.getChildNodes(deep, iterator));
  8107. }
  8108. }
  8109. });
  8110. return result;
  8111. },
  8112. /**
  8113. *
  8114. * @param {Object} deep
  8115. * @param {Object} iterator
  8116. */
  8117. getChildEdges: function(deep, iterator) {
  8118. var result = [];
  8119. this.children.each(function(uiObject) {
  8120. if(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {
  8121. if(iterator) {
  8122. iterator(uiObject);
  8123. }
  8124. result.push(uiObject);
  8125. }
  8126. if(uiObject instanceof ORYX.Core.Shape) {
  8127. if(deep) {
  8128. result = result.concat(uiObject.getChildEdges(deep, iterator));
  8129. }
  8130. }
  8131. });
  8132. return result;
  8133. },
  8134. /**
  8135. * Returns a sorted array of ORYX.Core.Node objects.
  8136. * Ordered in z Order, the last object has the highest z Order.
  8137. */
  8138. //TODO deep iterator
  8139. getAbstractShapesAtPosition: function() {
  8140. var x, y;
  8141. switch (arguments.length) {
  8142. case 1:
  8143. x = arguments[0].x;
  8144. y = arguments[0].y;
  8145. break;
  8146. case 2: //two or more arguments
  8147. x = arguments[0];
  8148. y = arguments[1];
  8149. break;
  8150. default:
  8151. throw "getAbstractShapesAtPosition needs 1 or 2 arguments!"
  8152. }
  8153. if(this.isPointIncluded(x, y)) {
  8154. var result = [];
  8155. result.push(this);
  8156. //check, if one child is at that position
  8157. var childNodes = this.getChildNodes();
  8158. var childEdges = this.getChildEdges();
  8159. [childNodes, childEdges].each(function(ne){
  8160. var nodesAtPosition = new Hash();
  8161. ne.each(function(node) {
  8162. if(!node.isVisible){ return }
  8163. var candidates = node.getAbstractShapesAtPosition( x , y );
  8164. if(candidates.length > 0) {
  8165. var nodesInZOrder = $A(node.node.parentNode.childNodes);
  8166. var zOrderIndex = nodesInZOrder.indexOf(node.node);
  8167. nodesAtPosition[zOrderIndex] = candidates;
  8168. }
  8169. });
  8170. nodesAtPosition.keys().sort().each(function(key) {
  8171. result = result.concat(nodesAtPosition[key]);
  8172. });
  8173. });
  8174. return result;
  8175. } else {
  8176. return [];
  8177. }
  8178. },
  8179. /**
  8180. *
  8181. * @param key {String} Must be 'prefix-id' of property
  8182. * @param value {Object} Can be of type String or Number according to property type.
  8183. */
  8184. setProperty: function(key, value, force) {
  8185. var oldValue = this.properties[key];
  8186. if(oldValue !== value || force === true) {
  8187. this.properties[key] = value;
  8188. this.propertiesChanged[key] = true;
  8189. this._changed();
  8190. // Raise an event, to show that the property has changed
  8191. //window.setTimeout( function(){
  8192. if (!this._isInSetProperty) {
  8193. this._isInSetProperty = true;
  8194. this._delegateEvent({
  8195. type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
  8196. elements : [this],
  8197. name : key,
  8198. value : value,
  8199. oldValue: oldValue
  8200. });
  8201. delete this._isInSetProperty;
  8202. }
  8203. //}.bind(this), 10)
  8204. }
  8205. },
  8206. /**
  8207. * Returns TRUE if one of the properties is flagged as dirty
  8208. * @return {boolean}
  8209. */
  8210. isPropertyChanged: function(){
  8211. return this.propertiesChanged.any(function(property){ return property.value });
  8212. },
  8213. /**
  8214. *
  8215. * @param {String} Must be 'prefix-id' of property
  8216. * @param {Object} Can be of type String or Number according to property type.
  8217. */
  8218. setHiddenProperty: function(key, value) {
  8219. // IF undefined, Delete
  8220. if (value === undefined) {
  8221. delete this.hiddenProperties[key];
  8222. return;
  8223. }
  8224. var oldValue = this.hiddenProperties[key];
  8225. if (oldValue !== value) {
  8226. this.hiddenProperties[key] = value;
  8227. }
  8228. },
  8229. /**
  8230. * Calculate if the point is inside the Shape
  8231. * @param {Point}
  8232. */
  8233. isPointIncluded: function(pointX, pointY, absoluteBounds) {
  8234. var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();
  8235. return absBounds.isIncluded(pointX, pointY);
  8236. },
  8237. /**
  8238. * Get the serialized object
  8239. * return Array with hash-entrees (prefix, name, value)
  8240. * Following values will given:
  8241. * Type
  8242. * Properties
  8243. */
  8244. serialize: function() {
  8245. var serializedObject = [];
  8246. // Add the type
  8247. serializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});
  8248. // Add hidden properties
  8249. this.hiddenProperties.each(function(prop){
  8250. serializedObject.push({name: prop.key.replace("oryx-", ""), prefix: "oryx", value: prop.value, type: 'literal'});
  8251. }.bind(this));
  8252. // Add all properties
  8253. this.getStencil().properties().each((function(property){
  8254. var prefix = property.prefix(); // Get prefix
  8255. var name = property.id(); // Get name
  8256. //if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "")
  8257. serializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});
  8258. }).bind(this));
  8259. return serializedObject;
  8260. },
  8261. deserialize: function(serialize){
  8262. // Search in Serialize
  8263. var initializedDocker = 0;
  8264. // Sort properties so that the hidden properties are first in the list
  8265. serialize = serialize.sort(function(a,b){ a = Number(this.properties.keys().member(a.prefix+"-"+a.name)); b = Number(this.properties.keys().member(b.prefix+"-"+b.name)); return a > b ? 1 : (a < b ? -1 : 0) }.bind(this));
  8266. serialize.each((function(obj){
  8267. var name = obj.name;
  8268. var prefix = obj.prefix;
  8269. var value = obj.value;
  8270. // Complex properties can be real json objects, encode them to a string
  8271. if (Object.prototype.toString.call(value) === "Object") value = JSON.stringify(value);
  8272. switch(prefix + "-" + name){
  8273. case 'raziel-parent':
  8274. // Set parent
  8275. if(!this.parent) {break};
  8276. // Set outgoing Shape
  8277. var parent = this.getCanvas().getChildShapeByResourceId(value);
  8278. if(parent) {
  8279. parent.add(this);
  8280. }
  8281. break;
  8282. default:
  8283. // If list, eval as an array
  8284. var prop = this.getStencil().property(prefix+"-"+name);
  8285. if (prop && prop.isList() && typeof value === "string"){
  8286. if ((value||"").strip()&&!value.startsWith("[")&&!value.startsWith("]"))
  8287. value = "[\""+value.strip()+"\"]";
  8288. value = ((value||"").strip()||"[]").evalJSON();
  8289. }
  8290. // Set property
  8291. if(this.properties.keys().member(prefix+"-"+name)) {
  8292. this.setProperty(prefix+"-"+name, value);
  8293. } else if(!(name === "bounds"||name === "parent"||name === "target"||name === "dockers"||name === "docker"||name === "outgoing"||name === "incoming")) {
  8294. this.setHiddenProperty(prefix+"-"+name, value);
  8295. }
  8296. }
  8297. }).bind(this));
  8298. },
  8299. toString: function() { return "ORYX.Core.AbstractShape " + this.id },
  8300. /**
  8301. * Converts the shape to a JSON representation.
  8302. * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.
  8303. */
  8304. toJSON: function(){
  8305. var json = {
  8306. resourceId: this.resourceId,
  8307. properties: jQuery.extend({}, this.properties, this.hiddenProperties).inject({}, function(props, prop){
  8308. var key = prop[0];
  8309. var value = prop[1];
  8310. //If complex property, value should be a json object
  8311. if ( this.getStencil().property(key)
  8312. && this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX
  8313. && Object.prototype.toString.call(value) === "String"){
  8314. try {value = JSON.parse(value);} catch(error){}
  8315. //try {value = JSON.parse(value);} catch(error){}
  8316. // Parse date
  8317. } else if (value instanceof Date&&this.getStencil().property(key)){
  8318. try {
  8319. value = value.format(this.getStencil().property(key).dateFormat());
  8320. } catch(e){}
  8321. }
  8322. //Takes "my_property" instead of "oryx-my_property" as key
  8323. key = key.replace(/^[\w_]+-/, "");
  8324. props[key] = value;
  8325. return props;
  8326. }.bind(this)),
  8327. stencil: {
  8328. id: this.getStencil().idWithoutNs()
  8329. },
  8330. childShapes: this.getChildShapes().map(function(shape){
  8331. return shape.toJSON();
  8332. })
  8333. };
  8334. if(this.getOutgoingShapes){
  8335. json.outgoing = this.getOutgoingShapes().map(function(shape){
  8336. return {
  8337. resourceId: shape.resourceId
  8338. };
  8339. });
  8340. }
  8341. if(this.bounds){
  8342. json.bounds = {
  8343. lowerRight: this.bounds.lowerRight(),
  8344. upperLeft: this.bounds.upperLeft()
  8345. };
  8346. }
  8347. if(this.dockers){
  8348. json.dockers = this.dockers.map(function(docker){
  8349. var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
  8350. d.getDocker = function(){return docker;};
  8351. return d;
  8352. });
  8353. }
  8354. jQuery.extend(json, ORYX.Core.AbstractShape.JSONHelper);
  8355. // do not pollute the json attributes (for serialization), so put the corresponding
  8356. // shape is encapsulated in a method
  8357. json.getShape = function(){
  8358. return this;
  8359. }.bind(this);
  8360. return json;
  8361. }
  8362. });
  8363. /**
  8364. * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).
  8365. * @example
  8366. * jQuery.extend(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);
  8367. */
  8368. ORYX.Core.AbstractShape.JSONHelper = {
  8369. /**
  8370. * Iterates over each child shape.
  8371. * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.
  8372. * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)
  8373. * @param {boolean} [modify=false] If true, the result of the iterator function is taken as new shape, return false to delete it. This enables modifying the object while iterating through the child shapes.
  8374. * @example
  8375. * // Increases the lowerRight x value of each direct child shape by one.
  8376. * myShapeAsJson.eachChild(function(shape, parentShape){
  8377. * shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;
  8378. * return shape;
  8379. * }, false, true);
  8380. */
  8381. eachChild: function(iterator, deep, modify){
  8382. if(!this.childShapes) return;
  8383. var newChildShapes = []; //needed if modify = true
  8384. this.childShapes.each(function(shape){
  8385. if (!(shape.eachChild instanceof Function)){
  8386. jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);
  8387. }
  8388. var res = iterator(shape, this);
  8389. if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.
  8390. if(deep) shape.eachChild(iterator, deep, modify);
  8391. }.bind(this));
  8392. if(modify) this.childShapes = newChildShapes;
  8393. },
  8394. getShape: function(){
  8395. return null;
  8396. },
  8397. getChildShapes: function(deep){
  8398. var allShapes = this.childShapes;
  8399. if(deep){
  8400. this.eachChild(function(shape){
  8401. if (!(shape.getChildShapes instanceof Function)){
  8402. jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper);
  8403. }
  8404. allShapes = allShapes.concat(shape.getChildShapes(deep));
  8405. }, true);
  8406. }
  8407. return allShapes;
  8408. },
  8409. /**
  8410. * @return {String} Serialized JSON object
  8411. */
  8412. serialize: function(){
  8413. return JSON.stringify(this);
  8414. }
  8415. }
  8416. /*
  8417. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  8418. * License rights for this program may be obtained from Alfresco Software, Ltd.
  8419. * pursuant to a written agreement and any use of this program without such an
  8420. * agreement is prohibited.
  8421. */
  8422. /*
  8423. * All code Copyright 2013 KIS Consultancy all rights reserved
  8424. */
  8425. /**
  8426. * Init namespaces
  8427. */
  8428. if(!ORYX) {var ORYX = {};}
  8429. /**
  8430. @namespace Namespace for the Oryx core elements.
  8431. @name ORYX.Core
  8432. */
  8433. if(!ORYX.Core) {ORYX.Core = {};}
  8434. /**
  8435. * @class Oryx canvas.
  8436. * @extends ORYX.Core.AbstractShape
  8437. *
  8438. */
  8439. ORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({
  8440. /** @lends ORYX.Core.Canvas.prototype */
  8441. /**
  8442. * Defines the current zoom level
  8443. */
  8444. zoomLevel:1,
  8445. /**
  8446. * Constructor
  8447. */
  8448. construct: function(options, stencil, facade) {
  8449. arguments.callee.$.construct.apply(this, arguments);
  8450. if(!(options && options.width && options.height)) {
  8451. ORYX.Log.fatal("Canvas is missing mandatory parameters options.width and options.height.");
  8452. return;
  8453. }
  8454. this.facade = facade;
  8455. //TODO: set document resource id
  8456. this.resourceId = options.id;
  8457. this.nodes = [];
  8458. this.edges = [];
  8459. // Row highlighting states
  8460. this.colHighlightState = 0;
  8461. this.colHighlightEnabled = false;
  8462. //init svg document
  8463. this.rootNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", options.parentNode,
  8464. ['svg', {id: this.id, width: options.width, height: options.height},
  8465. ['defs', {}]
  8466. ]);
  8467. this.rootNode.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
  8468. this.rootNode.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg");
  8469. this._htmlContainer = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", options.parentNode,
  8470. ['div', {id: "oryx_canvas_htmlContainer", style:"position:absolute; top:5px"}]);
  8471. // Additional SVG-node BELOW the stencils to allow underlays (if that is even a word) by plugins
  8472. this.underlayNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.rootNode,
  8473. ['svg', {id: "underlay-container"}]);
  8474. // Create 2 svg-elements in the svg-container
  8475. this.columnHightlight1 = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.underlayNode,
  8476. ['rect', {x: 0, width: ORYX.CONFIG.FORM_ROW_WIDTH + 35, height: "100%", style: "fill: #fff6d5", visibility: "hidden"}]);
  8477. this.columnHightlight2 = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.underlayNode,
  8478. ['rect', {x: ORYX.CONFIG.FORM_ROW_WIDTH + 35, width: ORYX.CONFIG.FORM_ROW_WIDTH + 25, height: "100%", style: "fill: #fff6d5", visibility: "hidden"}]);
  8479. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.rootNode,
  8480. ['g', {},
  8481. ['g', {"class": "stencils"},
  8482. ['g', {"class": "me"}],
  8483. ['g', {"class": "children"}],
  8484. ['g', {"class": "edge"}]
  8485. ],
  8486. ['g', {"class":"svgcontainer"}]
  8487. ]);
  8488. /*
  8489. var off = 2 * ORYX.CONFIG.GRID_DISTANCE;
  8490. var size = 3;
  8491. var d = "";
  8492. for(var i = 0; i <= options.width; i += off)
  8493. for(var j = 0; j <= options.height; j += off)
  8494. d = d + "M" + (i - size) + " " + j + " l" + (2*size) + " 0 m" + (-size) + " " + (-size) + " l0 " + (2*size) + " m0" + (-size) + " ";
  8495. ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node.firstChild.firstChild,
  8496. ['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]);
  8497. */
  8498. //Global definition of default font for shapes
  8499. //Definitions in the SVG definition of a stencil will overwrite these settings for
  8500. // that stencil.
  8501. /*if(navigator.platform.indexOf("Mac") > -1) {
  8502. this.node.setAttributeNS(null, 'stroke', 'black');
  8503. this.node.setAttributeNS(null, 'stroke-width', '0.5px');
  8504. this.node.setAttributeNS(null, 'font-family', 'Skia');
  8505. //this.node.setAttributeNS(null, 'letter-spacing', '2px');
  8506. this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
  8507. } else {
  8508. this.node.setAttributeNS(null, 'stroke', 'none');
  8509. this.node.setAttributeNS(null, 'font-family', 'Verdana');
  8510. this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
  8511. }*/
  8512. this.node.setAttributeNS(null, 'stroke', 'none');
  8513. this.node.setAttributeNS(null, 'font-family', 'Verdana, sans-serif');
  8514. this.node.setAttributeNS(null, 'font-size-adjust', 'none');
  8515. this.node.setAttributeNS(null, 'font-style', 'normal');
  8516. this.node.setAttributeNS(null, 'font-variant', 'normal');
  8517. this.node.setAttributeNS(null, 'font-weight', 'normal');
  8518. this.node.setAttributeNS(null, 'line-heigth', 'normal');
  8519. this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
  8520. this.bounds.set(0,0,options.width, options.height);
  8521. this.addEventHandlers(this.rootNode.parentNode);
  8522. //disable context menu
  8523. this.rootNode.oncontextmenu = function() {return false;};
  8524. },
  8525. focus: function(){
  8526. try {
  8527. // Get a href
  8528. if (!this.focusEl)
  8529. {
  8530. this.focusEl = jQuery('body').append(jQuery('<a href="#" class="x-grid3-focus x-grid3-focus-canvas"/>'));
  8531. this.focusEl.swallowEvent("click", true);
  8532. }
  8533. // Focus it
  8534. this.focusEl.focus.defer(1, this.focusEl);
  8535. this.focusEl.blur.defer(3, this.focusEl);
  8536. } catch(e){}
  8537. },
  8538. setHightlightState: function(state) {
  8539. if(this.colHighlightEnabled && this.colHighlightState != state) {
  8540. if(state == 0) {
  8541. this.columnHightlight1.setAttribute("visibility", "hidden");
  8542. this.columnHightlight2.setAttribute("visibility", "hidden");
  8543. } else if(state == 1) {
  8544. this.columnHightlight1.setAttribute("visibility", "visible");
  8545. this.columnHightlight2.setAttribute("visibility", "hidden");
  8546. } else if(state == 2) {
  8547. this.columnHightlight1.setAttribute("visibility", "hidden");
  8548. this.columnHightlight2.setAttribute("visibility", "visible");
  8549. } else if(state == 3) {
  8550. this.columnHightlight1.setAttribute("visibility", "visible");
  8551. this.columnHightlight2.setAttribute("visibility", "visible");
  8552. }
  8553. this.colHighlightState = state;
  8554. }
  8555. },
  8556. setHightlightStateBasedOnX : function(x) {
  8557. if(x > ORYX.CONFIG.FORM_ROW_WIDTH + 30) {
  8558. this.setHightlightState(2);
  8559. } else {
  8560. this.setHightlightState(1);
  8561. }
  8562. },
  8563. update: function() {
  8564. this.nodes.each(function(node) {
  8565. this._traverseForUpdate(node);
  8566. }.bind(this));
  8567. // call stencil's layout callback
  8568. // (needed for row layouting of xforms)
  8569. //this.getStencil().layout(this);
  8570. var layoutEvents = this.getStencil().layout();
  8571. if(layoutEvents) {
  8572. layoutEvents.each(function(event) {
  8573. // setup additional attributes
  8574. event.shape = this;
  8575. event.forceExecution = true;
  8576. event.target = this.rootNode;
  8577. // do layouting
  8578. this._delegateEvent(event);
  8579. }.bind(this))
  8580. }
  8581. this.nodes.invoke("_update");
  8582. this.edges.invoke("_update", true);
  8583. /*this.children.each(function(child) {
  8584. child._update();
  8585. });*/
  8586. },
  8587. _traverseForUpdate: function(shape) {
  8588. var childRet = shape.isChanged;
  8589. shape.getChildNodes(false, function(child) {
  8590. if(this._traverseForUpdate(child)) {
  8591. childRet = true;
  8592. }
  8593. }.bind(this));
  8594. if(childRet) {
  8595. shape.layout();
  8596. return true;
  8597. } else {
  8598. return false;
  8599. }
  8600. },
  8601. layout: function() {
  8602. },
  8603. /**
  8604. *
  8605. * @param {Object} deep
  8606. * @param {Object} iterator
  8607. */
  8608. getChildNodes: function(deep, iterator) {
  8609. if(!deep && !iterator) {
  8610. return this.nodes.clone();
  8611. } else {
  8612. var result = [];
  8613. this.nodes.each(function(uiObject) {
  8614. if(iterator) {
  8615. iterator(uiObject);
  8616. }
  8617. result.push(uiObject);
  8618. if(deep && uiObject instanceof ORYX.Core.Shape) {
  8619. result = result.concat(uiObject.getChildNodes(deep, iterator));
  8620. }
  8621. });
  8622. return result;
  8623. }
  8624. },
  8625. /**
  8626. * buggy crap! use base class impl instead!
  8627. * @param {Object} iterator
  8628. */
  8629. /* getChildEdges: function(iterator) {
  8630. if(iterator) {
  8631. this.edges.each(function(edge) {
  8632. iterator(edge);
  8633. });
  8634. }
  8635. return this.edges.clone();
  8636. },
  8637. */
  8638. /**
  8639. * Overrides the UIObject.add method. Adds uiObject to the correct sub node.
  8640. * @param {UIObject} uiObject
  8641. */
  8642. add: function(uiObject, index, silent) {
  8643. //if uiObject is child of another UIObject, remove it.
  8644. if(uiObject instanceof ORYX.Core.UIObject) {
  8645. if (!(this.children.member(uiObject))) {
  8646. //if uiObject is child of another parent, remove it from that parent.
  8647. if(uiObject.parent) {
  8648. uiObject.parent.remove(uiObject, true);
  8649. }
  8650. //add uiObject to the Canvas
  8651. //add uiObject to this Shape
  8652. if(index != undefined)
  8653. this.children.splice(index, 0, uiObject);
  8654. else
  8655. this.children.push(uiObject);
  8656. //set parent reference
  8657. uiObject.parent = this;
  8658. //add uiObject.node to this.node depending on the type of uiObject
  8659. if(uiObject instanceof ORYX.Core.Shape) {
  8660. if(uiObject instanceof ORYX.Core.Edge) {
  8661. uiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, "defs")[0]);
  8662. uiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node);
  8663. this.edges.push(uiObject);
  8664. } else {
  8665. uiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node);
  8666. this.nodes.push(uiObject);
  8667. }
  8668. } else { //UIObject
  8669. uiObject.node = this.node.appendChild(uiObject.node);
  8670. }
  8671. uiObject.bounds.registerCallback(this._changedCallback);
  8672. if(this.eventHandlerCallback && silent !== true)
  8673. this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})
  8674. } else {
  8675. ORYX.Log.warn("add: ORYX.Core.UIObject is already a child of this object.");
  8676. }
  8677. } else {
  8678. ORYX.Log.fatal("add: Parameter is not of type ORYX.Core.UIObject.");
  8679. }
  8680. },
  8681. /**
  8682. * Overrides the UIObject.remove method. Removes uiObject.
  8683. * @param {UIObject} uiObject
  8684. */
  8685. remove: function(uiObject, silent) {
  8686. //if uiObject is a child of this object, remove it.
  8687. if (this.children.member(uiObject)) {
  8688. //remove uiObject from children
  8689. var parent = uiObject.parent;
  8690. this.children = this.children.without(uiObject);
  8691. //delete parent reference of uiObject
  8692. uiObject.parent = undefined;
  8693. //delete uiObject.node from this.node
  8694. if(uiObject instanceof ORYX.Core.Shape) {
  8695. if(uiObject instanceof ORYX.Core.Edge) {
  8696. uiObject.removeMarkers();
  8697. uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);
  8698. this.edges = this.edges.without(uiObject);
  8699. } else {
  8700. uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);
  8701. this.nodes = this.nodes.without(uiObject);
  8702. }
  8703. } else { //UIObject
  8704. uiObject.node = this.node.removeChild(uiObject.node);
  8705. }
  8706. if(this.eventHandlerCallback && silent !== true)
  8707. this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:uiObject, parent:parent});
  8708. uiObject.bounds.unregisterCallback(this._changedCallback);
  8709. } else {
  8710. ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object.");
  8711. }
  8712. },
  8713. /**
  8714. * Creates shapes out of the given collection of shape objects and adds them to the canvas.
  8715. * @example
  8716. * canvas.addShapeObjects({
  8717. bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },
  8718. resourceId:"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD",
  8719. childShapes:[],
  8720. properties:{},
  8721. stencil:{
  8722. id:"Subprocess"
  8723. },
  8724. outgoing:[{resourceId: 'aShape'}],
  8725. target: {resourceId: 'aShape'}
  8726. });
  8727. * @param {Object} shapeObjects
  8728. * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback)
  8729. * @return {Array} A collection of ORYX.Core.Shape
  8730. * @methodOf ORYX.Core.Canvas.prototype
  8731. */
  8732. addShapeObjects: function(shapeObjects, eventHandler){
  8733. if(!shapeObjects) return;
  8734. this.initializingShapes = true;
  8735. /*FIXME This implementation is very evil! At first, all shapes are created on
  8736. canvas. In a second step, the attributes are applied. There must be a distinction
  8737. between the configuration phase (where the outgoings, for example, are just named),
  8738. and the creation phase (where the outgoings are evaluated). This must be reflected
  8739. in code to provide a nicer API/ implementation!!! */
  8740. var addShape = function(shape, parent){
  8741. // Create a new Stencil
  8742. var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id );
  8743. // Create a new Shape
  8744. var ShapeClass = (stencil.type() == "node") ? ORYX.Core.Node : ORYX.Core.Edge;
  8745. var newShape = new ShapeClass(
  8746. {'eventHandlerCallback': eventHandler},
  8747. stencil, this.facade);
  8748. // Set the resource id
  8749. newShape.resourceId = shape.resourceId;
  8750. newShape.node.id = "svg-" + shape.resourceId;
  8751. // Set parent to json object to be used later
  8752. // Due to the nested json structure, normally shape.parent is not set/ must not be set.
  8753. // In special cases, it can be easier to set this directly instead of a nested structure.
  8754. shape.parent = "#" + ((shape.parent && shape.parent.resourceId) || parent.resourceId);
  8755. // Add the shape to the canvas
  8756. this.add( newShape );
  8757. return {
  8758. json: shape,
  8759. object: newShape
  8760. };
  8761. }.bind(this);
  8762. /** Builds up recursively a flatted array of shapes, including a javascript object and json representation
  8763. * @param {Object} shape Any object that has Object#childShapes
  8764. */
  8765. var addChildShapesRecursively = function(shape){
  8766. var addedShapes = [];
  8767. if (shape.childShapes && shape.childShapes.constructor == String)
  8768. {
  8769. shape.childShapes = JSON.parse(shape.childShapes);
  8770. }
  8771. shape.childShapes.each(function(childShape){
  8772. addedShapes.push(addShape(childShape, shape));
  8773. addedShapes = addedShapes.concat(addChildShapesRecursively(childShape));
  8774. });
  8775. return addedShapes;
  8776. }.bind(this);
  8777. var shapes = addChildShapesRecursively({
  8778. childShapes: shapeObjects,
  8779. resourceId: this.resourceId
  8780. });
  8781. // prepare deserialisation parameter
  8782. shapes.each(
  8783. function(shape){
  8784. var properties = [];
  8785. for(field in shape.json.properties){
  8786. properties.push({
  8787. prefix: 'oryx',
  8788. name: field,
  8789. value: shape.json.properties[field]
  8790. });
  8791. }
  8792. // Outgoings
  8793. shape.json.outgoing.each(function(out){
  8794. properties.push({
  8795. prefix: 'raziel',
  8796. name: 'outgoing',
  8797. value: "#"+out.resourceId
  8798. });
  8799. });
  8800. // Target
  8801. // (because of a bug, the first outgoing is taken when there is no target,
  8802. // can be removed after some time)
  8803. if(shape.object instanceof ORYX.Core.Edge) {
  8804. var target = shape.json.target || shape.json.outgoing[0];
  8805. if(target){
  8806. properties.push({
  8807. prefix: 'raziel',
  8808. name: 'target',
  8809. value: "#"+target.resourceId
  8810. });
  8811. }
  8812. }
  8813. // Bounds
  8814. if (shape.json.bounds) {
  8815. properties.push({
  8816. prefix: 'oryx',
  8817. name: 'bounds',
  8818. value: shape.json.bounds.upperLeft.x + "," + shape.json.bounds.upperLeft.y + "," + shape.json.bounds.lowerRight.x + "," + shape.json.bounds.lowerRight.y
  8819. });
  8820. }
  8821. //Dockers [{x:40, y:50}, {x:30, y:60}] => "40 50 30 60 #"
  8822. if(shape.json.dockers){
  8823. properties.push({
  8824. prefix: 'oryx',
  8825. name: 'dockers',
  8826. value: shape.json.dockers.inject("", function(dockersStr, docker){
  8827. return dockersStr + docker.x + " " + docker.y + " ";
  8828. }) + " #"
  8829. });
  8830. }
  8831. //Parent
  8832. properties.push({
  8833. prefix: 'raziel',
  8834. name: 'parent',
  8835. value: shape.json.parent
  8836. });
  8837. shape.__properties = properties;
  8838. }.bind(this)
  8839. );
  8840. // Deserialize the properties from the shapes
  8841. // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there
  8842. // first, deserialize all nodes
  8843. shapes.each(function(shape) {
  8844. if(shape.object instanceof ORYX.Core.Node) {
  8845. shape.object.deserialize(shape.__properties, shape.json);
  8846. }
  8847. });
  8848. // second, deserialize all edges
  8849. shapes.each(function(shape) {
  8850. if(shape.object instanceof ORYX.Core.Edge) {
  8851. shape.object.deserialize(shape.__properties, shape.json);
  8852. shape.object._oldBounds = shape.object.bounds.clone();
  8853. shape.object._update();
  8854. }
  8855. });
  8856. delete this.initializingShapes;
  8857. return shapes.pluck("object");
  8858. },
  8859. /**
  8860. * Updates the size of the canvas, regarding to the containg shapes.
  8861. */
  8862. updateSize: function(){
  8863. // Check the size for the canvas
  8864. var maxWidth = 0;
  8865. var maxHeight = 0;
  8866. var offset = 100;
  8867. this.getChildShapes(true, function(shape){
  8868. var b = shape.bounds;
  8869. maxWidth = Math.max( maxWidth, b.lowerRight().x + offset)
  8870. maxHeight = Math.max( maxHeight, b.lowerRight().y + offset)
  8871. });
  8872. if( this.bounds.width() < maxWidth || this.bounds.height() < maxHeight ){
  8873. this.setSize({width: Math.max(this.bounds.width(), maxWidth), height: Math.max(this.bounds.height(), maxHeight)})
  8874. }
  8875. },
  8876. getRootNode: function() {
  8877. return this.rootNode;
  8878. },
  8879. getUnderlayNode: function() {
  8880. return this.underlayNode;
  8881. },
  8882. getSvgContainer: function() {
  8883. return this.node.childNodes[1];
  8884. },
  8885. getHTMLContainer: function() {
  8886. return this._htmlContainer;
  8887. },
  8888. /**
  8889. * Return all elements of the same highest level
  8890. * @param {Object} elements
  8891. */
  8892. getShapesWithSharedParent: function(elements) {
  8893. // If there is no elements, return []
  8894. if(!elements || elements.length < 1) { return []; }
  8895. // If there is one element, return this element
  8896. if(elements.length == 1) { return elements;}
  8897. return elements.findAll(function(value){
  8898. var parentShape = value.parent;
  8899. while(parentShape){
  8900. if(elements.member(parentShape)) return false;
  8901. parentShape = parentShape.parent;
  8902. }
  8903. return true;
  8904. });
  8905. },
  8906. setSize: function(size, dontSetBounds) {
  8907. if(!size || !size.width || !size.height){return;};
  8908. if(this.rootNode.parentNode){
  8909. this.rootNode.parentNode.style.width = size.width + 'px';
  8910. this.rootNode.parentNode.style.height = size.height + 'px';
  8911. }
  8912. this.rootNode.setAttributeNS(null, 'width', size.width);
  8913. this.rootNode.setAttributeNS(null, 'height', size.height);
  8914. //this._htmlContainer.style.top = "-" + (size.height + 4) + 'px';
  8915. if( !dontSetBounds ){
  8916. this.bounds.set({a:{x:0,y:0},b:{x:size.width/this.zoomLevel,y:size.height/this.zoomLevel}});
  8917. }
  8918. },
  8919. /**
  8920. * Returns an SVG document of the current process.
  8921. * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser,
  8922. * false, if you want to use the SVG document in browser on client side.
  8923. */
  8924. getSVGRepresentation: function(escapeText) {
  8925. // Get the serialized svg image source
  8926. var svgClone = this.getRootNode().cloneNode(true);
  8927. this._removeInvisibleElements(svgClone);
  8928. var x1, y1, x2, y2;
  8929. this.getChildShapes(true).each(function(shape) {
  8930. var absBounds = shape.absoluteBounds();
  8931. var ul = absBounds.upperLeft();
  8932. var lr = absBounds.lowerRight();
  8933. if(x1 == undefined) {
  8934. x1 = ul.x;
  8935. y1 = ul.y;
  8936. x2 = lr.x;
  8937. y2 = lr.y;
  8938. } else {
  8939. x1 = Math.min(x1, ul.x);
  8940. y1 = Math.min(y1, ul.y);
  8941. x2 = Math.max(x2, lr.x);
  8942. y2 = Math.max(y2, lr.y);
  8943. }
  8944. });
  8945. var margin = 50;
  8946. var width, height, tx, ty;
  8947. if(x1 == undefined) {
  8948. width = 0;
  8949. height = 0;
  8950. tx = 0;
  8951. ty = 0;
  8952. } else {
  8953. width = x2;
  8954. height = y2;
  8955. tx = -x1+margin/2;
  8956. ty = -y1+margin/2;
  8957. }
  8958. // Set the width and height
  8959. svgClone.setAttributeNS(null, 'width', width + margin);
  8960. svgClone.setAttributeNS(null, 'height', height + margin);
  8961. //remove scale factor
  8962. svgClone.childNodes[1].removeAttributeNS(null, 'transform');
  8963. try{
  8964. var svgCont = svgClone.childNodes[1].childNodes[1];
  8965. svgCont.parentNode.removeChild(svgCont);
  8966. } catch(e) {}
  8967. if(escapeText) {
  8968. $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function(elem) {
  8969. elem.textContent = elem.textContent.escapeHTML();
  8970. });
  8971. $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function(elem) {
  8972. if(elem.childNodes.length == 0)
  8973. elem.textContent = elem.textContent.escapeHTML();
  8974. });
  8975. }
  8976. // generating absolute urls for the pdf-exporter
  8977. $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function(elem) {
  8978. var href = elem.getAttributeNS("http://www.w3.org/1999/xlink","href");
  8979. if(!href.match("^(http|https)://")) {
  8980. href = window.location.protocol + "//" + window.location.host + href;
  8981. elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href);
  8982. }
  8983. });
  8984. // escape all links
  8985. $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function(elem) {
  8986. elem.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", (elem.getAttributeNS("http://www.w3.org/1999/xlink","href")||"").escapeHTML());
  8987. });
  8988. return svgClone;
  8989. },
  8990. /**
  8991. * Removes all nodes (and its children) that has the
  8992. * attribute visibility set to "hidden"
  8993. */
  8994. _removeInvisibleElements: function(element) {
  8995. var index = 0;
  8996. while(index < element.childNodes.length) {
  8997. var child = element.childNodes[index];
  8998. if(child.getAttributeNS &&
  8999. child.getAttributeNS(null, "visibility") === "hidden") {
  9000. element.removeChild(child);
  9001. } else {
  9002. this._removeInvisibleElements(child);
  9003. index++;
  9004. }
  9005. }
  9006. },
  9007. /**
  9008. * This method checks all shapes on the canvas and removes all shapes that
  9009. * contain invalid bounds values or dockers values(NaN)
  9010. */
  9011. /*cleanUp: function(parent) {
  9012. if (!parent) {
  9013. parent = this;
  9014. }
  9015. parent.getChildShapes().each(function(shape){
  9016. var a = shape.bounds.a;
  9017. var b = shape.bounds.b;
  9018. if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
  9019. parent.remove(shape);
  9020. }
  9021. else {
  9022. shape.getDockers().any(function(docker) {
  9023. a = docker.bounds.a;
  9024. b = docker.bounds.b;
  9025. if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
  9026. parent.remove(shape);
  9027. return true;
  9028. }
  9029. return false;
  9030. });
  9031. shape.getMagnets().any(function(magnet) {
  9032. a = magnet.bounds.a;
  9033. b = magnet.bounds.b;
  9034. if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
  9035. parent.remove(shape);
  9036. return true;
  9037. }
  9038. return false;
  9039. });
  9040. this.cleanUp(shape);
  9041. }
  9042. }.bind(this));
  9043. },*/
  9044. _delegateEvent: function(event) {
  9045. if(this.eventHandlerCallback && ( event.target == this.rootNode || event.target == this.rootNode.parentNode )) {
  9046. this.eventHandlerCallback(event, this);
  9047. }
  9048. },
  9049. toString: function() { return "Canvas " + this.id },
  9050. /**
  9051. * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information.
  9052. */
  9053. toJSON: function() {
  9054. var json = arguments.callee.$.toJSON.apply(this, arguments);
  9055. // if(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) {
  9056. // json.stencilset = {
  9057. // url: this.getStencil().stencilSet().namespace()
  9058. // };
  9059. // } else {
  9060. json.stencilset = {
  9061. url: this.getStencil().stencilSet().source(),
  9062. namespace: this.getStencil().stencilSet().namespace()
  9063. };
  9064. // }
  9065. return json;
  9066. }
  9067. });/*
  9068. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  9069. * License rights for this program may be obtained from Alfresco Software, Ltd.
  9070. * pursuant to a written agreement and any use of this program without such an
  9071. * agreement is prohibited.
  9072. */
  9073. var idCounter = 0;
  9074. var ID_PREFIX = "resource";
  9075. /**
  9076. * Main initialization method. To be called when loading
  9077. * of the document, including all scripts, is completed.
  9078. */
  9079. function init() {
  9080. ORYX.Log.debug("Querying editor instances");
  9081. // Hack for WebKit to set the SVGElement-Classes
  9082. ORYX.Editor.setMissingClasses();
  9083. // If someone wants to create the editor instance himself
  9084. if (window.onOryxResourcesLoaded) {
  9085. window.onOryxResourcesLoaded();
  9086. }
  9087. // Else fetch the model from server and display editor
  9088. else {
  9089. var modelId = window.location.search.substring(4);
  9090. var modelUrl = "./service/model/" + modelId + "/json";
  9091. ORYX.Editor.createByUrl(modelUrl);
  9092. }
  9093. }
  9094. /**
  9095. @namespace Global Oryx name space
  9096. @name ORYX
  9097. */
  9098. if(!ORYX) {var ORYX = {};}
  9099. /**
  9100. * The Editor class.
  9101. * @class ORYX.Editor
  9102. * @extends Clazz
  9103. * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized}
  9104. * @param {String} config.id Any ID that can be used inside the editor. If fullscreen=false, any HTML node with this id must be present to render the editor to this node.
  9105. * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not.
  9106. * @param {String} config.stencilset.url Stencil set URL.
  9107. * @param {String} [config.stencil.id] Stencil type used for creating the canvas.
  9108. * @param {Object} config.properties Any properties applied to the canvas.
  9109. */
  9110. ORYX.Editor = {
  9111. /** @lends ORYX.Editor.prototype */
  9112. // Defines the global dom event listener
  9113. DOMEventListeners: new Hash(),
  9114. // Defines the selection
  9115. selection: [],
  9116. // Defines the current zoom level
  9117. zoomLevel:1.0,
  9118. construct: function(config) {
  9119. // initialization.
  9120. this._eventsQueue = [];
  9121. this.loadedPlugins = [];
  9122. this.pluginsData = [];
  9123. //meta data about the model for the signavio warehouse
  9124. //directory, new, name, description, revision, model (the model data)
  9125. this.modelMetaData = config;
  9126. var model = config;
  9127. this.id = model.modelId;
  9128. if(config.model) {
  9129. model = config.model;
  9130. }
  9131. if(!this.id) {
  9132. this.id = model.id;
  9133. if(!this.id) {
  9134. this.id = ORYX.Editor.provideId();
  9135. }
  9136. }
  9137. // Defines if the editor should be fullscreen or not
  9138. this.fullscreen = config.fullscreen !== false;
  9139. // Initialize the eventlistener
  9140. this._initEventListener();
  9141. // Load particular stencilset
  9142. if(ORYX.CONFIG.BACKEND_SWITCH) {
  9143. var ssUrl = (model.stencilset.namespace||model.stencilset.url).replace("#", "%23");
  9144. ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);
  9145. } else {
  9146. var ssUrl = model.stencilset.url;
  9147. ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id);
  9148. }
  9149. // CREATES the canvas
  9150. this._createCanvas(model.stencil ? model.stencil.id : null, model.properties);
  9151. // GENERATES the whole EXT.VIEWPORT
  9152. this._generateGUI();
  9153. // Initializing of a callback to check loading ends
  9154. var loadPluginFinished = false;
  9155. var loadContentFinished = false;
  9156. var initFinished = function(){
  9157. if( !loadPluginFinished || !loadContentFinished ){ return }
  9158. this._finishedLoading();
  9159. }.bind(this)
  9160. // LOAD the plugins
  9161. window.setTimeout(function(){
  9162. this.loadPlugins();
  9163. loadPluginFinished = true;
  9164. initFinished();
  9165. }.bind(this), 100);
  9166. // LOAD the content of the current editor instance
  9167. window.setTimeout(function(){
  9168. this.loadSerialized(model, true); // Request the meta data as well
  9169. this.getCanvas().update();
  9170. loadContentFinished = true;
  9171. initFinished();
  9172. }.bind(this), 200);
  9173. },
  9174. _finishedLoading: function() {
  9175. // Raise Loaded Event
  9176. this.handleEvents( {type:ORYX.CONFIG.EVENT_LOADED} )
  9177. },
  9178. _initEventListener: function(){
  9179. // Register on Events
  9180. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false);
  9181. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false);
  9182. // Enable Key up and down Event
  9183. this._keydownEnabled = true;
  9184. this._keyupEnabled = true;
  9185. this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = [];
  9186. this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] = [];
  9187. this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = [];
  9188. this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] = [];
  9189. this.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = [];
  9190. this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = [];
  9191. },
  9192. /**
  9193. * Generate the whole viewport of the
  9194. * Editor and initialized the Ext-Framework
  9195. *
  9196. */
  9197. _generateGUI: function() {
  9198. // Defines the layout height if it's NOT fullscreen
  9199. var layoutHeight = ORYX.CONFIG.WINDOW_HEIGHT;
  9200. var canvasParent = this.getCanvas().rootNode.parentNode;
  9201. jQuery("#canvasSection").append(canvasParent);
  9202. // Set the editor to the center, and refresh the size
  9203. canvasParent.parentNode.setAttributeNS(null, 'align', 'center');
  9204. canvasParent.setAttributeNS(null, 'align', 'left');
  9205. this.getCanvas().setSize({
  9206. width : ORYX.CONFIG.CANVAS_WIDTH,
  9207. height : ORYX.CONFIG.CANVAS_HEIGHT
  9208. });
  9209. },
  9210. getAvailablePlugins: function(){
  9211. var curAvailablePlugins=ORYX.availablePlugins.clone();
  9212. curAvailablePlugins.each(function(plugin){
  9213. if(this.loadedPlugins.find(function(loadedPlugin){
  9214. return loadedPlugin.type==this.name;
  9215. }.bind(plugin))){
  9216. plugin.engaged=true;
  9217. }else{
  9218. plugin.engaged=false;
  9219. }
  9220. }.bind(this));
  9221. return curAvailablePlugins;
  9222. },
  9223. loadScript: function (url, callback){
  9224. var script = document.createElement("script")
  9225. script.type = "text/javascript";
  9226. if (script.readyState){ //IE
  9227. script.onreadystatechange = function(){
  9228. if (script.readyState == "loaded" || script.readyState == "complete"){
  9229. script.onreadystatechange = null;
  9230. callback();
  9231. }
  9232. };
  9233. } else { //Others
  9234. script.onload = function(){
  9235. callback();
  9236. };
  9237. }
  9238. script.src = url;
  9239. document.getElementsByTagName("head")[0].appendChild(script);
  9240. },
  9241. /**
  9242. * activate Plugin
  9243. *
  9244. * @param {String} name
  9245. * @param {Function} callback
  9246. * callback(sucess, [errorCode])
  9247. * errorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED
  9248. */
  9249. activatePluginByName: function(name, callback, loadTry){
  9250. var match=this.getAvailablePlugins().find(function(value){return value.name==name});
  9251. if(match && (!match.engaged || (match.engaged==='false'))){
  9252. var loadedStencilSetsNamespaces = this.getStencilSets().keys();
  9253. var facade = this._getPluginFacade();
  9254. var newPlugin;
  9255. var me=this;
  9256. ORYX.Log.debug("Initializing plugin '%0'", match.name);
  9257. if (!match.requires || !match.requires.namespaces || match.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ){
  9258. if(!match.notUsesIn || !match.notUsesIn.namespaces || !match.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 })){
  9259. try {
  9260. var className = eval(match.name);
  9261. var newPlugin = new className(facade, match);
  9262. newPlugin.type = match.name;
  9263. // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data
  9264. if (newPlugin.registryChanged)
  9265. newPlugin.registryChanged(me.pluginsData);
  9266. // If there have an onSelection-Method it will pushed to the Editor Event-Handler
  9267. if (newPlugin.onSelectionChanged)
  9268. me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, newPlugin.onSelectionChanged.bind(newPlugin));
  9269. this.loadedPlugins.push(newPlugin);
  9270. this.loadedPlugins.each(function(loaded){
  9271. if(loaded.registryChanged)
  9272. loaded.registryChanged(this.pluginsData);
  9273. }.bind(me));
  9274. callback(true);
  9275. } catch(e) {
  9276. ORYX.Log.warn("Plugin %0 is not available", match.name);
  9277. if(!!loadTry){
  9278. callback(false,"INITFAILED");
  9279. return;
  9280. }
  9281. this.loadScript("plugins/scripts/"+match.source, this.activatePluginByName.bind(this,match.name,callback,true));
  9282. }
  9283. }else{
  9284. callback(false,"NOTUSEINSTENCILSET");
  9285. ORYX.Log.info("Plugin need a stencilset which is not loaded'", match.name);
  9286. }
  9287. } else {
  9288. callback(false,"REQUIRESTENCILSET");
  9289. ORYX.Log.info("Plugin need a stencilset which is not loaded'", match.name);
  9290. }
  9291. }else{
  9292. callback(false, match?"NOTFOUND":"YETACTIVATED");
  9293. //TODO error handling
  9294. }
  9295. },
  9296. /**
  9297. * Laden der Plugins
  9298. */
  9299. loadPlugins: function() {
  9300. // if there should be plugins but still are none, try again.
  9301. // TODO this should wait for every plugin respectively.
  9302. /*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) {
  9303. window.setTimeout(this.loadPlugins.bind(this), 100);
  9304. return;
  9305. }*/
  9306. var me = this;
  9307. var newPlugins = [];
  9308. var loadedStencilSetsNamespaces = this.getStencilSets().keys();
  9309. // Available Plugins will be initalize
  9310. var facade = this._getPluginFacade();
  9311. // If there is an Array where all plugins are described, than only take those
  9312. // (that comes from the usage of oryx with a mashup api)
  9313. if( ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array ){
  9314. // Get the plugins from the available plugins (those who are in the plugins.xml)
  9315. ORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function(value){
  9316. return ORYX.MashupAPI.loadablePlugins.include( value.name )
  9317. })
  9318. // Add those plugins to the list, which are only in the loadablePlugins list
  9319. ORYX.MashupAPI.loadablePlugins.each(function( className ){
  9320. if( !(ORYX.availablePlugins.find(function(val){ return val.name == className }))){
  9321. ORYX.availablePlugins.push( {name: className } );
  9322. }
  9323. })
  9324. }
  9325. ORYX.availablePlugins.each(function(value) {
  9326. ORYX.Log.debug("Initializing plugin '%0'", value.name);
  9327. if( (!value.requires || !value.requires.namespaces || value.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) &&
  9328. (!value.notUsesIn || !value.notUsesIn.namespaces || !value.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&&
  9329. /*only load activated plugins or undefined */
  9330. (value.engaged || (value.engaged===undefined)) ){
  9331. try {
  9332. var className = eval(value.name);
  9333. if( className ){
  9334. var plugin = new className(facade, value);
  9335. plugin.type = value.name;
  9336. newPlugins.push( plugin );
  9337. plugin.engaged=true;
  9338. }
  9339. } catch(e) {
  9340. ORYX.Log.warn("Plugin %0 is not available %1", value.name, e);
  9341. }
  9342. } else {
  9343. ORYX.Log.info("Plugin need a stencilset which is not loaded'", value.name);
  9344. }
  9345. });
  9346. newPlugins.each(function(value) {
  9347. // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data
  9348. if(value.registryChanged)
  9349. value.registryChanged(me.pluginsData);
  9350. // If there have an onSelection-Method it will pushed to the Editor Event-Handler
  9351. if(value.onSelectionChanged)
  9352. me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value));
  9353. });
  9354. this.loadedPlugins = newPlugins;
  9355. this.registerPluginsOnKeyEvents();
  9356. this.setSelection();
  9357. },
  9358. /**
  9359. * Creates the Canvas
  9360. * @param {String} [stencilType] The stencil type used for creating the canvas. If not given, a stencil with myBeRoot = true from current stencil set is taken.
  9361. * @param {Object} [canvasConfig] Any canvas properties (like language).
  9362. */
  9363. _createCanvas: function(stencilType, canvasConfig) {
  9364. if (stencilType) {
  9365. // Add namespace to stencilType
  9366. if (stencilType.search(/^http/) === -1) {
  9367. stencilType = this.getStencilSets().values()[0].namespace() + stencilType;
  9368. }
  9369. }
  9370. else {
  9371. // Get any root stencil type
  9372. stencilType = this.getStencilSets().values()[0].findRootStencilName();
  9373. }
  9374. // get the stencil associated with the type
  9375. var canvasStencil = ORYX.Core.StencilSet.stencil(stencilType);
  9376. if (!canvasStencil)
  9377. ORYX.Log.fatal("Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.", stencilType);
  9378. // create all dom
  9379. // TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars
  9380. var div = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", null, ['div']);
  9381. // set class for custom styling
  9382. div.addClassName("ORYX_Editor");
  9383. // create the canvas
  9384. this._canvas = new ORYX.Core.Canvas({
  9385. width : ORYX.CONFIG.CANVAS_WIDTH,
  9386. height : ORYX.CONFIG.CANVAS_HEIGHT,
  9387. 'eventHandlerCallback' : this.handleEvents.bind(this),
  9388. id : this.id,
  9389. parentNode : div
  9390. }, canvasStencil, this._getPluginFacade());
  9391. if (canvasConfig) {
  9392. // Migrate canvasConfig to an RDF-like structure
  9393. //FIXME this isn't nice at all because we don't want rdf any longer
  9394. var properties = [];
  9395. for(field in canvasConfig){
  9396. properties.push({
  9397. prefix: 'oryx',
  9398. name: field,
  9399. value: canvasConfig[field]
  9400. });
  9401. }
  9402. this._canvas.deserialize(properties);
  9403. }
  9404. },
  9405. /**
  9406. * Returns a per-editor singleton plugin facade.
  9407. * To be used in plugin initialization.
  9408. */
  9409. _getPluginFacade: function() {
  9410. // if there is no pluginfacade already created:
  9411. if(!(this._pluginFacade))
  9412. // create it.
  9413. this._pluginFacade = {
  9414. activatePluginByName: this.activatePluginByName.bind(this),
  9415. //deactivatePluginByName: this.deactivatePluginByName.bind(this),
  9416. getAvailablePlugins: this.getAvailablePlugins.bind(this),
  9417. offer: this.offer.bind(this),
  9418. getStencilSets: this.getStencilSets.bind(this),
  9419. getStencilSetExtensionDefinition:function(){ return Object.clone(this.ss_extensions_def||{})}.bind(this),
  9420. getRules: this.getRules.bind(this),
  9421. loadStencilSet: this.loadStencilSet.bind(this),
  9422. createShape: this.createShape.bind(this),
  9423. deleteShape: this.deleteShape.bind(this),
  9424. getSelection: this.getSelection.bind(this),
  9425. setSelection: this.setSelection.bind(this),
  9426. updateSelection: this.updateSelection.bind(this),
  9427. getCanvas: this.getCanvas.bind(this),
  9428. importJSON: this.importJSON.bind(this),
  9429. getJSON: this.getJSON.bind(this),
  9430. getSerializedJSON: this.getSerializedJSON.bind(this),
  9431. executeCommands: this.executeCommands.bind(this),
  9432. isExecutingCommands: this.isExecutingCommands.bind(this),
  9433. registerOnEvent: this.registerOnEvent.bind(this),
  9434. unregisterOnEvent: this.unregisterOnEvent.bind(this),
  9435. raiseEvent: this.handleEvents.bind(this),
  9436. enableEvent: this.enableEvent.bind(this),
  9437. disableEvent: this.disableEvent.bind(this),
  9438. eventCoordinates: this.eventCoordinates.bind(this),
  9439. eventCoordinatesXY: this.eventCoordinatesXY.bind(this),
  9440. getModelMetaData: this.getModelMetaData.bind(this)
  9441. };
  9442. // return it.
  9443. return this._pluginFacade;
  9444. },
  9445. isExecutingCommands: function(){
  9446. return !!this.commandExecuting;
  9447. },
  9448. /**
  9449. * Implementes the command pattern
  9450. * (The real usage of the command pattern
  9451. * is implemented and shown in the Plugins/undo.js)
  9452. *
  9453. * @param <Oryx.Core.Command>[] Array of commands
  9454. */
  9455. executeCommands: function(commands){
  9456. if (!this.commandStack){
  9457. this.commandStack = [];
  9458. }
  9459. if (!this.commandStackExecuted){
  9460. this.commandStackExecuted = [];
  9461. }
  9462. this.commandStack = [].concat(this.commandStack)
  9463. .concat(commands);
  9464. // Check if already executes
  9465. if (this.commandExecuting){ return; }
  9466. // Start execution
  9467. this.commandExecuting = true;
  9468. // Iterate over all commands
  9469. while(this.commandStack.length > 0){
  9470. var command = this.commandStack.shift();
  9471. // and execute it
  9472. command.execute();
  9473. this.commandStackExecuted.push(command);
  9474. }
  9475. // Raise event for executing commands
  9476. this.handleEvents({
  9477. type : ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,
  9478. commands : this.commandStackExecuted
  9479. });
  9480. // Remove temporary vars
  9481. delete this.commandStack;
  9482. delete this.commandStackExecuted;
  9483. delete this.commandExecuting;
  9484. this.updateSelection();
  9485. },
  9486. /**
  9487. * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()).
  9488. * @return {Object} Returns JSON representation as JSON object.
  9489. */
  9490. getJSON: function(){
  9491. delete Array.prototype.toJSON;
  9492. var canvasJSON = this.getCanvas().toJSON();
  9493. canvasJSON.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function(sse){ return !sse.endsWith('/meta#') });
  9494. return canvasJSON;
  9495. },
  9496. /**
  9497. * Serializes a call to toJSON().
  9498. * @return {String} Returns JSON representation as string.
  9499. */
  9500. getSerializedJSON: function(){
  9501. return JSON.stringify(this.getJSON());
  9502. },
  9503. /**
  9504. * Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized}
  9505. * @param {Object|String} jsonObject The (serialized) json object to be imported
  9506. * @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import
  9507. * @throws {SyntaxError} If the serialized json object contains syntax errors
  9508. */
  9509. importJSON: function(jsonObject, noSelectionAfterImport) {
  9510. try {
  9511. jsonObject = this.renewResourceIds(jsonObject);
  9512. } catch(error){
  9513. throw error;
  9514. }
  9515. //check, if the imported json model can be loaded in this editor
  9516. // (stencil set has to fit)
  9517. if(jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) {
  9518. alert(String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace()));
  9519. return null;
  9520. } else {
  9521. var commandClass = ORYX.Core.Command.extend({
  9522. construct: function(jsonObject, loadSerializedCB, noSelectionAfterImport, facade){
  9523. this.jsonObject = jsonObject;
  9524. this.noSelection = noSelectionAfterImport;
  9525. this.facade = facade;
  9526. this.shapes;
  9527. this.connections = [];
  9528. this.parents = new Hash();
  9529. this.selection = this.facade.getSelection();
  9530. this.loadSerialized = loadSerializedCB;
  9531. },
  9532. execute: function(){
  9533. if (!this.shapes) {
  9534. // Import the shapes out of the serialization
  9535. this.shapes = this.loadSerialized( this.jsonObject );
  9536. //store all connections
  9537. this.shapes.each(function(shape) {
  9538. if (shape.getDockers) {
  9539. var dockers = shape.getDockers();
  9540. if (dockers) {
  9541. if (dockers.length > 0) {
  9542. this.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]);
  9543. }
  9544. if (dockers.length > 1) {
  9545. this.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]);
  9546. }
  9547. }
  9548. }
  9549. //store parents
  9550. this.parents[shape.id] = shape.parent;
  9551. }.bind(this));
  9552. } else {
  9553. this.shapes.each(function(shape) {
  9554. this.parents[shape.id].add(shape);
  9555. }.bind(this));
  9556. this.connections.each(function(con) {
  9557. con[0].setDockedShape(con[1]);
  9558. con[0].setReferencePoint(con[2]);
  9559. con[0].update();
  9560. });
  9561. }
  9562. //this.parents.values().uniq().invoke("update");
  9563. this.facade.getCanvas().update();
  9564. if(!this.noSelection)
  9565. this.facade.setSelection(this.shapes);
  9566. else
  9567. this.facade.updateSelection();
  9568. // call updateSize again, because during loadSerialized the edges' bounds
  9569. // are not yet initialized properly
  9570. this.facade.getCanvas().updateSize();
  9571. },
  9572. rollback: function(){
  9573. var selection = this.facade.getSelection();
  9574. this.shapes.each(function(shape) {
  9575. selection = selection.without(shape);
  9576. this.facade.deleteShape(shape);
  9577. }.bind(this));
  9578. /*this.parents.values().uniq().each(function(parent) {
  9579. if(!this.shapes.member(parent))
  9580. parent.update();
  9581. }.bind(this));*/
  9582. this.facade.getCanvas().update();
  9583. this.facade.setSelection(selection);
  9584. }
  9585. })
  9586. var command = new commandClass(jsonObject,
  9587. this.loadSerialized.bind(this),
  9588. noSelectionAfterImport,
  9589. this._getPluginFacade());
  9590. this.executeCommands([command]);
  9591. return command.shapes.clone();
  9592. }
  9593. },
  9594. /**
  9595. * This method renew all resource Ids and according references.
  9596. * Warning: The implementation performs a substitution on the serialized object for
  9597. * easier implementation. This results in a low performance which is acceptable if this
  9598. * is only used when importing models.
  9599. * @param {Object|String} jsonObject
  9600. * @throws {SyntaxError} If the serialized json object contains syntax errors.
  9601. * @return {Object} The jsonObject with renewed ids.
  9602. * @private
  9603. */
  9604. renewResourceIds: function(jsonObject){
  9605. // For renewing resource ids, a serialized and object version is needed
  9606. if(Object.prototype.toString.call(jsonObject) === "String"){
  9607. try {
  9608. var serJsonObject = jsonObject;
  9609. jsonObject = JSON.parse(jsonObject);
  9610. } catch(error){
  9611. throw new SyntaxError(error.message);
  9612. }
  9613. } else {
  9614. var serJsonObject = JSON.stringify(jsonObject);
  9615. }
  9616. // collect all resourceIds recursively
  9617. var collectResourceIds = function(shapes){
  9618. if(!shapes) return [];
  9619. return shapes.map(function(shape){
  9620. return collectResourceIds(shape.childShapes).concat(shape.resourceId);
  9621. }).flatten();
  9622. }
  9623. var resourceIds = collectResourceIds(jsonObject.childShapes);
  9624. // Replace each resource id by a new one
  9625. resourceIds.each(function(oldResourceId){
  9626. var newResourceId = ORYX.Editor.provideId();
  9627. serJsonObject = serJsonObject.replace(new RegExp(oldResourceId, 'g'), newResourceId);
  9628. });
  9629. return JSON.parse(serJsonObject);
  9630. },
  9631. /**
  9632. * Loads serialized model to the oryx.
  9633. * @example
  9634. * editor.loadSerialized({
  9635. * resourceId: "mymodel1",
  9636. * childShapes: [
  9637. * {
  9638. * stencil:{ id:"Subprocess" },
  9639. * outgoing:[{resourceId: 'aShape'}],
  9640. * target: {resourceId: 'aShape'},
  9641. * bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },
  9642. * resourceId: "myshape1",
  9643. * childShapes:[],
  9644. * properties:{},
  9645. * }
  9646. * ],
  9647. * properties:{
  9648. * language: "English"
  9649. * },
  9650. * stencilset:{
  9651. * url:"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json"
  9652. * },
  9653. * stencil:{
  9654. * id:"BPMNDiagram"
  9655. * }
  9656. * });
  9657. * @param {Object} model Description of the model to load.
  9658. * @param {Array} [model.ssextensions] List of stenctil set extensions.
  9659. * @param {String} model.stencilset.url
  9660. * @param {String} model.stencil.id
  9661. * @param {Array} model.childShapes
  9662. * @param {Array} [model.properties]
  9663. * @param {String} model.resourceId
  9664. * @return {ORYX.Core.Shape[]} List of created shapes
  9665. * @methodOf ORYX.Editor.prototype
  9666. */
  9667. loadSerialized: function(model, requestMeta){
  9668. var canvas = this.getCanvas();
  9669. // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240)
  9670. // Deserialize the canvas' stencil set extensions properties first!
  9671. this.loadSSExtensions(model.ssextensions);
  9672. // Load Meta Data Extension if available
  9673. // #Signavio
  9674. if (requestMeta === true) {
  9675. var metaDataExtension = this.getExtensionForMetaData();
  9676. if (metaDataExtension) {
  9677. this.loadSSExtension(metaDataExtension);
  9678. }
  9679. }
  9680. var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this));
  9681. if(model.properties) {
  9682. for(key in model.properties) {
  9683. var value = model.properties[key];
  9684. var prop = this.getCanvas().getStencil().property("oryx-"+key);
  9685. if (!(typeof value === "string") && (!prop || !prop.isList())) {
  9686. value = JSON.stringify(value);
  9687. }
  9688. this.getCanvas().setProperty("oryx-" + key, value);
  9689. }
  9690. }
  9691. this.getCanvas().updateSize();
  9692. // Force to update the selection
  9693. this.selection = [null];
  9694. this.setSelection([]);
  9695. return shapes;
  9696. },
  9697. /**
  9698. * Return the namespace of the extension which
  9699. * provided all the self defined meta data
  9700. * @return {String} Returns null if no extension is defined, otherwise the namespace
  9701. *
  9702. */
  9703. getExtensionForMetaData: function(){
  9704. if (!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){
  9705. return null;
  9706. }
  9707. var stencilsets = this.getStencilSets();
  9708. var extension = this.ss_extensions_def.extensions.find(function(ex){
  9709. return !!stencilsets[ex["extends"]] && ex.namespace.endsWith("/meta#");
  9710. });
  9711. return extension ? extension.namespace || null : null;
  9712. },
  9713. /**
  9714. * Calls ORYX.Editor.prototype.ss_extension_namespace for each element
  9715. * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces.
  9716. */
  9717. loadSSExtensions: function(ss_extension_namespaces){
  9718. if(!ss_extension_namespaces) return;
  9719. ss_extension_namespaces.each(function(ss_extension_namespace){
  9720. this.loadSSExtension(ss_extension_namespace);
  9721. }.bind(this));
  9722. },
  9723. /**
  9724. * Loads a stencil set extension.
  9725. * The stencil set extensions definiton file must already
  9726. * be loaded when the editor is initialized.
  9727. */
  9728. loadSSExtension: function(ss_extension_namespace) {
  9729. if (this.ss_extensions_def) {
  9730. var extension = this.ss_extensions_def.extensions.find(function(ex){
  9731. return (ex.namespace == ss_extension_namespace);
  9732. });
  9733. if (!extension) {
  9734. return;
  9735. }
  9736. var stencilset = this.getStencilSets()[extension["extends"]];
  9737. if (!stencilset) {
  9738. return;
  9739. }
  9740. // Check if absolute or relative url
  9741. if ((extension["definition"]||"").startsWith("/")){
  9742. stencilset.addExtension(extension["definition"])
  9743. } else {
  9744. stencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension["definition"])
  9745. }
  9746. //stencilset.addExtension("/oryx/build/stencilsets/extensions/" + extension["definition"])
  9747. this.getRules().initializeRules(stencilset);
  9748. this._getPluginFacade().raiseEvent({
  9749. type: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED
  9750. });
  9751. }
  9752. },
  9753. disableEvent: function(eventType){
  9754. if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {
  9755. this._keydownEnabled = false;
  9756. }
  9757. if(eventType == ORYX.CONFIG.EVENT_KEYUP) {
  9758. this._keyupEnabled = false;
  9759. }
  9760. if(this.DOMEventListeners.keys().member(eventType)) {
  9761. var value = this.DOMEventListeners.remove(eventType);
  9762. this.DOMEventListeners['disable_' + eventType] = value;
  9763. }
  9764. },
  9765. enableEvent: function(eventType){
  9766. if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {
  9767. this._keydownEnabled = true;
  9768. }
  9769. if(eventType == ORYX.CONFIG.EVENT_KEYUP) {
  9770. this._keyupEnabled = true;
  9771. }
  9772. if(this.DOMEventListeners.keys().member("disable_" + eventType)) {
  9773. var value = this.DOMEventListeners.remove("disable_" + eventType);
  9774. this.DOMEventListeners[eventType] = value;
  9775. }
  9776. },
  9777. /**
  9778. * Methods for the PluginFacade
  9779. */
  9780. registerOnEvent: function(eventType, callback) {
  9781. if(!(this.DOMEventListeners.keys().member(eventType))) {
  9782. this.DOMEventListeners[eventType] = [];
  9783. }
  9784. this.DOMEventListeners[eventType].push(callback);
  9785. },
  9786. unregisterOnEvent: function(eventType, callback) {
  9787. if(this.DOMEventListeners.keys().member(eventType)) {
  9788. this.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback);
  9789. } else {
  9790. // Event is not supported
  9791. // TODO: Error Handling
  9792. }
  9793. },
  9794. getSelection: function() {
  9795. return this.selection || [];
  9796. },
  9797. getStencilSets: function() {
  9798. return ORYX.Core.StencilSet.stencilSets(this.id);
  9799. },
  9800. getRules: function() {
  9801. return ORYX.Core.StencilSet.rules(this.id);
  9802. },
  9803. loadStencilSet: function(source) {
  9804. try {
  9805. ORYX.Core.StencilSet.loadStencilSet(source, this.modelMetaData, this.id);
  9806. this.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED});
  9807. } catch (e) {
  9808. ORYX.Log.warn("Requesting stencil set file failed. (" + e + ")");
  9809. }
  9810. },
  9811. offer: function(pluginData) {
  9812. if(!this.pluginsData.member(pluginData)){
  9813. this.pluginsData.push(pluginData);
  9814. }
  9815. },
  9816. /**
  9817. * It creates an new event or adds the callback, if already existing,
  9818. * for the key combination that the plugin passes in keyCodes attribute
  9819. * of the offer method.
  9820. *
  9821. * The new key down event fits the schema:
  9822. * key.event[.metactrl][.alt][.shift].'thekeyCode'
  9823. */
  9824. registerPluginsOnKeyEvents: function() {
  9825. this.pluginsData.each(function(pluginData) {
  9826. if(pluginData.keyCodes) {
  9827. pluginData.keyCodes.each(function(keyComb) {
  9828. var eventName = "key.event";
  9829. /* Include key action */
  9830. eventName += '.' + keyComb.keyAction;
  9831. if(keyComb.metaKeys) {
  9832. /* Register on ctrl or apple meta key as meta key */
  9833. if(keyComb.metaKeys.
  9834. indexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) {
  9835. eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL;
  9836. }
  9837. /* Register on alt key as meta key */
  9838. if(keyComb.metaKeys.
  9839. indexOf(ORYX.CONFIG.META_KEY_ALT) > -1) {
  9840. eventName += '.' + ORYX.CONFIG.META_KEY_ALT;
  9841. }
  9842. /* Register on shift key as meta key */
  9843. if(keyComb.metaKeys.
  9844. indexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) {
  9845. eventName += '.' + ORYX.CONFIG.META_KEY_SHIFT;
  9846. }
  9847. }
  9848. /* Register on the actual key */
  9849. if(keyComb.keyCode) {
  9850. eventName += '.' + keyComb.keyCode;
  9851. }
  9852. /* Register the event */
  9853. ORYX.Log.debug("Register Plugin on Key Event: %0", eventName);
  9854. if (pluginData.toggle === true && pluginData.buttonInstance) {
  9855. this.registerOnEvent(eventName, function(){
  9856. pluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle
  9857. pluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function
  9858. });
  9859. } else {
  9860. this.registerOnEvent(eventName, pluginData.functionality)
  9861. }
  9862. }.bind(this));
  9863. }
  9864. }.bind(this));
  9865. },
  9866. isEqual: function(a,b){
  9867. return a === b || (a.length === b.length && a.all(function(r){ return b.include(r) }))
  9868. },
  9869. isDirty: function(a){
  9870. return a.any(function(shape){ return shape.isPropertyChanged() })
  9871. },
  9872. setSelection: function(elements, subSelectionElement, force) {
  9873. if (!elements) { elements = []; }
  9874. if (!(elements instanceof Array)) { elements = [elements]; }
  9875. elements = elements.findAll(function(n){ return n && n instanceof ORYX.Core.Shape });
  9876. if (elements[0] instanceof ORYX.Core.Canvas) {
  9877. elements = [];
  9878. }
  9879. if (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)){
  9880. return;
  9881. }
  9882. this.selection = elements;
  9883. this._subSelection = subSelectionElement;
  9884. this.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED, elements:elements, subSelection: subSelectionElement, force: !!force})
  9885. },
  9886. updateSelection: function() {
  9887. this.setSelection(this.selection, this._subSelection, true);
  9888. /*var s = this.selection;
  9889. this.setSelection();
  9890. this.setSelection(s);*/
  9891. },
  9892. getCanvas: function() {
  9893. return this._canvas;
  9894. },
  9895. /**
  9896. * option = {
  9897. * type: string,
  9898. * position: {x:int, y:int},
  9899. * connectingType: uiObj-Class
  9900. * connectedShape: uiObj
  9901. * draggin: bool
  9902. * namespace: url
  9903. * parent: ORYX.Core.AbstractShape
  9904. * template: a template shape that the newly created inherits properties from.
  9905. * }
  9906. */
  9907. createShape: function(option) {
  9908. if(option && option.serialize && option.serialize instanceof Array){
  9909. var type = option.serialize.find(function(obj){return (obj.prefix+"-"+obj.name) == "oryx-type"});
  9910. var stencil = ORYX.Core.StencilSet.stencil(type.value);
  9911. if(stencil.type() == 'node'){
  9912. var newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());
  9913. } else {
  9914. var newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade());
  9915. }
  9916. this.getCanvas().add(newShapeObject);
  9917. newShapeObject.deserialize(option.serialize);
  9918. return newShapeObject;
  9919. }
  9920. // If there is no argument, throw an exception
  9921. if(!option || !option.type || !option.namespace) { throw "To create a new shape you have to give an argument with type and namespace";}
  9922. var canvas = this.getCanvas();
  9923. var newShapeObject;
  9924. // Get the shape type
  9925. var shapetype = option.type;
  9926. // Get the stencil set
  9927. var sset = ORYX.Core.StencilSet.stencilSet(option.namespace);
  9928. // Create an New Shape, dependents on an Edge or a Node
  9929. if(sset.stencil(shapetype).type() == "node") {
  9930. newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())
  9931. } else {
  9932. newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade())
  9933. }
  9934. // when there is a template, inherit the properties.
  9935. if(option.template) {
  9936. newShapeObject._jsonStencil.properties = option.template._jsonStencil.properties;
  9937. newShapeObject.postProcessProperties();
  9938. }
  9939. // Add to the canvas
  9940. if(option.parent && newShapeObject instanceof ORYX.Core.Node) {
  9941. option.parent.add(newShapeObject);
  9942. } else {
  9943. canvas.add(newShapeObject);
  9944. }
  9945. // Set the position
  9946. var point = option.position ? option.position : {x:100, y:200};
  9947. var con;
  9948. // If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge
  9949. if(option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) {
  9950. // there will be create a new Edge
  9951. con = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(option.connectingType));
  9952. // And both endings dockers will be referenced to the both shapes
  9953. con.dockers.first().setDockedShape(option.connectedShape);
  9954. var magnet = option.connectedShape.getDefaultMagnet()
  9955. var cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint();
  9956. con.dockers.first().setReferencePoint( cPoint );
  9957. con.dockers.last().setDockedShape(newShapeObject);
  9958. con.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center());
  9959. // The Edge will be added to the canvas and be updated
  9960. canvas.add(con);
  9961. //con.update();
  9962. }
  9963. // Move the new Shape to the position
  9964. if(newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) {
  9965. newShapeObject.dockers.first().setDockedShape(option.connectedShape);
  9966. if( option.connectedShape instanceof ORYX.Core.Node ){
  9967. newShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center());
  9968. newShapeObject.dockers.last().bounds.centerMoveTo(point);
  9969. } else {
  9970. newShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint());
  9971. }
  9972. var start = newShapeObject.dockers.first();
  9973. var end = newShapeObject.dockers.last();
  9974. if(start.getDockedShape() && end.getDockedShape()) {
  9975. var startPoint = start.getAbsoluteReferencePoint();
  9976. var endPoint = end.getAbsoluteReferencePoint();
  9977. var docker = newShapeObject.createDocker();
  9978. docker.bounds.centerMoveTo({
  9979. x: startPoint.x + (endPont.x - startPoint.x) / 2,
  9980. y: startPoint.y + (endPont.y - startPoint.y) / 2
  9981. });
  9982. }
  9983. } else {
  9984. var b = newShapeObject.bounds
  9985. if( newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1){
  9986. b = newShapeObject.dockers.first().bounds
  9987. }
  9988. b.centerMoveTo(point);
  9989. var upL = b.upperLeft();
  9990. b.moveBy( -Math.min(upL.x, 0) , -Math.min(upL.y, 0) )
  9991. var lwR = b.lowerRight();
  9992. b.moveBy( -Math.max(lwR.x-canvas.bounds.width(), 0) , -Math.max(lwR.y-canvas.bounds.height(), 0) )
  9993. }
  9994. // Update the shape
  9995. if (newShapeObject instanceof ORYX.Core.Edge) {
  9996. newShapeObject._update(false);
  9997. }
  9998. // And refresh the selection
  9999. if(!(newShapeObject instanceof ORYX.Core.Edge)&&!(option.dontUpdateSelection)) {
  10000. this.setSelection([newShapeObject]);
  10001. }
  10002. if(con && con.alignDockers) {
  10003. //con.alignDockers();
  10004. }
  10005. if(newShapeObject.alignDockers) {
  10006. newShapeObject.alignDockers();
  10007. }
  10008. return newShapeObject;
  10009. },
  10010. deleteShape: function(shape) {
  10011. if (!shape || !shape.parent){ return }
  10012. //remove shape from parent
  10013. // this also removes it from DOM
  10014. shape.parent.remove(shape);
  10015. //delete references to outgoing edges
  10016. shape.getOutgoingShapes().each(function(os) {
  10017. var docker = os.getDockers().first();
  10018. if(docker && docker.getDockedShape() == shape) {
  10019. docker.setDockedShape(undefined);
  10020. }
  10021. });
  10022. //delete references to incoming edges
  10023. shape.getIncomingShapes().each(function(is) {
  10024. var docker = is.getDockers().last();
  10025. if(docker && docker.getDockedShape() == shape) {
  10026. docker.setDockedShape(undefined);
  10027. }
  10028. });
  10029. //delete references of the shape's dockers
  10030. shape.getDockers().each(function(docker) {
  10031. docker.setDockedShape(undefined);
  10032. });
  10033. },
  10034. /**
  10035. * Returns an object with meta data about the model.
  10036. * Like name, description, ...
  10037. *
  10038. * Empty object with the current backend.
  10039. *
  10040. * @return {Object} Meta data about the model
  10041. */
  10042. getModelMetaData: function() {
  10043. return this.modelMetaData;
  10044. },
  10045. /* Event-Handler Methods */
  10046. /**
  10047. * Helper method to execute an event immediately. The event is not
  10048. * scheduled in the _eventsQueue. Needed to handle Layout-Callbacks.
  10049. */
  10050. _executeEventImmediately: function(eventObj) {
  10051. if(this.DOMEventListeners.keys().member(eventObj.event.type)) {
  10052. this.DOMEventListeners[eventObj.event.type].each((function(value) {
  10053. value(eventObj.event, eventObj.arg);
  10054. }).bind(this));
  10055. }
  10056. },
  10057. _executeEvents: function() {
  10058. this._queueRunning = true;
  10059. while(this._eventsQueue.length > 0) {
  10060. var val = this._eventsQueue.shift();
  10061. this._executeEventImmediately(val);
  10062. }
  10063. this._queueRunning = false;
  10064. },
  10065. /**
  10066. * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter
  10067. * @param {Object} event Event , welches gefeuert wurde
  10068. * @param {Object} uiObj Target-UiObj
  10069. */
  10070. handleEvents: function(event, uiObj) {
  10071. ORYX.Log.trace("Dispatching event type %0 on %1", event.type, uiObj);
  10072. switch(event.type) {
  10073. case ORYX.CONFIG.EVENT_MOUSEDOWN:
  10074. this._handleMouseDown(event, uiObj);
  10075. break;
  10076. case ORYX.CONFIG.EVENT_MOUSEMOVE:
  10077. this._handleMouseMove(event, uiObj);
  10078. break;
  10079. case ORYX.CONFIG.EVENT_MOUSEUP:
  10080. this._handleMouseUp(event, uiObj);
  10081. break;
  10082. case ORYX.CONFIG.EVENT_MOUSEOVER:
  10083. this._handleMouseHover(event, uiObj);
  10084. break;
  10085. case ORYX.CONFIG.EVENT_MOUSEOUT:
  10086. this._handleMouseOut(event, uiObj);
  10087. break;
  10088. }
  10089. /* Force execution if necessary. Used while handle Layout-Callbacks. */
  10090. if(event.forceExecution) {
  10091. this._executeEventImmediately({event: event, arg: uiObj});
  10092. } else {
  10093. this._eventsQueue.push({event: event, arg: uiObj});
  10094. }
  10095. if(!this._queueRunning) {
  10096. this._executeEvents();
  10097. }
  10098. // TODO: Make this return whether no listener returned false.
  10099. // So that, when one considers bubbling undesireable, it won't happen.
  10100. return false;
  10101. },
  10102. isValidEvent: function(e){
  10103. try {
  10104. var isInput = ["INPUT", "TEXTAREA"].include(e.target.tagName.toUpperCase());
  10105. var gridHasFocus = e.target.className.include("x-grid3-focus") && !e.target.className.include("x-grid3-focus-canvas");
  10106. return !isInput && !gridHasFocus;
  10107. } catch(e){
  10108. return false;
  10109. }
  10110. },
  10111. catchKeyUpEvents: function(event) {
  10112. if(!this._keyupEnabled) {
  10113. return;
  10114. }
  10115. /* assure we have the current event. */
  10116. if (!event)
  10117. event = window.event;
  10118. // Checks if the event comes from some input field
  10119. if (!this.isValidEvent(event)){
  10120. return;
  10121. }
  10122. /* Create key up event type */
  10123. var keyUpEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_UP);
  10124. ORYX.Log.debug("Key Event to handle: %0", keyUpEvent);
  10125. /* forward to dispatching. */
  10126. this.handleEvents({type: keyUpEvent, event:event});
  10127. },
  10128. /**
  10129. * Catches all key down events and forward the appropriated event to
  10130. * dispatching concerning to the pressed keys.
  10131. *
  10132. * @param {Event}
  10133. * The key down event to handle
  10134. */
  10135. catchKeyDownEvents: function(event) {
  10136. if(!this._keydownEnabled) {
  10137. return;
  10138. }
  10139. /* Assure we have the current event. */
  10140. if (!event)
  10141. event = window.event;
  10142. /* Fixed in FF3 */
  10143. // This is a mac-specific fix. The mozilla event object has no knowledge
  10144. // of meta key modifier on osx, however, it is needed for certain
  10145. // shortcuts. This fix adds the metaKey field to the event object, so
  10146. // that all listeners that registered per Oryx plugin facade profit from
  10147. // this. The original bug is filed in
  10148. // https://bugzilla.mozilla.org/show_bug.cgi?id=418334
  10149. //if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) {
  10150. // event.appleMetaKey = true;
  10151. //}
  10152. //this.__currentKey = pressedKey;
  10153. // Checks if the event comes from some input field
  10154. if (!this.isValidEvent(event)){
  10155. return;
  10156. }
  10157. /* Create key up event type */
  10158. var keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN);
  10159. ORYX.Log.debug("Key Event to handle: %0", keyDownEvent);
  10160. /* Forward to dispatching. */
  10161. this.handleEvents({type: keyDownEvent,event: event});
  10162. },
  10163. /**
  10164. * Creates the event type name concerning to the pressed keys.
  10165. *
  10166. * @param {Event} keyDownEvent
  10167. * The source keyDownEvent to build up the event name
  10168. */
  10169. createKeyCombEvent: function(keyEvent, keyAction) {
  10170. /* Get the currently pressed key code. */
  10171. var pressedKey = keyEvent.which || keyEvent.keyCode;
  10172. //this.__currentKey = pressedKey;
  10173. /* Event name */
  10174. var eventName = "key.event";
  10175. /* Key action */
  10176. if(keyAction) {
  10177. eventName += "." + keyAction;
  10178. }
  10179. /* Ctrl or apple meta key is pressed */
  10180. if(keyEvent.ctrlKey || keyEvent.metaKey) {
  10181. eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL;
  10182. }
  10183. /* Alt key is pressed */
  10184. if(keyEvent.altKey) {
  10185. eventName += "." + ORYX.CONFIG.META_KEY_ALT;
  10186. }
  10187. /* Alt key is pressed */
  10188. if(keyEvent.shiftKey) {
  10189. eventName += "." + ORYX.CONFIG.META_KEY_SHIFT;
  10190. }
  10191. /* Return the composed event name */
  10192. return eventName + "." + pressedKey;
  10193. },
  10194. _handleMouseDown: function(event, uiObj) {
  10195. // get canvas.
  10196. var canvas = this.getCanvas();
  10197. // Try to get the focus
  10198. canvas.focus()
  10199. // find the shape that is responsible for this element's id.
  10200. var element = event.currentTarget;
  10201. var elementController = uiObj;
  10202. // gather information on selection.
  10203. var currentIsSelectable = (elementController !== null) &&
  10204. (elementController !== undefined) && (elementController.isSelectable);
  10205. var currentIsMovable = (elementController !== null) &&
  10206. (elementController !== undefined) && (elementController.isMovable);
  10207. var modifierKeyPressed = event.shiftKey || event.ctrlKey;
  10208. var noObjectsSelected = this.selection.length === 0;
  10209. var currentIsSelected = this.selection.member(elementController);
  10210. // Rule #1: When there is nothing selected, select the clicked object.
  10211. if(currentIsSelectable && noObjectsSelected) {
  10212. this.setSelection([elementController]);
  10213. ORYX.Log.trace("Rule #1 applied for mouse down on %0", element.id);
  10214. // Rule #3: When at least one element is selected, and there is no
  10215. // control key pressed, and the clicked object is not selected, select
  10216. // the clicked object.
  10217. } else if(currentIsSelectable && !noObjectsSelected &&
  10218. !modifierKeyPressed && !currentIsSelected) {
  10219. this.setSelection([elementController]);
  10220. //var objectType = elementController.readAttributes();
  10221. //alert(objectType[0] + ": " + objectType[1]);
  10222. ORYX.Log.trace("Rule #3 applied for mouse down on %0", element.id);
  10223. // Rule #4: When the control key is pressed, and the current object is
  10224. // not selected, add it to the selection.
  10225. } else if(currentIsSelectable && modifierKeyPressed
  10226. && !currentIsSelected) {
  10227. var newSelection = this.selection.clone();
  10228. newSelection.push(elementController)
  10229. this.setSelection(newSelection)
  10230. ORYX.Log.trace("Rule #4 applied for mouse down on %0", element.id);
  10231. // Rule #6
  10232. } else if(currentIsSelectable && currentIsSelected &&
  10233. modifierKeyPressed) {
  10234. var newSelection = this.selection.clone();
  10235. this.setSelection(newSelection.without(elementController))
  10236. ORYX.Log.trace("Rule #6 applied for mouse down on %0", elementController.id);
  10237. // Rule #5: When there is at least one object selected and no control
  10238. // key pressed, we're dragging.
  10239. /*} else if(currentIsSelectable && !noObjectsSelected
  10240. && !modifierKeyPressed) {
  10241. if(this.log.isTraceEnabled())
  10242. this.log.trace("Rule #5 applied for mouse down on "+element.id);
  10243. */
  10244. // Rule #2: When clicked on something that is neither
  10245. // selectable nor movable, clear the selection, and return.
  10246. } else if (!currentIsSelectable && !currentIsMovable) {
  10247. this.setSelection([]);
  10248. ORYX.Log.trace("Rule #2 applied for mouse down on %0", element.id);
  10249. return;
  10250. // Rule #7: When the current object is not selectable but movable,
  10251. // it is probably a control. Leave the selection unchanged but set
  10252. // the movedObject to the current one and enable Drag. Dockers will
  10253. // be processed in the dragDocker plugin.
  10254. } else if(!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) {
  10255. // TODO: If there is any moveable elements, do this in a plugin
  10256. //ORYX.Core.UIEnableDrag(event, elementController);
  10257. ORYX.Log.trace("Rule #7 applied for mouse down on %0", element.id);
  10258. // Rule #8: When the element is selectable and is currently selected and no
  10259. // modifier key is pressed
  10260. } else if(currentIsSelectable && currentIsSelected &&
  10261. !modifierKeyPressed) {
  10262. this._subSelection = this._subSelection != elementController ? elementController : undefined;
  10263. this.setSelection(this.selection, this._subSelection);
  10264. ORYX.Log.trace("Rule #8 applied for mouse down on %0", element.id);
  10265. }
  10266. // prevent event from bubbling, return.
  10267. //Event.stop(event);
  10268. return;
  10269. },
  10270. _handleMouseMove: function(event, uiObj) {
  10271. return;
  10272. },
  10273. _handleMouseUp: function(event, uiObj) {
  10274. // get canvas.
  10275. var canvas = this.getCanvas();
  10276. // find the shape that is responsible for this elemement's id.
  10277. var elementController = uiObj;
  10278. //get event position
  10279. var evPos = this.eventCoordinates(event);
  10280. //Event.stop(event);
  10281. },
  10282. _handleMouseHover: function(event, uiObj) {
  10283. return;
  10284. },
  10285. _handleMouseOut: function(event, uiObj) {
  10286. return;
  10287. },
  10288. /**
  10289. * Calculates the event coordinates to SVG document coordinates.
  10290. * @param {Event} event
  10291. * @return {SVGPoint} The event coordinates in the SVG document
  10292. */
  10293. eventCoordinates: function(event) {
  10294. var canvas = this.getCanvas();
  10295. var svgPoint = canvas.node.ownerSVGElement.createSVGPoint();
  10296. svgPoint.x = event.clientX;
  10297. svgPoint.y = event.clientY;
  10298. var additionalIEZoom = 1;
  10299. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  10300. var ua = navigator.userAgent;
  10301. if (ua.indexOf('MSIE') >= 0) {
  10302. //IE 10 and below
  10303. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  10304. if (zoom !== 100) {
  10305. additionalIEZoom = zoom / 100
  10306. }
  10307. }
  10308. }
  10309. if (additionalIEZoom !== 1) {
  10310. svgPoint.x = svgPoint.x * additionalIEZoom;
  10311. svgPoint.y = svgPoint.y * additionalIEZoom;
  10312. }
  10313. var matrix = canvas.node.getScreenCTM();
  10314. return svgPoint.matrixTransform(matrix.inverse());
  10315. },
  10316. eventCoordinatesXY: function(x, y) {
  10317. var canvas = this.getCanvas();
  10318. var svgPoint = canvas.node.ownerSVGElement.createSVGPoint();
  10319. svgPoint.x = x;
  10320. svgPoint.y = y;
  10321. var additionalIEZoom = 1;
  10322. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  10323. var ua = navigator.userAgent;
  10324. if (ua.indexOf('MSIE') >= 0) {
  10325. //IE 10 and below
  10326. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  10327. if (zoom !== 100) {
  10328. additionalIEZoom = zoom / 100
  10329. }
  10330. }
  10331. }
  10332. if (additionalIEZoom !== 1) {
  10333. svgPoint.x = svgPoint.x * additionalIEZoom;
  10334. svgPoint.y = svgPoint.y * additionalIEZoom;
  10335. }
  10336. var matrix = canvas.node.getScreenCTM();
  10337. return svgPoint.matrixTransform(matrix.inverse());
  10338. }
  10339. };
  10340. ORYX.Editor = Clazz.extend(ORYX.Editor);
  10341. /**
  10342. * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur
  10343. * @param {String} modelUrl The JSON URL of a model.
  10344. * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl
  10345. */
  10346. ORYX.Editor.createByUrl = function(modelUrl){
  10347. new Ajax.Request(modelUrl, {
  10348. method: 'GET',
  10349. onSuccess: function(transport) {
  10350. var editorConfig = JSON.parse(transport.responseText);
  10351. new ORYX.Editor(editorConfig);
  10352. }.bind(this)
  10353. });
  10354. }
  10355. // TODO Implement namespace awareness on attribute level.
  10356. /**
  10357. * graft() function
  10358. * Originally by Sean M. Burke from interglacial.com, altered for usage with
  10359. * SVG and namespace (xmlns) support. Be sure you understand xmlns before
  10360. * using this funtion, as it creates all grafted elements in the xmlns
  10361. * provided by you and all element's attribures in default xmlns. If you
  10362. * need to graft elements in a certain xmlns and wish to assign attributes
  10363. * in both that and another xmlns, you will need to do stepwise grafting,
  10364. * adding non-default attributes yourself or you'll have to enhance this
  10365. * function. Latter, I would appreciate: martin???apfelfabrik.de
  10366. * @param {Object} namespace The namespace in which
  10367. * elements should be grafted.
  10368. * @param {Object} parent The element that should contain the grafted
  10369. * structure after the function returned.
  10370. * @param {Object} t the crafting structure.
  10371. * @param {Object} doc the document in which grafting is performed.
  10372. */
  10373. ORYX.Editor.graft = function(namespace, parent, t, doc) {
  10374. doc = (doc || (parent && parent.ownerDocument) || document);
  10375. var e;
  10376. if(t === undefined) {
  10377. throw "Can't graft an undefined value";
  10378. } else if(t.constructor == String) {
  10379. e = doc.createTextNode( t );
  10380. } else {
  10381. for(var i = 0; i < t.length; i++) {
  10382. if( i === 0 && t[i].constructor == String ) {
  10383. var snared;
  10384. snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i );
  10385. if( snared ) {
  10386. e = doc.createElementNS(namespace, snared[1] );
  10387. e.setAttributeNS(null, 'class', snared[2] );
  10388. continue;
  10389. }
  10390. snared = t[i].match( /^([a-z][a-z0-9]*)$/i );
  10391. if( snared ) {
  10392. e = doc.createElementNS(namespace, snared[1] ); // but no class
  10393. continue;
  10394. }
  10395. // Otherwise:
  10396. e = doc.createElementNS(namespace, "span" );
  10397. e.setAttribute(null, "class", "namelessFromLOL" );
  10398. }
  10399. if( t[i] === undefined ) {
  10400. throw "Can't graft an undefined value in a list!";
  10401. } else if( t[i].constructor == String || t[i].constructor == Array ) {
  10402. this.graft(namespace, e, t[i], doc );
  10403. } else if( t[i].constructor == Number ) {
  10404. this.graft(namespace, e, t[i].toString(), doc );
  10405. } else if( t[i].constructor == Object ) {
  10406. // hash's properties => element's attributes
  10407. for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }
  10408. } else {
  10409. }
  10410. }
  10411. }
  10412. if(parent && parent.appendChild) {
  10413. parent.appendChild( e );
  10414. } else {
  10415. }
  10416. return e; // return the topmost created node
  10417. };
  10418. ORYX.Editor.provideId = function() {
  10419. var res = [], hex = '0123456789ABCDEF';
  10420. for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);
  10421. res[14] = 4;
  10422. res[19] = (res[19] & 0x3) | 0x8;
  10423. for (var i = 0; i < 36; i++) res[i] = hex[res[i]];
  10424. res[8] = res[13] = res[18] = res[23] = '-';
  10425. return "oryx_" + res.join('');
  10426. };
  10427. /**
  10428. * When working with Ext, conditionally the window needs to be resized. To do
  10429. * so, use this class method. Resize is deferred until 100ms, and all subsequent
  10430. * resizeBugFix calls are ignored until the initially requested resize is
  10431. * performed.
  10432. */
  10433. ORYX.Editor.resizeFix = function() {
  10434. if (!ORYX.Editor._resizeFixTimeout) {
  10435. ORYX.Editor._resizeFixTimeout = window.setTimeout(function() {
  10436. window.resizeBy(1,1);
  10437. window.resizeBy(-1,-1);
  10438. ORYX.Editor._resizefixTimeout = null;
  10439. }, 100);
  10440. }
  10441. };
  10442. ORYX.Editor.Cookie = {
  10443. callbacks:[],
  10444. onChange: function( callback, interval ){
  10445. this.callbacks.push(callback);
  10446. this.start( interval )
  10447. },
  10448. start: function( interval ){
  10449. if( this.pe ){
  10450. return;
  10451. }
  10452. var currentString = document.cookie;
  10453. this.pe = new PeriodicalExecuter( function(){
  10454. if( currentString != document.cookie ){
  10455. currentString = document.cookie;
  10456. this.callbacks.each(function(callback){ callback(this.getParams()) }.bind(this));
  10457. }
  10458. }.bind(this), ( interval || 10000 ) / 1000);
  10459. },
  10460. stop: function(){
  10461. if( this.pe ){
  10462. this.pe.stop();
  10463. this.pe = null;
  10464. }
  10465. },
  10466. getParams: function(){
  10467. var res = {};
  10468. var p = document.cookie;
  10469. p.split("; ").each(function(param){ res[param.split("=")[0]] = param.split("=")[1];});
  10470. return res;
  10471. },
  10472. toString: function(){
  10473. return document.cookie;
  10474. }
  10475. };
  10476. /**
  10477. * Workaround for SAFARI/Webkit, because
  10478. * when trying to check SVGSVGElement of instanceof there is
  10479. * raising an error
  10480. *
  10481. */
  10482. ORYX.Editor.SVGClassElementsAreAvailable = true;
  10483. ORYX.Editor.setMissingClasses = function() {
  10484. try {
  10485. SVGElement;
  10486. } catch(e) {
  10487. ORYX.Editor.SVGClassElementsAreAvailable = false;
  10488. SVGSVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg').toString();
  10489. SVGGElement = document.createElementNS('http://www.w3.org/2000/svg', 'g').toString();
  10490. SVGPathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path').toString();
  10491. SVGTextElement = document.createElementNS('http://www.w3.org/2000/svg', 'text').toString();
  10492. //SVGMarkerElement = document.createElementNS('http://www.w3.org/2000/svg', 'marker').toString();
  10493. SVGRectElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect').toString();
  10494. SVGImageElement = document.createElementNS('http://www.w3.org/2000/svg', 'image').toString();
  10495. SVGCircleElement = document.createElementNS('http://www.w3.org/2000/svg', 'circle').toString();
  10496. SVGEllipseElement = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse').toString();
  10497. SVGLineElement = document.createElementNS('http://www.w3.org/2000/svg', 'line').toString();
  10498. SVGPolylineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline').toString();
  10499. SVGPolygonElement = document.createElementNS('http://www.w3.org/2000/svg', 'polygon').toString();
  10500. }
  10501. }
  10502. ORYX.Editor.checkClassType = function( classInst, classType ) {
  10503. if( ORYX.Editor.SVGClassElementsAreAvailable ){
  10504. return classInst instanceof classType
  10505. } else {
  10506. return classInst == classType
  10507. }
  10508. };
  10509. /*
  10510. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  10511. * License rights for this program may be obtained from Alfresco Software, Ltd.
  10512. * pursuant to a written agreement and any use of this program without such an
  10513. * agreement is prohibited.
  10514. */
  10515. /*
  10516. * All code Copyright 2013 KIS Consultancy all rights reserved
  10517. */
  10518. /**
  10519. * Init namespaces
  10520. */
  10521. if(!ORYX) {var ORYX = {};}
  10522. if(!ORYX.Core) {ORYX.Core = {};}
  10523. new function(){
  10524. ORYX.Core.UIEnableDrag = function(event, uiObj, option) {
  10525. this.uiObj = uiObj;
  10526. var upL = uiObj.bounds.upperLeft();
  10527. var a = uiObj.node.getScreenCTM();
  10528. this.faktorXY= {x: a.a, y: a.d};
  10529. this.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode;
  10530. this.offSetPosition = {
  10531. x: Event.pointerX(event) - (upL.x * this.faktorXY.x),
  10532. y: Event.pointerY(event) - (upL.y * this.faktorXY.y)};
  10533. this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
  10534. this.dragCallback = ORYX.Core.UIDragCallback.bind(this);
  10535. this.disableCallback = ORYX.Core.UIDisableDrag.bind(this);
  10536. this.movedCallback = option ? option.movedCallback : undefined;
  10537. this.upCallback = option ? option.upCallback : undefined;
  10538. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);
  10539. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback , false);
  10540. };
  10541. ORYX.Core.UIDragCallback = function(event) {
  10542. var position = {
  10543. x: Event.pointerX(event) - this.offSetPosition.x,
  10544. y: Event.pointerY(event) - this.offSetPosition.y}
  10545. position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
  10546. position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
  10547. position.x /= this.faktorXY.x;
  10548. position.y /= this.faktorXY.y;
  10549. this.uiObj.bounds.moveTo(position);
  10550. //this.uiObj.update();
  10551. if(this.movedCallback)
  10552. this.movedCallback(event);
  10553. //Event.stop(event);
  10554. };
  10555. ORYX.Core.UIDisableDrag = function(event) {
  10556. document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback, false);
  10557. document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);
  10558. if(this.upCallback)
  10559. this.upCallback(event);
  10560. this.upCallback = undefined;
  10561. this.movedCallback = undefined;
  10562. Event.stop(event);
  10563. };
  10564. /**
  10565. * Implements a command to move docker by an offset.
  10566. *
  10567. * @class ORYX.Core.MoveDockersCommand
  10568. * @param {Object} object An object with the docker id as key and docker and offset as object value
  10569. *
  10570. */
  10571. ORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({
  10572. construct: function(dockers){
  10573. this.dockers = $H(dockers);
  10574. this.edges = $H({});
  10575. },
  10576. execute: function(){
  10577. if (this.changes) {
  10578. this.executeAgain();
  10579. return;
  10580. } else {
  10581. this.changes = $H({});
  10582. }
  10583. this.dockers.values().each(function(docker){
  10584. var edge = docker.docker.parent;
  10585. if (!edge){ return }
  10586. if (!this.changes[edge.getId()]) {
  10587. this.changes[edge.getId()] = {
  10588. edge : edge,
  10589. oldDockerPositions : edge.dockers.map(function(r){ return r.bounds.center() })
  10590. }
  10591. }
  10592. docker.docker.bounds.moveBy(docker.offset);
  10593. this.edges[edge.getId()] = edge;
  10594. docker.docker.update();
  10595. }.bind(this));
  10596. this.edges.each(function(edge){
  10597. this.updateEdge(edge.value);
  10598. if (this.changes[edge.value.getId()])
  10599. this.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function(r){ return r.bounds.center() })
  10600. }.bind(this));
  10601. },
  10602. updateEdge: function(edge){
  10603. edge._update(true);
  10604. [edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke("_update", [true])
  10605. },
  10606. executeAgain: function(){
  10607. this.changes.values().each(function(change){
  10608. // Reset the dockers
  10609. this.removeAllDocker(change.edge);
  10610. change.dockerPositions.each(function(pos, i){
  10611. if (i==0||i==change.dockerPositions.length-1){ return }
  10612. var docker = change.edge.createDocker(undefined, pos);
  10613. docker.bounds.centerMoveTo(pos);
  10614. docker.update();
  10615. }.bind(this));
  10616. this.updateEdge(change.edge);
  10617. }.bind(this));
  10618. },
  10619. rollback: function(){
  10620. this.changes.values().each(function(change){
  10621. // Reset the dockers
  10622. this.removeAllDocker(change.edge);
  10623. change.oldDockerPositions.each(function(pos, i){
  10624. if (i==0||i==change.oldDockerPositions.length-1){ return }
  10625. var docker = change.edge.createDocker(undefined, pos);
  10626. docker.bounds.centerMoveTo(pos);
  10627. docker.update();
  10628. }.bind(this));
  10629. this.updateEdge(change.edge);
  10630. }.bind(this));
  10631. },
  10632. removeAllDocker: function(edge){
  10633. edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){
  10634. edge.removeDocker(docker);
  10635. })
  10636. }
  10637. });
  10638. }();
  10639. /*
  10640. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  10641. * License rights for this program may be obtained from Alfresco Software, Ltd.
  10642. * pursuant to a written agreement and any use of this program without such an
  10643. * agreement is prohibited.
  10644. */
  10645. /*
  10646. * All code Copyright 2013 KIS Consultancy all rights reserved
  10647. */
  10648. /**
  10649. * Init namespaces
  10650. */
  10651. if(!ORYX) {var ORYX = {};}
  10652. if(!ORYX.Core) {ORYX.Core = {};}
  10653. /**
  10654. * @classDescription Base class for Shapes.
  10655. * @extends ORYX.Core.AbstractShape
  10656. */
  10657. ORYX.Core.Shape = {
  10658. /**
  10659. * Constructor
  10660. */
  10661. construct: function(options, stencil, facade) {
  10662. // call base class constructor
  10663. arguments.callee.$.construct.apply(this, arguments);
  10664. this.facade = facade;
  10665. this.dockers = [];
  10666. this.magnets = [];
  10667. this._defaultMagnet;
  10668. this.incoming = [];
  10669. this.outgoing = [];
  10670. this.nodes = [];
  10671. this._dockerChangedCallback = this._dockerChanged.bind(this);
  10672. //Hash map for all labels. Labels are not treated as children of shapes.
  10673. this._labels = new Hash();
  10674. // create SVG node
  10675. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
  10676. null,
  10677. ['g', {id:"svg-" + this.resourceId},
  10678. ['g', {"class": "stencils"},
  10679. ['g', {"class": "me"}],
  10680. ['g', {"class": "children", style:"overflow:hidden"}],
  10681. ['g', {"class": "edge"}]
  10682. ],
  10683. ['g', {"class": "controls"},
  10684. ['g', {"class": "dockers"}],
  10685. ['g', {"class": "magnets"}]
  10686. ]
  10687. ]);
  10688. },
  10689. /**
  10690. * If changed flag is set, refresh method is called.
  10691. */
  10692. update: function() {
  10693. //if(this.isChanged) {
  10694. //this.layout();
  10695. //}
  10696. },
  10697. /**
  10698. * !!!Not called from any sub class!!!
  10699. */
  10700. _update: function() {
  10701. },
  10702. /**
  10703. * Calls the super class refresh method
  10704. * and updates the svg elements that are referenced by a property.
  10705. */
  10706. refresh: function() {
  10707. //call base class refresh method
  10708. arguments.callee.$.refresh.apply(this, arguments);
  10709. if(this.node.ownerDocument) {
  10710. //adjust SVG to properties' values
  10711. var me = this;
  10712. this.propertiesChanged.each((function(propChanged) {
  10713. if(propChanged.value) {
  10714. var prop = this.properties[propChanged.key];
  10715. var property = this.getStencil().property(propChanged.key);
  10716. if (property != undefined) {
  10717. this.propertiesChanged[propChanged.key] = false;
  10718. //handle choice properties
  10719. if(property.type() == ORYX.CONFIG.TYPE_CHOICE) {
  10720. //iterate all references to SVG elements
  10721. property.refToView().each((function(ref) {
  10722. //if property is referencing a label, update the label
  10723. if(ref !== "") {
  10724. var label = this._labels[this.id + ref];
  10725. if (label && property.item(prop)) {
  10726. label.text(property.item(prop).title());
  10727. }
  10728. }
  10729. }).bind(this));
  10730. //if the choice's items are referencing SVG elements
  10731. // show the selected and hide all other referenced SVG
  10732. // elements
  10733. var refreshedSvgElements = new Hash();
  10734. property.items().each((function(item) {
  10735. item.refToView().each((function(itemRef) {
  10736. if(itemRef == "") { return; }
  10737. var svgElem = this.node.ownerDocument.getElementById(this.id + itemRef);
  10738. if(!svgElem) { return; }
  10739. /* Do not refresh the same svg element multiple times */
  10740. if(!refreshedSvgElements[svgElem.id] || prop == item.value()) {
  10741. svgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none'));
  10742. refreshedSvgElements[svgElem.id] = svgElem;
  10743. }
  10744. // Reload the href if there is an image-tag
  10745. if(ORYX.Editor.checkClassType(svgElem, SVGImageElement)) {
  10746. svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href'));
  10747. }
  10748. }).bind(this));
  10749. }).bind(this));
  10750. } else { //handle properties that are not of type choice
  10751. //iterate all references to SVG elements
  10752. property.refToView().each((function(ref) {
  10753. //if the property does not reference an SVG element,
  10754. // do nothing
  10755. if(ref === "") { return; }
  10756. var refId = this.id + ref;
  10757. if (property.type() === ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE)
  10758. {
  10759. if (ref === "multiinstance") {
  10760. var svgElemParallel = this.node.ownerDocument.getElementById(this.id + 'parallel');
  10761. if(svgElemParallel)
  10762. {
  10763. if (prop === 'Parallel')
  10764. {
  10765. svgElemParallel.setAttributeNS(null, 'display', 'inherit');
  10766. }
  10767. else
  10768. {
  10769. svgElemParallel.setAttributeNS(null, 'display', 'none');
  10770. }
  10771. }
  10772. var svgElemSequential = this.node.ownerDocument.getElementById(this.id + 'sequential');
  10773. if(svgElemSequential)
  10774. {
  10775. if (prop === 'Sequential')
  10776. {
  10777. svgElemSequential.setAttributeNS(null, 'display', 'inherit');
  10778. }
  10779. else
  10780. {
  10781. svgElemSequential.setAttributeNS(null, 'display', 'none');
  10782. }
  10783. }
  10784. }
  10785. return;
  10786. }
  10787. else if (property.type() === "cancelactivity")
  10788. {
  10789. var svgElemFrame = this.node.ownerDocument.getElementById(this.id + 'frame');
  10790. var svgElemFrame2 = this.node.ownerDocument.getElementById(this.id + 'frame2');
  10791. if (prop === 'true')
  10792. {
  10793. svgElemFrame.setAttributeNS(null, 'display', 'inherit');
  10794. svgElemFrame2.setAttributeNS(null, 'display', 'inherit');
  10795. }
  10796. else
  10797. {
  10798. svgElemFrame.setAttributeNS(null, 'display', 'none');
  10799. svgElemFrame2.setAttributeNS(null, 'display', 'none');
  10800. }
  10801. }
  10802. //get the SVG element
  10803. var svgElem = this.node.ownerDocument.getElementById(refId);
  10804. //if the SVG element can not be found
  10805. if(!svgElem || !(svgElem.ownerSVGElement)) {
  10806. //if the referenced SVG element is a SVGAElement, it cannot
  10807. // be found with getElementById (Firefox bug).
  10808. // this is a work around
  10809. if(property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) {
  10810. var svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a');
  10811. svgElem = $A(svgElems).find(function(elem) {
  10812. return elem.getAttributeNS(null, 'id') === refId;
  10813. });
  10814. if(!svgElem) { return; }
  10815. } else {
  10816. //this.propertiesChanged[propChanged.key] = true;
  10817. return;
  10818. }
  10819. }
  10820. if (property.complexAttributeToView()) {
  10821. var label = this._labels[refId];
  10822. if (label) {
  10823. try {
  10824. propJson = prop.evalJSON();
  10825. var value = propJson[property.complexAttributeToView()]
  10826. label.text(value ? value : prop);
  10827. } catch (e) {
  10828. label.text(prop);
  10829. }
  10830. }
  10831. } else {
  10832. switch (property.type()) {
  10833. case ORYX.CONFIG.TYPE_BOOLEAN:
  10834. if (typeof prop == "string")
  10835. prop = prop === "true"
  10836. svgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none');
  10837. break;
  10838. case ORYX.CONFIG.TYPE_COLOR:
  10839. if(property.fill()) {
  10840. if (svgElem.tagName.toLowerCase() === "stop"){
  10841. if (prop){
  10842. if (property.lightness() && property.lightness() !== 1){
  10843. prop = ORYX.Utils.adjustLightness(prop, property.lightness());
  10844. }
  10845. svgElem.setAttributeNS(null, "stop-color", prop);
  10846. // Adjust stop color of the others
  10847. if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){
  10848. ORYX.Utils.adjustGradient(svgElem.parentNode, svgElem);
  10849. }
  10850. }
  10851. // If there is no value, set opaque
  10852. if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){
  10853. $A(svgElem.parentNode.getElementsByTagName('stop')).each(function(stop){
  10854. stop.setAttributeNS(null, "stop-opacity", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0);
  10855. }.bind(this))
  10856. }
  10857. } else {
  10858. svgElem.setAttributeNS(null, 'fill', prop);
  10859. }
  10860. }
  10861. if(property.stroke()) {
  10862. svgElem.setAttributeNS(null, 'stroke', prop);
  10863. }
  10864. break;
  10865. case ORYX.CONFIG.TYPE_STRING:
  10866. var label = this._labels[refId];
  10867. if (label) {
  10868. label.text(prop);
  10869. }
  10870. break;
  10871. case ORYX.CONFIG.TYPE_EXPRESSION:
  10872. var label = this._labels[refId];
  10873. if (label) {
  10874. label.text(prop);
  10875. }
  10876. break;
  10877. case ORYX.CONFIG.TYPE_DATASOURCE:
  10878. var label = this._labels[refId];
  10879. if (label) {
  10880. label.text(prop);
  10881. }
  10882. break;
  10883. case ORYX.CONFIG.TYPE_INTEGER:
  10884. var label = this._labels[refId];
  10885. if (label) {
  10886. label.text(prop);
  10887. }
  10888. break;
  10889. case ORYX.CONFIG.TYPE_FLOAT:
  10890. if(property.fillOpacity()) {
  10891. svgElem.setAttributeNS(null, 'fill-opacity', prop);
  10892. }
  10893. if(property.strokeOpacity()) {
  10894. svgElem.setAttributeNS(null, 'stroke-opacity', prop);
  10895. }
  10896. if(!property.fillOpacity() && !property.strokeOpacity()) {
  10897. var label = this._labels[refId];
  10898. if (label) {
  10899. label.text(prop);
  10900. }
  10901. }
  10902. break;
  10903. case ORYX.CONFIG.TYPE_FORM_LINK:
  10904. if (ref == "pimg") {
  10905. var onclickAttr = svgElem.getAttributeNodeNS('', 'onclick');
  10906. if(onclickAttr) {
  10907. if(prop && ("" + prop).length > 0) {
  10908. onclickAttr.textContent = "window.location = '../service/editor?id=" + prop + "_form'";
  10909. } else {
  10910. newFormFacade = this.facade;
  10911. onclickAttr.textContent = "displayNewFormDialog('" + this.resourceId + "');";
  10912. }
  10913. }
  10914. } else if (ref == "linkIndicator") {
  10915. if (prop && prop.length > 0) {
  10916. svgElem.setAttributeNS(null, 'display', 'inherit');
  10917. } else {
  10918. svgElem.setAttributeNS(null, 'display', 'none');
  10919. }
  10920. }
  10921. break;
  10922. case ORYX.CONFIG.TYPE_URL:
  10923. case ORYX.CONFIG.TYPE_DIAGRAM_LINK:
  10924. //TODO what is the dafault path?
  10925. var hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href');
  10926. if(hrefAttr) {
  10927. hrefAttr.textContent = prop;
  10928. } else {
  10929. svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop);
  10930. }
  10931. break;
  10932. }
  10933. }
  10934. }).bind(this));
  10935. }
  10936. }
  10937. }
  10938. }).bind(this));
  10939. //update labels
  10940. this._labels.values().each(function(label) {
  10941. label.update();
  10942. });
  10943. }
  10944. },
  10945. layout: function() {
  10946. //this.getStencil().layout(this)
  10947. var layoutEvents = this.getStencil().layout()
  10948. if (layoutEvents) {
  10949. layoutEvents.each(function(event) {
  10950. // setup additional attributes
  10951. event.shape = this;
  10952. event.forceExecution = true;
  10953. // do layouting
  10954. this._delegateEvent(event);
  10955. }.bind(this))
  10956. }
  10957. },
  10958. /**
  10959. * Returns an array of Label objects.
  10960. */
  10961. getLabels: function() {
  10962. return this._labels.values();
  10963. },
  10964. /**
  10965. * Returns the label for a given ref
  10966. * @return {ORYX.Core.Label} Returns null if there is no label
  10967. */
  10968. getLabel: function(ref){
  10969. if (!ref){
  10970. return null;
  10971. }
  10972. return (this._labels.find(function(o){
  10973. return o.key.endsWith(ref);
  10974. })||{}).value || null;
  10975. },
  10976. /**
  10977. * Hides all related labels
  10978. *
  10979. */
  10980. hideLabels: function(){
  10981. this.getLabels().invoke("hide");
  10982. },
  10983. /**
  10984. * Shows all related labels
  10985. *
  10986. */
  10987. showLabels: function(){
  10988. var labels = this.getLabels();
  10989. labels.invoke("show");
  10990. labels.each(function(label) {
  10991. label.update();
  10992. });
  10993. },
  10994. setOpacity: function(value, animate){
  10995. value = Math.max(Math.min((typeof value == "number" ? value : 1.0), 1.0), 0.0);
  10996. if (value !== 1.0){
  10997. value = String(value);
  10998. this.node.setAttributeNS(null, "fill-opacity", value)
  10999. this.node.setAttributeNS(null, "stroke-opacity", value)
  11000. } else {
  11001. this.node.removeAttributeNS(null, "fill-opacity");
  11002. this.node.removeAttributeNS(null, "stroke-opacity");
  11003. }
  11004. },
  11005. /**
  11006. * Returns an array of dockers of this object.
  11007. */
  11008. getDockers: function() {
  11009. return this.dockers;
  11010. },
  11011. getMagnets: function() {
  11012. return this.magnets;
  11013. },
  11014. getDefaultMagnet: function() {
  11015. if(this._defaultMagnet) {
  11016. return this._defaultMagnet;
  11017. } else if (this.magnets.length > 0) {
  11018. return this.magnets[0];
  11019. } else {
  11020. return undefined;
  11021. }
  11022. },
  11023. getParentShape: function() {
  11024. return this.parent;
  11025. },
  11026. getIncomingShapes: function(iterator) {
  11027. if(iterator) {
  11028. this.incoming.each(iterator);
  11029. }
  11030. return this.incoming;
  11031. },
  11032. getIncomingNodes: function(iterator) {
  11033. return this.incoming.select(function(incoming){
  11034. var isNode = (incoming instanceof ORYX.Core.Node);
  11035. if(isNode && iterator) iterator(incoming);
  11036. return isNode;
  11037. });
  11038. },
  11039. getOutgoingShapes: function(iterator) {
  11040. if(iterator) {
  11041. this.outgoing.each(iterator);
  11042. }
  11043. return this.outgoing;
  11044. },
  11045. getOutgoingNodes: function(iterator) {
  11046. return this.outgoing.select(function(out){
  11047. var isNode = (out instanceof ORYX.Core.Node);
  11048. if(isNode && iterator) iterator(out);
  11049. return isNode;
  11050. });
  11051. },
  11052. getAllDockedShapes: function(iterator) {
  11053. var result = this.incoming.concat(this.outgoing);
  11054. if(iterator) {
  11055. result.each(iterator);
  11056. }
  11057. return result
  11058. },
  11059. getCanvas: function() {
  11060. if(this.parent instanceof ORYX.Core.Canvas) {
  11061. return this.parent;
  11062. } else if(this.parent instanceof ORYX.Core.Shape) {
  11063. return this.parent.getCanvas();
  11064. } else {
  11065. return undefined;
  11066. }
  11067. },
  11068. /**
  11069. *
  11070. * @param {Object} deep
  11071. * @param {Object} iterator
  11072. */
  11073. getChildNodes: function(deep, iterator) {
  11074. if(!deep && !iterator) {
  11075. return this.nodes.clone();
  11076. } else {
  11077. var result = [];
  11078. this.nodes.each(function(uiObject) {
  11079. if(!uiObject.isVisible){return}
  11080. if(iterator) {
  11081. iterator(uiObject);
  11082. }
  11083. result.push(uiObject);
  11084. if(deep && uiObject instanceof ORYX.Core.Shape) {
  11085. result = result.concat(uiObject.getChildNodes(deep, iterator));
  11086. }
  11087. });
  11088. return result;
  11089. }
  11090. },
  11091. /**
  11092. * Overrides the UIObject.add method. Adds uiObject to the correct sub node.
  11093. * @param {UIObject} uiObject
  11094. * @param {Number} index
  11095. */
  11096. add: function(uiObject, index, silent) {
  11097. //parameter has to be an UIObject, but
  11098. // must not be an Edge.
  11099. if(uiObject instanceof ORYX.Core.UIObject
  11100. && !(uiObject instanceof ORYX.Core.Edge)) {
  11101. if (!(this.children.member(uiObject))) {
  11102. //if uiObject is child of another parent, remove it from that parent.
  11103. if(uiObject.parent) {
  11104. uiObject.parent.remove(uiObject, true);
  11105. }
  11106. //add uiObject to this Shape
  11107. if(index != undefined)
  11108. this.children.splice(index, 0, uiObject);
  11109. else
  11110. this.children.push(uiObject);
  11111. //set parent reference
  11112. uiObject.parent = this;
  11113. //add uiObject.node to this.node depending on the type of uiObject
  11114. var parent;
  11115. if(uiObject instanceof ORYX.Core.Node) {
  11116. parent = this.node.childNodes[0].childNodes[1];
  11117. this.nodes.push(uiObject);
  11118. } else if(uiObject instanceof ORYX.Core.Controls.Control) {
  11119. var ctrls = this.node.childNodes[1];
  11120. if(uiObject instanceof ORYX.Core.Controls.Docker) {
  11121. parent = ctrls.childNodes[0];
  11122. if (this.dockers.length >= 2){
  11123. this.dockers.splice(index!==undefined?Math.min(index, this.dockers.length-1):this.dockers.length-1, 0, uiObject);
  11124. } else {
  11125. this.dockers.push(uiObject);
  11126. }
  11127. } else if(uiObject instanceof ORYX.Core.Controls.Magnet) {
  11128. parent = ctrls.childNodes[1];
  11129. this.magnets.push(uiObject);
  11130. } else {
  11131. parent = ctrls;
  11132. }
  11133. } else { //UIObject
  11134. parent = this.node;
  11135. }
  11136. if(index != undefined && index < parent.childNodes.length)
  11137. uiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]);
  11138. else
  11139. uiObject.node = parent.appendChild(uiObject.node);
  11140. this._changed();
  11141. //uiObject.bounds.registerCallback(this._changedCallback);
  11142. if(this.eventHandlerCallback && silent !== true)
  11143. this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})
  11144. } else {
  11145. ORYX.Log.warn("add: ORYX.Core.UIObject is already a child of this object.");
  11146. }
  11147. } else {
  11148. ORYX.Log.warn("add: Parameter is not of type ORYX.Core.UIObject.");
  11149. }
  11150. },
  11151. /**
  11152. * Overrides the UIObject.remove method. Removes uiObject.
  11153. * @param {UIObject} uiObject
  11154. */
  11155. remove: function(uiObject, silent) {
  11156. //if uiObject is a child of this object, remove it.
  11157. if (this.children.member(uiObject)) {
  11158. //remove uiObject from children
  11159. var parent = uiObject.parent;
  11160. this.children = this.children.without(uiObject);
  11161. //delete parent reference of uiObject
  11162. uiObject.parent = undefined;
  11163. //delete uiObject.node from this.node
  11164. if(uiObject instanceof ORYX.Core.Shape) {
  11165. if(uiObject instanceof ORYX.Core.Edge) {
  11166. uiObject.removeMarkers();
  11167. uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);
  11168. } else {
  11169. uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);
  11170. this.nodes = this.nodes.without(uiObject);
  11171. }
  11172. } else if(uiObject instanceof ORYX.Core.Controls.Control) {
  11173. if (uiObject instanceof ORYX.Core.Controls.Docker) {
  11174. uiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node);
  11175. this.dockers = this.dockers.without(uiObject);
  11176. } else if (uiObject instanceof ORYX.Core.Controls.Magnet) {
  11177. uiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node);
  11178. this.magnets = this.magnets.without(uiObject);
  11179. } else {
  11180. uiObject.node = this.node.childNodes[1].removeChild(uiObject.node);
  11181. }
  11182. }
  11183. if(this.eventHandlerCallback && silent !== true)
  11184. this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent});
  11185. this._changed();
  11186. //uiObject.bounds.unregisterCallback(this._changedCallback);
  11187. } else {
  11188. ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object.");
  11189. }
  11190. },
  11191. /**
  11192. * Calculate the Border Intersection Point between two points
  11193. * @param {PointA}
  11194. * @param {PointB}
  11195. */
  11196. getIntersectionPoint: function() {
  11197. var pointAX, pointAY, pointBX, pointBY;
  11198. // Get the the two Points
  11199. switch(arguments.length) {
  11200. case 2:
  11201. pointAX = arguments[0].x;
  11202. pointAY = arguments[0].y;
  11203. pointBX = arguments[1].x;
  11204. pointBY = arguments[1].y;
  11205. break;
  11206. case 4:
  11207. pointAX = arguments[0];
  11208. pointAY = arguments[1];
  11209. pointBX = arguments[2];
  11210. pointBY = arguments[3];
  11211. break;
  11212. default:
  11213. throw "getIntersectionPoints needs two or four arguments";
  11214. }
  11215. // Defined an include and exclude point
  11216. var includePointX, includePointY, excludePointX, excludePointY;
  11217. var bounds = this.absoluteBounds();
  11218. if(this.isPointIncluded(pointAX, pointAY, bounds)){
  11219. includePointX = pointAX;
  11220. includePointY = pointAY;
  11221. } else {
  11222. excludePointX = pointAX;
  11223. excludePointY = pointAY;
  11224. }
  11225. if(this.isPointIncluded(pointBX, pointBY, bounds)){
  11226. includePointX = pointBX;
  11227. includePointY = pointBY;
  11228. } else {
  11229. excludePointX = pointBX;
  11230. excludePointY = pointBY;
  11231. }
  11232. // If there is no inclue or exclude Shape, than return
  11233. if(!includePointX || !includePointY || !excludePointX || !excludePointY) {
  11234. return undefined;
  11235. }
  11236. var midPointX = 0;
  11237. var midPointY = 0;
  11238. var refPointX, refPointY;
  11239. var minDifferent = 1;
  11240. // Get the UpperLeft and LowerRight
  11241. //var ul = bounds.upperLeft();
  11242. //var lr = bounds.lowerRight();
  11243. var i = 0;
  11244. while(true) {
  11245. // Calculate the midpoint of the current to points
  11246. var midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0);
  11247. var midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0);
  11248. // Set the new midpoint by the means of the include of the bounds
  11249. if(this.isPointIncluded(midPointX, midPointY, bounds)){
  11250. includePointX = midPointX;
  11251. includePointY = midPointY;
  11252. } else {
  11253. excludePointX = midPointX;
  11254. excludePointY = midPointY;
  11255. }
  11256. // Calc the length of the line
  11257. var length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2))
  11258. // Calc a point one step from the include point
  11259. refPointX = includePointX + ((excludePointX - includePointX) / length),
  11260. refPointY = includePointY + ((excludePointY - includePointY) / length)
  11261. // If the reference point not in the bounds, break
  11262. if(!this.isPointIncluded(refPointX, refPointY, bounds)) {
  11263. break
  11264. }
  11265. }
  11266. // Return the last includepoint
  11267. return {x:refPointX , y:refPointY};
  11268. },
  11269. /**
  11270. * Calculate if the point is inside the Shape
  11271. * @param {PointX}
  11272. * @param {PointY}
  11273. */
  11274. isPointIncluded: function(){
  11275. return false
  11276. },
  11277. /**
  11278. * Returns TRUE if the given node
  11279. * is a child node of the shapes node
  11280. * @param {Element} node
  11281. * @return {Boolean}
  11282. *
  11283. */
  11284. containsNode: function(node){
  11285. var me = this.node.firstChild.firstChild;
  11286. while(node){
  11287. if (node == me){
  11288. return true;
  11289. }
  11290. node = node.parentNode;
  11291. }
  11292. return false
  11293. },
  11294. /**
  11295. * Calculate if the point is over an special offset area
  11296. * @param {Point}
  11297. */
  11298. isPointOverOffset: function(){
  11299. return this.isPointIncluded.apply( this , arguments )
  11300. },
  11301. _dockerChanged: function() {
  11302. },
  11303. /**
  11304. * Create a Docker for this Edge
  11305. *
  11306. */
  11307. createDocker: function(index, position) {
  11308. var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});
  11309. docker.bounds.registerCallback(this._dockerChangedCallback);
  11310. if (position) {
  11311. docker.bounds.centerMoveTo(position);
  11312. }
  11313. this.add(docker, index);
  11314. return docker
  11315. },
  11316. /**
  11317. * Get the serialized object
  11318. * return Array with hash-entrees (prefix, name, value)
  11319. * Following values will given:
  11320. * Bounds
  11321. * Outgoing Shapes
  11322. * Parent
  11323. */
  11324. serialize: function() {
  11325. var serializedObject = arguments.callee.$.serialize.apply(this);
  11326. // Add the bounds
  11327. serializedObject.push({name: 'bounds', prefix:'oryx', value: this.bounds.serializeForERDF(), type: 'literal'});
  11328. // Add the outgoing shapes
  11329. this.getOutgoingShapes().each((function(followingShape){
  11330. serializedObject.push({name: 'outgoing', prefix:'raziel', value: '#'+ERDF.__stripHashes(followingShape.resourceId), type: 'resource'});
  11331. }).bind(this));
  11332. // Add the parent shape, if the parent not the canvas
  11333. //if(this.parent instanceof ORYX.Core.Shape){
  11334. serializedObject.push({name: 'parent', prefix:'raziel', value: '#'+ERDF.__stripHashes(this.parent.resourceId), type: 'resource'});
  11335. //}
  11336. return serializedObject;
  11337. },
  11338. deserialize: function(serialize, json){
  11339. arguments.callee.$.deserialize.apply(this, arguments);
  11340. // Set the Bounds
  11341. var bounds = serialize.find(function(ser){ return 'oryx-bounds' === (ser.prefix+"-"+ser.name) });
  11342. if (bounds) {
  11343. var b = bounds.value.replace(/,/g, " ").split(" ").without("");
  11344. if (this instanceof ORYX.Core.Edge) {
  11345. if (!this.dockers.first().isChanged)
  11346. this.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1]));
  11347. if (!this.dockers.last().isChanged)
  11348. this.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3]));
  11349. } else {
  11350. this.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3]));
  11351. }
  11352. }
  11353. if (json && json.labels instanceof Array){
  11354. json.labels.each(function(slabel){
  11355. var label = this.getLabel(slabel.ref);
  11356. if (label){
  11357. label.deserialize(slabel, this);
  11358. }
  11359. }.bind(this))
  11360. }
  11361. },
  11362. toJSON: function(){
  11363. var json = arguments.callee.$.toJSON.apply(this, arguments);
  11364. var labels = [], id = this.id;
  11365. this._labels.each(function(obj){
  11366. var slabel = obj.value.serialize();
  11367. if (slabel){
  11368. slabel.ref = obj.key.replace(id, '');
  11369. labels.push(slabel);
  11370. }
  11371. });
  11372. if (labels.length > 0){
  11373. json.labels = labels;
  11374. }
  11375. return json;
  11376. },
  11377. /**
  11378. * Private methods.
  11379. */
  11380. /**
  11381. * Child classes have to overwrite this method for initializing a loaded
  11382. * SVG representation.
  11383. * @param {SVGDocument} svgDocument
  11384. */
  11385. _init: function(svgDocument) {
  11386. //adjust ids
  11387. this._adjustIds(svgDocument, 0);
  11388. },
  11389. _adjustIds: function(element, idIndex) {
  11390. if(element instanceof Element) {
  11391. var eid = element.getAttributeNS(null, 'id');
  11392. if(eid && eid !== "") {
  11393. element.setAttributeNS(null, 'id', this.id + eid);
  11394. } else {
  11395. element.setAttributeNS(null, 'id', this.id + "_" + this.id + "_" + idIndex);
  11396. idIndex++;
  11397. }
  11398. // Replace URL in fill attribute
  11399. var fill = element.getAttributeNS(null, 'fill');
  11400. if (fill&&fill.include("url(#")){
  11401. fill = fill.replace(/url\(#/g, 'url(#'+this.id);
  11402. element.setAttributeNS(null, 'fill', fill);
  11403. }
  11404. if(element.hasChildNodes()) {
  11405. for(var i = 0; i < element.childNodes.length; i++) {
  11406. idIndex = this._adjustIds(element.childNodes[i], idIndex);
  11407. }
  11408. }
  11409. }
  11410. return idIndex;
  11411. },
  11412. toString: function() { return "ORYX.Core.Shape " + this.getId() }
  11413. };
  11414. ORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/*
  11415. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  11416. * License rights for this program may be obtained from Alfresco Software, Ltd.
  11417. * pursuant to a written agreement and any use of this program without such an
  11418. * agreement is prohibited.
  11419. */
  11420. /*
  11421. * All code Copyright 2013 KIS Consultancy all rights reserved
  11422. */
  11423. /**
  11424. * Init namespaces
  11425. */
  11426. if(!ORYX) {var ORYX = {};}
  11427. if(!ORYX.Core) {ORYX.Core = {};}
  11428. if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
  11429. /**
  11430. * @classDescription Abstract base class for all Controls.
  11431. */
  11432. ORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({
  11433. toString: function() { return "Control " + this.id; }
  11434. });/*
  11435. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  11436. * License rights for this program may be obtained from Alfresco Software, Ltd.
  11437. * pursuant to a written agreement and any use of this program without such an
  11438. * agreement is prohibited.
  11439. */
  11440. /*
  11441. * All code Copyright 2013 KIS Consultancy all rights reserved
  11442. */
  11443. /**
  11444. * Init namespaces
  11445. */
  11446. if(!ORYX) {var ORYX = {};}
  11447. if(!ORYX.Core) {ORYX.Core = {};}
  11448. if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
  11449. /**
  11450. * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used
  11451. * for positioning shape objects.
  11452. * @extends {Control}
  11453. *
  11454. * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!!
  11455. */
  11456. ORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({
  11457. /**
  11458. * Constructor
  11459. */
  11460. construct: function() {
  11461. arguments.callee.$.construct.apply(this, arguments);
  11462. this.isMovable = true; // Enables movability
  11463. this.bounds.set(0, 0, 16, 16); // Set the bounds
  11464. this.referencePoint = undefined; // Refrenzpoint
  11465. this._dockedShapeBounds = undefined;
  11466. this._dockedShape = undefined;
  11467. this._oldRefPoint1 = undefined;
  11468. this._oldRefPoint2 = undefined;
  11469. //this.anchors = [];
  11470. this.anchorLeft;
  11471. this.anchorRight;
  11472. this.anchorTop;
  11473. this.anchorBottom;
  11474. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
  11475. null,
  11476. ['g']);
  11477. // The DockerNode reprasentation
  11478. this._dockerNode = ORYX.Editor.graft("http://www.w3.org/2000/svg",
  11479. this.node,
  11480. ['g', {"pointer-events":"all"},
  11481. ['circle', {cx:"8", cy:"8", r:"8", stroke:"none", fill:"none"}],
  11482. ['circle', {cx:"8", cy:"8", r:"3", stroke:"black", fill:"red", "stroke-width":"1"}]
  11483. ]);
  11484. // The ReferenzNode reprasentation
  11485. this._referencePointNode = ORYX.Editor.graft("http://www.w3.org/2000/svg",
  11486. this.node,
  11487. ['g', {"pointer-events":"none"},
  11488. ['circle', {cx: this.bounds.upperLeft().x, cy: this.bounds.upperLeft().y, r: 3, fill:"red", "fill-opacity":0.4}]]);
  11489. // Hide the Docker
  11490. this.hide();
  11491. //Add to the EventHandler
  11492. this.addEventHandlers(this._dockerNode);
  11493. // Buffer the Update Callback for un-/register on Event-Handler
  11494. this._updateCallback = this._changed.bind(this);
  11495. },
  11496. update: function() {
  11497. // If there have an DockedShape
  11498. if(this._dockedShape) {
  11499. if(this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) {
  11500. // Calc the delta of width and height of the lastBounds and the current Bounds
  11501. var dswidth = this._dockedShapeBounds.width();
  11502. var dsheight = this._dockedShapeBounds.height();
  11503. if(!dswidth)
  11504. dswidth = 1;
  11505. if(!dsheight)
  11506. dsheight = 1;
  11507. var widthDelta = this._dockedShape.bounds.width() / dswidth;
  11508. var heightDelta = this._dockedShape.bounds.height() / dsheight;
  11509. // If there is an different
  11510. if(widthDelta !== 1.0 || heightDelta !== 1.0) {
  11511. // Set the delta
  11512. this.referencePoint.x *= widthDelta;
  11513. this.referencePoint.y *= heightDelta;
  11514. }
  11515. // Clone these bounds
  11516. this._dockedShapeBounds = this._dockedShape.bounds.clone();
  11517. }
  11518. // Get the first and the last Docker of the parent Shape
  11519. var dockerIndex = this.parent.dockers.indexOf(this)
  11520. var dock1 = this;
  11521. var dock2 = this.parent.dockers.length > 1 ?
  11522. (dockerIndex === 0? // If there is the first element
  11523. this.parent.dockers[dockerIndex + 1]: // then take the next docker
  11524. this.parent.dockers[dockerIndex - 1]): // if not, then take the docker before
  11525. undefined;
  11526. // Calculate the first absolute Refenzpoint
  11527. var absoluteReferenzPoint1 = dock1.getDockedShape() ?
  11528. dock1.getAbsoluteReferencePoint() :
  11529. dock1.bounds.center();
  11530. // Calculate the last absolute Refenzpoint
  11531. var absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ?
  11532. dock2.getAbsoluteReferencePoint() :
  11533. dock2 ?
  11534. dock2.bounds.center() :
  11535. undefined;
  11536. // If there is no last absolute Referenzpoint
  11537. if(!absoluteReferenzPoint2) {
  11538. // Calculate from the middle of the DockedShape
  11539. var center = this._dockedShape.absoluteCenterXY();
  11540. var minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height();
  11541. absoluteReferenzPoint2 = {
  11542. x: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension,
  11543. y: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension
  11544. }
  11545. }
  11546. var newPoint = undefined;
  11547. /*if (!this._oldRefPoint1 || !this._oldRefPoint2 ||
  11548. absoluteReferenzPoint1.x !== this._oldRefPoint1.x ||
  11549. absoluteReferenzPoint1.y !== this._oldRefPoint1.y ||
  11550. absoluteReferenzPoint2.x !== this._oldRefPoint2.x ||
  11551. absoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/
  11552. // Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points
  11553. newPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2);
  11554. // If there is new point, take the referencepoint as the new point
  11555. if(!newPoint) {
  11556. newPoint = this.getAbsoluteReferencePoint();
  11557. }
  11558. if(this.parent && this.parent.parent) {
  11559. var grandParentPos = this.parent.parent.absoluteXY();
  11560. newPoint.x -= grandParentPos.x;
  11561. newPoint.y -= grandParentPos.y;
  11562. }
  11563. // Set the bounds to the new point
  11564. this.bounds.centerMoveTo(newPoint)
  11565. this._oldRefPoint1 = absoluteReferenzPoint1;
  11566. this._oldRefPoint2 = absoluteReferenzPoint2;
  11567. }
  11568. /*else {
  11569. newPoint = this.bounds.center();
  11570. }*/
  11571. // }
  11572. // Call the super class
  11573. arguments.callee.$.update.apply(this, arguments);
  11574. },
  11575. /**
  11576. * Calls the super class refresh method and updates the view of the docker.
  11577. */
  11578. refresh: function() {
  11579. arguments.callee.$.refresh.apply(this, arguments);
  11580. // Refresh the dockers node
  11581. var p = this.bounds.upperLeft();
  11582. this._dockerNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
  11583. // Refresh the referencepoints node
  11584. p = Object.clone(this.referencePoint);
  11585. if(p && this._dockedShape){
  11586. var upL
  11587. if(this.parent instanceof ORYX.Core.Edge) {
  11588. upL = this._dockedShape.absoluteXY();
  11589. } else {
  11590. upL = this._dockedShape.bounds.upperLeft();
  11591. }
  11592. p.x += upL.x;
  11593. p.y += upL.y;
  11594. } else {
  11595. p = this.bounds.center();
  11596. }
  11597. this._referencePointNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
  11598. },
  11599. /**
  11600. * Set the reference point
  11601. * @param {Object} point
  11602. */
  11603. setReferencePoint: function(point) {
  11604. // Set the referencepoint
  11605. if(this.referencePoint !== point &&
  11606. (!this.referencePoint ||
  11607. !point ||
  11608. this.referencePoint.x !== point.x ||
  11609. this.referencePoint.y !== point.y)) {
  11610. this.referencePoint = point;
  11611. this._changed();
  11612. }
  11613. // Update directly, because the referencepoint has no influence of the bounds
  11614. //this.refresh();
  11615. },
  11616. /**
  11617. * Get the absolute referencepoint
  11618. */
  11619. getAbsoluteReferencePoint: function() {
  11620. if(!this.referencePoint || !this._dockedShape) {
  11621. return undefined;
  11622. } else {
  11623. var absUL = this._dockedShape.absoluteXY();
  11624. return {
  11625. x: this.referencePoint.x + absUL.x,
  11626. y: this.referencePoint.y + absUL.y
  11627. }
  11628. }
  11629. },
  11630. /**
  11631. * Set the docked Shape from the docker
  11632. * @param {Object} shape
  11633. */
  11634. setDockedShape: function(shape) {
  11635. // If there is an old docked Shape
  11636. if(this._dockedShape) {
  11637. this._dockedShape.bounds.unregisterCallback(this._updateCallback)
  11638. // Delete the Shapes from the incoming and outgoing array
  11639. // If this Docker the incoming of the Shape
  11640. if(this === this.parent.dockers.first()) {
  11641. this.parent.incoming = this.parent.incoming.without(this._dockedShape);
  11642. this._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent);
  11643. // If this Docker the outgoing of the Shape
  11644. } else if (this === this.parent.dockers.last()){
  11645. this.parent.outgoing = this.parent.outgoing.without(this._dockedShape);
  11646. this._dockedShape.incoming = this._dockedShape.incoming.without(this.parent);
  11647. }
  11648. }
  11649. // Set the new Shape
  11650. this._dockedShape = shape;
  11651. this._dockedShapeBounds = undefined;
  11652. var referencePoint = undefined;
  11653. // If there is an Shape, register the updateCallback if there are changes in the shape bounds
  11654. if(this._dockedShape) {
  11655. // Add the Shapes to the incoming and outgoing array
  11656. // If this Docker the incoming of the Shape
  11657. if(this === this.parent.dockers.first()) {
  11658. this.parent.incoming.push(shape);
  11659. shape.outgoing.push(this.parent);
  11660. // If this Docker the outgoing of the Shape
  11661. } else if (this === this.parent.dockers.last()){
  11662. this.parent.outgoing.push(shape);
  11663. shape.incoming.push(this.parent);
  11664. }
  11665. // Get the bounds and set the new referencepoint
  11666. var bounds = this.bounds;
  11667. var absUL = shape.absoluteXY();
  11668. /*if(shape.parent){
  11669. var b = shape.parent.bounds.upperLeft();
  11670. absUL.x -= b.x;
  11671. absUL.y -= b.y;
  11672. }*/
  11673. referencePoint = {
  11674. x: bounds.center().x - absUL.x,
  11675. y: bounds.center().y - absUL.y
  11676. }
  11677. this._dockedShapeBounds = this._dockedShape.bounds.clone();
  11678. this._dockedShape.bounds.registerCallback(this._updateCallback);
  11679. // Set the color of the docker as docked
  11680. this.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR);
  11681. } else {
  11682. // Set the color of the docker as undocked
  11683. this.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR);
  11684. }
  11685. // Set the referencepoint
  11686. this.setReferencePoint(referencePoint);
  11687. this._changed();
  11688. //this.update();
  11689. },
  11690. /**
  11691. * Get the docked Shape
  11692. */
  11693. getDockedShape: function() {
  11694. return this._dockedShape;
  11695. },
  11696. /**
  11697. * Returns TRUE if the docker has a docked shape
  11698. */
  11699. isDocked: function() {
  11700. return !!this._dockedShape;
  11701. },
  11702. /**
  11703. * Set the Color of the Docker
  11704. * @param {Object} color
  11705. */
  11706. setDockerColor: function(color) {
  11707. this._dockerNode.lastChild.setAttributeNS(null, "fill", color);
  11708. },
  11709. preventHiding: function(prevent){
  11710. this._preventHiding = Math.max(0, (this._preventHiding||0) + (prevent ? 1 : -1));
  11711. },
  11712. /**
  11713. * Hides this UIObject and all its children.
  11714. */
  11715. hide: function() {
  11716. if (this._preventHiding){
  11717. return false;
  11718. }
  11719. // Hide docker and reference point
  11720. this.node.setAttributeNS(null, 'visibility', 'hidden');
  11721. this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');
  11722. this.children.each(function(uiObj) {
  11723. uiObj.hide();
  11724. });
  11725. },
  11726. /**
  11727. * Enables visibility of this UIObject and all its children.
  11728. */
  11729. show: function() {
  11730. // Show docker
  11731. this.node.setAttributeNS(null, 'visibility', 'visible');
  11732. // Hide reference point if the connected shape is an edge
  11733. if (this.getDockedShape() instanceof ORYX.Core.Edge){
  11734. this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');
  11735. } else {
  11736. this._referencePointNode.setAttributeNS(null, 'visibility', 'visible');
  11737. }
  11738. this.children.each(function(uiObj) {
  11739. uiObj.show();
  11740. });
  11741. },
  11742. toString: function() { return "Docker " + this.id }
  11743. });/*
  11744. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  11745. * License rights for this program may be obtained from Alfresco Software, Ltd.
  11746. * pursuant to a written agreement and any use of this program without such an
  11747. * agreement is prohibited.
  11748. */
  11749. /*
  11750. * All code Copyright 2013 KIS Consultancy all rights reserved
  11751. */
  11752. /**
  11753. * Init namespaces
  11754. */
  11755. if(!ORYX) {var ORYX = {};}
  11756. if(!ORYX.Core) {ORYX.Core = {};}
  11757. if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
  11758. /**
  11759. * @classDescription Represents a magnet that is part of another shape and can
  11760. * be attached to dockers. Magnets are used for linking edge objects
  11761. * to other Shape objects.
  11762. * @extends {Control}
  11763. */
  11764. ORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({
  11765. /**
  11766. * Constructor
  11767. */
  11768. construct: function() {
  11769. arguments.callee.$.construct.apply(this, arguments);
  11770. //this.anchors = [];
  11771. this.anchorLeft;
  11772. this.anchorRight;
  11773. this.anchorTop;
  11774. this.anchorBottom;
  11775. this.bounds.set(0, 0, 16, 16);
  11776. //graft magnet's root node into owner's control group.
  11777. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
  11778. null,
  11779. ['g', {"pointer-events":"all"},
  11780. ['circle', {cx:"8", cy:"8", r:"4", stroke:"none", fill:"red", "fill-opacity":"0.3"}],
  11781. ]);
  11782. this.hide();
  11783. },
  11784. update: function() {
  11785. arguments.callee.$.update.apply(this, arguments);
  11786. //this.isChanged = true;
  11787. },
  11788. _update: function() {
  11789. arguments.callee.$.update.apply(this, arguments);
  11790. //this.isChanged = true;
  11791. },
  11792. refresh: function() {
  11793. arguments.callee.$.refresh.apply(this, arguments);
  11794. var p = this.bounds.upperLeft();
  11795. /*if(this.parent) {
  11796. var parentPos = this.parent.bounds.upperLeft();
  11797. p.x += parentPos.x;
  11798. p.y += parentPos.y;
  11799. }*/
  11800. this.node.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
  11801. },
  11802. show: function() {
  11803. //this.refresh();
  11804. arguments.callee.$.show.apply(this, arguments);
  11805. },
  11806. toString: function() {
  11807. return "Magnet " + this.id;
  11808. }
  11809. });
  11810. /*
  11811. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  11812. * License rights for this program may be obtained from Alfresco Software, Ltd.
  11813. * pursuant to a written agreement and any use of this program without such an
  11814. * agreement is prohibited.
  11815. */
  11816. /*
  11817. * All code Copyright 2013 KIS Consultancy all rights reserved
  11818. */
  11819. /**
  11820. * Init namespaces
  11821. */
  11822. if (!ORYX) {
  11823. var ORYX = {};
  11824. }
  11825. if (!ORYX.Core) {
  11826. ORYX.Core = {};
  11827. }
  11828. /**
  11829. * @classDescription Abstract base class for all Nodes.
  11830. * @extends ORYX.Core.Shape
  11831. */
  11832. ORYX.Core.Node = {
  11833. /**
  11834. * Constructor
  11835. * @param options {Object} A container for arguments.
  11836. * @param stencil {Stencil}
  11837. */
  11838. construct: function(options, stencil, facade){
  11839. arguments.callee.$.construct.apply(this, arguments);
  11840. this.isSelectable = true;
  11841. this.isMovable = true;
  11842. this._dockerUpdated = false;
  11843. this.facade = facade;
  11844. this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values
  11845. this._svgShapes = []; //array of all SVGShape objects of
  11846. // SVG representation
  11847. //TODO vielleicht in shape verschieben?
  11848. this.minimumSize = undefined; // {width:..., height:...}
  11849. this.maximumSize = undefined;
  11850. //TODO vielleicht in shape oder uiobject verschieben?
  11851. // vielleicht sogar isResizable ersetzen?
  11852. this.isHorizontallyResizable = false;
  11853. this.isVerticallyResizable = false;
  11854. this.dataId = undefined;
  11855. this._init(this._stencil.view());
  11856. this.forcedHeight = -1;
  11857. },
  11858. /**
  11859. * This method checks whether the shape is resized correctly and calls the
  11860. * super class update method.
  11861. */
  11862. _update: function(){
  11863. this.dockers.invoke("update");
  11864. if (this.isChanged) {
  11865. var bounds = this.bounds;
  11866. var oldBounds = this._oldBounds;
  11867. if (this.isResized) {
  11868. var widthDelta = bounds.width() / oldBounds.width();
  11869. var heightDelta = bounds.height() / oldBounds.height();
  11870. //iterate over all relevant svg elements and resize them
  11871. this._svgShapes.each(function(svgShape){
  11872. //adjust width
  11873. if (svgShape.isHorizontallyResizable) {
  11874. svgShape.width = svgShape.oldWidth * widthDelta;
  11875. }
  11876. //adjust height
  11877. if (svgShape.isVerticallyResizable) {
  11878. svgShape.height = svgShape.oldHeight * heightDelta;
  11879. }
  11880. //check, if anchors are set
  11881. var anchorOffset;
  11882. var leftIncluded = svgShape.anchorLeft;
  11883. var rightIncluded = svgShape.anchorRight;
  11884. if (rightIncluded) {
  11885. anchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth);
  11886. if (leftIncluded) {
  11887. svgShape.width = bounds.width() - svgShape.x - anchorOffset;
  11888. }
  11889. else {
  11890. svgShape.x = bounds.width() - (anchorOffset + svgShape.width);
  11891. }
  11892. }
  11893. else
  11894. if (!leftIncluded) {
  11895. svgShape.x = widthDelta * svgShape.oldX;
  11896. if (!svgShape.isHorizontallyResizable) {
  11897. svgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2;
  11898. }
  11899. }
  11900. var topIncluded = svgShape.anchorTop;
  11901. var bottomIncluded = svgShape.anchorBottom;
  11902. if (bottomIncluded) {
  11903. anchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight);
  11904. if (topIncluded) {
  11905. svgShape.height = bounds.height() - svgShape.y - anchorOffset;
  11906. }
  11907. else {
  11908. // Hack for choreography task layouting
  11909. if (!svgShape._isYLocked) {
  11910. svgShape.y = bounds.height() - (anchorOffset + svgShape.height);
  11911. }
  11912. }
  11913. }
  11914. else
  11915. if (!topIncluded) {
  11916. svgShape.y = heightDelta * svgShape.oldY;
  11917. if (!svgShape.isVerticallyResizable) {
  11918. svgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2;
  11919. }
  11920. }
  11921. });
  11922. //check, if the current bounds is unallowed horizontally or vertically resized
  11923. var p = {
  11924. x: 0,
  11925. y: 0
  11926. };
  11927. if (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) {
  11928. p.x = oldBounds.width() - bounds.width();
  11929. }
  11930. if (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) {
  11931. p.y = oldBounds.height() - bounds.height();
  11932. }
  11933. if (p.x !== 0 || p.y !== 0) {
  11934. bounds.extend(p);
  11935. }
  11936. //check, if the current bounds are between maximum and minimum bounds
  11937. p = {
  11938. x: 0,
  11939. y: 0
  11940. };
  11941. var widthDifference, heightDifference;
  11942. if (this.minimumSize) {
  11943. ORYX.Log.debug("Shape (%0)'s min size: (%1x%2)", this, this.minimumSize.width, this.minimumSize.height);
  11944. widthDifference = this.minimumSize.width - bounds.width();
  11945. if (widthDifference > 0) {
  11946. p.x += widthDifference;
  11947. }
  11948. heightDifference = this.minimumSize.height - bounds.height();
  11949. if (heightDifference > 0) {
  11950. p.y += heightDifference;
  11951. }
  11952. }
  11953. if (this.maximumSize) {
  11954. ORYX.Log.debug("Shape (%0)'s max size: (%1x%2)", this, this.maximumSize.width, this.maximumSize.height);
  11955. widthDifference = bounds.width() - this.maximumSize.width;
  11956. if (widthDifference > 0) {
  11957. p.x -= widthDifference;
  11958. }
  11959. heightDifference = bounds.height() - this.maximumSize.height;
  11960. if (heightDifference > 0) {
  11961. p.y -= heightDifference;
  11962. }
  11963. }
  11964. if (p.x !== 0 || p.y !== 0) {
  11965. bounds.extend(p);
  11966. }
  11967. //update magnets
  11968. var widthDelta = bounds.width() / oldBounds.width();
  11969. var heightDelta = bounds.height() / oldBounds.height();
  11970. var leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY;
  11971. this.magnets.each(function(magnet){
  11972. leftIncluded = magnet.anchorLeft;
  11973. rightIncluded = magnet.anchorRight;
  11974. topIncluded = magnet.anchorTop;
  11975. bottomIncluded = magnet.anchorBottom;
  11976. center = magnet.bounds.center();
  11977. if (leftIncluded) {
  11978. newX = center.x;
  11979. }
  11980. else
  11981. if (rightIncluded) {
  11982. newX = bounds.width() - (oldBounds.width() - center.x)
  11983. }
  11984. else {
  11985. newX = center.x * widthDelta;
  11986. }
  11987. if (topIncluded) {
  11988. newY = center.y;
  11989. }
  11990. else
  11991. if (bottomIncluded) {
  11992. newY = bounds.height() - (oldBounds.height() - center.y);
  11993. }
  11994. else {
  11995. newY = center.y * heightDelta;
  11996. }
  11997. if (center.x !== newX || center.y !== newY) {
  11998. magnet.bounds.centerMoveTo(newX, newY);
  11999. }
  12000. });
  12001. //set new position of labels
  12002. this.getLabels().each(function(label){
  12003. // Set the position dependings on it anchor
  12004. if (!label.isAnchorLeft()) {
  12005. if (label.isAnchorRight()) {
  12006. label.setX(bounds.width() - (oldBounds.width() - label.oldX))
  12007. } else {
  12008. label.setX((label.position?label.position.x:label.x) * widthDelta);
  12009. }
  12010. }
  12011. if (!label.isAnchorTop()) {
  12012. if (label.isAnchorBottom()) {
  12013. label.setY(bounds.height() - (oldBounds.height() - label.oldY));
  12014. } else {
  12015. label.setY((label.position?label.position.y:label.y) * heightDelta);
  12016. }
  12017. }
  12018. // If there is an position,
  12019. // set the origin position as well
  12020. if (label.position){
  12021. if (!label.isOriginAnchorLeft()) {
  12022. if (label.isOriginAnchorRight()) {
  12023. label.setOriginX(bounds.width() - (oldBounds.width() - label.oldX))
  12024. } else {
  12025. label.setOriginX(label.x * widthDelta);
  12026. }
  12027. }
  12028. if (!label.isOriginAnchorTop()) {
  12029. if (label.isOriginAnchorBottom()) {
  12030. label.setOriginY(bounds.height() - (oldBounds.height() - label.oldY));
  12031. } else {
  12032. label.setOriginY(label.y * heightDelta);
  12033. }
  12034. }
  12035. }
  12036. });
  12037. //update docker
  12038. var docker = this.dockers[0];
  12039. if (docker) {
  12040. docker.bounds.unregisterCallback(this._dockerChangedCallback);
  12041. if (!this._dockerUpdated) {
  12042. docker.bounds.centerMoveTo(this.bounds.center());
  12043. this._dockerUpdated = false;
  12044. }
  12045. docker.update();
  12046. docker.bounds.registerCallback(this._dockerChangedCallback);
  12047. }
  12048. this.isResized = false;
  12049. }
  12050. this.refresh();
  12051. this.isChanged = false;
  12052. this._oldBounds = this.bounds.clone();
  12053. }
  12054. this.children.each(function(value) {
  12055. if(!(value instanceof ORYX.Core.Controls.Docker)) {
  12056. value._update();
  12057. }
  12058. });
  12059. if (this.dockers.length > 0&&!this.dockers.first().getDockedShape()) {
  12060. this.dockers.each(function(docker){
  12061. docker.bounds.centerMoveTo(this.bounds.center())
  12062. }.bind(this))
  12063. }
  12064. /*this.incoming.each((function(edge) {
  12065. if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))
  12066. edge._update(true);
  12067. }).bind(this));
  12068. this.outgoing.each((function(edge) {
  12069. if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))
  12070. edge._update(true);
  12071. }).bind(this)); */
  12072. },
  12073. /**
  12074. * This method repositions and resizes the SVG representation
  12075. * of the shape.
  12076. */
  12077. refresh: function(){
  12078. arguments.callee.$.refresh.apply(this, arguments);
  12079. /** Movement */
  12080. var x = this.bounds.upperLeft().x;
  12081. var y = this.bounds.upperLeft().y;
  12082. // Move owner element
  12083. this.node.firstChild.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
  12084. // Move magnets
  12085. this.node.childNodes[1].childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
  12086. /** Resize */
  12087. //iterate over all relevant svg elements and update them
  12088. this._svgShapes.each(function(svgShape){
  12089. svgShape.update();
  12090. });
  12091. },
  12092. _dockerChanged: function(){
  12093. var docker = this.dockers[0];
  12094. //set the bounds of the the association
  12095. this.bounds.centerMoveTo(docker.bounds.center());
  12096. this._dockerUpdated = true;
  12097. //this._update(true);
  12098. },
  12099. /**
  12100. * This method traverses a tree of SVGElements and returns
  12101. * all SVGShape objects. For each basic shape or path element
  12102. * a SVGShape object is initialized.
  12103. *
  12104. * @param svgNode {SVGElement}
  12105. * @return {Array} Array of SVGShape objects
  12106. */
  12107. _initSVGShapes: function(svgNode){
  12108. var svgShapes = [];
  12109. try {
  12110. var svgShape = new ORYX.Core.SVG.SVGShape(svgNode);
  12111. svgShapes.push(svgShape);
  12112. }
  12113. catch (e) {
  12114. //do nothing
  12115. }
  12116. if (svgNode.hasChildNodes()) {
  12117. for (var i = 0; i < svgNode.childNodes.length; i++) {
  12118. svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i]));
  12119. }
  12120. }
  12121. return svgShapes;
  12122. },
  12123. /**
  12124. * Calculate if the point is inside the Shape
  12125. * @param {PointX}
  12126. * @param {PointY}
  12127. * @param {absoluteBounds} optional: for performance
  12128. */
  12129. isPointIncluded: function(pointX, pointY, absoluteBounds){
  12130. // If there is an arguments with the absoluteBounds
  12131. var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds();
  12132. if (!absBounds.isIncluded(pointX, pointY)) {
  12133. return false;
  12134. } else {
  12135. }
  12136. //point = Object.clone(point);
  12137. var ul = absBounds.upperLeft();
  12138. var x = pointX - ul.x;
  12139. var y = pointY - ul.y;
  12140. var i=0;
  12141. do {
  12142. var isPointIncluded = this._svgShapes[i++].isPointIncluded( x, y );
  12143. } while( !isPointIncluded && i < this._svgShapes.length)
  12144. return isPointIncluded;
  12145. /*return this._svgShapes.any(function(svgShape){
  12146. return svgShape.isPointIncluded(point);
  12147. });*/
  12148. },
  12149. /**
  12150. * Calculate if the point is over an special offset area
  12151. * @param {Point}
  12152. */
  12153. isPointOverOffset: function( pointX, pointY ){
  12154. var isOverEl = arguments.callee.$.isPointOverOffset.apply( this , arguments );
  12155. if (isOverEl) {
  12156. // If there is an arguments with the absoluteBounds
  12157. var absBounds = this.absoluteBounds();
  12158. absBounds.widen( - ORYX.CONFIG.BORDER_OFFSET );
  12159. if ( !absBounds.isIncluded( pointX, pointY )) {
  12160. return true;
  12161. }
  12162. }
  12163. return false;
  12164. },
  12165. serialize: function(){
  12166. var result = arguments.callee.$.serialize.apply(this);
  12167. // Add the docker's bounds
  12168. // nodes only have at most one docker!
  12169. this.dockers.each((function(docker){
  12170. if (docker.getDockedShape()) {
  12171. var center = docker.referencePoint;
  12172. center = center ? center : docker.bounds.center();
  12173. result.push({
  12174. name: 'docker',
  12175. prefix: 'oryx',
  12176. value: $H(center).values().join(','),
  12177. type: 'literal'
  12178. });
  12179. }
  12180. }).bind(this));
  12181. // Get the spezific serialized object from the stencil
  12182. try {
  12183. //result = this.getStencil().serialize(this, result);
  12184. var serializeEvent = this.getStencil().serialize();
  12185. /*
  12186. * call serialize callback by reference, result should be found
  12187. * in serializeEvent.result
  12188. */
  12189. if(serializeEvent.type) {
  12190. serializeEvent.shape = this;
  12191. serializeEvent.data = result;
  12192. serializeEvent.result = undefined;
  12193. serializeEvent.forceExecution = true;
  12194. this._delegateEvent(serializeEvent);
  12195. if(serializeEvent.result) {
  12196. result = serializeEvent.result;
  12197. }
  12198. }
  12199. }
  12200. catch (e) {
  12201. }
  12202. return result;
  12203. },
  12204. deserialize: function(data){
  12205. arguments.callee.$.deserialize.apply(this, arguments);
  12206. try {
  12207. //data = this.getStencil().deserialize(this, data);
  12208. var deserializeEvent = this.getStencil().deserialize();
  12209. /*
  12210. * call serialize callback by reference, result should be found
  12211. * in serializeEventInfo.result
  12212. */
  12213. if(deserializeEvent.type) {
  12214. deserializeEvent.shape = this;
  12215. deserializeEvent.data = data;
  12216. deserializeEvent.result = undefined;
  12217. deserializeEvent.forceExecution = true;
  12218. this._delegateEvent(deserializeEvent);
  12219. if(deserializeEvent.result) {
  12220. data = deserializeEvent.result;
  12221. }
  12222. }
  12223. }
  12224. catch (e) {
  12225. }
  12226. // Set the outgoing shapes
  12227. var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'});
  12228. outgoing.each((function(obj){
  12229. // TODO: Look at Canvas
  12230. if(!this.parent) {return};
  12231. // Set outgoing Shape
  12232. var next = this.getCanvas().getChildShapeByResourceId(obj.value);
  12233. if(next){
  12234. if(next instanceof ORYX.Core.Edge) {
  12235. //Set the first docker of the next shape
  12236. next.dockers.first().setDockedShape(this);
  12237. next.dockers.first().setReferencePoint(next.dockers.first().bounds.center());
  12238. } else if(next.dockers.length > 0) { //next is a node and next has a docker
  12239. next.dockers.first().setDockedShape(this);
  12240. //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
  12241. }
  12242. }
  12243. }).bind(this));
  12244. if (this.dockers.length === 1) {
  12245. var dockerPos;
  12246. dockerPos = data.find(function(entry){
  12247. return (entry.prefix + "-" + entry.name === "oryx-dockers");
  12248. });
  12249. if (dockerPos) {
  12250. var points = dockerPos.value.replace(/,/g, " ").split(" ").without("").without("#");
  12251. if (points.length === 2 && this.dockers[0].getDockedShape()) {
  12252. this.dockers[0].setReferencePoint({
  12253. x: parseFloat(points[0]),
  12254. y: parseFloat(points[1])
  12255. });
  12256. }
  12257. else {
  12258. this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1]));
  12259. }
  12260. }
  12261. }
  12262. },
  12263. /**
  12264. * This method excepts the SVGDoucment that is the SVG representation
  12265. * of this shape.
  12266. * The bounds of the shape are calculated, the SVG representation's upper left point
  12267. * is moved to 0,0 and it the method sets if this shape is resizable.
  12268. *
  12269. * @param {SVGDocument} svgDocument
  12270. */
  12271. _init: function(svgDocument){
  12272. arguments.callee.$._init.apply(this, arguments);
  12273. var svgNode = svgDocument.getElementsByTagName("g")[0]; //outer most g node
  12274. // set all required attributes
  12275. var attributeTitle = svgDocument.ownerDocument.createAttribute("title");
  12276. attributeTitle.nodeValue = this.getStencil().title();
  12277. svgNode.setAttributeNode(attributeTitle);
  12278. var attributeId = svgDocument.ownerDocument.createAttribute("id");
  12279. attributeId.nodeValue = this.id;
  12280. svgNode.setAttributeNode(attributeId);
  12281. //
  12282. var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //<g class=me>"
  12283. svgNode = stencilTargetNode.appendChild(svgNode);
  12284. // Add to the EventHandler
  12285. this.addEventHandlers(svgNode.parentNode);
  12286. /**set minimum and maximum size*/
  12287. var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "minimumSize");
  12288. if (minSizeAttr) {
  12289. minSizeAttr = minSizeAttr.replace("/,/g", " ");
  12290. var minSizeValues = minSizeAttr.split(" ");
  12291. minSizeValues = minSizeValues.without("");
  12292. if (minSizeValues.length > 1) {
  12293. this.minimumSize = {
  12294. width: parseFloat(minSizeValues[0]),
  12295. height: parseFloat(minSizeValues[1])
  12296. };
  12297. }
  12298. else {
  12299. //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0)
  12300. this.minimumSize = {
  12301. width: 1,
  12302. height: 1
  12303. };
  12304. }
  12305. }
  12306. var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "maximumSize");
  12307. if (maxSizeAttr) {
  12308. maxSizeAttr = maxSizeAttr.replace("/,/g", " ");
  12309. var maxSizeValues = maxSizeAttr.split(" ");
  12310. maxSizeValues = maxSizeValues.without("");
  12311. if (maxSizeValues.length > 1) {
  12312. this.maximumSize = {
  12313. width: parseFloat(maxSizeValues[0]),
  12314. height: parseFloat(maxSizeValues[1])
  12315. };
  12316. }
  12317. }
  12318. if (this.minimumSize && this.maximumSize &&
  12319. (this.minimumSize.width > this.maximumSize.width ||
  12320. this.minimumSize.height > this.maximumSize.height)) {
  12321. //TODO wird verschluckt!!!
  12322. throw this + ": Minimum Size must be greater than maxiumSize.";
  12323. }
  12324. /**get current bounds and adjust it to upperLeft == (0,0)*/
  12325. //initialize all SVGShape objects
  12326. this._svgShapes = this._initSVGShapes(svgNode);
  12327. //get upperLeft and lowerRight of stencil
  12328. var upperLeft = {
  12329. x: undefined,
  12330. y: undefined
  12331. };
  12332. var lowerRight = {
  12333. x: undefined,
  12334. y: undefined
  12335. };
  12336. var me = this;
  12337. this._svgShapes.each(function(svgShape){
  12338. upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x;
  12339. upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y;
  12340. lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width;
  12341. lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height;
  12342. /** set if resizing is enabled */
  12343. //TODO isResizable durch die beiden anderen booleans ersetzen?
  12344. if (svgShape.isHorizontallyResizable) {
  12345. me.isHorizontallyResizable = true;
  12346. me.isResizable = true;
  12347. }
  12348. if (svgShape.isVerticallyResizable) {
  12349. me.isVerticallyResizable = true;
  12350. me.isResizable = true;
  12351. }
  12352. if (svgShape.anchorTop && svgShape.anchorBottom) {
  12353. me.isVerticallyResizable = true;
  12354. me.isResizable = true;
  12355. }
  12356. if (svgShape.anchorLeft && svgShape.anchorRight) {
  12357. me.isHorizontallyResizable = true;
  12358. me.isResizable = true;
  12359. }
  12360. });
  12361. //move all SVGShapes by -upperLeft
  12362. this._svgShapes.each(function(svgShape){
  12363. svgShape.x -= upperLeft.x;
  12364. svgShape.y -= upperLeft.y;
  12365. svgShape.update();
  12366. });
  12367. //set bounds of shape
  12368. //the offsets are also needed for positioning the magnets and the docker
  12369. var offsetX = upperLeft.x;
  12370. var offsetY = upperLeft.y;
  12371. lowerRight.x -= offsetX;
  12372. lowerRight.y -= offsetY;
  12373. upperLeft.x = 0;
  12374. upperLeft.y = 0;
  12375. //prevent that width or height of initial bounds is 0
  12376. if (lowerRight.x === 0) {
  12377. lowerRight.x = 1;
  12378. }
  12379. if (lowerRight.y === 0) {
  12380. lowerRight.y = 1;
  12381. }
  12382. this._oldBounds.set(upperLeft, lowerRight);
  12383. this.bounds.set(upperLeft, lowerRight);
  12384. /**initialize magnets */
  12385. var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnets");
  12386. if (magnets && magnets.length > 0) {
  12387. magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnet"));
  12388. var me = this;
  12389. magnets.each(function(magnetElem){
  12390. var magnet = new ORYX.Core.Controls.Magnet({
  12391. eventHandlerCallback: me.eventHandlerCallback
  12392. });
  12393. var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx"));
  12394. var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy"));
  12395. magnet.bounds.centerMoveTo({
  12396. x: cx - offsetX,
  12397. y: cy - offsetY
  12398. });
  12399. //get anchors
  12400. var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
  12401. if (anchors) {
  12402. anchors = anchors.replace("/,/g", " ");
  12403. anchors = anchors.split(" ").without("");
  12404. for(var i = 0; i < anchors.length; i++) {
  12405. switch(anchors[i].toLowerCase()) {
  12406. case "left":
  12407. magnet.anchorLeft = true;
  12408. break;
  12409. case "right":
  12410. magnet.anchorRight = true;
  12411. break;
  12412. case "top":
  12413. magnet.anchorTop = true;
  12414. break;
  12415. case "bottom":
  12416. magnet.anchorBottom = true;
  12417. break;
  12418. }
  12419. }
  12420. }
  12421. me.add(magnet);
  12422. //check, if magnet is default magnet
  12423. if (!this._defaultMagnet) {
  12424. var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "default");
  12425. if (defaultAttr && defaultAttr.toLowerCase() === "yes") {
  12426. me._defaultMagnet = magnet;
  12427. }
  12428. }
  12429. });
  12430. }
  12431. else {
  12432. // Add a Magnet in the Center of Shape
  12433. var magnet = new ORYX.Core.Controls.Magnet();
  12434. magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2);
  12435. this.add(magnet);
  12436. }
  12437. /**initialize docker */
  12438. var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "docker");
  12439. if (dockerElem && dockerElem.length > 0) {
  12440. dockerElem = dockerElem[0];
  12441. var docker = this.createDocker();
  12442. var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx"));
  12443. var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy"));
  12444. docker.bounds.centerMoveTo({
  12445. x: cx - offsetX,
  12446. y: cy - offsetY
  12447. });
  12448. //get anchors
  12449. var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
  12450. if (anchors) {
  12451. anchors = anchors.replace("/,/g", " ");
  12452. anchors = anchors.split(" ").without("");
  12453. for(var i = 0; i < anchors.length; i++) {
  12454. switch(anchors[i].toLowerCase()) {
  12455. case "left":
  12456. docker.anchorLeft = true;
  12457. break;
  12458. case "right":
  12459. docker.anchorRight = true;
  12460. break;
  12461. case "top":
  12462. docker.anchorTop = true;
  12463. break;
  12464. case "bottom":
  12465. docker.anchorBottom = true;
  12466. break;
  12467. }
  12468. }
  12469. }
  12470. }
  12471. /**initialize labels*/
  12472. var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');
  12473. $A(textElems).each((function(textElem){
  12474. var label = new ORYX.Core.SVG.Label({
  12475. textElement: textElem,
  12476. shapeId: this.id
  12477. });
  12478. label.x -= offsetX;
  12479. label.y -= offsetY;
  12480. this._labels[label.id] = label;
  12481. label.registerOnChange(this.layout.bind(this));
  12482. // Only apply fitting on form-components
  12483. if(this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX) == 0) {
  12484. label.registerOnChange(this.fitToLabels.bind(this));
  12485. }
  12486. }).bind(this));
  12487. },
  12488. fitToLabels: function() {
  12489. var y = 0;
  12490. this.getLabels().each(function(label){
  12491. var lr = label.getY() + label.getHeight();
  12492. if(lr > y) {
  12493. y = lr;
  12494. }
  12495. });
  12496. var bounds = this.bounds;
  12497. var boundsChanged = false;
  12498. if(this.minimumSize) {
  12499. // Check if y-value exceeds the min-value. If not, stick to this value.
  12500. var minHeight = this.minimumSize.height;
  12501. if(y < minHeight && bounds.height() > minHeight && minHeight > this.forcedHeight) {
  12502. bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + minHeight);
  12503. boundsChanged = true;
  12504. } else if(y > minHeight && bounds.height() != y && y > this.forcedHeight){
  12505. bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + y);
  12506. boundsChanged = true;
  12507. } else if(bounds.height() > this.forcedHeight && this.forcedHeight > 0) {
  12508. bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + this.forcedHeight);
  12509. boundsChanged = true;
  12510. }
  12511. }
  12512. if(boundsChanged) {
  12513. // Force facade to re-layout since bounds are changed AFTER layout has been performed
  12514. if(this.facade.getCanvas() != null) {
  12515. this.facade.getCanvas().update();
  12516. }
  12517. // Re-select if needed to force the select
  12518. if(this.facade.getSelection().member(this)) {
  12519. var selectedNow = this.facade.getSelection();
  12520. this.facade.setSelection([]);
  12521. this.facade.setSelection(selectedNow);
  12522. }
  12523. }
  12524. },
  12525. /**
  12526. * Override the Method, that a docker is not shown
  12527. *
  12528. */
  12529. createDocker: function() {
  12530. var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});
  12531. docker.bounds.registerCallback(this._dockerChangedCallback);
  12532. this.dockers.push( docker );
  12533. docker.parent = this;
  12534. docker.bounds.registerCallback(this._changedCallback);
  12535. return docker
  12536. },
  12537. toString: function(){
  12538. return this._stencil.title() + " " + this.id
  12539. }
  12540. };
  12541. ORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node);
  12542. /*
  12543. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  12544. * License rights for this program may be obtained from Alfresco Software, Ltd.
  12545. * pursuant to a written agreement and any use of this program without such an
  12546. * agreement is prohibited.
  12547. */
  12548. /*
  12549. * All code Copyright 2013 KIS Consultancy all rights reserved
  12550. */
  12551. NAMESPACE_SVG = "http://www.w3.org/2000/svg";
  12552. NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
  12553. /**
  12554. * Init namespaces
  12555. */
  12556. if (!ORYX) {
  12557. var ORYX = {};
  12558. }
  12559. if (!ORYX.Core) {
  12560. ORYX.Core = {};
  12561. }
  12562. /**
  12563. * @classDescription Abstract base class for all connections.
  12564. * @extends {ORYX.Core.Shape}
  12565. * @param options {Object}
  12566. *
  12567. * TODO da die verschiebung der Edge nicht ueber eine
  12568. * translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt,
  12569. * muessen die kinder hier beim verschieben speziell betrachtet werden.
  12570. * Das sollte ueberarbeitet werden.
  12571. *
  12572. */
  12573. ORYX.Core.Edge = {
  12574. /**
  12575. * Constructor
  12576. * @param {Object} options
  12577. * @param {Stencil} stencil
  12578. */
  12579. construct: function(options, stencil, facade){
  12580. arguments.callee.$.construct.apply(this, arguments);
  12581. this.isMovable = true;
  12582. this.isSelectable = true;
  12583. this._dockerUpdated = false;
  12584. this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids
  12585. this._paths = [];
  12586. this._interactionPaths = [];
  12587. this._dockersByPath = new Hash();
  12588. this._markersByPath = new Hash();
  12589. /* Data structures to store positioning information of attached child nodes */
  12590. this.attachedNodePositionData = new Hash();
  12591. //TODO was muss hier initial erzeugt werden?
  12592. var stencilNode = this.node.childNodes[0].childNodes[0];
  12593. stencilNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", stencilNode, ['g', {
  12594. "pointer-events": "painted"
  12595. }]);
  12596. //Add to the EventHandler
  12597. this.addEventHandlers(stencilNode.parentNode);
  12598. this._oldBounds = this.bounds.clone();
  12599. //load stencil
  12600. this._init(this._stencil.view());
  12601. if (stencil instanceof Array) {
  12602. this.deserialize(stencil);
  12603. }
  12604. },
  12605. _update: function(force){
  12606. if(this._dockerUpdated || this.isChanged || force) {
  12607. this.dockers.invoke("update");
  12608. if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) {
  12609. var width = this.bounds.width();
  12610. var height = this.bounds.height();
  12611. this.bounds.extend({
  12612. x: width === 0 ? 2 : 0,
  12613. y: height === 0 ? 2 : 0
  12614. });
  12615. this.bounds.moveBy({
  12616. x: width === 0 ? -1 : 0,
  12617. y: height === 0 ? -1 : 0
  12618. });
  12619. }
  12620. // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden
  12621. var upL = this.bounds.upperLeft();
  12622. var oldUpL = this._oldBounds.upperLeft();
  12623. var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width();
  12624. var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height();
  12625. var diffX = upL.x - oldUpL.x;
  12626. var diffY = upL.y - oldUpL.y;
  12627. var diffWidth = (this.bounds.width() / oldWidth) || 1;
  12628. var diffHeight = (this.bounds.height() / oldHeight) || 1;
  12629. this.dockers.each((function(docker){
  12630. // Unregister on BoundsChangedCallback
  12631. docker.bounds.unregisterCallback(this._dockerChangedCallback);
  12632. // If there is any changes at the edge and is there is not an DockersUpdate
  12633. // set the new bounds to the docker
  12634. if (!this._dockerUpdated) {
  12635. docker.bounds.moveBy(diffX, diffY);
  12636. if (diffWidth !== 1 || diffHeight !== 1) {
  12637. var relX = docker.bounds.upperLeft().x - upL.x;
  12638. var relY = docker.bounds.upperLeft().y - upL.y;
  12639. docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight);
  12640. }
  12641. }
  12642. // Do Docker update and register on DockersBoundChange
  12643. docker.update();
  12644. docker.bounds.registerCallback(this._dockerChangedCallback);
  12645. }).bind(this));
  12646. if (this._dockerUpdated) {
  12647. var a = this.dockers.first().bounds.center();
  12648. var b = this.dockers.first().bounds.center();
  12649. this.dockers.each((function(docker){
  12650. var center = docker.bounds.center();
  12651. a.x = Math.min(a.x, center.x);
  12652. a.y = Math.min(a.y, center.y);
  12653. b.x = Math.max(b.x, center.x);
  12654. b.y = Math.max(b.y, center.y);
  12655. }).bind(this));
  12656. //set the bounds of the the association
  12657. this.bounds.set(Object.clone(a), Object.clone(b));
  12658. }
  12659. upL = this.bounds.upperLeft(); oldUpL = this._oldBounds.upperLeft();
  12660. diffWidth = (this.bounds.width() / (oldWidth||this.bounds.width())); diffHeight = (this.bounds.height() / (oldHeight||this.bounds.height()));
  12661. diffX = upL.x - oldUpL.x; diffY = upL.y - oldUpL.y;
  12662. //reposition labels
  12663. this.getLabels().each(function(label) {
  12664. if (label.getReferencePoint()){
  12665. var ref = label.getReferencePoint();
  12666. var from = ref.segment.from, to = ref.segment.to;
  12667. if (!from || !from.parent || !to || !to.parent) {
  12668. return;
  12669. }
  12670. var fromPosition = from.bounds.center(), toPosition = to.bounds.center();
  12671. if (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y &&
  12672. toPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty){
  12673. return;
  12674. }
  12675. if (!this.parent.initializingShapes) {
  12676. var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);
  12677. var newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance);
  12678. /**
  12679. * Set position
  12680. */
  12681. // Get the orthogonal identity vector of the current segment
  12682. var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);
  12683. var isHor = Math.abs(oiv.y)===1, isVer = Math.abs(oiv.x)===1;
  12684. oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance
  12685. oiv.x += newIntersection.x; oiv.y += newIntersection.y; // vector + the intersection point
  12686. var mx = isHor && ref.orientation && (ref.iorientation||ref.orientation).endsWith("r") ? -label.getWidth() : 0;
  12687. var my = isVer && ref.orientation && (ref.iorientation||ref.orientation).startsWith("l") ? -label.getHeight()+2 : 0;
  12688. label.setX(oiv.x+mx); label.setY(oiv.y+my);
  12689. // Update the reference point
  12690. this.updateReferencePointOfLabel(label, newIntersection, from, to);
  12691. } else {
  12692. var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);
  12693. oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance
  12694. oiv.x += ref.intersection.x; oiv.y += ref.intersection.y; // vector + the intersection point
  12695. label.setX(oiv.x); label.setY(oiv.y);
  12696. ref.segment.fromPosition = fromPosition; ref.segment.toPosition = toPosition;
  12697. }
  12698. return;
  12699. }
  12700. // Update label position if no reference point is set
  12701. if (label.position && !this.parent.initializingShapes){
  12702. var x = label.position.x + (diffX * (diffWidth||1));
  12703. if (x > this.bounds.lowerRight().x){
  12704. x += this.bounds.width()-(this.bounds.width()/(diffWidth||1));
  12705. }
  12706. var y = label.position.y + (diffY * (diffHeight||1));
  12707. if (y > this.bounds.lowerRight().y){
  12708. y += this.bounds.height()-(this.bounds.height()/(diffHeight||1));
  12709. }
  12710. label.setX(x);label.setY(y);
  12711. return;
  12712. }
  12713. switch (label.getEdgePosition()) {
  12714. case "starttop":
  12715. var angle = this._getAngle(this.dockers[0], this.dockers[1]);
  12716. var pos = this.dockers.first().bounds.center();
  12717. if (angle <= 90 || angle > 270) {
  12718. label.horizontalAlign("left");
  12719. label.verticalAlign("bottom");
  12720. label.x = pos.x + label.getOffsetTop();
  12721. label.y = pos.y - label.getOffsetTop();
  12722. label.rotate(360 - angle, pos);
  12723. } else {
  12724. label.horizontalAlign("right");
  12725. label.verticalAlign("bottom");
  12726. label.x = pos.x - label.getOffsetTop();
  12727. label.y = pos.y - label.getOffsetTop();
  12728. label.rotate(180 - angle, pos);
  12729. }
  12730. break;
  12731. case "startmiddle":
  12732. var angle = this._getAngle(this.dockers[0], this.dockers[1]);
  12733. var pos = this.dockers.first().bounds.center();
  12734. if (angle <= 90 || angle > 270) {
  12735. label.horizontalAlign("left");
  12736. label.verticalAlign("bottom");
  12737. label.x = pos.x + 2;
  12738. label.y = pos.y + 4;
  12739. label.rotate(360 - angle, pos);
  12740. } else {
  12741. label.horizontalAlign("right");
  12742. label.verticalAlign("bottom");
  12743. label.x = pos.x + 1;
  12744. label.y = pos.y + 4;
  12745. label.rotate(180 - angle, pos);
  12746. }
  12747. break;
  12748. case "startbottom":
  12749. var angle = this._getAngle(this.dockers[0], this.dockers[1]);
  12750. var pos = this.dockers.first().bounds.center();
  12751. if (angle <= 90 || angle > 270) {
  12752. label.horizontalAlign("left");
  12753. label.verticalAlign("top");
  12754. label.x = pos.x + label.getOffsetBottom();
  12755. label.y = pos.y + label.getOffsetBottom();
  12756. label.rotate(360 - angle, pos);
  12757. } else {
  12758. label.horizontalAlign("right");
  12759. label.verticalAlign("top");
  12760. label.x = pos.x - label.getOffsetBottom();
  12761. label.y = pos.y + label.getOffsetBottom();
  12762. label.rotate(180 - angle, pos);
  12763. }
  12764. break;
  12765. case "midtop":
  12766. var numOfDockers = this.dockers.length;
  12767. if(numOfDockers%2 == 0) {
  12768. var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])
  12769. var pos1 = this.dockers[numOfDockers/2-1].bounds.center();
  12770. var pos2 = this.dockers[numOfDockers/2].bounds.center();
  12771. var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};
  12772. label.horizontalAlign("center");
  12773. label.verticalAlign("bottom");
  12774. label.x = pos.x;
  12775. label.y = pos.y - label.getOffsetTop();
  12776. if (angle <= 90 || angle > 270) {
  12777. label.rotate(360 - angle, pos);
  12778. } else {
  12779. label.rotate(180 - angle, pos);
  12780. }
  12781. } else {
  12782. var index = parseInt(numOfDockers/2);
  12783. var angle = this._getAngle(this.dockers[index], this.dockers[index+1])
  12784. var pos = this.dockers[index].bounds.center();
  12785. if (angle <= 90 || angle > 270) {
  12786. label.horizontalAlign("left");
  12787. label.verticalAlign("bottom");
  12788. label.x = pos.x + label.getOffsetTop();
  12789. label.y = pos.y - label.getOffsetTop();
  12790. label.rotate(360 - angle, pos);
  12791. } else {
  12792. label.horizontalAlign("right");
  12793. label.verticalAlign("bottom");
  12794. label.x = pos.x - label.getOffsetTop();
  12795. label.y = pos.y - label.getOffsetTop();
  12796. label.rotate(180 - angle, pos);
  12797. }
  12798. }
  12799. break;
  12800. case "midbottom":
  12801. var numOfDockers = this.dockers.length;
  12802. if(numOfDockers%2 == 0) {
  12803. var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])
  12804. var pos1 = this.dockers[numOfDockers/2-1].bounds.center();
  12805. var pos2 = this.dockers[numOfDockers/2].bounds.center();
  12806. var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};
  12807. label.horizontalAlign("center");
  12808. label.verticalAlign("top");
  12809. label.x = pos.x;
  12810. label.y = pos.y + label.getOffsetTop();
  12811. if (angle <= 90 || angle > 270) {
  12812. label.rotate(360 - angle, pos);
  12813. } else {
  12814. label.rotate(180 - angle, pos);
  12815. }
  12816. } else {
  12817. var index = parseInt(numOfDockers/2);
  12818. var angle = this._getAngle(this.dockers[index], this.dockers[index+1])
  12819. var pos = this.dockers[index].bounds.center();
  12820. if (angle <= 90 || angle > 270) {
  12821. label.horizontalAlign("left");
  12822. label.verticalAlign("top");
  12823. label.x = pos.x + label.getOffsetBottom();
  12824. label.y = pos.y + label.getOffsetBottom();
  12825. label.rotate(360 - angle, pos);
  12826. } else {
  12827. label.horizontalAlign("right");
  12828. label.verticalAlign("top");
  12829. label.x = pos.x - label.getOffsetBottom();
  12830. label.y = pos.y + label.getOffsetBottom();
  12831. label.rotate(180 - angle, pos);
  12832. }
  12833. }
  12834. break;
  12835. case "endtop":
  12836. var length = this.dockers.length;
  12837. var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);
  12838. var pos = this.dockers.last().bounds.center();
  12839. if (angle <= 90 || angle > 270) {
  12840. label.horizontalAlign("right");
  12841. label.verticalAlign("bottom");
  12842. label.x = pos.x - label.getOffsetTop();
  12843. label.y = pos.y - label.getOffsetTop();
  12844. label.rotate(360 - angle, pos);
  12845. } else {
  12846. label.horizontalAlign("left");
  12847. label.verticalAlign("bottom");
  12848. label.x = pos.x + label.getOffsetTop();
  12849. label.y = pos.y - label.getOffsetTop();
  12850. label.rotate(180 - angle, pos);
  12851. }
  12852. break;
  12853. case "endbottom":
  12854. var length = this.dockers.length;
  12855. var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);
  12856. var pos = this.dockers.last().bounds.center();
  12857. if (angle <= 90 || angle > 270) {
  12858. label.horizontalAlign("right");
  12859. label.verticalAlign("top");
  12860. label.x = pos.x - label.getOffsetBottom();
  12861. label.y = pos.y + label.getOffsetBottom();
  12862. label.rotate(360 - angle, pos);
  12863. } else {
  12864. label.horizontalAlign("left");
  12865. label.verticalAlign("top");
  12866. label.x = pos.x + label.getOffsetBottom();
  12867. label.y = pos.y + label.getOffsetBottom();
  12868. label.rotate(180 - angle, pos);
  12869. }
  12870. break;
  12871. }
  12872. }.bind(this));
  12873. this.children.each(function(value) {
  12874. if(value instanceof ORYX.Core.Node) {
  12875. this.calculatePositionOfAttachedChildNode.call(this, value);
  12876. }
  12877. }.bind(this));
  12878. this.refreshAttachedNodes();
  12879. this.refresh();
  12880. this.isChanged = false;
  12881. this._dockerUpdated = false;
  12882. this._oldBounds = this.bounds.clone();
  12883. }
  12884. // IE10 specific fix, start and end-markes get left behind when moving path
  12885. var userAgent = navigator.userAgent;
  12886. if (navigator.appVersion.indexOf("MSIE 10") !== -1 || (userAgent.indexOf('Trident') !== -1 && userAgent.indexOf('rv:11') !== -1))
  12887. {
  12888. this.node.parentNode.insertBefore(this.node, this.node);
  12889. }
  12890. },
  12891. /**
  12892. * Moves a point to the upperLeft of a node's bounds.
  12893. *
  12894. * @param {point} point
  12895. * The point to move
  12896. * @param {ORYX.Core.Bounds} bounds
  12897. * The Bounds of the related noe
  12898. */
  12899. movePointToUpperLeftOfNode: function(point, bounds) {
  12900. point.x -= bounds.width()/2;
  12901. point.y -= bounds.height()/2;
  12902. },
  12903. /**
  12904. * Refreshes the visual representation of edge's attached nodes.
  12905. */
  12906. refreshAttachedNodes: function() {
  12907. this.attachedNodePositionData.values().each(function(nodeData) {
  12908. var startPoint = nodeData.segment.docker1.bounds.center();
  12909. var endPoint = nodeData.segment.docker2.bounds.center();
  12910. this.relativizePoint(startPoint);
  12911. this.relativizePoint(endPoint);
  12912. var newNodePosition = new Object();
  12913. /* Calculate new x-coordinate */
  12914. newNodePosition.x = startPoint.x
  12915. + nodeData.relativDistanceFromDocker1
  12916. * (endPoint.x - startPoint.x);
  12917. /* Calculate new y-coordinate */
  12918. newNodePosition.y = startPoint.y
  12919. + nodeData.relativDistanceFromDocker1
  12920. * (endPoint.y - startPoint.y);
  12921. /* Convert new position to the upper left of the node */
  12922. this.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds);
  12923. /* Move node to its new position */
  12924. nodeData.node.bounds.moveTo(newNodePosition);
  12925. nodeData.node._update();
  12926. }.bind(this));
  12927. },
  12928. /**
  12929. * Calculates the position of an edge's child node. The node is placed on
  12930. * the path of the edge.
  12931. *
  12932. * @param {node}
  12933. * The node to calculate the new position
  12934. * @return {Point}
  12935. * The calculated upper left point of the node's shape.
  12936. */
  12937. calculatePositionOfAttachedChildNode: function(node) {
  12938. /* Initialize position */
  12939. var position = new Object();
  12940. position.x = 0;
  12941. position.y = 0;
  12942. /* Case: Node was just added */
  12943. if(!this.attachedNodePositionData[node.getId()]) {
  12944. this.attachedNodePositionData[node.getId()] = new Object();
  12945. this.attachedNodePositionData[node.getId()]
  12946. .relativDistanceFromDocker1 = 0;
  12947. this.attachedNodePositionData[node.getId()].node = node;
  12948. this.attachedNodePositionData[node.getId()].segment = new Object();
  12949. this.findEdgeSegmentForNode(node);
  12950. }else if(node.isChanged) {
  12951. this.findEdgeSegmentForNode(node);
  12952. }
  12953. },
  12954. /**
  12955. * Finds the appropriate edge segement for a node.
  12956. * The segment is choosen, which has the smallest distance to the node.
  12957. *
  12958. * @param {ORYX.Core.Node} node
  12959. * The concerning node
  12960. */
  12961. findEdgeSegmentForNode: function(node) {
  12962. var length = this.dockers.length;
  12963. var smallestDistance = undefined;
  12964. for(i=1;i<length;i++) {
  12965. var lineP1 = this.dockers[i-1].bounds.center();
  12966. var lineP2 = this.dockers[i].bounds.center();
  12967. this.relativizePoint(lineP1);
  12968. this.relativizePoint(lineP2);
  12969. var nodeCenterPoint = node.bounds.center();
  12970. var distance = ORYX.Core.Math.distancePointLinie(
  12971. lineP1,
  12972. lineP2,
  12973. nodeCenterPoint,
  12974. true);
  12975. if((distance || distance == 0) && ((!smallestDistance && smallestDistance != 0)
  12976. || distance < smallestDistance)) {
  12977. smallestDistance = distance;
  12978. this.attachedNodePositionData[node.getId()].segment.docker1 =
  12979. this.dockers[i-1];
  12980. this.attachedNodePositionData[node.getId()].segment.docker2 =
  12981. this.dockers[i];
  12982. }
  12983. /* Either the distance does not match the segment or the distance
  12984. * between docker1 and docker2 is 0
  12985. *
  12986. * In this case choose the nearest docker as attaching point.
  12987. *
  12988. */
  12989. if(!distance && !smallestDistance && smallestDistance != 0) {
  12990. (ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1)
  12991. < ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2)) ?
  12992. this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 0 :
  12993. this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 1;
  12994. this.attachedNodePositionData[node.getId()].segment.docker1 =
  12995. this.dockers[i-1];
  12996. this.attachedNodePositionData[node.getId()].segment.docker2 =
  12997. this.dockers[i];
  12998. }
  12999. }
  13000. /* Calculate position on edge segment for the node */
  13001. if(smallestDistance || smallestDistance == 0) {
  13002. this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 =
  13003. this.getLineParameterForPosition(
  13004. this.attachedNodePositionData[node.getId()].segment.docker1,
  13005. this.attachedNodePositionData[node.getId()].segment.docker2,
  13006. node);
  13007. }
  13008. },
  13009. /**
  13010. *
  13011. * @param {ORYX.Core.Node|Object} node or position
  13012. * @return {Object} An object with the following attribute: {ORYX.Core.Docker} fromDocker, {ORYX.Core.Docker} toDocker, {X/Y} position, {int} distance
  13013. */
  13014. findSegment: function(node){
  13015. var length = this.dockers.length;
  13016. var result;
  13017. var nodeCenterPoint = node instanceof ORYX.Core.UIObject ? node.bounds.center() : node;
  13018. for (i = 1; i < length; i++) {
  13019. var lineP1 = this.dockers[i - 1].bounds.center();
  13020. var lineP2 = this.dockers[i].bounds.center();
  13021. var distance = ORYX.Core.Math.distancePointLinie(lineP1, lineP2, nodeCenterPoint, true);
  13022. if (typeof distance == "number" && (result === undefined || distance < result.distance)) {
  13023. result = {
  13024. distance: distance,
  13025. fromDocker: this.dockers[i - 1],
  13026. toDocker: this.dockers[i]
  13027. }
  13028. }
  13029. }
  13030. return result;
  13031. },
  13032. /**
  13033. * Returns the value of the scalar to determine the position of the node on
  13034. * line defined by docker1 and docker2.
  13035. *
  13036. * @param {point} docker1
  13037. * The docker that defines the start of the line segment
  13038. * @param {point} docker2
  13039. * The docker that defines the end of the line segment
  13040. * @param {ORYX.Core.Node} node
  13041. * The concerning node
  13042. *
  13043. * @return {float} positionParameter
  13044. * The scalar value to determine the position on the line
  13045. */
  13046. getLineParameterForPosition: function(docker1, docker2, node) {
  13047. var dockerPoint1 = docker1.bounds.center();
  13048. var dockerPoint2 = docker2.bounds.center();
  13049. this.relativizePoint(dockerPoint1);
  13050. this.relativizePoint(dockerPoint2);
  13051. var intersectionPoint = ORYX.Core.Math.getPointOfIntersectionPointLine(
  13052. dockerPoint1,
  13053. dockerPoint2,
  13054. node.bounds.center(), true);
  13055. if(!intersectionPoint) {
  13056. return 0;
  13057. }
  13058. var relativeDistance =
  13059. ORYX.Core.Math.getDistancePointToPoint(intersectionPoint, dockerPoint1) /
  13060. ORYX.Core.Math.getDistancePointToPoint(dockerPoint1, dockerPoint2);
  13061. return relativeDistance;
  13062. },
  13063. /**
  13064. * Makes point relative to the upper left of the edge's bound.
  13065. *
  13066. * @param {point} point
  13067. * The point to relativize
  13068. */
  13069. relativizePoint: function(point) {
  13070. point.x -= this.bounds.upperLeft().x;
  13071. point.y -= this.bounds.upperLeft().y;
  13072. },
  13073. /**
  13074. * Move the first and last docker and calls the refresh method.
  13075. * Attention: This does not calculates intersection point between the
  13076. * edge and the bounded nodes. This only works if only the nodes are
  13077. * moves.
  13078. *
  13079. */
  13080. optimizedUpdate: function(){
  13081. var updateDocker = function(docker){
  13082. if (!docker._dockedShape || !docker._dockedShapeBounds)
  13083. return;
  13084. var off = {
  13085. x: docker._dockedShape.bounds.a.x - docker._dockedShapeBounds.a.x,
  13086. y: docker._dockedShape.bounds.a.y - docker._dockedShapeBounds.a.y
  13087. };
  13088. docker.bounds.moveBy(off);
  13089. docker._dockedShapeBounds.moveBy(off);
  13090. }
  13091. updateDocker(this.dockers.first());
  13092. updateDocker(this.dockers.last());
  13093. this.refresh();
  13094. },
  13095. refresh: function(){
  13096. //call base class refresh method
  13097. arguments.callee.$.refresh.apply(this, arguments);
  13098. //TODO consider points for marker mids
  13099. var lastPoint;
  13100. this._paths.each((function(path, index){
  13101. var dockers = this._dockersByPath[path.id];
  13102. var c = undefined;
  13103. var d = undefined;
  13104. if (lastPoint) {
  13105. d = "M" + lastPoint.x + " " + lastPoint.y;
  13106. }
  13107. else {
  13108. c = dockers[0].bounds.center();
  13109. lastPoint = c;
  13110. d = "M" + c.x + " " + c.y;
  13111. }
  13112. for (var i = 1; i < dockers.length; i++) {
  13113. // for each docker, draw a line to the center
  13114. c = dockers[i].bounds.center();
  13115. d = d + "L" + c.x + " " + c.y + " ";
  13116. lastPoint = c;
  13117. }
  13118. path.setAttributeNS(null, "d", d);
  13119. this._interactionPaths[index].setAttributeNS(null, "d", d);
  13120. }).bind(this));
  13121. /* move child shapes of an edge */
  13122. if(this.getChildNodes().length > 0) {
  13123. var x = this.bounds.upperLeft().x;
  13124. var y = this.bounds.upperLeft().y;
  13125. this.node.firstChild.childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
  13126. }
  13127. },
  13128. /**
  13129. * Calculate the Border Intersection Point between two points
  13130. * @param {PointA}
  13131. * @param {PointB}
  13132. */
  13133. getIntersectionPoint: function(){
  13134. var length = Math.floor(this.dockers.length / 2)
  13135. return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center())
  13136. },
  13137. /**
  13138. * Returns TRUE if the bounds is over the edge
  13139. * @param {Bounds}
  13140. *
  13141. */
  13142. isBoundsIncluded: function(bounds){
  13143. var dockers = this.dockers, size = dockers.length;
  13144. return dockers.any(function(docker, i){
  13145. if (i == size-1){ return false; }
  13146. var a = docker.bounds.center();
  13147. var b = dockers[i+1].bounds.center();
  13148. return ORYX.Core.Math.isRectOverLine(a.x, a.y, b.x, b.y, bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y);
  13149. });
  13150. },
  13151. /**
  13152. * Calculate if the point is inside the Shape
  13153. * @param {PointX}
  13154. * @param {PointY}
  13155. */
  13156. isPointIncluded: function(pointX, pointY){
  13157. var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY,
  13158. ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
  13159. var isPointIncluded = undefined;
  13160. if (isbetweenAB && this.dockers.length > 0) {
  13161. var i = 0;
  13162. var point1, point2;
  13163. do {
  13164. point1 = this.dockers[i].bounds.center();
  13165. point2 = this.dockers[++i].bounds.center();
  13166. isPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY,
  13167. point1.x, point1.y,
  13168. point2.x, point2.y,
  13169. ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
  13170. } while (!isPointIncluded && i < this.dockers.length - 1)
  13171. }
  13172. return isPointIncluded;
  13173. },
  13174. /**
  13175. * Calculate if the point is over an special offset area
  13176. * @param {Point}
  13177. */
  13178. isPointOverOffset: function(){
  13179. return false
  13180. },
  13181. /**
  13182. * Returns TRUE if the given node
  13183. * is a child node of the shapes node
  13184. * @param {Element} node
  13185. * @return {Boolean}
  13186. *
  13187. */
  13188. containsNode: function(node){
  13189. if (this._paths.include(node) ||
  13190. this._interactionPaths.include(node)){
  13191. return true;
  13192. }
  13193. return false;
  13194. },
  13195. /**
  13196. * Returns the angle of the line between two dockers
  13197. * (0 - 359.99999999)
  13198. */
  13199. _getAngle: function(docker1, docker2) {
  13200. var p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1;
  13201. var p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2;
  13202. return ORYX.Core.Math.getAngle(p1, p2);
  13203. },
  13204. alignDockers: function(){
  13205. this._update(true);
  13206. var firstPoint = this.dockers.first().bounds.center();
  13207. var lastPoint = this.dockers.last().bounds.center();
  13208. var deltaX = lastPoint.x - firstPoint.x;
  13209. var deltaY = lastPoint.y - firstPoint.y;
  13210. var numOfDockers = this.dockers.length - 1;
  13211. this.dockers.each((function(docker, index){
  13212. var part = index / numOfDockers;
  13213. docker.bounds.unregisterCallback(this._dockerChangedCallback);
  13214. docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY);
  13215. docker.bounds.registerCallback(this._dockerChangedCallback);
  13216. }).bind(this));
  13217. this._dockerChanged();
  13218. },
  13219. add: function(shape){
  13220. arguments.callee.$.add.apply(this, arguments);
  13221. // If the new shape is a Docker which is not contained
  13222. if (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)){
  13223. // Add it to the dockers list ordered by paths
  13224. var pathArray = this._dockersByPath.values()[0];
  13225. if (pathArray) {
  13226. pathArray.splice(this.dockers.indexOf(shape), 0, shape);
  13227. }
  13228. /* Perform nessary adjustments on the edge's child shapes */
  13229. this.handleChildShapesAfterAddDocker(shape);
  13230. }
  13231. },
  13232. /**
  13233. * Performs nessary adjustments on the edge's child shapes.
  13234. *
  13235. * @param {ORYX.Core.Controls.Docker} docker
  13236. * The added docker
  13237. */
  13238. handleChildShapesAfterAddDocker: function(docker) {
  13239. /* Ensure type of Docker */
  13240. if(!docker instanceof ORYX.Core.Controls.Docker) {return undefined;}
  13241. var index = this.dockers.indexOf(docker);
  13242. if(!(0 < index && index < this.dockers.length - 1)) {
  13243. /* Exception: Expect added docker between first and last node of the edge */
  13244. return undefined;
  13245. }
  13246. /* Get child nodes concerning the segment of the new docker */
  13247. var startDocker = this.dockers[index-1];
  13248. var endDocker = this.dockers[index+1];
  13249. /* Adjust the position of edge's child nodes */
  13250. var segmentElements =
  13251. this.getAttachedNodePositionDataForSegment(startDocker, endDocker);
  13252. var lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint(
  13253. startDocker.bounds.center(),
  13254. docker.bounds.center());
  13255. var lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint(
  13256. endDocker.bounds.center(),
  13257. docker.bounds.center());
  13258. if(!(lengthSegmentPart1 + lengthSegmentPart2)) {return;}
  13259. var relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2);
  13260. segmentElements.each(function(nodePositionData) {
  13261. /* Assign child node to the new segment */
  13262. if(nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) {
  13263. /* Case: before added Docker */
  13264. nodePositionData.value.segment.docker2 = docker;
  13265. nodePositionData.value.relativDistanceFromDocker1 =
  13266. nodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition;
  13267. } else {
  13268. /* Case: after added Docker */
  13269. nodePositionData.value.segment.docker1 = docker;
  13270. var newFullDistance = 1 - relativDockerPosition;
  13271. var relativPartOfSegment =
  13272. nodePositionData.value.relativDistanceFromDocker1
  13273. - relativDockerPosition;
  13274. nodePositionData.value.relativDistanceFromDocker1 =
  13275. relativPartOfSegment / newFullDistance;
  13276. }
  13277. })
  13278. // Update all labels reference points
  13279. this.getLabels().each(function(label){
  13280. var ref = label.getReferencePoint();
  13281. if (!ref) {
  13282. return;
  13283. }
  13284. var index = this.dockers.indexOf(docker);
  13285. if (index >= ref.segment.fromIndex && index <= ref.segment.toIndex){
  13286. var segment = this.findSegment(ref.intersection);
  13287. if (!segment){
  13288. // Choose whether the first of the last segment
  13289. segment.fromDocker = ref.segment.fromIndex >= (this.dockers.length/2) ? this.dockers[0] : this.dockers[this.dockers.length-2];
  13290. segment.toDocker = this.dockers[this.dockers.indexOf(from)+1]; // The next one if the to docker
  13291. }
  13292. var fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center();
  13293. var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(
  13294. fromPosition, // P1 - Center of the first docker
  13295. toPosition, // P2 - Center of the second docker
  13296. ref.intersection, // P3 - Center of the label
  13297. true);
  13298. //var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);
  13299. //intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew);
  13300. // Update the reference point
  13301. this.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true);
  13302. }
  13303. }.bind(this));
  13304. /* Update attached nodes visual representation */
  13305. this.refreshAttachedNodes();
  13306. },
  13307. /**
  13308. * Returns elements from {@link attachedNodePositiondata} that match the
  13309. * segement defined by startDocker and endDocker.
  13310. *
  13311. * @param {ORYX.Core.Controls.Docker} startDocker
  13312. * The docker defining the begin of the segment.
  13313. * @param {ORYX.Core.Controls.Docker} endDocker
  13314. * The docker defining the begin of the segment.
  13315. *
  13316. * @return {Hash} attachedNodePositionData
  13317. * Child elements matching the segment
  13318. */
  13319. getAttachedNodePositionDataForSegment: function(startDocker, endDocker) {
  13320. /* Ensure that the segment is defined correctly */
  13321. if(!((startDocker instanceof ORYX.Core.Controls.Docker)
  13322. && (endDocker instanceof ORYX.Core.Controls.Docker))) {
  13323. return [];
  13324. }
  13325. /* Get elements of the segment */
  13326. var elementsOfSegment =
  13327. this.attachedNodePositionData.findAll(function(nodePositionData) {
  13328. return nodePositionData.value.segment.docker1 === startDocker &&
  13329. nodePositionData.value.segment.docker2 === endDocker;
  13330. });
  13331. /* Return a Hash in each case */
  13332. if(!elementsOfSegment) {return [];}
  13333. return elementsOfSegment;
  13334. },
  13335. /**
  13336. * Removes an edge's child shape
  13337. */
  13338. remove: function(shape) {
  13339. arguments.callee.$.remove.apply(this, arguments);
  13340. if(this.attachedNodePositionData[shape.getId()]) {
  13341. delete this.attachedNodePositionData[shape.getId()];
  13342. }
  13343. /* Adjust child shapes if neccessary */
  13344. if(shape instanceof ORYX.Core.Controls.Docker) {
  13345. this.handleChildShapesAfterRemoveDocker(shape);
  13346. }
  13347. },
  13348. updateReferencePointOfLabel: function(label, intersection, from, to, dirty){
  13349. if (!label.getReferencePoint() || !label.isVisible) {
  13350. return;
  13351. }
  13352. var ref = label.getReferencePoint();
  13353. //
  13354. if (ref.orientation && ref.orientation !== "ce"){
  13355. var angle = this._getAngle(from, to);
  13356. if (ref.distance >= 0){
  13357. if(angle == 0){
  13358. label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left");
  13359. label.verticalAlign("bottom");
  13360. } else if (angle > 0 && angle < 90){
  13361. label.horizontalAlign("right");
  13362. label.verticalAlign("bottom");
  13363. } else if (angle == 90){
  13364. label.horizontalAlign("right");
  13365. label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top");
  13366. } else if (angle > 90 && angle < 180){
  13367. label.horizontalAlign("right");
  13368. label.verticalAlign("top");
  13369. } else if (angle == 180){
  13370. label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left");
  13371. label.verticalAlign("top");
  13372. } else if (angle > 180 && angle < 270){
  13373. label.horizontalAlign("left");
  13374. label.verticalAlign("top");
  13375. } else if (angle == 270){
  13376. label.horizontalAlign("left");
  13377. label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top");
  13378. } else if (angle > 270 && angle <= 360){
  13379. label.horizontalAlign("left");
  13380. label.verticalAlign("bottom");
  13381. }
  13382. } else {
  13383. if(angle == 0){
  13384. label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left");
  13385. label.verticalAlign("top");
  13386. } else if (angle > 0 && angle < 90){
  13387. label.horizontalAlign("left");
  13388. label.verticalAlign("top");
  13389. } else if (angle == 90){
  13390. label.horizontalAlign("left");
  13391. label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top");
  13392. } else if (angle > 90 && angle < 180){
  13393. label.horizontalAlign("left");
  13394. label.verticalAlign("bottom");
  13395. } else if (angle == 180){
  13396. label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left");
  13397. label.verticalAlign("bottom");
  13398. } else if (angle > 180 && angle < 270){
  13399. label.horizontalAlign("right");
  13400. label.verticalAlign("bottom");
  13401. } else if (angle == 270){
  13402. label.horizontalAlign("right");
  13403. label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top");
  13404. } else if (angle > 270 && angle <= 360){
  13405. label.horizontalAlign("right");
  13406. label.verticalAlign("top");
  13407. }
  13408. }
  13409. ref.iorientation = ref.iorientation || ref.orientation;
  13410. ref.orientation = (label.verticalAlign()=="top"?"u":"l") + (label.horizontalAlign()=="left"?"l":"r");
  13411. }
  13412. label.setReferencePoint(jQuery.extend({},{
  13413. intersection: intersection,
  13414. segment: {
  13415. from: from,
  13416. fromIndex: this.dockers.indexOf(from),
  13417. fromPosition: from.bounds.center(),
  13418. to: to,
  13419. toIndex: this.dockers.indexOf(to),
  13420. toPosition: to.bounds.center()
  13421. },
  13422. dirty: dirty || false
  13423. },ref))
  13424. },
  13425. /**
  13426. * Adjusts the child shapes of an edges after a docker was removed.
  13427. *
  13428. * @param{ORYX.Core.Controls.Docker} docker
  13429. * The removed docker.
  13430. */
  13431. handleChildShapesAfterRemoveDocker: function(docker) {
  13432. /* Ensure docker type */
  13433. if(!(docker instanceof ORYX.Core.Controls.Docker)) {return;}
  13434. this.attachedNodePositionData.each(function(nodePositionData) {
  13435. if(nodePositionData.value.segment.docker1 === docker) {
  13436. /* The new start of the segment is the predecessor of docker2. */
  13437. var index = this.dockers.indexOf(nodePositionData.value.segment.docker2);
  13438. if(index == -1) {return;}
  13439. nodePositionData.value.segment.docker1 = this.dockers[index - 1];
  13440. }
  13441. else if(nodePositionData.value.segment.docker2 === docker) {
  13442. /* The new end of the segment is the successor of docker1. */
  13443. var index = this.dockers.indexOf(nodePositionData.value.segment.docker1);
  13444. if(index == -1) {return;}
  13445. nodePositionData.value.segment.docker2 = this.dockers[index + 1];
  13446. }
  13447. }.bind(this));
  13448. // Update all labels reference points
  13449. this.getLabels().each(function(label){
  13450. var ref = label.getReferencePoint();
  13451. if (!ref) {
  13452. return;
  13453. }
  13454. var from = ref.segment.from;
  13455. var to = ref.segment.to;
  13456. if (from !== docker && to !== docker){
  13457. return;
  13458. }
  13459. var segment = this.findSegment(ref.intersection);
  13460. if (!segment){
  13461. from = segment.fromDocker;
  13462. to = segment.toDocker;
  13463. } else {
  13464. from = from === docker ? this.dockers[this.dockers.indexOf(to)-1] : from;
  13465. to = this.dockers[this.dockers.indexOf(from)+1];
  13466. }
  13467. var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true);
  13468. // Update the reference point
  13469. this.updateReferencePointOfLabel(label, intersection, from, to, true);
  13470. }.bind(this));
  13471. /* Update attached nodes visual representation */
  13472. this.refreshAttachedNodes();
  13473. },
  13474. /**
  13475. *@deprecated Use the .createDocker() Method and set the point via the bounds
  13476. */
  13477. addDocker: function(position, exDocker){
  13478. var lastDocker;
  13479. var result;
  13480. this._dockersByPath.any((function(pair){
  13481. return pair.value.any((function(docker, index){
  13482. if (!lastDocker) {
  13483. lastDocker = docker;
  13484. return false;
  13485. }
  13486. else {
  13487. var point1 = lastDocker.bounds.center();
  13488. var point2 = docker.bounds.center();
  13489. var additionalIEZoom = 1;
  13490. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  13491. var ua = navigator.userAgent;
  13492. if (ua.indexOf('MSIE') >= 0) {
  13493. //IE 10 and below
  13494. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  13495. if (zoom !== 100) {
  13496. additionalIEZoom = zoom / 100
  13497. }
  13498. }
  13499. }
  13500. if (additionalIEZoom !== 1) {
  13501. position.x = position.x / additionalIEZoom;
  13502. position.y = position.y / additionalIEZoom;
  13503. }
  13504. if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) {
  13505. var path = this._paths.find(function(path){
  13506. return path.id === pair.key;
  13507. });
  13508. if (path) {
  13509. var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers');
  13510. if (allowAttr && allowAttr.toLowerCase() === "no") {
  13511. return true;
  13512. }
  13513. }
  13514. var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position);
  13515. newDocker.bounds.centerMoveTo(position);
  13516. if(exDocker)
  13517. this.add(newDocker, this.dockers.indexOf(lastDocker) + 1);
  13518. result = newDocker;
  13519. return true;
  13520. }
  13521. else {
  13522. lastDocker = docker;
  13523. return false;
  13524. }
  13525. }
  13526. }).bind(this));
  13527. }).bind(this));
  13528. return result;
  13529. },
  13530. removeDocker: function(docker){
  13531. if (this.dockers.length > 2 && !(this.dockers.first() === docker)) {
  13532. this._dockersByPath.any((function(pair){
  13533. if (pair.value.member(docker)) {
  13534. if (docker === pair.value.last()) {
  13535. return true;
  13536. }
  13537. else {
  13538. this.remove(docker);
  13539. this._dockersByPath[pair.key] = pair.value.without(docker);
  13540. this.isChanged = true;
  13541. this._dockerChanged();
  13542. return true;
  13543. }
  13544. }
  13545. return false;
  13546. }).bind(this));
  13547. }
  13548. },
  13549. /**
  13550. * Removes all dockers from the edge which are on
  13551. * the line between two dockers
  13552. * @return {Object} Removed dockers in an indicied array
  13553. * (key is the removed position of the docker, value is docker themselve)
  13554. */
  13555. removeUnusedDockers:function(){
  13556. var marked = $H({});
  13557. this.dockers.each(function(docker, i){
  13558. if (i==0||i==this.dockers.length-1){ return }
  13559. var previous = this.dockers[i-1];
  13560. /* Do not consider already removed dockers */
  13561. if(marked.values().indexOf(previous) != -1 && this.dockers[i-2]) {
  13562. previous = this.dockers[i-2];
  13563. }
  13564. var next = this.dockers[i+1];
  13565. var cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center();
  13566. var cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center();
  13567. var cd = docker.bounds.center();
  13568. if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)){
  13569. marked[i] = docker;
  13570. }
  13571. }.bind(this))
  13572. marked.each(function(docker){
  13573. this.removeDocker(docker.value);
  13574. }.bind(this))
  13575. if (marked.values().length > 0){
  13576. this._update(true);
  13577. }
  13578. return marked;
  13579. },
  13580. /**
  13581. * Initializes the Edge after loading the SVG representation of the edge.
  13582. * @param {SVGDocument} svgDocument
  13583. */
  13584. _init: function(svgDocument){
  13585. arguments.callee.$._init.apply(this, arguments);
  13586. var minPointX, minPointY, maxPointX, maxPointY;
  13587. //init markers
  13588. var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "defs");
  13589. if (defs.length > 0) {
  13590. defs = defs[0];
  13591. var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, "marker"));
  13592. var marker;
  13593. var me = this;
  13594. markerElements.each(function(markerElement){
  13595. try {
  13596. marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true));
  13597. me._markers[marker.id] = marker;
  13598. var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, "text"));
  13599. var label;
  13600. textElements.each(function(textElement){
  13601. label = new ORYX.Core.SVG.Label({
  13602. textElement: textElement,
  13603. shapeId: this.id
  13604. });
  13605. me._labels[label.id] = label;
  13606. });
  13607. }
  13608. catch (e) {
  13609. }
  13610. });
  13611. }
  13612. var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "g");
  13613. if (gs.length <= 0) {
  13614. throw "Edge: No g element found.";
  13615. }
  13616. var g = gs[0];
  13617. g.setAttributeNS(null, "id", null);
  13618. var isFirst = true;
  13619. $A(g.childNodes).each((function(path, index){
  13620. if (ORYX.Editor.checkClassType(path, SVGPathElement)) {
  13621. path = path.cloneNode(false);
  13622. var pathId = this.id + "_" + index;
  13623. path.setAttributeNS(null, "id", pathId);
  13624. this._paths.push(path);
  13625. //check, if markers are set and update the id
  13626. var markersByThisPath = [];
  13627. var markerUrl = path.getAttributeNS(null, "marker-start");
  13628. if (markerUrl && markerUrl !== "") {
  13629. markerUrl = markerUrl.strip();
  13630. markerUrl = markerUrl.replace(/^url\(#/, '');
  13631. var markerStartId = this.getValidMarkerId(markerUrl);
  13632. path.setAttributeNS(null, "marker-start", "url(#" + markerStartId + ")");
  13633. markersByThisPath.push(this._markers[markerStartId]);
  13634. }
  13635. markerUrl = path.getAttributeNS(null, "marker-mid");
  13636. if (markerUrl && markerUrl !== "") {
  13637. markerUrl = markerUrl.strip();
  13638. markerUrl = markerUrl.replace(/^url\(#/, '');
  13639. var markerMidId = this.getValidMarkerId(markerUrl);
  13640. path.setAttributeNS(null, "marker-mid", "url(#" + markerMidId + ")");
  13641. markersByThisPath.push(this._markers[markerMidId]);
  13642. }
  13643. markerUrl = path.getAttributeNS(null, "marker-end");
  13644. if (markerUrl && markerUrl !== "") {
  13645. markerUrl = markerUrl.strip();
  13646. var markerEndId = this.getValidMarkerId(markerUrl);
  13647. path.setAttributeNS(null, "marker-end", "url(#" + markerEndId + ")");
  13648. markersByThisPath.push(this._markers[markerEndId]);
  13649. }
  13650. this._markersByPath[pathId] = markersByThisPath;
  13651. //init dockers
  13652. var parser = new PathParser();
  13653. var handler = new ORYX.Core.SVG.PointsPathHandler();
  13654. parser.setHandler(handler);
  13655. parser.parsePath(path);
  13656. if (handler.points.length < 4) {
  13657. throw "Edge: Path has to have two or more points specified.";
  13658. }
  13659. this._dockersByPath[pathId] = [];
  13660. for (var i = 0; i < handler.points.length; i += 2) {
  13661. //handler.points.each((function(point, pIndex){
  13662. var x = handler.points[i];
  13663. var y = handler.points[i+1];
  13664. if (isFirst || i > 0) {
  13665. var docker = new ORYX.Core.Controls.Docker({
  13666. eventHandlerCallback: this.eventHandlerCallback
  13667. });
  13668. docker.bounds.centerMoveTo(x,y);
  13669. docker.bounds.registerCallback(this._dockerChangedCallback);
  13670. this.add(docker, this.dockers.length);
  13671. //this._dockersByPath[pathId].push(docker);
  13672. //calculate minPoint and maxPoint
  13673. if (minPointX) {
  13674. minPointX = Math.min(x, minPointX);
  13675. minPointY = Math.min(y, minPointY);
  13676. }
  13677. else {
  13678. minPointX = x;
  13679. minPointY = y;
  13680. }
  13681. if (maxPointX) {
  13682. maxPointX = Math.max(x, maxPointX);
  13683. maxPointY = Math.max(y, maxPointY);
  13684. }
  13685. else {
  13686. maxPointX = x;
  13687. maxPointY = y;
  13688. }
  13689. }
  13690. //}).bind(this));
  13691. }
  13692. isFirst = false;
  13693. }
  13694. }).bind(this));
  13695. this.bounds.set(minPointX, minPointY, maxPointX, maxPointY);
  13696. if (false&&(this.bounds.width() === 0 || this.bounds.height() === 0)) {
  13697. var width = this.bounds.width();
  13698. var height = this.bounds.height();
  13699. this.bounds.extend({
  13700. x: width === 0 ? 2 : 0,
  13701. y: height === 0 ? 2 : 0
  13702. });
  13703. this.bounds.moveBy({
  13704. x: width === 0 ? -1 : 0,
  13705. y: height === 0 ? -1 : 0
  13706. });
  13707. }
  13708. this._oldBounds = this.bounds.clone();
  13709. //add paths to this.node
  13710. this._paths.reverse();
  13711. var paths = [];
  13712. this._paths.each((function(path){
  13713. paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path));
  13714. }).bind(this));
  13715. this._paths = paths;
  13716. //init interaction path
  13717. this._paths.each((function(path){
  13718. var iPath = path.cloneNode(false);
  13719. iPath.setAttributeNS(null, "id", undefined);
  13720. iPath.setAttributeNS(null, "stroke-width", 10);
  13721. iPath.setAttributeNS(null, "visibility", "hidden");
  13722. iPath.setAttributeNS(null, "stroke-dasharray", null);
  13723. iPath.setAttributeNS(null, "stroke", "black");
  13724. iPath.setAttributeNS(null, "fill", "none");
  13725. iPath.setAttributeNS(null, "title", this.getStencil().title());
  13726. this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath));
  13727. }).bind(this));
  13728. this._paths.reverse();
  13729. this._interactionPaths.reverse();
  13730. /**initialize labels*/
  13731. var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');
  13732. $A(textElems).each((function(textElem){
  13733. var label = new ORYX.Core.SVG.Label({
  13734. textElement: textElem,
  13735. shapeId: this.id
  13736. });
  13737. this.node.childNodes[0].childNodes[0].appendChild(label.node);
  13738. this._labels[label.id] = label;
  13739. label.registerOnChange(this.layout.bind(this));
  13740. }).bind(this));
  13741. this.propertiesChanged.each(function(pair){
  13742. pair.value = true;
  13743. });
  13744. //if(this.dockers.length == 2) {
  13745. // }
  13746. //this._update(true);
  13747. },
  13748. getValidMarkerId: function(markerUrl) {
  13749. if(markerUrl.indexOf("url(\"#") >= 0) {
  13750. // Fix for IE9, additional quotes are added to the <id
  13751. var rawId = markerUrl.replace(/^url\(\"#/, "").replace(/\"\)$/, '');
  13752. return this.id + rawId;
  13753. } else {
  13754. markerUrl = markerUrl.replace(/^url\(#/, '');
  13755. return this.id.concat(markerUrl.replace(/\)$/, ''));
  13756. }
  13757. },
  13758. /**
  13759. * Adds all necessary markers of this Edge to the SVG document.
  13760. * Has to be called, while this.node is part of DOM.
  13761. */
  13762. addMarkers: function(defs){
  13763. this._markers.each(function(marker){
  13764. if (!defs.ownerDocument.getElementById(marker.value.id)) {
  13765. marker.value.element = defs.appendChild(marker.value.element);
  13766. }
  13767. });
  13768. },
  13769. /**
  13770. * Removes all necessary markers of this Edge from the SVG document.
  13771. * Has to be called, while this.node is part of DOM.
  13772. */
  13773. removeMarkers: function(){
  13774. var svgElement = this.node.ownerSVGElement;
  13775. if (svgElement) {
  13776. var defs = svgElement.getElementsByTagNameNS(NAMESPACE_SVG, "defs");
  13777. if (defs.length > 0) {
  13778. defs = defs[0];
  13779. this._markers.each(function(marker){
  13780. var foundMarker = defs.ownerDocument.getElementById(marker.value.id);
  13781. if (foundMarker) {
  13782. marker.value.element = defs.removeChild(marker.value.element);
  13783. }
  13784. });
  13785. }
  13786. }
  13787. },
  13788. /**
  13789. * Calls when a docker has changed
  13790. */
  13791. _dockerChanged: function(){
  13792. //this._update(true);
  13793. this._dockerUpdated = true;
  13794. },
  13795. serialize: function(){
  13796. var result = arguments.callee.$.serialize.apply(this);
  13797. //add dockers triple
  13798. var value = "";
  13799. this._dockersByPath.each((function(pair){
  13800. pair.value.each(function(docker){
  13801. var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
  13802. value = value.concat(position.x + " " + position.y + " ");
  13803. });
  13804. value += " # ";
  13805. }).bind(this));
  13806. result.push({
  13807. name: 'dockers',
  13808. prefix: 'oryx',
  13809. value: value,
  13810. type: 'literal'
  13811. });
  13812. //add parent triple dependant on the dockedShapes
  13813. //TODO change this when canvas becomes a resource
  13814. /* var source = this.dockers.first().getDockedShape();
  13815. var target = this.dockers.last().getDockedShape();
  13816. var sharedParent;
  13817. if (source && target) {
  13818. //get shared parent
  13819. while (source.parent) {
  13820. source = source.parent;
  13821. if (source instanceof ORYX.Core.Canvas) {
  13822. sharedParent = source;
  13823. break;
  13824. }
  13825. else {
  13826. var targetParent = target.parent;
  13827. var found;
  13828. while (targetParent) {
  13829. if (source === targetParent) {
  13830. sharedParent = source;
  13831. found = true;
  13832. break;
  13833. }
  13834. else {
  13835. targetParent = targetParent.parent;
  13836. }
  13837. }
  13838. if (found) {
  13839. break;
  13840. }
  13841. }
  13842. }
  13843. }
  13844. else
  13845. if (source) {
  13846. sharedParent = source.parent;
  13847. }
  13848. else
  13849. if (target) {
  13850. sharedParent = target.parent;
  13851. }
  13852. */
  13853. //if (sharedParent) {
  13854. /* result.push({
  13855. name: 'parent',
  13856. prefix: 'raziel',
  13857. //value: '#' + ERDF.__stripHashes(sharedParent.resourceId),
  13858. value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId),
  13859. type: 'resource'
  13860. });*/
  13861. //}
  13862. //serialize target and source
  13863. var lastDocker = this.dockers.last();
  13864. var target = lastDocker.getDockedShape();
  13865. if(target) {
  13866. result.push({
  13867. name: 'target',
  13868. prefix: 'raziel',
  13869. value: '#' + ERDF.__stripHashes(target.resourceId),
  13870. type: 'resource'
  13871. });
  13872. }
  13873. try {
  13874. //result = this.getStencil().serialize(this, result);
  13875. var serializeEvent = this.getStencil().serialize();
  13876. /*
  13877. * call serialize callback by reference, result should be found
  13878. * in serializeEvent.result
  13879. */
  13880. if(serializeEvent.type) {
  13881. serializeEvent.shape = this;
  13882. serializeEvent.data = result;
  13883. serializeEvent.result = undefined;
  13884. serializeEvent.forceExecution = true;
  13885. this._delegateEvent(serializeEvent);
  13886. if(serializeEvent.result) {
  13887. result = serializeEvent.result;
  13888. }
  13889. }
  13890. }
  13891. catch (e) {
  13892. }
  13893. return result;
  13894. },
  13895. deserialize: function(data){
  13896. try {
  13897. //data = this.getStencil().deserialize(this, data);
  13898. var deserializeEvent = this.getStencil().deserialize();
  13899. /*
  13900. * call serialize callback by reference, result should be found
  13901. * in serializeEventInfo.result
  13902. */
  13903. if(deserializeEvent.type) {
  13904. deserializeEvent.shape = this;
  13905. deserializeEvent.data = data;
  13906. deserializeEvent.result = undefined;
  13907. deserializeEvent.forceExecution = true;
  13908. this._delegateEvent(deserializeEvent);
  13909. if(deserializeEvent.result) {
  13910. data = deserializeEvent.result;
  13911. }
  13912. }
  13913. }
  13914. catch (e) {
  13915. }
  13916. // Set the outgoing shapes
  13917. var target = data.find(function(ser) {return (ser.prefix+"-"+ser.name) == 'raziel-target'});
  13918. var targetShape;
  13919. if(target) {
  13920. targetShape = this.getCanvas().getChildShapeByResourceId(target.value);
  13921. }
  13922. var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'});
  13923. outgoing.each((function(obj){
  13924. // TODO: Look at Canvas
  13925. if(!this.parent) {return};
  13926. // Set outgoing Shape
  13927. var next = this.getCanvas().getChildShapeByResourceId(obj.value);
  13928. if(next){
  13929. if(next == targetShape) {
  13930. // If this is an edge, set the last docker to the next shape
  13931. this.dockers.last().setDockedShape(next);
  13932. this.dockers.last().setReferencePoint({x: next.bounds.width() / 2.0, y: next.bounds.height() / 2.0});
  13933. } else if(next instanceof ORYX.Core.Edge) {
  13934. //Set the first docker of the next shape
  13935. next.dockers.first().setDockedShape(this);
  13936. //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
  13937. } /*else if(next.dockers.length > 0) { //next is a node and next has a docker
  13938. next.dockers.first().setDockedShape(this);
  13939. next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
  13940. }*/
  13941. }
  13942. }).bind(this));
  13943. var oryxDockers = data.find(function(obj){
  13944. return (obj.prefix === "oryx" &&
  13945. obj.name === "dockers");
  13946. });
  13947. if (oryxDockers) {
  13948. var dataByPath = oryxDockers.value.split("#").without("").without(" ");
  13949. dataByPath.each((function(data, index){
  13950. var values = data.replace(/,/g, " ").split(" ").without("");
  13951. //for each docker two values must be defined
  13952. if (values.length % 2 === 0) {
  13953. var path = this._paths[index];
  13954. if (path) {
  13955. if (index === 0) {
  13956. while (this._dockersByPath[path.id].length > 2) {
  13957. this.removeDocker(this._dockersByPath[path.id][1]);
  13958. }
  13959. }
  13960. else {
  13961. while (this._dockersByPath[path.id].length > 1) {
  13962. this.removeDocker(this._dockersByPath[path.id][0]);
  13963. }
  13964. }
  13965. var dockersByPath = this._dockersByPath[path.id];
  13966. if (index === 0) {
  13967. //set position of first docker
  13968. var x = parseFloat(values.shift());
  13969. var y = parseFloat(values.shift());
  13970. if (dockersByPath.first().getDockedShape()) {
  13971. dockersByPath.first().setReferencePoint({
  13972. x: x,
  13973. y: y
  13974. });
  13975. }
  13976. else {
  13977. dockersByPath.first().bounds.centerMoveTo(x, y);
  13978. }
  13979. }
  13980. //set position of last docker
  13981. y = parseFloat(values.pop());
  13982. x = parseFloat(values.pop());
  13983. if (dockersByPath.last().getDockedShape()) {
  13984. dockersByPath.last().setReferencePoint({
  13985. x: x,
  13986. y: y
  13987. });
  13988. } else {
  13989. dockersByPath.last().bounds.centerMoveTo(x, y);
  13990. }
  13991. //add additional dockers
  13992. for (var i = 0; i < values.length; i++) {
  13993. x = parseFloat(values[i]);
  13994. y = parseFloat(values[++i]);
  13995. var newDocker = this.createDocker();
  13996. newDocker.bounds.centerMoveTo(x, y);
  13997. //this.dockers = this.dockers.without(newDocker);
  13998. //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);
  13999. //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);
  14000. }
  14001. }
  14002. }
  14003. }).bind(this));
  14004. } else {
  14005. this.alignDockers();
  14006. }
  14007. arguments.callee.$.deserialize.apply(this, arguments);
  14008. this._changed();
  14009. },
  14010. toString: function(){
  14011. return this.getStencil().title() + " " + this.id;
  14012. },
  14013. /**
  14014. * @return {ORYX.Core.Shape} Returns last docked shape or null.
  14015. */
  14016. getTarget: function(){
  14017. return this.dockers.last() ? this.dockers.last().getDockedShape() : null;
  14018. },
  14019. /**
  14020. * @return {ORYX.Core.Shape} Returns the first docked shape or null
  14021. */
  14022. getSource: function() {
  14023. return this.dockers.first() ? this.dockers.first().getDockedShape() : null;
  14024. },
  14025. /**
  14026. * Checks whether the edge is at least docked to one shape.
  14027. *
  14028. * @return {boolean} True if edge is docked
  14029. */
  14030. isDocked: function() {
  14031. var isDocked = false;
  14032. this.dockers.each(function(docker) {
  14033. if(docker.isDocked()) {
  14034. isDocked = true;
  14035. throw $break;
  14036. }
  14037. });
  14038. return isDocked;
  14039. },
  14040. /**
  14041. * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information.
  14042. */
  14043. toJSON: function() {
  14044. var json = arguments.callee.$.toJSON.apply(this, arguments);
  14045. if(this.getTarget()) {
  14046. json.target = {
  14047. resourceId: this.getTarget().resourceId
  14048. };
  14049. }
  14050. return json;
  14051. }
  14052. };
  14053. ORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge);
  14054. /*
  14055. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  14056. * License rights for this program may be obtained from Alfresco Software, Ltd.
  14057. * pursuant to a written agreement and any use of this program without such an
  14058. * agreement is prohibited.
  14059. */
  14060. /*
  14061. * All code Copyright 2013 KIS Consultancy all rights reserved
  14062. */
  14063. if(!ORYX){ var ORYX = {} }
  14064. if(!ORYX.Plugins){ ORYX.Plugins = {} }
  14065. /**
  14066. This abstract plugin class can be used to build plugins on.
  14067. It provides some more basic functionality like registering events (on*-handlers)...
  14068. @example
  14069. ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({
  14070. construct: function() {
  14071. // Call super class constructor
  14072. arguments.callee.$.construct.apply(this, arguments);
  14073. [...]
  14074. },
  14075. [...]
  14076. });
  14077. @class ORYX.Plugins.AbstractPlugin
  14078. @constructor Creates a new instance
  14079. @author Willi Tscheschner
  14080. */
  14081. ORYX.Plugins.AbstractPlugin = Clazz.extend({
  14082. /**
  14083. * The facade which offer editor-specific functionality
  14084. * @type Facade
  14085. * @memberOf ORYX.Plugins.AbstractPlugin.prototype
  14086. */
  14087. facade: null,
  14088. construct: function( facade ){
  14089. this.facade = facade;
  14090. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this));
  14091. },
  14092. /**
  14093. Overwrite to handle load event. TODO: Document params!!!
  14094. @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14095. */
  14096. onLoaded: function(){},
  14097. /**
  14098. Overwrite to handle selection changed event. TODO: Document params!!!
  14099. @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14100. */
  14101. onSelectionChanged: function(){},
  14102. /**
  14103. Show overlay on given shape.
  14104. @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14105. @example
  14106. showOverlay(
  14107. myShape,
  14108. { stroke: "green" },
  14109. ORYX.Editor.graft("http://www.w3.org/2000/svg", null, ['path', {
  14110. "title": "Click the element to execute it!",
  14111. "stroke-width": 2.0,
  14112. "stroke": "black",
  14113. "d": "M0,-5 L5,0 L0,5 Z",
  14114. "line-captions": "round"
  14115. }])
  14116. )
  14117. @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on
  14118. @param {Oryx.XXX.Attributes} attributes some attributes...
  14119. @param {Oryx.svg.node} svgNode The svg node which should be used as overlay
  14120. @param {String} [svgNode="NW"] The svg node position where the overlay should be placed
  14121. */
  14122. showOverlay: function(shapes, attributes, svgNode, svgNodePosition ){
  14123. if( !(shapes instanceof Array) ){
  14124. shapes = [shapes]
  14125. }
  14126. // Define Shapes
  14127. shapes = shapes.map(function(shape){
  14128. var el = shape;
  14129. if( typeof shape == "string" ){
  14130. el = this.facade.getCanvas().getChildShapeByResourceId( shape );
  14131. el = el || this.facade.getCanvas().getChildById( shape, true );
  14132. }
  14133. return el;
  14134. }.bind(this)).compact();
  14135. // Define unified id
  14136. if( !this.overlayID ){
  14137. this.overlayID = this.type + ORYX.Editor.provideId();
  14138. }
  14139. this.facade.raiseEvent({
  14140. type : ORYX.CONFIG.EVENT_OVERLAY_SHOW,
  14141. id : this.overlayID,
  14142. shapes : shapes,
  14143. attributes : attributes,
  14144. node : svgNode,
  14145. nodePosition: svgNodePosition || "NW"
  14146. });
  14147. },
  14148. /**
  14149. Hide current overlay.
  14150. @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14151. */
  14152. hideOverlay: function(){
  14153. this.facade.raiseEvent({
  14154. type : ORYX.CONFIG.EVENT_OVERLAY_HIDE,
  14155. id : this.overlayID
  14156. });
  14157. },
  14158. /**
  14159. Does a transformation with the given xslt stylesheet.
  14160. @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14161. @param {String} data The data (e.g. eRDF) which should be transformed
  14162. @param {String} stylesheet URL of a stylesheet which should be used for transforming data.
  14163. */
  14164. doTransform: function( data, stylesheet ) {
  14165. if( !stylesheet || !data ){
  14166. return ""
  14167. }
  14168. var parser = new DOMParser();
  14169. var parsedData = parser.parseFromString(data, "text/xml");
  14170. source=stylesheet;
  14171. new Ajax.Request(source, {
  14172. asynchronous: false,
  14173. method: 'get',
  14174. onSuccess: function(transport){
  14175. xsl = transport.responseText
  14176. }.bind(this),
  14177. onFailure: (function(transport){
  14178. ORYX.Log.error("XSL load failed" + transport);
  14179. }).bind(this)
  14180. });
  14181. var xsltProcessor = new XSLTProcessor();
  14182. var domParser = new DOMParser();
  14183. var xslObject = domParser.parseFromString(xsl, "text/xml");
  14184. xsltProcessor.importStylesheet(xslObject);
  14185. try {
  14186. var newData = xsltProcessor.transformToFragment(parsedData, document);
  14187. var serializedData = (new XMLSerializer()).serializeToString(newData);
  14188. /* Firefox 2 to 3 problem?! */
  14189. serializedData = !serializedData.startsWith("<?xml") ? "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serializedData : serializedData;
  14190. return serializedData;
  14191. }catch (error) {
  14192. return -1;
  14193. }
  14194. },
  14195. /**
  14196. * Opens a new window that shows the given XML content.
  14197. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14198. * @param {Object} content The XML content to be shown.
  14199. * @example
  14200. * openDownloadWindow( "my.xml", "<exampleXML />" );
  14201. */
  14202. openXMLWindow: function(content) {
  14203. var win = window.open(
  14204. 'data:application/xml,' + encodeURIComponent(
  14205. content
  14206. ),
  14207. '_blank', "resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes"
  14208. );
  14209. },
  14210. /**
  14211. * Opens a download window for downloading the given content.
  14212. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14213. * @param {String} filename The content's file name
  14214. * @param {String} content The content to download
  14215. */
  14216. openDownloadWindow: function(filename, content) {
  14217. var win = window.open("");
  14218. if (win != null) {
  14219. win.document.open();
  14220. win.document.write("<html><body>");
  14221. var submitForm = win.document.createElement("form");
  14222. win.document.body.appendChild(submitForm);
  14223. var createHiddenElement = function(name, value) {
  14224. var newElement = document.createElement("input");
  14225. newElement.name=name;
  14226. newElement.type="hidden";
  14227. newElement.value = value;
  14228. return newElement
  14229. }
  14230. submitForm.appendChild( createHiddenElement("download", content) );
  14231. submitForm.appendChild( createHiddenElement("file", filename) );
  14232. submitForm.method = "POST";
  14233. win.document.write("</body></html>");
  14234. win.document.close();
  14235. submitForm.action= ORYX.PATH + "/download";
  14236. submitForm.submit();
  14237. }
  14238. },
  14239. /**
  14240. * Serializes DOM.
  14241. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14242. * @type {String} Serialized DOM
  14243. */
  14244. getSerializedDOM: function(){
  14245. // Force to set all resource IDs
  14246. var serializedDOM = DataManager.serializeDOM( this.facade );
  14247. //add namespaces
  14248. serializedDOM = '<?xml version="1.0" encoding="utf-8"?>' +
  14249. '<html xmlns="http://www.w3.org/1999/xhtml" ' +
  14250. 'xmlns:b3mn="http://b3mn.org/2007/b3mn" ' +
  14251. 'xmlns:ext="http://b3mn.org/2007/ext" ' +
  14252. 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ' +
  14253. 'xmlns:atom="http://b3mn.org/2007/atom+xhtml">' +
  14254. '<head profile="http://purl.org/NET/erdf/profile">' +
  14255. '<link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" />' +
  14256. '<link rel="schema.dcTerms" href="http://purl.org/dc/terms/ " />' +
  14257. '<link rel="schema.b3mn" href="http://b3mn.org" />' +
  14258. '<link rel="schema.oryx" href="http://oryx-editor.org/" />' +
  14259. '<link rel="schema.raziel" href="http://raziel.org/" />' +
  14260. '<base href="' +
  14261. location.href.split("?")[0] +
  14262. '" />' +
  14263. '</head><body>' +
  14264. serializedDOM +
  14265. '</body></html>';
  14266. return serializedDOM;
  14267. },
  14268. /**
  14269. * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore,
  14270. * shapes cannot be selected anymore.
  14271. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14272. */
  14273. enableReadOnlyMode: function(){
  14274. //Edges cannot be moved anymore
  14275. this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);
  14276. // Stop the user from editing the diagram while the plugin is active
  14277. this._stopSelectionChange = function(){
  14278. if(this.facade.getSelection().length > 0) {
  14279. this.facade.setSelection([]);
  14280. }
  14281. };
  14282. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));
  14283. },
  14284. /**
  14285. * Disables read only mode, see @see
  14286. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14287. * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode
  14288. */
  14289. disableReadOnlyMode: function(){
  14290. // Edges can be moved now again
  14291. this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);
  14292. if (this._stopSelectionChange) {
  14293. this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));
  14294. this._stopSelectionChange = undefined;
  14295. }
  14296. },
  14297. /**
  14298. * Extracts RDF from DOM.
  14299. * @methodOf ORYX.Plugins.AbstractPlugin.prototype
  14300. * @type {String} Extracted RFD. Null if there are transformation errors.
  14301. */
  14302. getRDFFromDOM: function(){
  14303. //convert to RDF
  14304. try {
  14305. var xsl = "";
  14306. source=ORYX.PATH + "lib/extract-rdf.xsl";
  14307. new Ajax.Request(source, {
  14308. asynchronous: false,
  14309. method: 'get',
  14310. onSuccess: function(transport){
  14311. xsl = transport.responseText
  14312. }.bind(this),
  14313. onFailure: (function(transport){
  14314. ORYX.Log.error("XSL load failed" + transport);
  14315. }).bind(this)
  14316. });
  14317. var domParser = new DOMParser();
  14318. var xmlObject = domParser.parseFromString(this.getSerializedDOM(), "text/xml");
  14319. var xslObject = domParser.parseFromString(xsl, "text/xml");
  14320. var xsltProcessor = new XSLTProcessor();
  14321. xsltProcessor.importStylesheet(xslObject);
  14322. var result = xsltProcessor.transformToFragment(xmlObject, document);
  14323. var serializer = new XMLSerializer();
  14324. return serializer.serializeToString(result);
  14325. } catch(e){
  14326. console.log("error serializing " + e);
  14327. return "";
  14328. }
  14329. },
  14330. /**
  14331. * Checks if a certain stencil set is loaded right now.
  14332. *
  14333. */
  14334. isStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) {
  14335. return this.facade.getStencilSets().values().any(
  14336. function(ss){
  14337. return ss.extensions().keys().any(
  14338. function(extensionKey) {
  14339. return extensionKey == stencilSetExtensionNamespace;
  14340. }.bind(this)
  14341. );
  14342. }.bind(this)
  14343. );
  14344. },
  14345. /**
  14346. * Raises an event so that registered layouters does
  14347. * have the posiblility to layout the given shapes
  14348. * For further reading, have a look into the AbstractLayouter
  14349. * class
  14350. * @param {Object} shapes
  14351. */
  14352. doLayout: function(shapes){
  14353. // Raises a do layout event
  14354. if (this.facade.raiseEvent)
  14355. {
  14356. this.facade.raiseEvent({
  14357. type : ORYX.CONFIG.EVENT_LAYOUT,
  14358. shapes : shapes
  14359. });
  14360. }
  14361. else
  14362. {
  14363. this.facade.handleEvents({
  14364. type : ORYX.CONFIG.EVENT_LAYOUT,
  14365. shapes : shapes
  14366. });
  14367. }
  14368. },
  14369. /**
  14370. * Does a primitive layouting with the incoming/outgoing
  14371. * edges (set the dockers to the right position) and if
  14372. * necessary, it will be called the real layouting
  14373. * @param {ORYX.Core.Node} node
  14374. * @param {Array} edges
  14375. */
  14376. layoutEdges : function(node, allEdges, offset){
  14377. if (!this.facade.isExecutingCommands()){ return }
  14378. var Command = ORYX.Core.Command.extend({
  14379. construct: function(edges, node, offset, plugin){
  14380. this.edges = edges;
  14381. this.node = node;
  14382. this.plugin = plugin;
  14383. this.offset = offset;
  14384. // Get the new absolute center
  14385. var center = node.absoluteXY();
  14386. this.ulo = {x: center.x - offset.x, y:center.y - offset.y};
  14387. },
  14388. execute: function(){
  14389. if (this.changes){
  14390. this.executeAgain();
  14391. return;
  14392. } else {
  14393. this.changes = [];
  14394. this.edges.each(function(edge){
  14395. this.changes.push({
  14396. edge: edge,
  14397. oldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() })
  14398. })
  14399. }.bind(this));
  14400. }
  14401. // Find all edges, which are related to the node and
  14402. // have more than two dockers
  14403. this.edges
  14404. // Find all edges with more than two dockers
  14405. .findAll(function(r){ return r.dockers.length > 2 }.bind(this))
  14406. // For every edge, check second and one before last docker
  14407. // if there are horizontal/vertical on the same level
  14408. // and if so, align the the bounds
  14409. .each(function(edge){
  14410. if (edge.dockers.first().getDockedShape() === this.node){
  14411. var second = edge.dockers[1];
  14412. if (this.align(second.bounds, edge.dockers.first())){ second.update(); }
  14413. } else if (edge.dockers.last().getDockedShape() === this.node) {
  14414. var beforeLast = edge.dockers[edge.dockers.length-2];
  14415. if (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); }
  14416. }
  14417. edge._update(true);
  14418. edge.removeUnusedDockers();
  14419. if (this.isBendPointIncluded(edge)){
  14420. this.plugin.doLayout(edge);
  14421. return;
  14422. }
  14423. }.bind(this));
  14424. // Find all edges, which have only to dockers
  14425. // and is located horizontal/vertical.
  14426. // Do layout with those edges
  14427. this.edges
  14428. // Find all edges with exactly two dockers
  14429. .each(function(edge){
  14430. if (edge.dockers.length == 2){
  14431. var p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();
  14432. var p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();
  14433. // Find all horizontal/vertical edges
  14434. if (Math.abs(-Math.abs(p1.x - p2.x) + Math.abs(this.offset.x)) < 2 || Math.abs(-Math.abs(p1.y - p2.y) + Math.abs(this.offset.y)) < 2){
  14435. this.plugin.doLayout(edge);
  14436. }
  14437. }
  14438. }.bind(this));
  14439. this.edges.each(function(edge, i){
  14440. this.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() });
  14441. }.bind(this));
  14442. },
  14443. /**
  14444. * Align the bounds if the center is
  14445. * the same than the old center
  14446. * @params {Object} bounds
  14447. * @params {Object} bounds2
  14448. */
  14449. align: function(bounds, refDocker){
  14450. var abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center();
  14451. var xdif = bounds.center().x-abRef.x;
  14452. var ydif = bounds.center().y-abRef.y;
  14453. if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){
  14454. bounds.moveBy({x:-xdif, y:0})
  14455. }
  14456. if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){
  14457. bounds.moveBy({y:-ydif, x:0})
  14458. }
  14459. if (this.offset.xs !== undefined || this.offset.ys !== undefined){
  14460. var absPXY = refDocker.getDockedShape().absoluteXY();
  14461. xdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs));
  14462. ydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys));
  14463. if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){
  14464. bounds.moveBy({x:-(bounds.center().x-abRef.x), y:0})
  14465. }
  14466. if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){
  14467. bounds.moveBy({y:-(bounds.center().y-abRef.y), x:0})
  14468. }
  14469. }
  14470. },
  14471. /**
  14472. * Returns a TRUE if there are bend point which overlay the shape
  14473. */
  14474. isBendPointIncluded: function(edge){
  14475. // Get absolute bounds
  14476. var ab = edge.dockers.first().getDockedShape();
  14477. var bb = edge.dockers.last().getDockedShape();
  14478. if (ab) {
  14479. ab = ab.absoluteBounds();
  14480. ab.widen(5);
  14481. }
  14482. if (bb) {
  14483. bb = bb.absoluteBounds();
  14484. bb.widen(20); // Wide with 20 because of the arrow from the edge
  14485. }
  14486. return edge.dockers
  14487. .any(function(docker, i){
  14488. var c = docker.bounds.center();
  14489. // Dont count first and last
  14490. return i != 0 && i != edge.dockers.length-1 &&
  14491. // Check if the point is included to the absolute bounds
  14492. ((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c)))
  14493. })
  14494. },
  14495. removeAllDocker: function(edge){
  14496. edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){
  14497. edge.removeDocker(docker);
  14498. })
  14499. },
  14500. executeAgain: function(){
  14501. this.changes.each(function(change){
  14502. // Reset the dockers
  14503. this.removeAllDocker(change.edge);
  14504. change.dockerPositions.each(function(pos, i){
  14505. if (i==0||i==change.dockerPositions.length-1){ return }
  14506. var docker = change.edge.createDocker(undefined, pos);
  14507. docker.bounds.centerMoveTo(pos);
  14508. docker.update();
  14509. }.bind(this));
  14510. change.edge._update(true);
  14511. }.bind(this));
  14512. },
  14513. rollback: function(){
  14514. this.changes.each(function(change){
  14515. // Reset the dockers
  14516. this.removeAllDocker(change.edge);
  14517. change.oldDockerPositions.each(function(pos, i){
  14518. if (i==0||i==change.oldDockerPositions.length-1){ return }
  14519. var docker = change.edge.createDocker(undefined, pos);
  14520. docker.bounds.centerMoveTo(pos);
  14521. docker.update();
  14522. }.bind(this));
  14523. change.edge._update(true);
  14524. }.bind(this));
  14525. }
  14526. });
  14527. this.facade.executeCommands([new Command(allEdges, node, offset, this)]);
  14528. }
  14529. });/*
  14530. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  14531. * License rights for this program may be obtained from Alfresco Software, Ltd.
  14532. * pursuant to a written agreement and any use of this program without such an
  14533. * agreement is prohibited.
  14534. */
  14535. /*
  14536. * All code Copyright 2013 KIS Consultancy all rights reserved
  14537. */
  14538. if(!ORYX){ var ORYX = {} }
  14539. if(!ORYX.Plugins){ ORYX.Plugins = {} }
  14540. /**
  14541. This abstract plugin implements the core behaviour of layout
  14542. @class ORYX.Plugins.AbstractLayouter
  14543. @constructor Creates a new instance
  14544. @author Willi Tscheschner
  14545. */
  14546. ORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({
  14547. /**
  14548. * 'layouted' defined all types of shapes which will be layouted.
  14549. * It can be one value or an array of values. The value
  14550. * can be a Stencil ID (as String) or an class type of either
  14551. * a ORYX.Core.Node or ORYX.Core.Edge
  14552. * @type Array|String|Object
  14553. * @memberOf ORYX.Plugins.AbstractLayouter.prototype
  14554. */
  14555. layouted : [],
  14556. /**
  14557. * Constructor
  14558. * @param {Object} facade
  14559. * @memberOf ORYX.Plugins.AbstractLayouter.prototype
  14560. */
  14561. construct: function( facade ){
  14562. arguments.callee.$.construct.apply(this, arguments);
  14563. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this));
  14564. },
  14565. /**
  14566. * Proofs if this shape should be layouted or not
  14567. * @param {Object} shape
  14568. * @memberOf ORYX.Plugins.AbstractLayouter.prototype
  14569. */
  14570. isIncludedInLayout: function(shape){
  14571. if (!(this.layouted instanceof Array)){
  14572. this.layouted = [this.layouted].compact();
  14573. }
  14574. // If there are no elements
  14575. if (this.layouted.length <= 0) {
  14576. // Return TRUE
  14577. return true;
  14578. }
  14579. // Return TRUE if there is any correlation between
  14580. // the 'layouted' attribute and the shape themselve.
  14581. return this.layouted.any(function(s){
  14582. if (typeof s == "string") {
  14583. return shape.getStencil().id().include(s);
  14584. } else {
  14585. return shape instanceof s;
  14586. }
  14587. })
  14588. },
  14589. /**
  14590. * Callback to start the layouting
  14591. * @param {Object} event Layout event
  14592. * @param {Object} shapes Given shapes
  14593. * @memberOf ORYX.Plugins.AbstractLayouter.prototype
  14594. */
  14595. _initLayout: function(event){
  14596. // Get the shapes
  14597. var shapes = [event.shapes].flatten().compact();
  14598. // Find all shapes which should be layouted
  14599. var toLayout = shapes.findAll(function(shape){
  14600. return this.isIncludedInLayout(shape)
  14601. }.bind(this))
  14602. // If there are shapes left
  14603. if (toLayout.length > 0){
  14604. // Do layout
  14605. this.layout(toLayout);
  14606. }
  14607. },
  14608. /**
  14609. * Implementation of layouting a set on shapes
  14610. * @param {Object} shapes Given shapes
  14611. * @memberOf ORYX.Plugins.AbstractLayouter.prototype
  14612. */
  14613. layout: function(shapes){
  14614. throw new Error("Layouter has to implement the layout function.")
  14615. }
  14616. });/*
  14617. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  14618. * License rights for this program may be obtained from Alfresco Software, Ltd.
  14619. * pursuant to a written agreement and any use of this program without such an
  14620. * agreement is prohibited.
  14621. */
  14622. /*
  14623. * All code Copyright 2013 KIS Consultancy all rights reserved
  14624. */
  14625. if (!ORYX.Plugins)
  14626. ORYX.Plugins = new Object();
  14627. ORYX.Plugins.Edit = Clazz.extend({
  14628. construct: function(facade){
  14629. this.facade = facade;
  14630. this.clipboard = new ORYX.Plugins.Edit.ClipBoard();
  14631. //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));
  14632. this.facade.offer({
  14633. name: ORYX.I18N.Edit.cut,
  14634. description: ORYX.I18N.Edit.cutDesc,
  14635. icon: ORYX.PATH + "images/cut.png",
  14636. keyCodes: [{
  14637. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  14638. keyCode: 88,
  14639. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  14640. }
  14641. ],
  14642. functionality: this.callEdit.bind(this, this.editCut),
  14643. group: ORYX.I18N.Edit.group,
  14644. index: 1,
  14645. minShape: 1
  14646. });
  14647. this.facade.offer({
  14648. name: ORYX.I18N.Edit.copy,
  14649. description: ORYX.I18N.Edit.copyDesc,
  14650. icon: ORYX.PATH + "images/page_copy.png",
  14651. keyCodes: [{
  14652. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  14653. keyCode: 67,
  14654. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  14655. }
  14656. ],
  14657. functionality: this.callEdit.bind(this, this.editCopy, [true, false]),
  14658. group: ORYX.I18N.Edit.group,
  14659. index: 2,
  14660. minShape: 1
  14661. });
  14662. this.facade.offer({
  14663. name: ORYX.I18N.Edit.paste,
  14664. description: ORYX.I18N.Edit.pasteDesc,
  14665. icon: ORYX.PATH + "images/page_paste.png",
  14666. keyCodes: [{
  14667. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  14668. keyCode: 86,
  14669. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  14670. }
  14671. ],
  14672. functionality: this.callEdit.bind(this, this.editPaste),
  14673. isEnabled: this.clipboard.isOccupied.bind(this.clipboard),
  14674. group: ORYX.I18N.Edit.group,
  14675. index: 3,
  14676. minShape: 0,
  14677. maxShape: 0
  14678. });
  14679. this.facade.offer({
  14680. name: ORYX.I18N.Edit.del,
  14681. description: ORYX.I18N.Edit.delDesc,
  14682. icon: ORYX.PATH + "images/cross.png",
  14683. keyCodes: [{
  14684. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  14685. keyCode: 8,
  14686. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  14687. },
  14688. {
  14689. keyCode: 46,
  14690. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  14691. }
  14692. ],
  14693. functionality: this.callEdit.bind(this, this.editDelete),
  14694. group: ORYX.I18N.Edit.group,
  14695. index: 4,
  14696. minShape: 1
  14697. });
  14698. },
  14699. callEdit: function(fn, args){
  14700. window.setTimeout(function(){
  14701. fn.apply(this, (args instanceof Array ? args : []));
  14702. }.bind(this), 1);
  14703. },
  14704. /**
  14705. * Handles the mouse down event and starts the copy-move-paste action, if
  14706. * control or meta key is pressed.
  14707. */
  14708. handleMouseDown: function(event) {
  14709. if(this._controlPressed) {
  14710. this._controlPressed = false;
  14711. this.editCopy();
  14712. // console.log("copiedEle: %0",this.clipboard.shapesAsJson)
  14713. // console.log("mousevent: %o",event)
  14714. this.editPaste();
  14715. event.forceExecution = true;
  14716. this.facade.raiseEvent(event, this.clipboard.shapesAsJson);
  14717. }
  14718. },
  14719. /**
  14720. * The key handler for this plugin. Every action from the set of cut, copy,
  14721. * paste and delete should be accessible trough simple keyboard shortcuts.
  14722. * This method checks whether any event triggers one of those actions.
  14723. *
  14724. * @param {Object} event The keyboard event that should be analysed for
  14725. * triggering of this plugin.
  14726. */
  14727. // keyHandler: function(event){
  14728. // //TODO document what event.which is.
  14729. //
  14730. // ORYX.Log.debug("edit.js handles a keyEvent.");
  14731. //
  14732. // // assure we have the current event.
  14733. // if (!event)
  14734. // event = window.event;
  14735. //
  14736. //
  14737. // // get the currently pressed key and state of control key.
  14738. // var pressedKey = event.which || event.keyCode;
  14739. // var ctrlPressed = event.ctrlKey;
  14740. //
  14741. // // if the object is to be deleted, do so, and return immediately.
  14742. // if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) ||
  14743. // ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) &&
  14744. // (event.metaKey || event.appleMetaKey))) {
  14745. //
  14746. // ORYX.Log.debug("edit.js deletes the shape.");
  14747. // this.editDelete();
  14748. // return;
  14749. // }
  14750. //
  14751. // // if control key is not pressed, we're not interested anymore.
  14752. // if (!ctrlPressed)
  14753. // return;
  14754. //
  14755. // // when ctrl is pressed, switch trough the possibilities.
  14756. // switch (pressedKey) {
  14757. //
  14758. // // cut.
  14759. // case ORYX.CONFIG.KEY_CODE_X:
  14760. // this.editCut();
  14761. // break;
  14762. //
  14763. // // copy.
  14764. // case ORYX.CONFIG.KEY_CODE_C:
  14765. // this.editCopy();
  14766. // break;
  14767. //
  14768. // // paste.
  14769. // case ORYX.CONFIG.KEY_CODE_V:
  14770. // this.editPaste();
  14771. // break;
  14772. // }
  14773. // },
  14774. /**
  14775. * Returns a list of shapes which should be considered while copying.
  14776. * Besides the shapes of given ones, edges and attached nodes are added to the result set.
  14777. * If one of the given shape is a child of another given shape, it is not put into the result.
  14778. */
  14779. getAllShapesToConsider: function(shapes){
  14780. var shapesToConsider = []; // only top-level shapes
  14781. var childShapesToConsider = []; // all child shapes of top-level shapes
  14782. shapes.each(function(shape){
  14783. //Throw away these shapes which have a parent in given shapes
  14784. isChildShapeOfAnother = shapes.any(function(s2){
  14785. return s2.hasChildShape(shape);
  14786. });
  14787. if(isChildShapeOfAnother) return;
  14788. // This shape should be considered
  14789. shapesToConsider.push(shape);
  14790. // Consider attached nodes (e.g. intermediate events)
  14791. if (shape instanceof ORYX.Core.Node) {
  14792. var attached = shape.getOutgoingNodes();
  14793. attached = attached.findAll(function(a){ return !shapes.include(a) });
  14794. shapesToConsider = shapesToConsider.concat(attached);
  14795. }
  14796. childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true));
  14797. }.bind(this));
  14798. // All edges between considered child shapes should be considered
  14799. // Look for these edges having incoming and outgoing in childShapesToConsider
  14800. var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function(edge){
  14801. // Ignore if already added
  14802. if(shapesToConsider.include(edge)) return false;
  14803. // Ignore if there are no docked shapes
  14804. if(edge.getAllDockedShapes().size() === 0) return false;
  14805. // True if all docked shapes are in considered child shapes
  14806. return edge.getAllDockedShapes().all(function(shape){
  14807. // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider
  14808. return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape);
  14809. });
  14810. });
  14811. shapesToConsider = shapesToConsider.concat(edgesToConsider);
  14812. return shapesToConsider;
  14813. },
  14814. /**
  14815. * Performs the cut operation by first copy-ing and then deleting the
  14816. * current selection.
  14817. */
  14818. editCut: function(){
  14819. //TODO document why this returns false.
  14820. //TODO document what the magic boolean parameters are supposed to do.
  14821. this.editCopy(false, true);
  14822. this.editDelete(true);
  14823. return false;
  14824. },
  14825. /**
  14826. * Performs the copy operation.
  14827. * @param {Object} will_not_update ??
  14828. */
  14829. editCopy: function( will_update, useNoOffset ){
  14830. var selection = this.facade.getSelection();
  14831. //if the selection is empty, do not remove the previously copied elements
  14832. if(selection.length == 0) return;
  14833. this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset);
  14834. if( will_update ) this.facade.updateSelection();
  14835. },
  14836. /**
  14837. * Performs the paste operation.
  14838. */
  14839. editPaste: function(){
  14840. // Create a new canvas with childShapes
  14841. //and stencilset namespace to be JSON Import conform
  14842. var canvas = {
  14843. childShapes: this.clipboard.shapesAsJson,
  14844. stencilset:{
  14845. namespace:this.clipboard.SSnamespace
  14846. }
  14847. };
  14848. // Apply json helper to iterate over json object
  14849. jQuery.extend(canvas, ORYX.Core.AbstractShape.JSONHelper);
  14850. var childShapeResourceIds = canvas.getChildShapes(true).pluck("resourceId");
  14851. var outgoings = {};
  14852. // Iterate over all shapes
  14853. canvas.eachChild(function(shape, parent){
  14854. // Throw away these references where referenced shape isn't copied
  14855. shape.outgoing = shape.outgoing.select(function(out){
  14856. return childShapeResourceIds.include(out.resourceId);
  14857. });
  14858. shape.outgoing.each(function(out){
  14859. if (!outgoings[out.resourceId]){ outgoings[out.resourceId] = []; }
  14860. outgoings[out.resourceId].push(shape);
  14861. });
  14862. return shape;
  14863. }.bind(this), true, true);
  14864. // Iterate over all shapes
  14865. canvas.eachChild(function(shape, parent){
  14866. // Check if there has a valid target
  14867. if(shape.target && !(childShapeResourceIds.include(shape.target.resourceId))){
  14868. shape.target = undefined;
  14869. shape.targetRemoved = true;
  14870. }
  14871. // Check if the first docker is removed
  14872. if( shape.dockers &&
  14873. shape.dockers.length >= 1 &&
  14874. shape.dockers[0].getDocker &&
  14875. ((shape.dockers[0].getDocker().getDockedShape() &&
  14876. !childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) ||
  14877. !shape.getShape().dockers[0].getDockedShape()&&!outgoings[shape.resourceId])) {
  14878. shape.sourceRemoved = true;
  14879. }
  14880. return shape;
  14881. }.bind(this), true, true);
  14882. // Iterate over top-level shapes
  14883. canvas.eachChild(function(shape, parent){
  14884. // All top-level shapes should get an offset in their bounds
  14885. // Move the shape occording to COPY_MOVE_OFFSET
  14886. if (this.clipboard.useOffset) {
  14887. shape.bounds = {
  14888. lowerRight: {
  14889. x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14890. y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET
  14891. },
  14892. upperLeft: {
  14893. x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14894. y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET
  14895. }
  14896. };
  14897. }
  14898. // Only apply offset to shapes with a target
  14899. if (shape.dockers){
  14900. shape.dockers = shape.dockers.map(function(docker, i){
  14901. // If shape had a target but the copied does not have anyone anymore,
  14902. // migrate the relative dockers to absolute ones.
  14903. if( (shape.targetRemoved === true && i == shape.dockers.length - 1&&docker.getDocker) ||
  14904. (shape.sourceRemoved === true && i == 0&&docker.getDocker)){
  14905. docker = docker.getDocker().bounds.center();
  14906. }
  14907. // If it is the first docker and it has a docked shape,
  14908. // just return the coordinates
  14909. if ((i == 0 && docker.getDocker instanceof Function &&
  14910. shape.sourceRemoved !== true && (docker.getDocker().getDockedShape() || ((outgoings[shape.resourceId]||[]).length > 0 && (!(shape.getShape() instanceof ORYX.Core.Node) || outgoings[shape.resourceId][0].getShape() instanceof ORYX.Core.Node)))) ||
  14911. (i == shape.dockers.length - 1 && docker.getDocker instanceof Function &&
  14912. shape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))){
  14913. return {
  14914. x: docker.x,
  14915. y: docker.y,
  14916. getDocker: docker.getDocker
  14917. }
  14918. } else if (this.clipboard.useOffset) {
  14919. return {
  14920. x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14921. y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14922. getDocker: docker.getDocker
  14923. };
  14924. } else {
  14925. return {
  14926. x: docker.x,
  14927. y: docker.y,
  14928. getDocker: docker.getDocker
  14929. };
  14930. }
  14931. }.bind(this));
  14932. } else if (shape.getShape() instanceof ORYX.Core.Node && shape.dockers && shape.dockers.length > 0 && (!shape.dockers.first().getDocker || shape.sourceRemoved === true || !(shape.dockers.first().getDocker().getDockedShape() || outgoings[shape.resourceId]))){
  14933. shape.dockers = shape.dockers.map(function(docker, i){
  14934. if((shape.sourceRemoved === true && i == 0&&docker.getDocker)){
  14935. docker = docker.getDocker().bounds.center();
  14936. }
  14937. if (this.clipboard.useOffset) {
  14938. return {
  14939. x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14940. y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,
  14941. getDocker: docker.getDocker
  14942. };
  14943. } else {
  14944. return {
  14945. x: docker.x,
  14946. y: docker.y,
  14947. getDocker: docker.getDocker
  14948. };
  14949. }
  14950. }.bind(this));
  14951. }
  14952. return shape;
  14953. }.bind(this), false, true);
  14954. this.clipboard.useOffset = true;
  14955. this.facade.importJSON(canvas);
  14956. },
  14957. /**
  14958. * Performs the delete operation. No more asking.
  14959. */
  14960. editDelete: function(){
  14961. var selection = this.facade.getSelection();
  14962. var clipboard = new ORYX.Plugins.Edit.ClipBoard();
  14963. clipboard.refresh(selection, this.getAllShapesToConsider(selection));
  14964. var command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade);
  14965. this.facade.executeCommands([command]);
  14966. }
  14967. });
  14968. ORYX.Plugins.Edit.ClipBoard = Clazz.extend({
  14969. construct: function(){
  14970. this.shapesAsJson = [];
  14971. this.selection = [];
  14972. this.SSnamespace="";
  14973. this.useOffset=true;
  14974. },
  14975. isOccupied: function(){
  14976. return this.shapesAsJson.length > 0;
  14977. },
  14978. refresh: function(selection, shapes, namespace, useNoOffset){
  14979. this.selection = selection;
  14980. this.SSnamespace=namespace;
  14981. // Store outgoings, targets and parents to restore them later on
  14982. this.outgoings = {};
  14983. this.parents = {};
  14984. this.targets = {};
  14985. this.useOffset = useNoOffset !== true;
  14986. this.shapesAsJson = shapes.map(function(shape){
  14987. var s = shape.toJSON();
  14988. s.parent = {resourceId : shape.getParentShape().resourceId};
  14989. s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape)
  14990. return s;
  14991. });
  14992. }
  14993. });
  14994. ORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({
  14995. construct: function(clipboard, facade){
  14996. this.clipboard = clipboard;
  14997. this.shapesAsJson = clipboard.shapesAsJson;
  14998. this.facade = facade;
  14999. // Store dockers of deleted shapes to restore connections
  15000. this.dockers = this.shapesAsJson.map(function(shapeAsJson) {
  15001. var shape = shapeAsJson.getShape();
  15002. var incomingDockers = shape.getIncomingShapes().map(function(s){return s.getDockers().last();});
  15003. var outgoingDockers = shape.getOutgoingShapes().map(function(s){return s.getDockers().first();});
  15004. var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function(docker){
  15005. return {
  15006. object: docker,
  15007. referencePoint: docker.referencePoint,
  15008. dockedShape: docker.getDockedShape()
  15009. };
  15010. });
  15011. return dockers;
  15012. }).flatten();
  15013. },
  15014. execute: function(){
  15015. this.shapesAsJson.each(function(shapeAsJson){
  15016. // Delete shape
  15017. this.facade.deleteShape(shapeAsJson.getShape());
  15018. }.bind(this));
  15019. this.facade.setSelection([]);
  15020. this.facade.getCanvas().update();
  15021. this.facade.updateSelection();
  15022. },
  15023. rollback: function(){
  15024. this.shapesAsJson.each(function(shapeAsJson) {
  15025. var shape = shapeAsJson.getShape();
  15026. var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas();
  15027. parent.add(shape, shape.parentIndex);
  15028. }.bind(this));
  15029. //reconnect shapes
  15030. this.dockers.each(function(d) {
  15031. d.object.setDockedShape(d.dockedShape);
  15032. d.object.setReferencePoint(d.referencePoint);
  15033. }.bind(this));
  15034. this.facade.setSelection(this.selectedShapes);
  15035. this.facade.getCanvas().update();
  15036. this.facade.updateSelection();
  15037. }
  15038. });/*
  15039. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15040. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15041. * pursuant to a written agreement and any use of this program without such an
  15042. * agreement is prohibited.
  15043. */
  15044. /*
  15045. * All code Copyright 2013 KIS Consultancy all rights reserved
  15046. */
  15047. /**
  15048. * @namespace Oryx name space for plugins
  15049. * @name ORYX.Plugins
  15050. */
  15051. if(!ORYX.Plugins)
  15052. ORYX.Plugins = new Object();
  15053. /**
  15054. * The view plugin offers all of zooming functionality accessible over the
  15055. * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model.
  15056. *
  15057. * @class ORYX.Plugins.View
  15058. * @extends Clazz
  15059. * @param {Object} facade The editor facade for plugins.
  15060. */
  15061. ORYX.Plugins.View = {
  15062. /** @lends ORYX.Plugins.View.prototype */
  15063. facade: undefined,
  15064. construct: function(facade, ownPluginData) {
  15065. this.facade = facade;
  15066. //Standard Values
  15067. this.zoomLevel = 1.0;
  15068. this.maxFitToScreenLevel=1.5;
  15069. this.minZoomLevel = 0.1;
  15070. this.maxZoomLevel = 2.5;
  15071. this.diff=5; //difference between canvas and view port, s.th. like toolbar??
  15072. //Read properties
  15073. if (ownPluginData !== undefined && ownPluginData !== null) {
  15074. ownPluginData.properties.each( function(property) {
  15075. if (property.zoomLevel) {this.zoomLevel = Number(1.0);}
  15076. if (property.maxFitToScreenLevel) {this.maxFitToScreenLevel=Number(property.maxFitToScreenLevel);}
  15077. if (property.minZoomLevel) {this.minZoomLevel = Number(property.minZoomLevel);}
  15078. if (property.maxZoomLevel) {this.maxZoomLevel = Number(property.maxZoomLevel);}
  15079. }.bind(this));
  15080. }
  15081. /* Register zoom in */
  15082. this.facade.offer({
  15083. 'name':ORYX.I18N.View.zoomIn,
  15084. 'functionality': this.zoom.bind(this, [1.0 + ORYX.CONFIG.ZOOM_OFFSET]),
  15085. 'group': ORYX.I18N.View.group,
  15086. 'icon': ORYX.PATH + "images/magnifier_zoom_in.png",
  15087. 'description': ORYX.I18N.View.zoomInDesc,
  15088. 'index': 1,
  15089. 'minShape': 0,
  15090. 'maxShape': 0,
  15091. 'isEnabled': function(){return this.zoomLevel < this.maxZoomLevel }.bind(this)});
  15092. /* Register zoom out */
  15093. this.facade.offer({
  15094. 'name':ORYX.I18N.View.zoomOut,
  15095. 'functionality': this.zoom.bind(this, [1.0 - ORYX.CONFIG.ZOOM_OFFSET]),
  15096. 'group': ORYX.I18N.View.group,
  15097. 'icon': ORYX.PATH + "images/magnifier_zoom_out.png",
  15098. 'description': ORYX.I18N.View.zoomOutDesc,
  15099. 'index': 2,
  15100. 'minShape': 0,
  15101. 'maxShape': 0,
  15102. 'isEnabled': function(){ return this._checkSize() }.bind(this)});
  15103. /* Register zoom standard */
  15104. this.facade.offer({
  15105. 'name':ORYX.I18N.View.zoomStandard,
  15106. 'functionality': this.setAFixZoomLevel.bind(this, 1),
  15107. 'group': ORYX.I18N.View.group,
  15108. 'icon': ORYX.PATH + "images/zoom_standard.png",
  15109. 'cls' : 'icon-large',
  15110. 'description': ORYX.I18N.View.zoomStandardDesc,
  15111. 'index': 3,
  15112. 'minShape': 0,
  15113. 'maxShape': 0,
  15114. 'isEnabled': function(){return this.zoomLevel != 1}.bind(this)
  15115. });
  15116. /* Register zoom fit to model */
  15117. this.facade.offer({
  15118. 'name':ORYX.I18N.View.zoomFitToModel,
  15119. 'functionality': this.zoomFitToModel.bind(this),
  15120. 'group': ORYX.I18N.View.group,
  15121. 'icon': ORYX.PATH + "images/image.png",
  15122. 'description': ORYX.I18N.View.zoomFitToModelDesc,
  15123. 'index': 4,
  15124. 'minShape': 0,
  15125. 'maxShape': 0
  15126. });
  15127. },
  15128. /**
  15129. * It sets the zoom level to a fix value and call the zooming function.
  15130. *
  15131. * @param {Number} zoomLevel
  15132. * the zoom level
  15133. */
  15134. setAFixZoomLevel : function(zoomLevel) {
  15135. this.zoomLevel = zoomLevel;
  15136. this._checkZoomLevelRange();
  15137. this.zoom(1);
  15138. },
  15139. /**
  15140. * It does the actual zooming. It changes the viewable size of the canvas
  15141. * and all to its child elements.
  15142. *
  15143. * @param {Number} factor
  15144. * the factor to adjust the zoom level
  15145. */
  15146. zoom: function(factor) {
  15147. // TODO: Zoomen auf allen Objekten im SVG-DOM
  15148. this.zoomLevel *= factor;
  15149. var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;
  15150. var canvas = this.facade.getCanvas();
  15151. var newWidth = canvas.bounds.width() * this.zoomLevel;
  15152. var newHeight = canvas.bounds.height() * this.zoomLevel;
  15153. /* Set new top offset */
  15154. var offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0;
  15155. offsetTop = offsetTop > 20 ? offsetTop - 20 : 0;
  15156. canvas.node.parentNode.parentNode.style.marginTop = offsetTop + "px";
  15157. offsetTop += 5;
  15158. canvas.getHTMLContainer().style.top = offsetTop + "px";
  15159. /*readjust scrollbar*/
  15160. var newScrollTop= scrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight()-newHeight) / 2)+this.diff;
  15161. var newScrollLeft= scrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth()-newWidth) / 2)+this.diff;
  15162. /* Set new Zoom-Level */
  15163. canvas.setSize({width: newWidth, height: newHeight}, true);
  15164. /* Set Scale-Factor */
  15165. canvas.node.setAttributeNS(null, "transform", "scale(" +this.zoomLevel+ ")");
  15166. /* Refresh the Selection */
  15167. this.facade.updateSelection();
  15168. scrollNode.scrollTop=newScrollTop;
  15169. scrollNode.scrollLeft=newScrollLeft;
  15170. /* Update the zoom-level*/
  15171. canvas.zoomLevel = this.zoomLevel;
  15172. },
  15173. /**
  15174. * It calculates the zoom level to fit whole model into the visible area
  15175. * of the canvas. Than the model gets zoomed and the position of the
  15176. * scroll bars are adjusted.
  15177. *
  15178. */
  15179. zoomFitToModel: function() {
  15180. /* Get the size of the visible area of the canvas */
  15181. var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;
  15182. var visibleHeight = scrollNode.getHeight() - 30;
  15183. var visibleWidth = scrollNode.getWidth() - 30;
  15184. var nodes = this.facade.getCanvas().getChildShapes();
  15185. if(!nodes || nodes.length < 1) {
  15186. return false;
  15187. }
  15188. /* Calculate size of canvas to fit the model */
  15189. var bounds = nodes[0].absoluteBounds().clone();
  15190. nodes.each(function(node) {
  15191. bounds.include(node.absoluteBounds().clone());
  15192. });
  15193. /* Set new Zoom Level */
  15194. var scaleFactorWidth = visibleWidth / bounds.width();
  15195. var scaleFactorHeight = visibleHeight / bounds.height();
  15196. /* Choose the smaller zoom level to fit the whole model */
  15197. var zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth;
  15198. /*Test if maximum zoom is reached*/
  15199. if(zoomFactor>this.maxFitToScreenLevel){zoomFactor=this.maxFitToScreenLevel}
  15200. /* Do zooming */
  15201. this.setAFixZoomLevel(zoomFactor);
  15202. /* Set scroll bar position */
  15203. scrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5;
  15204. scrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5;
  15205. },
  15206. /**
  15207. * It checks if the zoom level is less or equal to the level, which is required
  15208. * to schow the whole canvas.
  15209. *
  15210. * @private
  15211. */
  15212. _checkSize:function(){
  15213. var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;
  15214. var minForCanvas= Math.min((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));
  15215. return 1.05 > minForCanvas;
  15216. },
  15217. /**
  15218. * It checks if the zoom level is included in the definined zoom
  15219. * level range.
  15220. *
  15221. * @private
  15222. */
  15223. _checkZoomLevelRange: function() {
  15224. /*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;
  15225. var maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));
  15226. if(this.zoomLevel > maxForCanvas) {
  15227. this.zoomLevel = maxForCanvas;
  15228. }*/
  15229. if(this.zoomLevel < this.minZoomLevel) {
  15230. this.zoomLevel = this.minZoomLevel;
  15231. }
  15232. if(this.zoomLevel > this.maxZoomLevel) {
  15233. this.zoomLevel = this.maxZoomLevel;
  15234. }
  15235. }
  15236. };
  15237. ORYX.Plugins.View = Clazz.extend(ORYX.Plugins.View);
  15238. /*
  15239. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15240. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15241. * pursuant to a written agreement and any use of this program without such an
  15242. * agreement is prohibited.
  15243. */
  15244. if(!Signavio){ var Signavio = {} };
  15245. if (!Signavio.Core) { Signavio.Core = {} };
  15246. Signavio.Core.Version = "1.0";
  15247. /*
  15248. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15249. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15250. * pursuant to a written agreement and any use of this program without such an
  15251. * agreement is prohibited.
  15252. */
  15253. /*
  15254. * All code Copyright 2013 KIS Consultancy all rights reserved
  15255. */
  15256. if (!Signavio) {
  15257. var Signavio = new Object();
  15258. }
  15259. if (!Signavio.Plugins) {
  15260. Signavio.Plugins = new Object();
  15261. }
  15262. if (!Signavio.Plugins.Utils) {
  15263. Signavio.Plugins.Utils = new Object();
  15264. }
  15265. if (!Signavio.Helper) {
  15266. Signavio.Helper = new Object();
  15267. }
  15268. new function() {
  15269. /**
  15270. * Provides an uniq id
  15271. * @overwrite
  15272. * @return {String}
  15273. *
  15274. */
  15275. ORYX.Editor.provideId = function() {
  15276. var res = [], hex = '0123456789ABCDEF';
  15277. for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);
  15278. res[14] = 4;
  15279. res[19] = (res[19] & 0x3) | 0x8;
  15280. for (var i = 0; i < 36; i++) res[i] = hex[res[i]];
  15281. res[8] = res[13] = res[18] = res[23] = '-';
  15282. return "sid-" + res.join('');
  15283. };
  15284. }();
  15285. /*
  15286. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15287. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15288. * pursuant to a written agreement and any use of this program without such an
  15289. * agreement is prohibited.
  15290. */
  15291. /*
  15292. * All code Copyright 2013 KIS Consultancy all rights reserved
  15293. */
  15294. if (!ORYX.Plugins) {
  15295. ORYX.Plugins = new Object();
  15296. }
  15297. /**
  15298. * This plugin is responsible for displaying loading indicators and to prevent
  15299. * the user from accidently unloading the page by, e.g., pressing the backspace
  15300. * button and returning to the previous site in history.
  15301. * @param {Object} facade The editor plugin facade to register enhancements with.
  15302. */
  15303. ORYX.Plugins.Loading = {
  15304. construct: function(facade){
  15305. this.facade = facade;
  15306. // The parent Node
  15307. this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.facade.getCanvas().getHTMLContainer().parentNode, ['div', {
  15308. 'class': 'LoadingIndicator'
  15309. }, '']);
  15310. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_ENABLE, this.enableLoading.bind(this));
  15311. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_DISABLE, this.disableLoading.bind(this));
  15312. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_STATUS, this.showStatus.bind(this));
  15313. this.disableLoading();
  15314. },
  15315. enableLoading: function(options){
  15316. if(options.text)
  15317. this.node.innerHTML = options.text + "...";
  15318. else
  15319. this.node.innerHTML = ORYX.I18N.Loading.waiting;
  15320. this.node.removeClassName('StatusIndicator');
  15321. this.node.addClassName('LoadingIndicator');
  15322. this.node.style.display = "block";
  15323. var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;
  15324. this.node.style.top = pos.offsetTop + 'px';
  15325. this.node.style.left = pos.offsetLeft +'px';
  15326. },
  15327. disableLoading: function(){
  15328. this.node.style.display = "none";
  15329. },
  15330. showStatus: function(options) {
  15331. if(options.text) {
  15332. this.node.innerHTML = options.text;
  15333. this.node.addClassName('StatusIndicator');
  15334. this.node.removeClassName('LoadingIndicator');
  15335. this.node.style.display = 'block';
  15336. var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;
  15337. this.node.style.top = pos.offsetTop + 'px';
  15338. this.node.style.left = pos.offsetLeft +'px';
  15339. var tout = options.timeout ? options.timeout : 2000;
  15340. window.setTimeout((function(){
  15341. this.disableLoading();
  15342. }).bind(this), tout);
  15343. }
  15344. }
  15345. }
  15346. ORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading);
  15347. /*
  15348. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15349. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15350. * pursuant to a written agreement and any use of this program without such an
  15351. * agreement is prohibited.
  15352. */
  15353. if (!ORYX.Plugins) {
  15354. ORYX.Plugins = new Object();
  15355. }
  15356. /*
  15357. * All code Copyright 2013 KIS Consultancy all rights reserved
  15358. */
  15359. /**
  15360. * This plugin is responsible for resizing the canvas.
  15361. * @param {Object} facade The editor plugin facade to register enhancements with.
  15362. */
  15363. ORYX.Plugins.CanvasResize = Clazz.extend({
  15364. construct: function(facade){
  15365. this.facade = facade;
  15366. new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "N", this.resize.bind(this));
  15367. new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "W", this.resize.bind(this));
  15368. new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "E", this.resize.bind(this));
  15369. new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "S", this.resize.bind(this));
  15370. window.setTimeout(function(){jQuery(window).trigger('resize');});
  15371. },
  15372. resize: function( position, shrink ){
  15373. resizeCanvas = function(position, extentionSize, facade) {
  15374. var canvas = facade.getCanvas();
  15375. var b = canvas.bounds;
  15376. var scrollNode = facade.getCanvas().getHTMLContainer().parentNode.parentNode;
  15377. if( position == "E" || position == "W"){
  15378. canvas.setSize({width: (b.width() + extentionSize)*canvas.zoomLevel, height: (b.height())*canvas.zoomLevel})
  15379. } else if( position == "S" || position == "N"){
  15380. canvas.setSize({width: (b.width())*canvas.zoomLevel, height: (b.height() + extentionSize)*canvas.zoomLevel})
  15381. }
  15382. if( position == "N" || position == "W"){
  15383. var move = position == "N" ? {x: 0, y: extentionSize}: {x: extentionSize, y: 0 };
  15384. // Move all children
  15385. canvas.getChildNodes(false, function(shape){ shape.bounds.moveBy(move) })
  15386. // Move all dockers, when the edge has at least one docked shape
  15387. var edges = canvas.getChildEdges().findAll(function(edge){ return edge.getAllDockedShapes().length > 0})
  15388. var dockers = edges.collect(function(edge){ return edge.dockers.findAll(function(docker){ return !docker.getDockedShape() })}).flatten();
  15389. dockers.each(function(docker){ docker.bounds.moveBy(move)})
  15390. } else if( position == "S" ){
  15391. scrollNode.scrollTop += extentionSize;
  15392. } else if( position == "E" ){
  15393. scrollNode.scrollLeft += extentionSize;
  15394. }
  15395. jQuery(window).trigger('resize');
  15396. canvas.update();
  15397. facade.updateSelection();
  15398. }
  15399. var commandClass = ORYX.Core.Command.extend({
  15400. construct: function(position, extentionSize, facade){
  15401. this.position = position;
  15402. this.extentionSize = extentionSize;
  15403. this.facade = facade;
  15404. },
  15405. execute: function(){
  15406. resizeCanvas(this.position, this.extentionSize, this.facade);
  15407. },
  15408. rollback: function(){
  15409. resizeCanvas(this.position, -this.extentionSize, this.facade);
  15410. },
  15411. update:function(){
  15412. }
  15413. });
  15414. var extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL;
  15415. if(shrink) extentionSize = -extentionSize;
  15416. var command = new commandClass(position, extentionSize, this.facade);
  15417. this.facade.executeCommands([command]);
  15418. }
  15419. });
  15420. ORYX.Plugins.CanvasResizeButton = Clazz.extend({
  15421. construct: function(canvas, position, callback){
  15422. this.canvas = canvas;
  15423. var parentNode = canvas.getHTMLContainer().parentNode;
  15424. window.myParent=parentNode;
  15425. var actualScrollNode = jQuery('#canvasSection')[0];
  15426. var scrollNode = actualScrollNode;
  15427. var canvasNode = jQuery('#canvasSection').find(".ORYX_Editor")[0];
  15428. var svgRootNode = canvasNode.children[0];
  15429. var iconClass = 'glyphicon glyphicon-chevron-';
  15430. var iconClassShrink = 'glyphicon glyphicon-chevron-';
  15431. if(position == 'N') {
  15432. iconClass += 'up';
  15433. iconClassShrink += 'down';
  15434. } else if(position == 'S') {
  15435. iconClass += 'down';
  15436. iconClassShrink += 'up';
  15437. } else if(position == 'E') {
  15438. iconClass += 'right';
  15439. iconClassShrink += 'left';
  15440. } else if(position == 'W') {
  15441. iconClass += 'left';
  15442. iconClassShrink += 'right';
  15443. }
  15444. // The buttons
  15445. var idGrow = 'canvas-shrink-' + position;
  15446. var idShrink = 'canvas-grow-' + position;
  15447. var buttonGrow = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_grow' + ' ' + position, 'id': idGrow ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},
  15448. ['i', {'class' : iconClass}]
  15449. ]);
  15450. var buttonShrink = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parentNode, ['div', {'class': 'canvas_resize_indicator canvas_resize_indicator_shrink' + ' ' + position, 'id': idShrink ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]},
  15451. ['i', {'class' : iconClassShrink}]
  15452. ]);
  15453. // Defines a callback which gives back
  15454. // a boolean if the current mouse event
  15455. // is over the particular button area
  15456. var offSetWidth = 60;
  15457. var isOverOffset = function(event) {
  15458. var isOverButton = event.target.id.indexOf("canvas-shrink") != -1
  15459. || event.target.id.indexOf("canvas-grow") != -1
  15460. || event.target.parentNode.id.indexOf("canvas-shrink") != -1
  15461. || event.target.parentNode.id.indexOf("canvas-grow") != -1;
  15462. if(isOverButton) {
  15463. if(event.target.id == idGrow || event.target.id == idShrink ||
  15464. event.target.parentNode.id == idGrow || event.target.parentNode.id == idShrink ) {
  15465. return true;
  15466. } else {
  15467. return false;
  15468. }
  15469. }
  15470. if(event.target!=parentNode && event.target!=scrollNode&& event.target!=scrollNode.firstChild&& event.target!=svgRootNode&& event.target!=scrollNode){ return false; }
  15471. //if(inCanvas){offSetWidth=30}else{offSetWidth=30*2}
  15472. //Safari work around
  15473. var X=event.offsetX !== undefined ? event.offsetX : event.layerX;
  15474. var Y=event.offsetY !== undefined ? event.offsetY : event.layerY;
  15475. var canvasOffset = 0;
  15476. if(canvasNode.clientWidth < actualScrollNode.clientWidth) {
  15477. var widthDiff = actualScrollNode.clientWidth - canvasNode.clientWidth;
  15478. canvasOffset = widthDiff / 2;
  15479. }
  15480. // Adjust to relative location to the actual viewport
  15481. Y = Y - actualScrollNode.scrollTop;
  15482. X = X - actualScrollNode.scrollLeft;
  15483. if(position == "N"){
  15484. return Y < offSetWidth;
  15485. } else if(position == "W"){
  15486. return X < offSetWidth + canvasOffset;
  15487. } else if(position == "E"){
  15488. return actualScrollNode.clientWidth - X < offSetWidth + canvasOffset;
  15489. } else if(position == "S"){
  15490. return actualScrollNode.clientHeight - Y < offSetWidth;
  15491. }
  15492. return false;
  15493. };
  15494. var showButtons = (function() {
  15495. buttonGrow.show();
  15496. var w = canvas.bounds.width();
  15497. var h = canvas.bounds.height();
  15498. if(position=="N" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();
  15499. else if(position=="E" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();
  15500. else if(position=="S" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show();
  15501. else if(position=="W" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show();
  15502. else buttonShrink.hide();
  15503. }).bind(this);
  15504. var hideButtons = function() {
  15505. buttonGrow.hide();
  15506. buttonShrink.hide();
  15507. };
  15508. // If the mouse move is over the button area, show the button
  15509. parentNode.parentNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEMOVE, function(event){ if( isOverOffset(event) ){showButtons();} else {hideButtons()}} , false );
  15510. // If the mouse is over the button, show them
  15511. buttonGrow.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true );
  15512. buttonShrink.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true );
  15513. // If the mouse is out, hide the button
  15514. //scrollNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){button.hide()}, true )
  15515. parentNode.parentNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){hideButtons()} , true );
  15516. //svgRootNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){ inCanvas = false } , true );
  15517. // Hide the button initialy
  15518. hideButtons();
  15519. // Add the callbacks
  15520. buttonGrow.addEventListener('click', function(){callback( position ); showButtons();}, true);
  15521. buttonShrink.addEventListener('click', function(){callback( position, true ); showButtons();}, true);
  15522. }
  15523. });
  15524. /*
  15525. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15526. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15527. * pursuant to a written agreement and any use of this program without such an
  15528. * agreement is prohibited.
  15529. */
  15530. /*
  15531. * All code Copyright 2013 KIS Consultancy all rights reserved
  15532. */
  15533. if (!ORYX.Plugins)
  15534. ORYX.Plugins = new Object();
  15535. ORYX.Plugins.RenameShapes = Clazz.extend({
  15536. facade: undefined,
  15537. construct: function(facade){
  15538. this.facade = facade;
  15539. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_CANVAS_SCROLL, this.hideField.bind(this));
  15540. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK, this.actOnDBLClick.bind(this));
  15541. this.facade.offer({
  15542. keyCodes: [{
  15543. keyCode: 113, // F2-Key
  15544. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  15545. }
  15546. ],
  15547. functionality: this.renamePerF2.bind(this)
  15548. });
  15549. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true);
  15550. },
  15551. /**
  15552. * This method handles the "F2" key down event. The selected shape are looked
  15553. * up and the editing of title/name of it gets started.
  15554. */
  15555. renamePerF2 : function() {
  15556. var selectedShapes = this.facade.getSelection();
  15557. this.actOnDBLClick(undefined, selectedShapes.first());
  15558. },
  15559. actOnDBLClick: function(evt, shape){
  15560. if( !(shape instanceof ORYX.Core.Shape) ){ return; }
  15561. // Destroys the old input, if there is one
  15562. this.destroy();
  15563. // Get all properties which where at least one ref to view is set
  15564. var props = shape.getStencil().properties().findAll(function(item){
  15565. return (item.refToView()
  15566. && item.refToView().length > 0
  15567. && item.directlyEditable());
  15568. });
  15569. // from these, get all properties where write access are and the type is String or Expression
  15570. props = props.findAll(function(item){ return !item.readonly() && (item.type() == ORYX.CONFIG.TYPE_STRING || item.type() == ORYX.CONFIG.TYPE_EXPRESSION || item.type() == ORYX.CONFIG.TYPE_DATASOURCE); });
  15571. // Get all ref ids
  15572. var allRefToViews = props.collect(function(prop){ return prop.refToView(); }).flatten().compact();
  15573. // Get all labels from the shape with the ref ids
  15574. var labels = shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView); }); });
  15575. // If there are no referenced labels --> return
  15576. if( labels.length == 0 ){ return; }
  15577. // Define the nearest label
  15578. var nearestLabel = labels.length <= 1 ? labels[0] : null;
  15579. if( !nearestLabel ){
  15580. nearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode; });
  15581. if( !nearestLabel ){
  15582. var evtCoord = this.facade.eventCoordinates(evt);
  15583. var additionalIEZoom = 1;
  15584. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  15585. var ua = navigator.userAgent;
  15586. if (ua.indexOf('MSIE') >= 0) {
  15587. //IE 10 and below
  15588. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  15589. if (zoom !== 100) {
  15590. additionalIEZoom = zoom / 100
  15591. }
  15592. }
  15593. }
  15594. if (additionalIEZoom !== 1) {
  15595. evtCoord.x = evtCoord.x / additionalIEZoom;
  15596. evtCoord.y = evtCoord.y / additionalIEZoom;
  15597. }
  15598. evtCoord.y += $("editor-header").clientHeight - $("canvasSection").scrollTop - 5;
  15599. if (KISBPM.HEADER_CONFIG.showAppTitle == false)
  15600. {
  15601. evtCoord.y += 61;
  15602. }
  15603. evtCoord.x -= $("canvasSection").scrollLeft;
  15604. var trans = this.facade.getCanvas().rootNode.lastChild.getScreenCTM();
  15605. evtCoord.x *= trans.a;
  15606. evtCoord.y *= trans.d;
  15607. var diff = labels.collect(function(label){
  15608. var center = this.getCenterPosition( label.node );
  15609. var len = Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));
  15610. return {diff: len, label: label};
  15611. }.bind(this));
  15612. diff.sort(function(a, b){ return a.diff > b.diff; });
  15613. nearestLabel = diff[0].label;
  15614. }
  15615. }
  15616. // Get the particular property for the label
  15617. var prop = props.find(function(item){ return item.refToView().any(function(toView){ return nearestLabel.id == shape.id + toView; });});
  15618. // Get the center position from the nearest label
  15619. var width = Math.min(Math.max(100, shape.bounds.width()), 200);
  15620. var center = this.getCenterPosition( nearestLabel.node, shape );
  15621. center.x -= (width/2);
  15622. var propId = prop.prefix() + "-" + prop.id();
  15623. var textInput = document.createElement("textarea");
  15624. textInput.id = 'shapeTextInput';
  15625. textInput.style.position = 'absolute';
  15626. textInput.style.width = width + 'px';
  15627. textInput.style.left = (center.x < 10) ? 10 : center.x + 'px';
  15628. textInput.style.top = (center.y - 15) + 'px';
  15629. textInput.className = 'x-form-textarea x-form-field x_form_text_set_absolute';
  15630. textInput.value = shape.properties[propId];
  15631. this.oldValueText = shape.properties[propId];
  15632. document.getElementById('canvasSection').appendChild(textInput);
  15633. this.shownTextField = textInput;
  15634. // Value change listener needs to be defined now since we reference it in the text field
  15635. this.updateValueFunction = function(newValue, oldValue) {
  15636. var currentEl = shape;
  15637. var facade = this.facade;
  15638. if (oldValue != newValue) {
  15639. // Implement the specific command for property change
  15640. var commandClass = ORYX.Core.Command.extend({
  15641. construct: function(){
  15642. this.el = currentEl;
  15643. this.propId = propId;
  15644. this.oldValue = oldValue;
  15645. this.newValue = newValue;
  15646. this.facade = facade;
  15647. },
  15648. execute: function(){
  15649. this.el.setProperty(this.propId, this.newValue);
  15650. //this.el.update();
  15651. this.facade.setSelection([this.el]);
  15652. this.facade.getCanvas().update();
  15653. this.facade.updateSelection();
  15654. },
  15655. rollback: function(){
  15656. this.el.setProperty(this.propId, this.oldValue);
  15657. //this.el.update();
  15658. this.facade.setSelection([this.el]);
  15659. this.facade.getCanvas().update();
  15660. this.facade.updateSelection();
  15661. }
  15662. });
  15663. // Instantiated the class
  15664. var command = new commandClass();
  15665. // Execute the command
  15666. this.facade.executeCommands([command]);
  15667. }
  15668. }.bind(this);
  15669. jQuery("#shapeTextInput").focus();
  15670. jQuery("#shapeTextInput").autogrow();
  15671. // Disable the keydown in the editor (that when hitting the delete button, the shapes not get deleted)
  15672. this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
  15673. },
  15674. getCenterPosition: function(svgNode, shape){
  15675. if (!svgNode) { return {x:0, y:0}; }
  15676. var scale = this.facade.getCanvas().node.getScreenCTM();
  15677. var absoluteXY = shape.bounds.upperLeft();
  15678. var hasParent = true;
  15679. var searchShape = shape;
  15680. while (hasParent)
  15681. {
  15682. if (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram')
  15683. {
  15684. hasParent = false;
  15685. }
  15686. else
  15687. {
  15688. var parentXY = searchShape.getParentShape().bounds.upperLeft();
  15689. absoluteXY.x += parentXY.x;
  15690. absoluteXY.y += parentXY.y;
  15691. searchShape = searchShape.getParentShape();
  15692. }
  15693. }
  15694. var center = shape.bounds.midPoint();
  15695. center.x += absoluteXY.x + scale.e;
  15696. center.y += absoluteXY.y + scale.f;
  15697. center.x *= scale.a;
  15698. center.y *= scale.d;
  15699. var additionalIEZoom = 1;
  15700. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  15701. var ua = navigator.userAgent;
  15702. if (ua.indexOf('MSIE') >= 0) {
  15703. //IE 10 and below
  15704. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  15705. if (zoom !== 100) {
  15706. additionalIEZoom = zoom / 100
  15707. }
  15708. }
  15709. }
  15710. if (additionalIEZoom === 1) {
  15711. center.y = center.y - jQuery("#canvasSection").offset().top + 5;
  15712. center.x -= jQuery("#canvasSection").offset().left;
  15713. } else {
  15714. var canvasOffsetLeft = jQuery("#canvasSection").offset().left;
  15715. var canvasScrollLeft = jQuery("#canvasSection").scrollLeft();
  15716. var canvasScrollTop = jQuery("#canvasSection").scrollTop();
  15717. var offset = scale.e - (canvasOffsetLeft * additionalIEZoom);
  15718. var additionaloffset = 0;
  15719. if (offset > 10) {
  15720. additionaloffset = (offset / additionalIEZoom) - offset;
  15721. }
  15722. center.y = center.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop);
  15723. center.x = center.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft);
  15724. }
  15725. return center;
  15726. },
  15727. hide: function(e){
  15728. if (this.shownTextField && (!e || e.target !== this.shownTextField)) {
  15729. var newValue = this.shownTextField.value;
  15730. if (newValue !== this.oldValueText)
  15731. {
  15732. this.updateValueFunction(newValue, this.oldValueText);
  15733. }
  15734. this.destroy();
  15735. }
  15736. },
  15737. hideField: function(e){
  15738. if (this.shownTextField) {
  15739. this.destroy();
  15740. }
  15741. },
  15742. destroy: function(e){
  15743. var textInputComp = jQuery("#shapeTextInput");
  15744. if( textInputComp ){
  15745. textInputComp.remove();
  15746. delete this.shownTextField;
  15747. this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
  15748. }
  15749. }
  15750. });
  15751. /*
  15752. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15753. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15754. * pursuant to a written agreement and any use of this program without such an
  15755. * agreement is prohibited.
  15756. */
  15757. /*
  15758. * All code Copyright 2013 KIS Consultancy all rights reserved
  15759. */
  15760. if(!ORYX.Plugins)
  15761. ORYX.Plugins = new Object();
  15762. /**
  15763. * Supports EPCs by offering a syntax check and export and import ability..
  15764. *
  15765. *
  15766. */
  15767. ORYX.Plugins.ProcessLink = Clazz.extend({
  15768. facade: undefined,
  15769. /**
  15770. * Offers the plugin functionality:
  15771. *
  15772. */
  15773. construct: function(facade) {
  15774. this.facade = facade;
  15775. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this) );
  15776. },
  15777. /**
  15778. *
  15779. * @param {Object} option
  15780. */
  15781. propertyChanged: function( option, node){
  15782. if( option.name !== "oryx-refuri" || !node instanceof ORYX.Core.Node ){ return }
  15783. if( option.value && option.value.length > 0 && option.value != "undefined"){
  15784. this.show( node, option.value );
  15785. } else {
  15786. this.hide( node );
  15787. }
  15788. },
  15789. /**
  15790. * Shows the Link for a particular shape with a specific url
  15791. *
  15792. * @param {Object} shape
  15793. * @param {Object} url
  15794. */
  15795. show: function( shape, url){
  15796. // Generate the svg-representation of a link
  15797. var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null ,
  15798. [ 'a',
  15799. {'target': '_blank'},
  15800. ['path',
  15801. { "stroke-width": 1.0, "stroke":"#00DD00", "fill": "#00AA00", "d": "M3,3 l0,-2.5 l7.5,0 l0,-2.5 l7.5,4.5 l-7.5,3.5 l0,-2.5 l-8,0", "line-captions": "round"}
  15802. ]
  15803. ]);
  15804. var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null ,
  15805. [ 'a',
  15806. {'target': '_blank'},
  15807. ['path', { "style": "fill:#92BFFC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72", "d": "M0 1.44 L0 15.05 L11.91 15.05 L11.91 5.98 L7.37 1.44 L0 1.44 Z"}],
  15808. ['path', { "style": "stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72;fill:none;", "transform": "translate(7.5, -8.5)", "d": "M0 10.51 L0 15.05 L4.54 15.05"}],
  15809. ['path', { "style": "fill:#f28226;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72", "transform": "translate(-3, -1)", "d": "M0 8.81 L0 13.06 L5.95 13.06 L5.95 15.05 A50.2313 50.2313 -175.57 0 0 10.77 11.08 A49.9128 49.9128 -1.28 0 0 5.95 6.54 L5.95 8.81 L0 8.81 Z"}],
  15810. ]);
  15811. /*
  15812. *
  15813. * [ 'a',
  15814. {'target': '_blank'},
  15815. ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M7,4 l0,2"}],
  15816. ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M4,8 l-2,0 l0,6"}],
  15817. ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M10,8 l2,0 l0,6"}],
  15818. ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 0}],
  15819. ['rect', { "style": "fill:#ffafff;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 6}],
  15820. ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 0, "y": 12}],
  15821. ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 8, "y": 12}],
  15822. ['rect', { "style": "fill:none;stroke:none;pointer-events:all", "width": 14, "height": 16, "x": 0, "y": 0}]
  15823. ]);
  15824. */
  15825. // Set the link with the special namespace
  15826. link.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url);
  15827. // Shows the link in the overlay
  15828. this.facade.raiseEvent({
  15829. type: ORYX.CONFIG.EVENT_OVERLAY_SHOW,
  15830. id: "arissupport.urlref_" + shape.id,
  15831. shapes: [shape],
  15832. node: link,
  15833. nodePosition: "SE"
  15834. });
  15835. },
  15836. /**
  15837. * Hides the Link for a particular shape
  15838. *
  15839. * @param {Object} shape
  15840. */
  15841. hide: function( shape ){
  15842. this.facade.raiseEvent({
  15843. type: ORYX.CONFIG.EVENT_OVERLAY_HIDE,
  15844. id: "arissupport.urlref_" + shape.id
  15845. });
  15846. }
  15847. });/*
  15848. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  15849. * License rights for this program may be obtained from Alfresco Software, Ltd.
  15850. * pursuant to a written agreement and any use of this program without such an
  15851. * agreement is prohibited.
  15852. */
  15853. /*
  15854. * All code Copyright 2013 KIS Consultancy all rights reserved
  15855. */
  15856. Array.prototype.insertFrom = function(from, to){
  15857. to = Math.max(0, to);
  15858. from = Math.min( Math.max(0, from), this.length-1 );
  15859. var el = this[from];
  15860. var old = this.without(el);
  15861. var newA = old.slice(0, to);
  15862. newA.push(el);
  15863. if(old.length > to ){
  15864. newA = newA.concat(old.slice(to))
  15865. };
  15866. return newA;
  15867. }
  15868. if(!ORYX.Plugins)
  15869. ORYX.Plugins = new Object();
  15870. ORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({
  15871. facade: undefined,
  15872. construct: function(facade) {
  15873. this.facade = facade;
  15874. // Z-Ordering
  15875. /** Hide for SIGNAVIO
  15876. this.facade.offer({
  15877. 'name':ORYX.I18N.Arrangement.btf,
  15878. 'functionality': this.setZLevel.bind(this, this.setToTop),
  15879. 'group': ORYX.I18N.Arrangement.groupZ,
  15880. 'icon': ORYX.PATH + "images/shape_move_front.png",
  15881. 'description': ORYX.I18N.Arrangement.btfDesc,
  15882. 'index': 1,
  15883. 'minShape': 1});
  15884. this.facade.offer({
  15885. 'name':ORYX.I18N.Arrangement.btb,
  15886. 'functionality': this.setZLevel.bind(this, this.setToBack),
  15887. 'group': ORYX.I18N.Arrangement.groupZ,
  15888. 'icon': ORYX.PATH + "images/shape_move_back.png",
  15889. 'description': ORYX.I18N.Arrangement.btbDesc,
  15890. 'index': 2,
  15891. 'minShape': 1});
  15892. this.facade.offer({
  15893. 'name':ORYX.I18N.Arrangement.bf,
  15894. 'functionality': this.setZLevel.bind(this, this.setForward),
  15895. 'group': ORYX.I18N.Arrangement.groupZ,
  15896. 'icon': ORYX.PATH + "images/shape_move_forwards.png",
  15897. 'description': ORYX.I18N.Arrangement.bfDesc,
  15898. 'index': 3,
  15899. 'minShape': 1});
  15900. this.facade.offer({
  15901. 'name':ORYX.I18N.Arrangement.bb,
  15902. 'functionality': this.setZLevel.bind(this, this.setBackward),
  15903. 'group': ORYX.I18N.Arrangement.groupZ,
  15904. 'icon': ORYX.PATH + "images/shape_move_backwards.png",
  15905. 'description': ORYX.I18N.Arrangement.bbDesc,
  15906. 'index': 4,
  15907. 'minShape': 1});
  15908. // Aligment
  15909. this.facade.offer({
  15910. 'name':ORYX.I18N.Arrangement.ab,
  15911. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]),
  15912. 'group': ORYX.I18N.Arrangement.groupA,
  15913. 'icon': ORYX.PATH + "images/shape_align_bottom.png",
  15914. 'description': ORYX.I18N.Arrangement.abDesc,
  15915. 'index': 1,
  15916. 'minShape': 2});
  15917. this.facade.offer({
  15918. 'name':ORYX.I18N.Arrangement.at,
  15919. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]),
  15920. 'group': ORYX.I18N.Arrangement.groupA,
  15921. 'icon': ORYX.PATH + "images/shape_align_top.png",
  15922. 'description': ORYX.I18N.Arrangement.atDesc,
  15923. 'index': 3,
  15924. 'minShape': 2});
  15925. this.facade.offer({
  15926. 'name':ORYX.I18N.Arrangement.al,
  15927. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]),
  15928. 'group': ORYX.I18N.Arrangement.groupA,
  15929. 'icon': ORYX.PATH + "images/shape_align_left.png",
  15930. 'description': ORYX.I18N.Arrangement.alDesc,
  15931. 'index': 4,
  15932. 'minShape': 2});
  15933. this.facade.offer({
  15934. 'name':ORYX.I18N.Arrangement.ar,
  15935. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]),
  15936. 'group': ORYX.I18N.Arrangement.groupA,
  15937. 'icon': ORYX.PATH + "images/shape_align_right.png",
  15938. 'description': ORYX.I18N.Arrangement.arDesc,
  15939. 'index': 6,
  15940. 'minShape': 2});
  15941. **/
  15942. this.facade.offer({
  15943. 'name':ORYX.I18N.Arrangement.am,
  15944. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]),
  15945. 'group': ORYX.I18N.Arrangement.groupA,
  15946. 'icon': ORYX.PATH + "images/shape_align_middle.png",
  15947. 'description': ORYX.I18N.Arrangement.amDesc,
  15948. 'index': 1,
  15949. 'minShape': 2});
  15950. this.facade.offer({
  15951. 'name':ORYX.I18N.Arrangement.ac,
  15952. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_CENTER]),
  15953. 'group': ORYX.I18N.Arrangement.groupA,
  15954. 'icon': ORYX.PATH + "images/shape_align_center.png",
  15955. 'description': ORYX.I18N.Arrangement.acDesc,
  15956. 'index': 2,
  15957. 'minShape': 2});
  15958. this.facade.offer({
  15959. 'name':ORYX.I18N.Arrangement.as,
  15960. 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_SIZE]),
  15961. 'group': ORYX.I18N.Arrangement.groupA,
  15962. 'icon': ORYX.PATH + "images/shape_align_size.png",
  15963. 'description': ORYX.I18N.Arrangement.asDesc,
  15964. 'index': 3,
  15965. 'minShape': 2});
  15966. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, this.setZLevel.bind(this, this.setToTop) );
  15967. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACK, this.setZLevel.bind(this, this.setToBack) );
  15968. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD, this.setZLevel.bind(this, this.setForward) );
  15969. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD, this.setZLevel.bind(this, this.setBackward) );
  15970. },
  15971. onSelectionChanged: function(elemnt){
  15972. var selection = this.facade.getSelection();
  15973. if (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) {
  15974. this.setToTop(selection);
  15975. }
  15976. },
  15977. setZLevel:function(callback, event){
  15978. //Command-Pattern for dragging one docker
  15979. var zLevelCommand = ORYX.Core.Command.extend({
  15980. construct: function(callback, elements, facade){
  15981. this.callback = callback;
  15982. this.elements = elements;
  15983. // For redo, the previous elements get stored
  15984. this.elAndIndex = elements.map(function(el){ return {el:el, previous:el.parent.children[el.parent.children.indexOf(el)-1]} })
  15985. this.facade = facade;
  15986. },
  15987. execute: function(){
  15988. // Call the defined z-order callback with the elements
  15989. this.callback( this.elements )
  15990. this.facade.setSelection( this.elements )
  15991. },
  15992. rollback: function(){
  15993. // Sort all elements on the index of there containment
  15994. var sortedEl = this.elAndIndex.sortBy( function( el ) {
  15995. var value = el.el;
  15996. var t = $A(value.node.parentNode.childNodes);
  15997. return t.indexOf(value.node);
  15998. });
  15999. // Every element get setted back bevor the old previous element
  16000. for(var i=0; i<sortedEl.length; i++){
  16001. var el = sortedEl[i].el;
  16002. var p = el.parent;
  16003. var oldIndex = p.children.indexOf(el);
  16004. var newIndex = p.children.indexOf(sortedEl[i].previous);
  16005. newIndex = newIndex || 0
  16006. p.children = p.children.insertFrom(oldIndex, newIndex)
  16007. el.node.parentNode.insertBefore(el.node, el.node.parentNode.childNodes[newIndex+1]);
  16008. }
  16009. // Reset the selection
  16010. this.facade.setSelection( this.elements )
  16011. }
  16012. });
  16013. // Instanziate the dockCommand
  16014. var command = new zLevelCommand(callback, this.facade.getSelection(), this.facade);
  16015. if( event.excludeCommand ){
  16016. command.execute();
  16017. } else {
  16018. this.facade.executeCommands( [command] );
  16019. }
  16020. },
  16021. setToTop: function(elements) {
  16022. // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
  16023. var tmpElem = elements.sortBy( function(value, index) {
  16024. var t = $A(value.node.parentNode.childNodes);
  16025. return t.indexOf(value.node);
  16026. });
  16027. // Sortiertes Array wird nach oben verschoben.
  16028. tmpElem.each( function(value) {
  16029. var p = value.parent;
  16030. if (p.children.last() === value){
  16031. return;
  16032. }
  16033. p.children = p.children.without( value )
  16034. p.children.push(value);
  16035. value.node.parentNode.appendChild(value.node);
  16036. });
  16037. },
  16038. setToBack: function(elements) {
  16039. // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
  16040. var tmpElem = elements.sortBy( function(value, index) {
  16041. var t = $A(value.node.parentNode.childNodes);
  16042. return t.indexOf(value.node);
  16043. });
  16044. tmpElem = tmpElem.reverse();
  16045. // Sortiertes Array wird nach unten verschoben.
  16046. tmpElem.each( function(value) {
  16047. var p = value.parent
  16048. p.children = p.children.without( value )
  16049. p.children.unshift( value );
  16050. value.node.parentNode.insertBefore(value.node, value.node.parentNode.firstChild);
  16051. });
  16052. },
  16053. setBackward: function(elements) {
  16054. // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
  16055. var tmpElem = elements.sortBy( function(value, index) {
  16056. var t = $A(value.node.parentNode.childNodes);
  16057. return t.indexOf(value.node);
  16058. });
  16059. // Reverse the elements
  16060. tmpElem = tmpElem.reverse();
  16061. // Delete all Nodes who are the next Node in the nodes-Array
  16062. var compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.previousSibling})});
  16063. // Sortiertes Array wird nach eine Ebene nach oben verschoben.
  16064. compactElem.each( function(el) {
  16065. if(el.node.previousSibling === null) { return; }
  16066. var p = el.parent;
  16067. var index = p.children.indexOf(el);
  16068. p.children = p.children.insertFrom(index, index-1)
  16069. el.node.parentNode.insertBefore(el.node, el.node.previousSibling);
  16070. });
  16071. },
  16072. setForward: function(elements) {
  16073. // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
  16074. var tmpElem = elements.sortBy( function(value, index) {
  16075. var t = $A(value.node.parentNode.childNodes);
  16076. return t.indexOf(value.node);
  16077. });
  16078. // Delete all Nodes who are the next Node in the nodes-Array
  16079. var compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.nextSibling})});
  16080. // Sortiertes Array wird eine Ebene nach unten verschoben.
  16081. compactElem.each( function(el) {
  16082. var nextNode = el.node.nextSibling
  16083. if(nextNode === null) { return; }
  16084. var index = el.parent.children.indexOf(el);
  16085. var p = el.parent;
  16086. p.children = p.children.insertFrom(index, index+1)
  16087. el.node.parentNode.insertBefore(nextNode, el.node);
  16088. });
  16089. },
  16090. alignShapes: function(way) {
  16091. var elements = this.facade.getSelection();
  16092. // Set the elements to all Top-Level elements
  16093. elements = this.facade.getCanvas().getShapesWithSharedParent(elements);
  16094. // Get only nodes
  16095. elements = elements.findAll(function(value) {
  16096. return (value instanceof ORYX.Core.Node)
  16097. });
  16098. // Delete all attached intermediate events from the array
  16099. elements = elements.findAll(function(value) {
  16100. var d = value.getIncomingShapes()
  16101. return d.length == 0 || !elements.include(d[0])
  16102. });
  16103. if(elements.length < 2) { return; }
  16104. // get bounds of all shapes.
  16105. var bounds = elements[0].absoluteBounds().clone();
  16106. elements.each(function(shape) {
  16107. bounds.include(shape.absoluteBounds().clone());
  16108. });
  16109. // get biggest width and heigth
  16110. var maxWidth = 0;
  16111. var maxHeight = 0;
  16112. elements.each(function(shape){
  16113. maxWidth = Math.max(shape.bounds.width(), maxWidth);
  16114. maxHeight = Math.max(shape.bounds.height(), maxHeight);
  16115. });
  16116. var commandClass = ORYX.Core.Command.extend({
  16117. construct: function(elements, bounds, maxHeight, maxWidth, way, plugin){
  16118. this.elements = elements;
  16119. this.bounds = bounds;
  16120. this.maxHeight = maxHeight;
  16121. this.maxWidth = maxWidth;
  16122. this.way = way;
  16123. this.facade = plugin.facade;
  16124. this.plugin = plugin;
  16125. this.orgPos = [];
  16126. },
  16127. setBounds: function(shape, maxSize) {
  16128. if(!maxSize)
  16129. maxSize = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};
  16130. if(!shape.bounds) { throw "Bounds not definined." }
  16131. var newBounds = {
  16132. a: {x: shape.bounds.upperLeft().x - (this.maxWidth - shape.bounds.width())/2,
  16133. y: shape.bounds.upperLeft().y - (this.maxHeight - shape.bounds.height())/2},
  16134. b: {x: shape.bounds.lowerRight().x + (this.maxWidth - shape.bounds.width())/2,
  16135. y: shape.bounds.lowerRight().y + (this.maxHeight - shape.bounds.height())/2}
  16136. }
  16137. /* If the new width of shape exceeds the maximum width, set width value to maximum. */
  16138. if(this.maxWidth > maxSize.width) {
  16139. newBounds.a.x = shape.bounds.upperLeft().x -
  16140. (maxSize.width - shape.bounds.width())/2;
  16141. newBounds.b.x = shape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width())/2
  16142. }
  16143. /* If the new height of shape exceeds the maximum height, set height value to maximum. */
  16144. if(this.maxHeight > maxSize.height) {
  16145. newBounds.a.y = shape.bounds.upperLeft().y -
  16146. (maxSize.height - shape.bounds.height())/2;
  16147. newBounds.b.y = shape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height())/2
  16148. }
  16149. /* set bounds of shape */
  16150. shape.bounds.set(newBounds);
  16151. },
  16152. execute: function(){
  16153. // align each shape according to the way that was specified.
  16154. this.elements.each(function(shape, index) {
  16155. this.orgPos[index] = shape.bounds.upperLeft();
  16156. var relBounds = this.bounds.clone();
  16157. var newCoordinates;
  16158. if (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas) ) {
  16159. var upL = shape.parent.absoluteBounds().upperLeft();
  16160. relBounds.moveBy(-upL.x, -upL.y);
  16161. }
  16162. switch (this.way) {
  16163. // align the shapes in the requested way.
  16164. case ORYX.CONFIG.EDITOR_ALIGN_BOTTOM:
  16165. newCoordinates = {
  16166. x: shape.bounds.upperLeft().x,
  16167. y: relBounds.b.y - shape.bounds.height()
  16168. }; break;
  16169. case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE:
  16170. newCoordinates = {
  16171. x: shape.bounds.upperLeft().x,
  16172. y: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2
  16173. }; break;
  16174. case ORYX.CONFIG.EDITOR_ALIGN_TOP:
  16175. newCoordinates = {
  16176. x: shape.bounds.upperLeft().x,
  16177. y: relBounds.a.y
  16178. }; break;
  16179. case ORYX.CONFIG.EDITOR_ALIGN_LEFT:
  16180. newCoordinates = {
  16181. x: relBounds.a.x,
  16182. y: shape.bounds.upperLeft().y
  16183. }; break;
  16184. case ORYX.CONFIG.EDITOR_ALIGN_CENTER:
  16185. newCoordinates = {
  16186. x: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2,
  16187. y: shape.bounds.upperLeft().y
  16188. }; break;
  16189. case ORYX.CONFIG.EDITOR_ALIGN_RIGHT:
  16190. newCoordinates = {
  16191. x: relBounds.b.x - shape.bounds.width(),
  16192. y: shape.bounds.upperLeft().y
  16193. }; break;
  16194. case ORYX.CONFIG.EDITOR_ALIGN_SIZE:
  16195. if(shape.isResizable) {
  16196. this.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()};
  16197. this.setBounds(shape, shape.maximumSize);
  16198. }
  16199. break;
  16200. }
  16201. if (newCoordinates){
  16202. var offset = {
  16203. x: shape.bounds.upperLeft().x - newCoordinates.x,
  16204. y: shape.bounds.upperLeft().y - newCoordinates.y
  16205. }
  16206. // Set the new position
  16207. shape.bounds.moveTo(newCoordinates);
  16208. this.plugin.layoutEdges(shape, shape.getAllDockedShapes(),offset);
  16209. //shape.update()
  16210. }
  16211. }.bind(this));
  16212. //this.facade.getCanvas().update();
  16213. //this.facade.updateSelection();
  16214. },
  16215. rollback: function(){
  16216. this.elements.each(function(shape, index) {
  16217. if (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) {
  16218. if(shape.isResizable) {shape.bounds.set(this.orgPos[index]);}
  16219. } else {shape.bounds.moveTo(this.orgPos[index]);}
  16220. }.bind(this));
  16221. //this.facade.getCanvas().update();
  16222. //this.facade.updateSelection();
  16223. }
  16224. })
  16225. var command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this);
  16226. this.facade.executeCommands([command]);
  16227. }
  16228. });/*
  16229. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  16230. * License rights for this program may be obtained from Alfresco Software, Ltd.
  16231. * pursuant to a written agreement and any use of this program without such an
  16232. * agreement is prohibited.
  16233. */
  16234. /*
  16235. * All code Copyright 2013 KIS Consultancy all rights reserved
  16236. */
  16237. if (!ORYX.Plugins)
  16238. ORYX.Plugins = new Object();
  16239. ORYX.Plugins.Save = Clazz.extend({
  16240. facade: undefined,
  16241. processURI: undefined,
  16242. changeSymbol : "*",
  16243. construct: function(facade){
  16244. this.facade = facade;
  16245. document.addEventListener("keydown", function(e){
  16246. if (e.ctrlKey&&e.keyCode === 83){
  16247. Event.stop(e);
  16248. }
  16249. }, false);
  16250. window.onbeforeunload = this.onUnLoad.bind(this);
  16251. this.changeDifference = 0;
  16252. // Register on event for executing commands --> store all commands in a stack
  16253. // --> Execute
  16254. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_EXECUTE, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );
  16255. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );
  16256. // --> Saved from other places in the editor
  16257. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED, function(){ this.changeDifference = 0; this.updateTitle(); }.bind(this) );
  16258. // --> Rollback
  16259. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function(){ this.changeDifference--; this.updateTitle(); }.bind(this) );
  16260. //TODO very critical for load time performance!!!
  16261. //this.serializedDOM = DataManager.__persistDOM(this.facade);
  16262. this.hasChanges = this._hasChanges.bind(this);
  16263. },
  16264. updateTitle: function(){
  16265. var value = window.document.title || document.getElementsByTagName("title")[0].childNodes[0].nodeValue;
  16266. if (this.changeDifference === 0 && value.startsWith(this.changeSymbol)){
  16267. window.document.title = value.slice(1);
  16268. } else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)){
  16269. window.document.title = this.changeSymbol + "" + value;
  16270. }
  16271. },
  16272. _hasChanges: function() {
  16273. return this.changeDifference !== 0 || (this.facade.getModelMetaData()['new'] && this.facade.getCanvas().getChildShapes().size() > 0);
  16274. },
  16275. onUnLoad: function(){
  16276. if(this._hasChanges()) {
  16277. return ORYX.I18N.Save.unsavedData;
  16278. }
  16279. }
  16280. });
  16281. /*
  16282. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  16283. * License rights for this program may be obtained from Alfresco Software, Ltd.
  16284. * pursuant to a written agreement and any use of this program without such an
  16285. * agreement is prohibited.
  16286. */
  16287. /*
  16288. * All code Copyright 2013 KIS Consultancy all rights reserved
  16289. */
  16290. if(!ORYX.Plugins)
  16291. ORYX.Plugins = new Object();
  16292. ORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({
  16293. /**
  16294. * Constructor
  16295. * @param {Object} Facade: The Facade of the Editor
  16296. */
  16297. construct: function(facade) {
  16298. this.facade = facade;
  16299. // Initialize variables
  16300. this.currentShapes = []; // Current selected Shapes
  16301. //this.pluginsData = []; // Available Plugins
  16302. this.toMoveShapes = []; // Shapes there will be moved
  16303. this.distPoints = []; // Distance Points for Snap on Grid
  16304. this.isResizing = false; // Flag: If there was currently resized
  16305. this.dragEnable = false; // Flag: If Dragging is enabled
  16306. this.dragIntialized = false; // Flag: If the Dragging is initialized
  16307. this.edgesMovable = true; // Flag: If an edge is docked it is not movable
  16308. this.offSetPosition = {x: 0, y: 0}; // Offset of the Dragging
  16309. this.faktorXY = {x: 1, y: 1}; // The Current Zoom-Faktor
  16310. this.containmentParentNode; // the current future parent node for the dragged shapes
  16311. this.isAddingAllowed = false; // flag, if adding current selected shapes to containmentParentNode is allowed
  16312. this.isAttachingAllowed = false; // flag, if attaching to the current shape is allowed
  16313. this.callbackMouseMove = this.handleMouseMove.bind(this);
  16314. this.callbackMouseUp = this.handleMouseUp.bind(this);
  16315. // Get the SVG-Containernode
  16316. var containerNode = this.facade.getCanvas().getSvgContainer();
  16317. // Create the Selected Rectangle in the SVG
  16318. this.selectedRect = new ORYX.Plugins.SelectedRect(containerNode);
  16319. // Show grid line if enabled
  16320. if (ORYX.CONFIG.SHOW_GRIDLINE) {
  16321. this.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL);
  16322. this.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL);
  16323. }
  16324. // Get a HTML-ContainerNode
  16325. containerNode = this.facade.getCanvas().getHTMLContainer();
  16326. this.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;
  16327. // Create the southeastern button for resizing
  16328. this.resizerSE = new ORYX.Plugins.Resizer(containerNode, "southeast", this.facade);
  16329. this.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback
  16330. this.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback
  16331. this.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback
  16332. // Create the northwestern button for resizing
  16333. this.resizerNW = new ORYX.Plugins.Resizer(containerNode, "northwest", this.facade);
  16334. this.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback
  16335. this.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback
  16336. this.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback
  16337. // For the Drag and Drop
  16338. // Register on MouseDown-Event on a Shape
  16339. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
  16340. },
  16341. /**
  16342. * On Mouse Down
  16343. *
  16344. */
  16345. handleMouseDown: function(event, uiObj) {
  16346. // If the selection Bounds not intialized and the uiObj is not member of current selectio
  16347. // then return
  16348. if(!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) {return;};
  16349. // Start Dragging
  16350. this.dragEnable = true;
  16351. this.dragIntialized = true;
  16352. this.edgesMovable = true;
  16353. // Calculate the current zoom factor
  16354. var a = this.facade.getCanvas().node.getScreenCTM();
  16355. this.faktorXY.x = a.a;
  16356. this.faktorXY.y = a.d;
  16357. var eventX = Event.pointerX(event);
  16358. var eventY = Event.pointerY(event);
  16359. // Set the offset position of dragging
  16360. var upL = this.dragBounds.upperLeft();
  16361. this.offSetPosition = {
  16362. x: eventX - (upL.x * this.faktorXY.x),
  16363. y: eventY - (upL.y * this.faktorXY.y)};
  16364. this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
  16365. // Register on Global Mouse-MOVE Event
  16366. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);
  16367. // Register on Global Mouse-UP Event
  16368. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);
  16369. return;
  16370. },
  16371. /**
  16372. * On Key Mouse Up
  16373. *
  16374. */
  16375. handleMouseUp: function(event) {
  16376. //disable containment highlighting
  16377. this.facade.raiseEvent({
  16378. type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
  16379. highlightId:"dragdropresize.contain"
  16380. });
  16381. this.facade.raiseEvent({
  16382. type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
  16383. highlightId:"dragdropresize.attached"
  16384. });
  16385. // If Dragging is finished
  16386. if(this.dragEnable) {
  16387. // and update the current selection
  16388. if(!this.dragIntialized) {
  16389. // Do Method after Dragging
  16390. this.afterDrag();
  16391. // Check if the Shape is allowed to dock to the other Shape
  16392. if ( this.isAttachingAllowed &&
  16393. this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node &&
  16394. this.toMoveShapes[0].dockers.length > 0) {
  16395. // Get the position and the docker
  16396. var position = this.facade.eventCoordinates( event );
  16397. var docker = this.toMoveShapes[0].dockers[0];
  16398. //Command-Pattern for dragging several Shapes
  16399. var dockCommand = ORYX.Core.Command.extend({
  16400. construct: function(docker, position, newDockedShape, facade){
  16401. this.docker = docker;
  16402. this.newPosition = position;
  16403. this.newDockedShape = newDockedShape;
  16404. this.newParent = newDockedShape.parent || facade.getCanvas();
  16405. this.oldPosition = docker.parent.bounds.center();
  16406. this.oldDockedShape = docker.getDockedShape();
  16407. this.oldParent = docker.parent.parent || facade.getCanvas();
  16408. this.facade = facade;
  16409. if( this.oldDockedShape ){
  16410. this.oldPosition = docker.parent.absoluteBounds().center();
  16411. }
  16412. },
  16413. execute: function(){
  16414. this.dock( this.newDockedShape, this.newParent, this.newPosition );
  16415. // Raise Event for having the docked shape on top of the other shape
  16416. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true})
  16417. },
  16418. rollback: function(){
  16419. this.dock( this.oldDockedShape, this.oldParent, this.oldPosition );
  16420. },
  16421. dock:function( toDockShape, parent, pos ){
  16422. // Add to the same parent Shape
  16423. parent.add( this.docker.parent )
  16424. // Set the Docker to the new Shape
  16425. this.docker.setDockedShape( undefined );
  16426. this.docker.bounds.centerMoveTo( pos )
  16427. this.docker.setDockedShape( toDockShape );
  16428. //this.docker.update();
  16429. this.facade.setSelection( [this.docker.parent] );
  16430. this.facade.getCanvas().update();
  16431. this.facade.updateSelection();
  16432. }
  16433. });
  16434. // Instanziate the dockCommand
  16435. var commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)];
  16436. this.facade.executeCommands(commands);
  16437. // Check if adding is allowed to the other Shape
  16438. } else if( this.isAddingAllowed ) {
  16439. // Refresh all Shapes --> Set the new Bounds
  16440. this.refreshSelectedShapes();
  16441. }
  16442. this.facade.updateSelection();
  16443. //this.currentShapes.each(function(shape) {shape.update()})
  16444. // Raise Event: Dragging is finished
  16445. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END});
  16446. }
  16447. if (this.vLine)
  16448. this.vLine.hide();
  16449. if (this.hLine)
  16450. this.hLine.hide();
  16451. }
  16452. // Disable
  16453. this.dragEnable = false;
  16454. // UnRegister on Global Mouse-UP/-Move Event
  16455. document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);
  16456. document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);
  16457. return;
  16458. },
  16459. /**
  16460. * On Key Mouse Move
  16461. *
  16462. */
  16463. handleMouseMove: function(event) {
  16464. // If dragging is not enabled, go return
  16465. if(!this.dragEnable) { return };
  16466. // If Dragging is initialized
  16467. if(this.dragIntialized) {
  16468. // Raise Event: Drag will be started
  16469. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START});
  16470. this.dragIntialized = false;
  16471. // And hide the resizers and the highlighting
  16472. this.resizerSE.hide();
  16473. this.resizerNW.hide();
  16474. // if only edges are selected, containmentParentNode must be the canvas
  16475. this._onlyEdges = this.currentShapes.all(function(currentShape) {
  16476. return (currentShape instanceof ORYX.Core.Edge);
  16477. });
  16478. // Do method before Drag
  16479. this.beforeDrag();
  16480. this._currentUnderlyingNodes = [];
  16481. }
  16482. // Calculate the new position
  16483. var position = {
  16484. x: Event.pointerX(event) - this.offSetPosition.x,
  16485. y: Event.pointerY(event) - this.offSetPosition.y}
  16486. position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
  16487. position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
  16488. // If not the Control-Key are pressed
  16489. var modifierKeyPressed = event.shiftKey || event.ctrlKey;
  16490. if(ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) {
  16491. // Snap the current position to the nearest Snap-Point
  16492. position = this.snapToGrid(position);
  16493. } else {
  16494. if (this.vLine)
  16495. this.vLine.hide();
  16496. if (this.hLine)
  16497. this.hLine.hide();
  16498. }
  16499. // Adjust the point by the zoom faktor
  16500. position.x /= this.faktorXY.x;
  16501. position.y /= this.faktorXY.y;
  16502. // Set that the position is not lower than zero
  16503. position.x = Math.max( 0 , position.x)
  16504. position.y = Math.max( 0 , position.y)
  16505. // Set that the position is not bigger than the canvas
  16506. var c = this.facade.getCanvas();
  16507. position.x = Math.min( c.bounds.width() - this.dragBounds.width(), position.x)
  16508. position.y = Math.min( c.bounds.height() - this.dragBounds.height(), position.y)
  16509. // Drag this bounds
  16510. this.dragBounds.moveTo(position);
  16511. // Update all selected shapes and the selection rectangle
  16512. //this.refreshSelectedShapes();
  16513. this.resizeRectangle(this.dragBounds);
  16514. this.isAttachingAllowed = false;
  16515. //check, if a node can be added to the underlying node
  16516. var eventCoordinates = this.facade.eventCoordinates(event);
  16517. var additionalIEZoom = 1;
  16518. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  16519. var ua = navigator.userAgent;
  16520. if (ua.indexOf('MSIE') >= 0) {
  16521. //IE 10 and below
  16522. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  16523. if (zoom !== 100) {
  16524. additionalIEZoom = zoom / 100
  16525. }
  16526. }
  16527. }
  16528. if (additionalIEZoom !== 1) {
  16529. eventCoordinates.x = eventCoordinates.x / additionalIEZoom;
  16530. eventCoordinates.y = eventCoordinates.y / additionalIEZoom;
  16531. }
  16532. var underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(eventCoordinates));
  16533. var checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0
  16534. checkIfAttachable = checkIfAttachable && underlyingNodes.length != 1
  16535. if (!checkIfAttachable &&
  16536. underlyingNodes.length === this._currentUnderlyingNodes.length &&
  16537. underlyingNodes.all(function(node, index){return this._currentUnderlyingNodes[index] === node}.bind(this))) {
  16538. return
  16539. } else if(this._onlyEdges) {
  16540. this.isAddingAllowed = true;
  16541. this.containmentParentNode = this.facade.getCanvas();
  16542. } else {
  16543. /* Check the containment and connection rules */
  16544. var options = {
  16545. event : event,
  16546. underlyingNodes : underlyingNodes,
  16547. checkIfAttachable : checkIfAttachable
  16548. };
  16549. this.checkRules(options);
  16550. }
  16551. this._currentUnderlyingNodes = underlyingNodes.reverse();
  16552. //visualize the containment result
  16553. if( this.isAttachingAllowed ) {
  16554. this.facade.raiseEvent({
  16555. type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  16556. highlightId: "dragdropresize.attached",
  16557. elements: [this.containmentParentNode],
  16558. style: ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,
  16559. color: ORYX.CONFIG.SELECTION_VALID_COLOR
  16560. });
  16561. } else {
  16562. this.facade.raiseEvent({
  16563. type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
  16564. highlightId:"dragdropresize.attached"
  16565. });
  16566. }
  16567. if( !this.isAttachingAllowed ){
  16568. if( this.isAddingAllowed ) {
  16569. this.facade.raiseEvent({
  16570. type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  16571. highlightId:"dragdropresize.contain",
  16572. elements:[this.containmentParentNode],
  16573. color: ORYX.CONFIG.SELECTION_VALID_COLOR
  16574. });
  16575. } else {
  16576. this.facade.raiseEvent({
  16577. type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  16578. highlightId:"dragdropresize.contain",
  16579. elements:[this.containmentParentNode],
  16580. color: ORYX.CONFIG.SELECTION_INVALID_COLOR
  16581. });
  16582. }
  16583. } else {
  16584. this.facade.raiseEvent({
  16585. type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
  16586. highlightId:"dragdropresize.contain"
  16587. });
  16588. }
  16589. // Stop the Event
  16590. //Event.stop(event);
  16591. return;
  16592. },
  16593. // /**
  16594. // * Rollbacks the docked shape of an edge, if the edge is not movable.
  16595. // */
  16596. // redockEdges: function() {
  16597. // this._undockedEdgesCommand.dockers.each(function(el){
  16598. // el.docker.setDockedShape(el.dockedShape);
  16599. // el.docker.setReferencePoint(el.refPoint);
  16600. // })
  16601. // },
  16602. /**
  16603. * Checks the containment and connection rules for the selected shapes.
  16604. */
  16605. checkRules : function(options) {
  16606. var event = options.event;
  16607. var underlyingNodes = options.underlyingNodes;
  16608. var checkIfAttachable = options.checkIfAttachable;
  16609. var noEdges = options.noEdges;
  16610. //get underlying node that is not the same than one of the currently selected shapes or
  16611. // a child of one of the selected shapes with the highest z Order.
  16612. // The result is a shape or the canvas
  16613. this.containmentParentNode = underlyingNodes.reverse().find((function(node) {
  16614. return (node instanceof ORYX.Core.Canvas) ||
  16615. (((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges))
  16616. && (!(this.currentShapes.member(node) ||
  16617. this.currentShapes.any(function(shape) {
  16618. return (shape.children.length > 0 && shape.getChildNodes(true).member(node));
  16619. }))));
  16620. }).bind(this));
  16621. if( checkIfAttachable ){
  16622. this.isAttachingAllowed = this.facade.getRules().canConnect({
  16623. sourceShape: this.containmentParentNode,
  16624. edgeShape: this.toMoveShapes[0],
  16625. targetShape: this.toMoveShapes[0]
  16626. });
  16627. if ( this.isAttachingAllowed ) {
  16628. var point = this.facade.eventCoordinates(event);
  16629. this.isAttachingAllowed = this.containmentParentNode.isPointOverOffset( point.x, point.y );
  16630. }
  16631. }
  16632. if( !this.isAttachingAllowed ){
  16633. //check all selected shapes, if they can be added to containmentParentNode
  16634. this.isAddingAllowed = this.toMoveShapes.all((function(currentShape) {
  16635. if(currentShape instanceof ORYX.Core.Edge ||
  16636. currentShape instanceof ORYX.Core.Controls.Docker ||
  16637. this.containmentParentNode === currentShape.parent) {
  16638. return true;
  16639. } else if(this.containmentParentNode !== currentShape) {
  16640. if(!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) {
  16641. if(this.facade.getRules().canContain({containingShape:this.containmentParentNode,
  16642. containedShape:currentShape})) {
  16643. return true;
  16644. }
  16645. }
  16646. }
  16647. return false;
  16648. }).bind(this));
  16649. }
  16650. if(!this.isAttachingAllowed && !this.isAddingAllowed &&
  16651. (this.containmentParentNode instanceof ORYX.Core.Edge)) {
  16652. options.noEdges = true;
  16653. options.underlyingNodes.reverse();
  16654. this.checkRules(options);
  16655. }
  16656. },
  16657. /**
  16658. * Redraw the selected Shapes.
  16659. *
  16660. */
  16661. refreshSelectedShapes: function() {
  16662. // If the selection bounds not initialized, return
  16663. if(!this.dragBounds) {return}
  16664. // Calculate the offset between the bounds and the old bounds
  16665. var upL = this.dragBounds.upperLeft();
  16666. var oldUpL = this.oldDragBounds.upperLeft();
  16667. var offset = {
  16668. x: upL.x - oldUpL.x,
  16669. y: upL.y - oldUpL.y };
  16670. // Instanciate the dragCommand
  16671. var commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)];
  16672. // If the undocked edges command is setted, add this command
  16673. if( this._undockedEdgesCommand instanceof ORYX.Core.Command ){
  16674. commands.unshift( this._undockedEdgesCommand );
  16675. }
  16676. // Execute the commands
  16677. this.facade.executeCommands( commands );
  16678. // copy the bounds to the old bounds
  16679. if( this.dragBounds )
  16680. this.oldDragBounds = this.dragBounds.clone();
  16681. },
  16682. /**
  16683. * Callback for Resize
  16684. *
  16685. */
  16686. onResize: function(bounds) {
  16687. // If the selection bounds not initialized, return
  16688. if(!this.dragBounds) {return}
  16689. this.dragBounds = bounds;
  16690. this.isResizing = true;
  16691. // Update the rectangle
  16692. this.resizeRectangle(this.dragBounds);
  16693. },
  16694. onResizeStart: function() {
  16695. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_START});
  16696. },
  16697. onResizeEnd: function() {
  16698. if (!(this.currentShapes instanceof Array)||this.currentShapes.length<=0) {
  16699. return;
  16700. }
  16701. // If Resizing finished, the Shapes will be resize
  16702. if(this.isResizing) {
  16703. var commandClass = ORYX.Core.Command.extend({
  16704. construct: function(shape, newBounds, plugin){
  16705. this.shape = shape;
  16706. this.oldBounds = shape.bounds.clone();
  16707. this.newBounds = newBounds;
  16708. this.plugin = plugin;
  16709. },
  16710. execute: function(){
  16711. this.shape.bounds.set(this.newBounds.a, this.newBounds.b);
  16712. this.update(this.getOffset(this.oldBounds, this.newBounds));
  16713. },
  16714. rollback: function(){
  16715. this.shape.bounds.set(this.oldBounds.a, this.oldBounds.b);
  16716. this.update(this.getOffset(this.newBounds, this.oldBounds))
  16717. },
  16718. getOffset:function(b1, b2){
  16719. return {
  16720. x: b2.a.x - b1.a.x,
  16721. y: b2.a.y - b1.a.y,
  16722. xs: b2.width()/b1.width(),
  16723. ys: b2.height()/b1.height()
  16724. }
  16725. },
  16726. update:function(offset){
  16727. this.shape.getLabels().each(function(label) {
  16728. label.changed();
  16729. });
  16730. var allEdges = [].concat(this.shape.getIncomingShapes())
  16731. .concat(this.shape.getOutgoingShapes())
  16732. // Remove all edges which are included in the selection from the list
  16733. .findAll(function(r){ return r instanceof ORYX.Core.Edge }.bind(this))
  16734. this.plugin.layoutEdges(this.shape, allEdges, offset);
  16735. this.plugin.facade.setSelection([this.shape]);
  16736. this.plugin.facade.getCanvas().update();
  16737. this.plugin.facade.updateSelection();
  16738. }
  16739. });
  16740. var bounds = this.dragBounds.clone();
  16741. var shape = this.currentShapes[0];
  16742. if(shape.parent) {
  16743. var parentPosition = shape.parent.absoluteXY();
  16744. bounds.moveBy(-parentPosition.x, -parentPosition.y);
  16745. }
  16746. var command = new commandClass(shape, bounds, this);
  16747. this.facade.executeCommands([command]);
  16748. this.isResizing = false;
  16749. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END});
  16750. }
  16751. },
  16752. /**
  16753. * Prepare the Dragging
  16754. *
  16755. */
  16756. beforeDrag: function(){
  16757. var undockEdgeCommand = ORYX.Core.Command.extend({
  16758. construct: function(moveShapes){
  16759. this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();
  16760. },
  16761. execute: function(){
  16762. this.dockers.each(function(el){
  16763. el.docker.setDockedShape(undefined);
  16764. })
  16765. },
  16766. rollback: function(){
  16767. this.dockers.each(function(el){
  16768. el.docker.setDockedShape(el.dockedShape);
  16769. el.docker.setReferencePoint(el.refPoint);
  16770. //el.docker.update();
  16771. })
  16772. }
  16773. });
  16774. this._undockedEdgesCommand = new undockEdgeCommand( this.toMoveShapes );
  16775. this._undockedEdgesCommand.execute();
  16776. },
  16777. hideAllLabels: function(shape) {
  16778. // Hide all labels from the shape
  16779. shape.getLabels().each(function(label) {
  16780. label.hide();
  16781. });
  16782. // Hide all labels from docked shapes
  16783. shape.getAllDockedShapes().each(function(dockedShape) {
  16784. var labels = dockedShape.getLabels();
  16785. if(labels.length > 0) {
  16786. labels.each(function(label) {
  16787. label.hide();
  16788. });
  16789. }
  16790. });
  16791. // Do this recursive for all child shapes
  16792. // EXP-NICO use getShapes
  16793. shape.getChildren().each((function(value) {
  16794. if(value instanceof ORYX.Core.Shape)
  16795. this.hideAllLabels(value);
  16796. }).bind(this));
  16797. },
  16798. /**
  16799. * Finished the Dragging
  16800. *
  16801. */
  16802. afterDrag: function(){
  16803. },
  16804. /**
  16805. * Show all Labels at these shape
  16806. *
  16807. */
  16808. showAllLabels: function(shape) {
  16809. // Show the label of these shape
  16810. //shape.getLabels().each(function(label) {
  16811. for(var i=0; i<shape.length ;i++){
  16812. var label = shape[i];
  16813. label.show();
  16814. }//);
  16815. // Show all labels at docked shapes
  16816. //shape.getAllDockedShapes().each(function(dockedShape) {
  16817. var allDockedShapes = shape.getAllDockedShapes()
  16818. for(var i=0; i<allDockedShapes.length ;i++){
  16819. var dockedShape = allDockedShapes[i];
  16820. var labels = dockedShape.getLabels();
  16821. if(labels.length > 0) {
  16822. labels.each(function(label) {
  16823. label.show();
  16824. });
  16825. }
  16826. }//);
  16827. // Do this recursive
  16828. //shape.children.each((function(value) {
  16829. for(var i=0; i<shape.children.length ;i++){
  16830. var value = shape.children[i];
  16831. if(value instanceof ORYX.Core.Shape)
  16832. this.showAllLabels(value);
  16833. }//).bind(this));
  16834. },
  16835. /**
  16836. * Intialize Method, if there are new Plugins
  16837. *
  16838. */
  16839. /*registryChanged: function(pluginsData) {
  16840. // Save all new Plugin, sorted by group and index
  16841. this.pluginsData = pluginsData.sortBy( function(value) {
  16842. return (value.group + "" + value.index);
  16843. });
  16844. },*/
  16845. /**
  16846. * On the Selection-Changed
  16847. *
  16848. */
  16849. onSelectionChanged: function(event) {
  16850. var elements = event.elements;
  16851. // Reset the drag-variables
  16852. this.dragEnable = false;
  16853. this.dragIntialized = false;
  16854. this.resizerSE.hide();
  16855. this.resizerNW.hide();
  16856. // If there is no elements
  16857. if(!elements || elements.length == 0) {
  16858. // Hide all things and reset all variables
  16859. this.selectedRect.hide();
  16860. this.currentShapes = [];
  16861. this.toMoveShapes = [];
  16862. this.dragBounds = undefined;
  16863. this.oldDragBounds = undefined;
  16864. } else {
  16865. // Set the current Shapes
  16866. this.currentShapes = elements;
  16867. // Get all shapes with the highest parent in object hierarchy (canvas is the top most parent)
  16868. var topLevelElements = this.facade.getCanvas().getShapesWithSharedParent(elements);
  16869. this.toMoveShapes = topLevelElements;
  16870. this.toMoveShapes = this.toMoveShapes.findAll( function(shape) { return shape instanceof ORYX.Core.Node &&
  16871. (shape.dockers.length === 0 || !elements.member(shape.dockers.first().getDockedShape()))});
  16872. elements.each((function(shape){
  16873. if(!(shape instanceof ORYX.Core.Edge)) {return;}
  16874. var dks = shape.getDockers();
  16875. var hasF = elements.member(dks.first().getDockedShape());
  16876. var hasL = elements.member(dks.last().getDockedShape());
  16877. // if(!hasL) {
  16878. // this.toMoveShapes.push(dks.last());
  16879. // }
  16880. // if(!hasF){
  16881. // this.toMoveShapes.push(dks.first())
  16882. // }
  16883. /* Enable movement of undocked edges */
  16884. if(!hasF && !hasL) {
  16885. var isUndocked = !dks.first().getDockedShape() && !dks.last().getDockedShape();
  16886. if(isUndocked) {
  16887. this.toMoveShapes = this.toMoveShapes.concat(dks);
  16888. }
  16889. }
  16890. if( shape.dockers.length > 2 && hasF && hasL){
  16891. this.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function(el,index){ return index > 0 && index < dks.length-1}));
  16892. }
  16893. }).bind(this));
  16894. // Calculate the new area-bounds of the selection
  16895. var newBounds = undefined;
  16896. this.toMoveShapes.each(function(value) {
  16897. var shape = value;
  16898. if(value instanceof ORYX.Core.Controls.Docker) {
  16899. /* Get the Shape */
  16900. shape = value.parent;
  16901. }
  16902. if(!newBounds){
  16903. newBounds = shape.absoluteBounds();
  16904. }
  16905. else {
  16906. newBounds.include(shape.absoluteBounds());
  16907. }
  16908. }.bind(this));
  16909. if(!newBounds){
  16910. elements.each(function(value){
  16911. if(!newBounds) {
  16912. newBounds = value.absoluteBounds();
  16913. } else {
  16914. newBounds.include(value.absoluteBounds());
  16915. }
  16916. });
  16917. }
  16918. // Set the new bounds
  16919. this.dragBounds = newBounds;
  16920. this.oldDragBounds = newBounds.clone();
  16921. // Update and show the rectangle
  16922. this.resizeRectangle(newBounds);
  16923. this.selectedRect.show();
  16924. // Show the resize button, if there is only one element and this is resizeable
  16925. if(elements.length == 1 && elements[0].isResizable) {
  16926. var aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined;
  16927. this.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);
  16928. this.resizerSE.show();
  16929. this.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);
  16930. this.resizerNW.show();
  16931. } else {
  16932. this.resizerSE.setBounds(undefined);
  16933. this.resizerNW.setBounds(undefined);
  16934. }
  16935. // If Snap-To-Grid is enabled, the Snap-Point will be calculate
  16936. if(ORYX.CONFIG.GRID_ENABLED) {
  16937. // Reset all points
  16938. this.distPoints = [];
  16939. if (this.distPointTimeout)
  16940. window.clearTimeout(this.distPointTimeout)
  16941. this.distPointTimeout = window.setTimeout(function(){
  16942. // Get all the shapes, there will consider at snapping
  16943. // Consider only those elements who shares the same parent element
  16944. var distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function(value){
  16945. var parentShape = value.parent;
  16946. while(parentShape){
  16947. if(elements.member(parentShape)) return false;
  16948. parentShape = parentShape.parent
  16949. }
  16950. return true;
  16951. })
  16952. // The current selection will delete from this array
  16953. //elements.each(function(shape) {
  16954. // distShapes = distShapes.without(shape);
  16955. //});
  16956. // For all these shapes
  16957. distShapes.each((function(value) {
  16958. if(!(value instanceof ORYX.Core.Edge)) {
  16959. var ul = value.absoluteXY();
  16960. var width = value.bounds.width();
  16961. var height = value.bounds.height();
  16962. // Add the upperLeft, center and lowerRight - Point to the distancePoints
  16963. this.distPoints.push({
  16964. ul: {
  16965. x: ul.x,
  16966. y: ul.y
  16967. },
  16968. c: {
  16969. x: ul.x + (width / 2),
  16970. y: ul.y + (height / 2)
  16971. },
  16972. lr: {
  16973. x: ul.x + width,
  16974. y: ul.y + height
  16975. }
  16976. });
  16977. }
  16978. }).bind(this));
  16979. }.bind(this), 10)
  16980. }
  16981. }
  16982. },
  16983. /**
  16984. * Adjust an Point to the Snap Points
  16985. *
  16986. */
  16987. snapToGrid: function(position) {
  16988. // Get the current Bounds
  16989. var bounds = this.dragBounds;
  16990. var point = {};
  16991. var ulThres = 6;
  16992. var cThres = 10;
  16993. var lrThres = 6;
  16994. var scale = this.vLine ? this.vLine.getScale() : 1;
  16995. var ul = { x: (position.x/scale), y: (position.y/scale)};
  16996. var c = { x: (position.x/scale) + (bounds.width()/2), y: (position.y/scale) + (bounds.height()/2)};
  16997. var lr = { x: (position.x/scale) + (bounds.width()), y: (position.y/scale) + (bounds.height())};
  16998. var offsetX, offsetY;
  16999. var gridX, gridY;
  17000. // For each distant point
  17001. this.distPoints.each(function(value) {
  17002. var x, y, gx, gy;
  17003. if (Math.abs(value.c.x-c.x) < cThres){
  17004. x = value.c.x-c.x;
  17005. gx = value.c.x;
  17006. }/* else if (Math.abs(value.ul.x-ul.x) < ulThres){
  17007. x = value.ul.x-ul.x;
  17008. gx = value.ul.x;
  17009. } else if (Math.abs(value.lr.x-lr.x) < lrThres){
  17010. x = value.lr.x-lr.x;
  17011. gx = value.lr.x;
  17012. } */
  17013. if (Math.abs(value.c.y-c.y) < cThres){
  17014. y = value.c.y-c.y;
  17015. gy = value.c.y;
  17016. }/* else if (Math.abs(value.ul.y-ul.y) < ulThres){
  17017. y = value.ul.y-ul.y;
  17018. gy = value.ul.y;
  17019. } else if (Math.abs(value.lr.y-lr.y) < lrThres){
  17020. y = value.lr.y-lr.y;
  17021. gy = value.lr.y;
  17022. } */
  17023. if (x !== undefined) {
  17024. offsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX);
  17025. if (offsetX === x)
  17026. gridX = gx;
  17027. }
  17028. if (y !== undefined) {
  17029. offsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY);
  17030. if (offsetY === y)
  17031. gridY = gy;
  17032. }
  17033. });
  17034. if (offsetX !== undefined) {
  17035. ul.x += offsetX;
  17036. ul.x *= scale;
  17037. if (this.vLine&&gridX)
  17038. this.vLine.update(gridX);
  17039. } else {
  17040. ul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE/2)));
  17041. if (this.vLine)
  17042. this.vLine.hide()
  17043. }
  17044. if (offsetY !== undefined) {
  17045. ul.y += offsetY;
  17046. ul.y *= scale;
  17047. if (this.hLine&&gridY)
  17048. this.hLine.update(gridY);
  17049. } else {
  17050. ul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE/2)));
  17051. if (this.hLine)
  17052. this.hLine.hide();
  17053. }
  17054. return ul;
  17055. },
  17056. showGridLine: function(){
  17057. },
  17058. /**
  17059. * Redraw of the Rectangle of the SelectedArea
  17060. * @param {Object} bounds
  17061. */
  17062. resizeRectangle: function(bounds) {
  17063. // Resize the Rectangle
  17064. this.selectedRect.resize(bounds);
  17065. }
  17066. });
  17067. ORYX.Plugins.SelectedRect = Clazz.extend({
  17068. construct: function(parentId) {
  17069. this.parentId = parentId;
  17070. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", $(parentId),
  17071. ['g']);
  17072. this.dashedArea = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
  17073. ['rect', {x: 0, y: 0,
  17074. 'stroke-width': 1, stroke: '#777777', fill: 'none',
  17075. 'stroke-dasharray': '2,2',
  17076. 'pointer-events': 'none'}]);
  17077. this.hide();
  17078. },
  17079. hide: function() {
  17080. this.node.setAttributeNS(null, 'display', 'none');
  17081. },
  17082. show: function() {
  17083. this.node.setAttributeNS(null, 'display', '');
  17084. },
  17085. resize: function(bounds) {
  17086. var upL = bounds.upperLeft();
  17087. var padding = ORYX.CONFIG.SELECTED_AREA_PADDING;
  17088. this.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2*padding);
  17089. this.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2*padding);
  17090. this.node.setAttributeNS(null, 'transform', "translate("+ (upL.x - padding) +", "+ (upL.y - padding) +")");
  17091. }
  17092. });
  17093. ORYX.Plugins.GridLine = Clazz.extend({
  17094. construct: function(parentId, direction) {
  17095. if (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) {
  17096. direction = ORYX.Plugins.GridLine.DIR_HORIZONTAL
  17097. }
  17098. this.parent = $(parentId);
  17099. this.direction = direction;
  17100. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parent,
  17101. ['g']);
  17102. this.line = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
  17103. ['path', {
  17104. 'stroke-width': 1, stroke: 'silver', fill: 'none',
  17105. 'stroke-dasharray': '5,5',
  17106. 'pointer-events': 'none'}]);
  17107. this.hide();
  17108. },
  17109. hide: function() {
  17110. this.node.setAttributeNS(null, 'display', 'none');
  17111. },
  17112. show: function() {
  17113. this.node.setAttributeNS(null, 'display', '');
  17114. },
  17115. getScale: function(){
  17116. try {
  17117. return this.parent.parentNode.transform.baseVal.getItem(0).matrix.a;
  17118. } catch(e) {
  17119. return 1;
  17120. }
  17121. },
  17122. update: function(pos) {
  17123. if (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) {
  17124. var y = pos instanceof Object ? pos.y : pos;
  17125. var cWidth = this.parent.parentNode.parentNode.width.baseVal.value/this.getScale();
  17126. this.line.setAttributeNS(null, 'd', 'M 0 '+y+ ' L '+cWidth+' '+y);
  17127. } else {
  17128. var x = pos instanceof Object ? pos.x : pos;
  17129. var cHeight = this.parent.parentNode.parentNode.height.baseVal.value/this.getScale();
  17130. this.line.setAttributeNS(null, 'd', 'M'+x+ ' 0 L '+x+' '+cHeight);
  17131. }
  17132. this.show();
  17133. }
  17134. });
  17135. ORYX.Plugins.GridLine.DIR_HORIZONTAL = "hor";
  17136. ORYX.Plugins.GridLine.DIR_VERTICAL = "ver";
  17137. ORYX.Plugins.Resizer = Clazz.extend({
  17138. construct: function(parentId, orientation, facade) {
  17139. this.parentId = parentId;
  17140. this.orientation = orientation;
  17141. this.facade = facade;
  17142. this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $('canvasSection'),
  17143. ['div', {'class': 'resizer_'+ this.orientation, style:'left:0px; top:0px;position:absolute;'}]);
  17144. this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this), true);
  17145. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);
  17146. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.handleMouseMove.bind(this), false);
  17147. this.dragEnable = false;
  17148. this.offSetPosition = {x: 0, y: 0};
  17149. this.bounds = undefined;
  17150. this.canvasNode = this.facade.getCanvas().node;
  17151. this.minSize = undefined;
  17152. this.maxSize = undefined;
  17153. this.aspectRatio = undefined;
  17154. this.resizeCallbacks = [];
  17155. this.resizeStartCallbacks = [];
  17156. this.resizeEndCallbacks = [];
  17157. this.hide();
  17158. // Calculate the Offset
  17159. this.scrollNode = this.node.parentNode.parentNode.parentNode;
  17160. },
  17161. handleMouseDown: function(event) {
  17162. this.dragEnable = true;
  17163. this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
  17164. this.offSetPosition = {
  17165. x: Event.pointerX(event) - this.position.x,
  17166. y: Event.pointerY(event) - this.position.y};
  17167. this.resizeStartCallbacks.each((function(value) {
  17168. value(this.bounds);
  17169. }).bind(this));
  17170. },
  17171. handleMouseUp: function(event) {
  17172. this.dragEnable = false;
  17173. this.containmentParentNode = null;
  17174. this.resizeEndCallbacks.each((function(value) {
  17175. value(this.bounds);
  17176. }).bind(this));
  17177. },
  17178. handleMouseMove: function(event) {
  17179. if(!this.dragEnable) { return }
  17180. if(event.shiftKey || event.ctrlKey) {
  17181. this.aspectRatio = this.bounds.width() / this.bounds.height();
  17182. } else {
  17183. this.aspectRatio = undefined;
  17184. }
  17185. var position = {
  17186. x: Event.pointerX(event) - this.offSetPosition.x,
  17187. y: Event.pointerY(event) - this.offSetPosition.y};
  17188. position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
  17189. position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
  17190. position.x = Math.min( position.x, this.facade.getCanvas().bounds.width());
  17191. position.y = Math.min( position.y, this.facade.getCanvas().bounds.height());
  17192. var offset = {
  17193. x: position.x - this.position.x,
  17194. y: position.y - this.position.y
  17195. };
  17196. if(this.aspectRatio) {
  17197. // fixed aspect ratio
  17198. newAspectRatio = (this.bounds.width()+offset.x) / (this.bounds.height()+offset.y);
  17199. if(newAspectRatio>this.aspectRatio) {
  17200. offset.x = this.aspectRatio * (this.bounds.height()+offset.y) - this.bounds.width();
  17201. } else if(newAspectRatio<this.aspectRatio) {
  17202. offset.y = (this.bounds.width()+offset.x) / this.aspectRatio - this.bounds.height();
  17203. }
  17204. }
  17205. // respect minimum and maximum sizes of stencil
  17206. if(this.orientation==="northwest") {
  17207. if(this.bounds.width()-offset.x > this.maxSize.width) {
  17208. offset.x = -(this.maxSize.width - this.bounds.width());
  17209. if(this.aspectRatio)
  17210. offset.y = this.aspectRatio * offset.x;
  17211. }
  17212. if(this.bounds.width()-offset.x < this.minSize.width) {
  17213. offset.x = -(this.minSize.width - this.bounds.width());
  17214. if(this.aspectRatio)
  17215. offset.y = this.aspectRatio * offset.x;
  17216. }
  17217. if(this.bounds.height()-offset.y > this.maxSize.height) {
  17218. offset.y = -(this.maxSize.height - this.bounds.height());
  17219. if(this.aspectRatio)
  17220. offset.x = offset.y / this.aspectRatio;
  17221. }
  17222. if(this.bounds.height()-offset.y < this.minSize.height) {
  17223. offset.y = -(this.minSize.height - this.bounds.height());
  17224. if(this.aspectRatio)
  17225. offset.x = offset.y / this.aspectRatio;
  17226. }
  17227. } else { // defaults to southeast
  17228. if(this.bounds.width()+offset.x > this.maxSize.width) {
  17229. offset.x = this.maxSize.width - this.bounds.width();
  17230. if(this.aspectRatio)
  17231. offset.y = this.aspectRatio * offset.x;
  17232. }
  17233. if(this.bounds.width()+offset.x < this.minSize.width) {
  17234. offset.x = this.minSize.width - this.bounds.width();
  17235. if(this.aspectRatio)
  17236. offset.y = this.aspectRatio * offset.x;
  17237. }
  17238. if(this.bounds.height()+offset.y > this.maxSize.height) {
  17239. offset.y = this.maxSize.height - this.bounds.height();
  17240. if(this.aspectRatio)
  17241. offset.x = offset.y / this.aspectRatio;
  17242. }
  17243. if(this.bounds.height()+offset.y < this.minSize.height) {
  17244. offset.y = this.minSize.height - this.bounds.height();
  17245. if(this.aspectRatio)
  17246. offset.x = offset.y / this.aspectRatio;
  17247. }
  17248. }
  17249. if(this.orientation==="northwest") {
  17250. this.bounds.extend({x:-offset.x, y:-offset.y});
  17251. this.bounds.moveBy(offset);
  17252. } else { // defaults to southeast
  17253. this.bounds.extend(offset);
  17254. }
  17255. this.update();
  17256. this.resizeCallbacks.each((function(value) {
  17257. value(this.bounds);
  17258. }).bind(this));
  17259. Event.stop(event);
  17260. },
  17261. registerOnResizeStart: function(callback) {
  17262. if(!this.resizeStartCallbacks.member(callback)) {
  17263. this.resizeStartCallbacks.push(callback);
  17264. }
  17265. },
  17266. unregisterOnResizeStart: function(callback) {
  17267. if(this.resizeStartCallbacks.member(callback)) {
  17268. this.resizeStartCallbacks = this.resizeStartCallbacks.without(callback);
  17269. }
  17270. },
  17271. registerOnResizeEnd: function(callback) {
  17272. if(!this.resizeEndCallbacks.member(callback)) {
  17273. this.resizeEndCallbacks.push(callback);
  17274. }
  17275. },
  17276. unregisterOnResizeEnd: function(callback) {
  17277. if(this.resizeEndCallbacks.member(callback)) {
  17278. this.resizeEndCallbacks = this.resizeEndCallbacks.without(callback);
  17279. }
  17280. },
  17281. registerOnResize: function(callback) {
  17282. if(!this.resizeCallbacks.member(callback)) {
  17283. this.resizeCallbacks.push(callback);
  17284. }
  17285. },
  17286. unregisterOnResize: function(callback) {
  17287. if(this.resizeCallbacks.member(callback)) {
  17288. this.resizeCallbacks = this.resizeCallbacks.without(callback);
  17289. }
  17290. },
  17291. hide: function() {
  17292. this.node.style.display = "none";
  17293. },
  17294. show: function() {
  17295. if(this.bounds)
  17296. this.node.style.display = "";
  17297. },
  17298. setBounds: function(bounds, min, max, aspectRatio) {
  17299. this.bounds = bounds;
  17300. if(!min)
  17301. min = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE};
  17302. if(!max)
  17303. max = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};
  17304. this.minSize = min;
  17305. this.maxSize = max;
  17306. this.aspectRatio = aspectRatio;
  17307. this.update();
  17308. },
  17309. update: function() {
  17310. if(!this.bounds) { return; }
  17311. var upL = this.bounds.upperLeft();
  17312. if(this.bounds.width() < this.minSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height());};
  17313. if(this.bounds.height() < this.minSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height);};
  17314. if(this.bounds.width() > this.maxSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height());};
  17315. if(this.bounds.height() > this.maxSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height);};
  17316. var a = this.canvasNode.getScreenCTM();
  17317. upL.x *= a.a;
  17318. upL.y *= a.d;
  17319. var additionalIEZoom = 1;
  17320. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  17321. var ua = navigator.userAgent;
  17322. if (ua.indexOf('MSIE') >= 0) {
  17323. //IE 10 and below
  17324. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  17325. if (zoom !== 100) {
  17326. additionalIEZoom = zoom / 100
  17327. }
  17328. }
  17329. }
  17330. if (additionalIEZoom === 1) {
  17331. upL.y = upL.y - jQuery("#canvasSection").offset().top + a.f;
  17332. upL.x = upL.x - jQuery("#canvasSection").offset().left + a.e;
  17333. } else {
  17334. var canvasOffsetLeft = jQuery("#canvasSection").offset().left;
  17335. var canvasScrollLeft = jQuery("#canvasSection").scrollLeft();
  17336. var canvasScrollTop = jQuery("#canvasSection").scrollTop();
  17337. var offset = a.e - (canvasOffsetLeft * additionalIEZoom);
  17338. var additionaloffset = 0;
  17339. if (offset > 10) {
  17340. additionaloffset = (offset / additionalIEZoom) - offset;
  17341. }
  17342. upL.y = upL.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop) + a.f;
  17343. upL.x = upL.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft) + a.e;
  17344. }
  17345. if(this.orientation==="northwest") {
  17346. upL.x -= 13;
  17347. upL.y -= 13;
  17348. } else { // defaults to southeast
  17349. upL.x += (a.a * this.bounds.width()) + 3 ;
  17350. upL.y += (a.d * this.bounds.height()) + 3;
  17351. }
  17352. this.position = upL;
  17353. this.node.style.left = this.position.x + "px";
  17354. this.node.style.top = this.position.y + "px";
  17355. }
  17356. });
  17357. /**
  17358. * Implements a Command to move shapes
  17359. *
  17360. */
  17361. ORYX.Core.Command.Move = ORYX.Core.Command.extend({
  17362. construct: function(moveShapes, offset, parent, selectedShapes, plugin){
  17363. this.moveShapes = moveShapes;
  17364. this.selectedShapes = selectedShapes;
  17365. this.offset = offset;
  17366. this.plugin = plugin;
  17367. // Defines the old/new parents for the particular shape
  17368. this.newParents = moveShapes.collect(function(t){ return parent || t.parent });
  17369. this.oldParents = moveShapes.collect(function(shape){ return shape.parent });
  17370. this.dockedNodes= moveShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Node && shape.dockers.length == 1}).collect(function(shape){ return {docker:shape.dockers[0], dockedShape:shape.dockers[0].getDockedShape(), refPoint:shape.dockers[0].referencePoint} });
  17371. },
  17372. execute: function(){
  17373. this.dockAllShapes()
  17374. // Moves by the offset
  17375. this.move( this.offset);
  17376. // Addes to the new parents
  17377. this.addShapeToParent( this.newParents );
  17378. // Set the selection to the current selection
  17379. this.selectCurrentShapes();
  17380. this.plugin.facade.getCanvas().update();
  17381. this.plugin.facade.updateSelection();
  17382. },
  17383. rollback: function(){
  17384. // Moves by the inverted offset
  17385. var offset = { x:-this.offset.x, y:-this.offset.y };
  17386. this.move( offset );
  17387. // Addes to the old parents
  17388. this.addShapeToParent( this.oldParents );
  17389. this.dockAllShapes(true)
  17390. // Set the selection to the current selection
  17391. this.selectCurrentShapes();
  17392. this.plugin.facade.getCanvas().update();
  17393. this.plugin.facade.updateSelection();
  17394. },
  17395. move:function(offset, doLayout){
  17396. // Move all Shapes by these offset
  17397. for(var i=0; i<this.moveShapes.length ;i++){
  17398. var value = this.moveShapes[i];
  17399. value.bounds.moveBy(offset);
  17400. if (value instanceof ORYX.Core.Node) {
  17401. (value.dockers||[]).each(function(d){
  17402. d.bounds.moveBy(offset);
  17403. })
  17404. // Update all Dockers of Child shapes
  17405. /*var childShapesNodes = value.getChildShapes(true).findAll(function(shape){ return shape instanceof ORYX.Core.Node });
  17406. var childDockedShapes = childShapesNodes.collect(function(shape){ return shape.getAllDockedShapes() }).flatten().uniq();
  17407. var childDockedEdge = childDockedShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Edge });
  17408. childDockedEdge = childDockedEdge.findAll(function(shape){ return shape.getAllDockedShapes().all(function(dsh){ return childShapesNodes.include(dsh) }) });
  17409. var childDockedDockers = childDockedEdge.collect(function(shape){ return shape.dockers }).flatten();
  17410. for (var j = 0; j < childDockedDockers.length; j++) {
  17411. var docker = childDockedDockers[j];
  17412. if (!docker.getDockedShape() && !this.moveShapes.include(docker)) {
  17413. //docker.bounds.moveBy(offset);
  17414. //docker.update();
  17415. }
  17416. }*/
  17417. var allEdges = [].concat(value.getIncomingShapes())
  17418. .concat(value.getOutgoingShapes())
  17419. // Remove all edges which are included in the selection from the list
  17420. .findAll(function(r){ return r instanceof ORYX.Core.Edge && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))
  17421. // Remove all edges which are between the node and a node contained in the selection from the list
  17422. .findAll(function(r){ return (r.dockers.first().getDockedShape() == value || !this.moveShapes.include(r.dockers.first().getDockedShape())) &&
  17423. (r.dockers.last().getDockedShape() == value || !this.moveShapes.include(r.dockers.last().getDockedShape()))}.bind(this))
  17424. // Layout all outgoing/incoming edges
  17425. this.plugin.layoutEdges(value, allEdges, offset);
  17426. var allSameEdges = [].concat(value.getIncomingShapes())
  17427. .concat(value.getOutgoingShapes())
  17428. // Remove all edges which are included in the selection from the list
  17429. .findAll(function(r){ return r instanceof ORYX.Core.Edge && r.dockers.first().isDocked() && r.dockers.last().isDocked() && !this.moveShapes.include(r) && !this.moveShapes.any(function(d){ return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r)}) }.bind(this))
  17430. // Remove all edges which are included in the selection from the list
  17431. .findAll(function(r){ return this.moveShapes.indexOf(r.dockers.first().getDockedShape()) > i || this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i}.bind(this))
  17432. for (var j = 0; j < allSameEdges.length; j++) {
  17433. for (var k = 1; k < allSameEdges[j].dockers.length-1; k++) {
  17434. var docker = allSameEdges[j].dockers[k];
  17435. if (!docker.getDockedShape() && !this.moveShapes.include(docker)) {
  17436. docker.bounds.moveBy(offset);
  17437. }
  17438. }
  17439. }
  17440. /*var i=-1;
  17441. var nodes = value.getChildShapes(true);
  17442. var allEdges = [];
  17443. while(++i<nodes.length){
  17444. var edges = [].concat(nodes[i].getIncomingShapes())
  17445. .concat(nodes[i].getOutgoingShapes())
  17446. // Remove all edges which are included in the selection from the list
  17447. .findAll(function(r){ return r instanceof ORYX.Core.Edge && !allEdges.include(r) && r.dockers.any(function(d){ return !value.bounds.isIncluded(d.bounds.center)})})
  17448. allEdges = allEdges.concat(edges);
  17449. if (edges.length <= 0){ continue }
  17450. //this.plugin.layoutEdges(nodes[i], edges, offset);
  17451. }*/
  17452. }
  17453. }
  17454. },
  17455. dockAllShapes: function(shouldDocked){
  17456. // Undock all Nodes
  17457. for (var i = 0; i < this.dockedNodes.length; i++) {
  17458. var docker = this.dockedNodes[i].docker;
  17459. docker.setDockedShape( shouldDocked ? this.dockedNodes[i].dockedShape : undefined )
  17460. if (docker.getDockedShape()) {
  17461. docker.setReferencePoint(this.dockedNodes[i].refPoint);
  17462. //docker.update();
  17463. }
  17464. }
  17465. },
  17466. addShapeToParent:function( parents ){
  17467. // For every Shape, add this and reset the position
  17468. for(var i=0; i<this.moveShapes.length ;i++){
  17469. var currentShape = this.moveShapes[i];
  17470. if(currentShape instanceof ORYX.Core.Node &&
  17471. currentShape.parent !== parents[i]) {
  17472. // Calc the new position
  17473. var unul = parents[i].absoluteXY();
  17474. var csul = currentShape.absoluteXY();
  17475. var x = csul.x - unul.x;
  17476. var y = csul.y - unul.y;
  17477. // Add the shape to the new contained shape
  17478. parents[i].add(currentShape);
  17479. // Add all attached shapes as well
  17480. currentShape.getOutgoingShapes((function(shape) {
  17481. if(shape instanceof ORYX.Core.Node && !this.moveShapes.member(shape)) {
  17482. parents[i].add(shape);
  17483. }
  17484. }).bind(this));
  17485. // Set the new position
  17486. if(currentShape instanceof ORYX.Core.Node && currentShape.dockers.length == 1){
  17487. var b = currentShape.bounds;
  17488. x += b.width()/2;y += b.height()/2
  17489. currentShape.dockers.first().bounds.centerMoveTo(x, y);
  17490. } else {
  17491. currentShape.bounds.moveTo(x, y);
  17492. }
  17493. }
  17494. // Update the shape
  17495. //currentShape.update();
  17496. }
  17497. },
  17498. selectCurrentShapes:function(){
  17499. this.plugin.facade.setSelection( this.selectedShapes );
  17500. }
  17501. });
  17502. /*
  17503. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  17504. * License rights for this program may be obtained from Alfresco Software, Ltd.
  17505. * pursuant to a written agreement and any use of this program without such an
  17506. * agreement is prohibited.
  17507. */
  17508. /*
  17509. * All code Copyright 2013 KIS Consultancy all rights reserved
  17510. */
  17511. if(!ORYX.Plugins)
  17512. ORYX.Plugins = new Object();
  17513. ORYX.Plugins.DragDocker = Clazz.extend({
  17514. /**
  17515. * Constructor
  17516. * @param {Object} Facade: The Facade of the Editor
  17517. */
  17518. construct: function(facade) {
  17519. this.facade = facade;
  17520. // Set the valid and invalid color
  17521. this.VALIDCOLOR = ORYX.CONFIG.SELECTION_VALID_COLOR;
  17522. this.INVALIDCOLOR = ORYX.CONFIG.SELECTION_INVALID_COLOR;
  17523. // Define Variables
  17524. this.shapeSelection = undefined;
  17525. this.docker = undefined;
  17526. this.dockerParent = undefined;
  17527. this.dockerSource = undefined;
  17528. this.dockerTarget = undefined;
  17529. this.lastUIObj = undefined;
  17530. this.isStartDocker = undefined;
  17531. this.isEndDocker = undefined;
  17532. this.undockTreshold = 10;
  17533. this.initialDockerPosition = undefined;
  17534. this.outerDockerNotMoved = undefined;
  17535. this.isValid = false;
  17536. // For the Drag and Drop
  17537. // Register on MouseDown-Event on a Docker
  17538. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
  17539. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG, this.handleDockerDrag.bind(this));
  17540. // Register on over/out to show / hide a docker
  17541. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER, this.handleMouseOver.bind(this));
  17542. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT, this.handleMouseOut.bind(this));
  17543. },
  17544. /**
  17545. * MouseOut Handler
  17546. *
  17547. */
  17548. handleMouseOut: function(event, uiObj) {
  17549. // If there is a Docker, hide this
  17550. if(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {
  17551. uiObj.hide();
  17552. } else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {
  17553. uiObj.dockers.each(function(docker){
  17554. docker.hide();
  17555. });
  17556. }
  17557. },
  17558. /**
  17559. * MouseOver Handler
  17560. *
  17561. */
  17562. handleMouseOver: function(event, uiObj) {
  17563. // If there is a Docker, show this
  17564. if(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {
  17565. uiObj.show();
  17566. } else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {
  17567. uiObj.dockers.each(function(docker){
  17568. docker.show();
  17569. });
  17570. }
  17571. },
  17572. /**
  17573. * DockerDrag Handler
  17574. * delegates the uiEvent of the drag event to the mouseDown function
  17575. */
  17576. handleDockerDrag: function(event, uiObj) {
  17577. this.handleMouseDown(event.uiEvent, uiObj);
  17578. },
  17579. /**
  17580. * MouseDown Handler
  17581. *
  17582. */
  17583. handleMouseDown: function(event, uiObj) {
  17584. // If there is a Docker
  17585. if(uiObj instanceof ORYX.Core.Controls.Docker && uiObj.isMovable) {
  17586. /* Buffering shape selection and clear selection*/
  17587. this.shapeSelection = this.facade.getSelection();
  17588. this.facade.setSelection();
  17589. this.docker = uiObj;
  17590. this.initialDockerPosition = this.docker.bounds.center();
  17591. this.outerDockerNotMoved = false;
  17592. this.dockerParent = uiObj.parent;
  17593. // Define command arguments
  17594. this._commandArg = {docker:uiObj, dockedShape:uiObj.getDockedShape(), refPoint:uiObj.referencePoint || uiObj.bounds.center()};
  17595. // Show the Docker
  17596. this.docker.show();
  17597. // If the Dockers Parent is an Edge,
  17598. // and the Docker is either the first or last Docker of the Edge
  17599. if(uiObj.parent instanceof ORYX.Core.Edge &&
  17600. (uiObj.parent.dockers.first() == uiObj || uiObj.parent.dockers.last() == uiObj)) {
  17601. // Get the Edge Source or Target
  17602. if(uiObj.parent.dockers.first() == uiObj && uiObj.parent.dockers.last().getDockedShape()) {
  17603. this.dockerTarget = uiObj.parent.dockers.last().getDockedShape();
  17604. } else if(uiObj.parent.dockers.last() == uiObj && uiObj.parent.dockers.first().getDockedShape()) {
  17605. this.dockerSource = uiObj.parent.dockers.first().getDockedShape();
  17606. }
  17607. } else {
  17608. // If there parent is not an Edge, undefined the Source and Target
  17609. this.dockerSource = undefined;
  17610. this.dockerTarget = undefined;
  17611. }
  17612. this.isStartDocker = this.docker.parent.dockers.first() === this.docker;
  17613. this.isEndDocker = this.docker.parent.dockers.last() === this.docker;
  17614. // add to canvas while dragging
  17615. this.facade.getCanvas().add(this.docker.parent);
  17616. // Hide all Labels from Docker
  17617. this.docker.parent.getLabels().each(function(label) {
  17618. label.hide();
  17619. });
  17620. var eventCoordinates = this.facade.eventCoordinates(event);
  17621. var additionalIEZoom = 1;
  17622. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  17623. var ua = navigator.userAgent;
  17624. if (ua.indexOf('MSIE') >= 0) {
  17625. //IE 10 and below
  17626. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  17627. if (zoom !== 100) {
  17628. additionalIEZoom = zoom / 100
  17629. }
  17630. }
  17631. }
  17632. if (additionalIEZoom !== 1) {
  17633. eventCoordinates.x = eventCoordinates.x / additionalIEZoom;
  17634. eventCoordinates.y = eventCoordinates.y / additionalIEZoom;
  17635. }
  17636. // Undocked the Docker from current Shape
  17637. if ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) {
  17638. this.docker.setDockedShape(undefined);
  17639. // Set the Docker to the center of the mouse pointer
  17640. this.docker.bounds.centerMoveTo(eventCoordinates);
  17641. this.dockerParent._update();
  17642. } else {
  17643. this.outerDockerNotMoved = true;
  17644. }
  17645. var option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)};
  17646. this.startEventPos = eventCoordinates;
  17647. // Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with
  17648. ORYX.Core.UIEnableDrag(event, uiObj, option);
  17649. }
  17650. },
  17651. /**
  17652. * Docker MouseMove Handler
  17653. *
  17654. */
  17655. dockerMoved: function(event) {
  17656. this.outerDockerNotMoved = false;
  17657. var snapToMagnet = undefined;
  17658. if (this.docker.parent) {
  17659. if (this.isStartDocker || this.isEndDocker) {
  17660. // Get the EventPosition and all Shapes on these point
  17661. var evPos = this.facade.eventCoordinates(event);
  17662. var additionalIEZoom = 1;
  17663. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  17664. var ua = navigator.userAgent;
  17665. if (ua.indexOf('MSIE') >= 0) {
  17666. //IE 10 and below
  17667. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  17668. if (zoom !== 100) {
  17669. additionalIEZoom = zoom / 100
  17670. }
  17671. }
  17672. }
  17673. if (additionalIEZoom !== 1) {
  17674. evPos.x = evPos.x / additionalIEZoom;
  17675. evPos.y = evPos.y / additionalIEZoom;
  17676. }
  17677. if(this.docker.isDocked()) {
  17678. /* Only consider start/end dockers if they are moved over a treshold */
  17679. var distanceDockerPointer =
  17680. ORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition);
  17681. if(distanceDockerPointer < this.undockTreshold) {
  17682. this.outerDockerNotMoved = true;
  17683. return;
  17684. }
  17685. /* Undock the docker */
  17686. this.docker.setDockedShape(undefined);
  17687. // Set the Docker to the center of the mouse pointer
  17688. //this.docker.bounds.centerMoveTo(evPos);
  17689. this.dockerParent._update();
  17690. }
  17691. var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);
  17692. // Get the top level Shape on these, but not the same as Dockers parent
  17693. var uiObj = shapes.pop();
  17694. if (this.docker.parent === uiObj) {
  17695. uiObj = shapes.pop();
  17696. }
  17697. // If the top level Shape the same as the last Shape, then return
  17698. if (this.lastUIObj == uiObj) {
  17699. //return;
  17700. // If the top level uiObj instance of Shape and this isn't the parent of the docker
  17701. }
  17702. else
  17703. if (uiObj instanceof ORYX.Core.Shape) {
  17704. // Ask by the StencilSet if the source, the edge and the target valid connections.
  17705. if (this.docker.parent instanceof ORYX.Core.Edge) {
  17706. var highestParent = this.getHighestParentBeforeCanvas(uiObj);
  17707. /* Ensure that the shape to dock is not a child shape
  17708. * of the same edge.
  17709. */
  17710. if (highestParent instanceof ORYX.Core.Edge && this.docker.parent === highestParent)
  17711. {
  17712. this.isValid = false;
  17713. this.dockerParent._update();
  17714. return;
  17715. }
  17716. this.isValid = false;
  17717. var curObj = uiObj, orgObj = uiObj;
  17718. while (!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas))
  17719. {
  17720. uiObj = curObj;
  17721. this.isValid = this.facade.getRules().canConnect({
  17722. sourceShape: this.dockerSource ? // Is there a docked source
  17723. this.dockerSource : // than set this
  17724. (this.isStartDocker ? // if not and if the Docker is the start docker
  17725. uiObj : // take the last uiObj
  17726. undefined), // if not set it to undefined;
  17727. edgeShape: this.docker.parent,
  17728. targetShape: this.dockerTarget ? // Is there a docked target
  17729. this.dockerTarget : // than set this
  17730. (this.isEndDocker ? // if not and if the Docker is not the start docker
  17731. uiObj : // take the last uiObj
  17732. undefined) // if not set it to undefined;
  17733. });
  17734. curObj = curObj.parent;
  17735. }
  17736. // Reset uiObj if no
  17737. // valid parent is found
  17738. if (!this.isValid){
  17739. uiObj = orgObj;
  17740. }
  17741. }
  17742. else {
  17743. this.isValid = this.facade.getRules().canConnect({
  17744. sourceShape: uiObj,
  17745. edgeShape: this.docker.parent,
  17746. targetShape: this.docker.parent
  17747. });
  17748. }
  17749. // If there is a lastUIObj, hide the magnets
  17750. if (this.lastUIObj) {
  17751. this.hideMagnets(this.lastUIObj);
  17752. }
  17753. // If there is a valid connection, show the magnets
  17754. if (this.isValid) {
  17755. this.showMagnets(uiObj);
  17756. }
  17757. // Set the Highlight Rectangle by these value
  17758. this.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR);
  17759. // Buffer the current Shape
  17760. this.lastUIObj = uiObj;
  17761. }
  17762. else {
  17763. // If there is no top level Shape, then hide the highligting of the last Shape
  17764. this.hideHighlight();
  17765. this.lastUIObj ? this.hideMagnets(this.lastUIObj) : null;
  17766. this.lastUIObj = undefined;
  17767. this.isValid = false;
  17768. }
  17769. // Snap to the nearest Magnet
  17770. if (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) {
  17771. snapToMagnet = this.lastUIObj.magnets.find(function(magnet){
  17772. return magnet.absoluteBounds().isIncluded(evPos);
  17773. });
  17774. if (snapToMagnet) {
  17775. this.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY());
  17776. //this.docker.update()
  17777. }
  17778. }
  17779. }
  17780. }
  17781. // Snap to on the nearest Docker of the same parent
  17782. if(!(event.shiftKey || event.ctrlKey) && !snapToMagnet) {
  17783. var minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET;
  17784. var nearestX = minOffset + 1;
  17785. var nearestY = minOffset + 1;
  17786. var dockerCenter = this.docker.bounds.center();
  17787. if (this.docker.parent) {
  17788. this.docker.parent.dockers.each((function(docker){
  17789. if (this.docker == docker) {
  17790. return
  17791. };
  17792. var center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center();
  17793. nearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX;
  17794. nearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY;
  17795. }).bind(this));
  17796. if (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) {
  17797. nearestX = Math.abs(nearestX) < minOffset ? nearestX : 0;
  17798. nearestY = Math.abs(nearestY) < minOffset ? nearestY : 0;
  17799. this.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY);
  17800. //this.docker.update()
  17801. } else {
  17802. var previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1, 0)];
  17803. var next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1, this.docker.parent.dockers.length-1)];
  17804. if (previous && next && previous !== this.docker && next !== this.docker){
  17805. var cp = previous.bounds.center();
  17806. var cn = next.bounds.center();
  17807. var cd = this.docker.bounds.center();
  17808. // Checks if the point is on the line between previous and next
  17809. if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) {
  17810. // Get the rise
  17811. var raise = (Number(cn.y)-Number(cp.y))/(Number(cn.x)-Number(cp.x));
  17812. // Calculate the intersection point
  17813. var intersecX = ((cp.y-(cp.x*raise))-(cd.y-(cd.x*(-Math.pow(raise,-1)))))/((-Math.pow(raise,-1))-raise);
  17814. var intersecY = (cp.y-(cp.x*raise))+(raise*intersecX);
  17815. if(isNaN(intersecX) || isNaN(intersecY)) {return;}
  17816. this.docker.bounds.centerMoveTo(intersecX, intersecY);
  17817. }
  17818. }
  17819. }
  17820. }
  17821. }
  17822. //this.facade.getCanvas().update();
  17823. this.dockerParent._update();
  17824. },
  17825. /**
  17826. * Docker MouseUp Handler
  17827. *
  17828. */
  17829. dockerMovedFinished: function(event) {
  17830. /* Reset to buffered shape selection */
  17831. this.facade.setSelection(this.shapeSelection);
  17832. // Hide the border
  17833. this.hideHighlight();
  17834. // Show all Labels from Docker
  17835. this.dockerParent.getLabels().each(function(label){
  17836. label.show();
  17837. //label.update();
  17838. });
  17839. // If there is a last top level Shape
  17840. if(this.lastUIObj && (this.isStartDocker || this.isEndDocker)){
  17841. // If there is a valid connection, the set as a docked Shape to them
  17842. if(this.isValid) {
  17843. this.docker.setDockedShape(this.lastUIObj);
  17844. this.facade.raiseEvent({
  17845. type :ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED,
  17846. docker : this.docker,
  17847. parent : this.docker.parent,
  17848. target : this.lastUIObj
  17849. });
  17850. }
  17851. this.hideMagnets(this.lastUIObj);
  17852. }
  17853. // Hide the Docker
  17854. this.docker.hide();
  17855. if(this.outerDockerNotMoved) {
  17856. // Get the EventPosition and all Shapes on these point
  17857. var evPos = this.facade.eventCoordinates(event);
  17858. var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);
  17859. /* Remove edges from selection */
  17860. var shapeWithoutEdges = shapes.findAll(function(node) {
  17861. return node instanceof ORYX.Core.Node;
  17862. });
  17863. shapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes;
  17864. this.facade.setSelection(shapes);
  17865. } else {
  17866. //Command-Pattern for dragging one docker
  17867. var dragDockerCommand = ORYX.Core.Command.extend({
  17868. construct: function(docker, newPos, oldPos, newDockedShape, oldDockedShape, facade){
  17869. this.docker = docker;
  17870. this.index = docker.parent.dockers.indexOf(docker);
  17871. this.newPosition = newPos;
  17872. this.newDockedShape = newDockedShape;
  17873. this.oldPosition = oldPos;
  17874. this.oldDockedShape = oldDockedShape;
  17875. this.facade = facade;
  17876. this.index = docker.parent.dockers.indexOf(docker);
  17877. this.shape = docker.parent;
  17878. },
  17879. execute: function(){
  17880. if (!this.docker.parent){
  17881. this.docker = this.shape.dockers[this.index];
  17882. }
  17883. this.dock( this.newDockedShape, this.newPosition );
  17884. this.removedDockers = this.shape.removeUnusedDockers();
  17885. this.facade.updateSelection();
  17886. },
  17887. rollback: function(){
  17888. this.dock( this.oldDockedShape, this.oldPosition );
  17889. (this.removedDockers||$H({})).each(function(d){
  17890. this.shape.add(d.value, Number(d.key));
  17891. this.shape._update(true);
  17892. }.bind(this));
  17893. this.facade.updateSelection();
  17894. },
  17895. dock:function( toDockShape, pos ){
  17896. // Set the Docker to the new Shape
  17897. this.docker.setDockedShape( undefined );
  17898. if( toDockShape ){
  17899. this.docker.setDockedShape( toDockShape );
  17900. this.docker.setReferencePoint( pos );
  17901. //this.docker.update();
  17902. //this.docker.parent._update();
  17903. } else {
  17904. this.docker.bounds.centerMoveTo( pos );
  17905. }
  17906. this.facade.getCanvas().update();
  17907. }
  17908. });
  17909. if (this.docker.parent){
  17910. // Instanziate the dockCommand
  17911. var command = new dragDockerCommand(this.docker, this.docker.getDockedShape() ? this.docker.referencePoint : this.docker.bounds.center(), this._commandArg.refPoint, this.docker.getDockedShape(), this._commandArg.dockedShape, this.facade);
  17912. this.facade.executeCommands( [command] );
  17913. }
  17914. }
  17915. // Update all Shapes
  17916. //this.facade.updateSelection();
  17917. // Undefined all variables
  17918. this.docker = undefined;
  17919. this.dockerParent = undefined;
  17920. this.dockerSource = undefined;
  17921. this.dockerTarget = undefined;
  17922. this.lastUIObj = undefined;
  17923. },
  17924. /**
  17925. * Hide the highlighting
  17926. */
  17927. hideHighlight: function() {
  17928. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'validDockedShape'});
  17929. },
  17930. /**
  17931. * Show the highlighting
  17932. *
  17933. */
  17934. showHighlight: function(uiObj, color) {
  17935. this.facade.raiseEvent({
  17936. type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  17937. highlightId:'validDockedShape',
  17938. elements: [uiObj],
  17939. color: color
  17940. });
  17941. },
  17942. showMagnets: function(uiObj){
  17943. uiObj.magnets.each(function(magnet) {
  17944. magnet.show();
  17945. });
  17946. },
  17947. hideMagnets: function(uiObj){
  17948. uiObj.magnets.each(function(magnet) {
  17949. magnet.hide();
  17950. });
  17951. },
  17952. getHighestParentBeforeCanvas: function(shape) {
  17953. if(!(shape instanceof ORYX.Core.Shape)) {return undefined;}
  17954. var parent = shape.parent;
  17955. while(parent && !(parent.parent instanceof ORYX.Core.Canvas)) {
  17956. parent = parent.parent;
  17957. }
  17958. return parent;
  17959. }
  17960. });
  17961. /*
  17962. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  17963. * License rights for this program may be obtained from Alfresco Software, Ltd.
  17964. * pursuant to a written agreement and any use of this program without such an
  17965. * agreement is prohibited.
  17966. */
  17967. /*
  17968. * All code Copyright 2013 KIS Consultancy all rights reserved
  17969. */
  17970. if(!ORYX.Plugins)
  17971. ORYX.Plugins = new Object();
  17972. ORYX.Plugins.AddDocker = Clazz.extend({
  17973. /**
  17974. * Constructor
  17975. * @param {Object} Facade: The Facade of the Editor
  17976. */
  17977. construct: function(facade) {
  17978. this.facade = facade;
  17979. this.enableAdd = false;
  17980. this.enableRemove = false;
  17981. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
  17982. },
  17983. setEnableAdd: function(enable){
  17984. this.enableAdd = enable;
  17985. if(this.enableAdd) {
  17986. jQuery("#add-bendpoint-button").addClass('pressed');
  17987. } else {
  17988. jQuery("#add-bendpoint-button").removeClass('pressed');
  17989. jQuery("#add-bendpoint-button").blur();
  17990. }
  17991. },
  17992. setEnableRemove: function(enable){
  17993. this.enableRemove = enable;
  17994. if(this.enableRemove) {
  17995. jQuery("#remove-bendpoint-button").addClass('pressed');
  17996. } else {
  17997. jQuery("#remove-bendpoint-button").removeClass('pressed');
  17998. jQuery("#remove-bendpoint-button").blur();
  17999. }
  18000. },
  18001. enabledAdd: function(enable){
  18002. return this.enableAdd;
  18003. },
  18004. enabledRemove: function(){
  18005. return this.enableRemove;
  18006. },
  18007. /**
  18008. * MouseDown Handler
  18009. *
  18010. */
  18011. handleMouseDown: function(event, uiObj) {
  18012. if (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) {
  18013. this.newDockerCommand({
  18014. edge: uiObj,
  18015. position: this.facade.eventCoordinates(event)
  18016. });
  18017. this.setEnableAdd(false);
  18018. } else if (this.enabledRemove() &&
  18019. uiObj instanceof ORYX.Core.Controls.Docker &&
  18020. uiObj.parent instanceof ORYX.Core.Edge) {
  18021. this.newDockerCommand({
  18022. edge: uiObj.parent,
  18023. docker: uiObj
  18024. });
  18025. this.setEnableRemove(false);
  18026. }
  18027. document.body.style.cursor = 'default';
  18028. },
  18029. // Options: edge (required), position (required if add), docker (required if delete)
  18030. newDockerCommand: function(options){
  18031. if(!options.edge)
  18032. return;
  18033. var commandClass = ORYX.Core.Command.extend({
  18034. construct: function(addEnabled, deleteEnabled, edge, docker, pos, facade){
  18035. this.addEnabled = addEnabled;
  18036. this.deleteEnabled = deleteEnabled;
  18037. this.edge = edge;
  18038. this.docker = docker;
  18039. this.pos = pos;
  18040. this.facade = facade;
  18041. },
  18042. execute: function(){
  18043. if (this.addEnabled) {
  18044. if (!this.docker){
  18045. this.docker = this.edge.addDocker(this.pos);
  18046. this.index = this.edge.dockers.indexOf(this.docker);
  18047. } else {
  18048. this.edge.add(this.docker, this.index);
  18049. }
  18050. }
  18051. else if (this.deleteEnabled) {
  18052. this.index = this.edge.dockers.indexOf(this.docker);
  18053. this.pos = this.docker.bounds.center();
  18054. this.edge.removeDocker(this.docker);
  18055. }
  18056. this.edge.getLabels().invoke("show");
  18057. this.facade.getCanvas().update();
  18058. this.facade.updateSelection();
  18059. },
  18060. rollback: function(){
  18061. if (this.addEnabled) {
  18062. if (this.docker instanceof ORYX.Core.Controls.Docker) {
  18063. this.edge.removeDocker(this.docker);
  18064. }
  18065. }
  18066. else if (this.deleteEnabled) {
  18067. this.edge.add(this.docker, this.index);
  18068. }
  18069. this.edge.getLabels().invoke("show");
  18070. this.facade.getCanvas().update();
  18071. this.facade.updateSelection();
  18072. }
  18073. })
  18074. var command = new commandClass(this.enabledAdd(), this.enabledRemove(), options.edge, options.docker, options.position, this.facade);
  18075. this.facade.executeCommands([command]);
  18076. }
  18077. });
  18078. /*
  18079. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  18080. * License rights for this program may be obtained from Alfresco Software, Ltd.
  18081. * pursuant to a written agreement and any use of this program without such an
  18082. * agreement is prohibited.
  18083. */
  18084. /*
  18085. * All code Copyright 2013 KIS Consultancy all rights reserved
  18086. */
  18087. if(!ORYX.Plugins)
  18088. ORYX.Plugins = new Object();
  18089. ORYX.Plugins.SelectionFrame = Clazz.extend({
  18090. construct: function(facade) {
  18091. this.facade = facade;
  18092. // Register on MouseEvents
  18093. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
  18094. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);
  18095. // Some initiale variables
  18096. this.position = {x:0, y:0};
  18097. this.size = {width:0, height:0};
  18098. this.offsetPosition = {x: 0, y: 0};
  18099. // (Un)Register Mouse-Move Event
  18100. this.moveCallback = undefined;
  18101. this.offsetScroll = {x:0,y:0};
  18102. // HTML-Node of Selection-Frame
  18103. this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $('canvasSection'),
  18104. ['div', {'class':'Oryx_SelectionFrame'}]);
  18105. this.hide();
  18106. },
  18107. handleMouseDown: function(event, uiObj) {
  18108. // If there is the Canvas
  18109. if( uiObj instanceof ORYX.Core.Canvas ) {
  18110. // Calculate the Offset
  18111. var scrollNode = uiObj.rootNode.parentNode.parentNode;
  18112. var a = this.facade.getCanvas().node.getScreenCTM();
  18113. this.offsetPosition = {
  18114. x: a.e,
  18115. y: a.f
  18116. };
  18117. // Set the new Position
  18118. this.setPos({
  18119. x: Event.pointerX(event) - jQuery("#canvasSection").offset().left,
  18120. y: Event.pointerY(event) - jQuery("#canvasSection").offset().top + 5
  18121. });
  18122. // Reset the size
  18123. this.resize({width:0, height:0});
  18124. this.moveCallback = this.handleMouseMove.bind(this);
  18125. // Register Mouse-Move Event
  18126. document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);
  18127. this.offsetScroll = {x:scrollNode.scrollLeft,y:scrollNode.scrollTop};
  18128. // Show the Frame
  18129. this.show();
  18130. }
  18131. Event.stop(event);
  18132. },
  18133. handleMouseUp: function(event) {
  18134. // If there was an MouseMoving
  18135. if(this.moveCallback) {
  18136. // Hide the Frame
  18137. this.hide();
  18138. // Unregister Mouse-Move
  18139. document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);
  18140. this.moveCallback = undefined;
  18141. var corrSVG = this.facade.getCanvas().node.getScreenCTM();
  18142. // Calculate the positions of the Frame
  18143. var a = {
  18144. x: this.size.width > 0 ? this.position.x : this.position.x + this.size.width,
  18145. y: this.size.height > 0 ? this.position.y : this.position.y + this.size.height
  18146. };
  18147. var b = {
  18148. x: a.x + Math.abs(this.size.width),
  18149. y: a.y + Math.abs(this.size.height)
  18150. };
  18151. var additionalIEZoom = 1;
  18152. if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
  18153. var ua = navigator.userAgent;
  18154. if (ua.indexOf('MSIE') >= 0) {
  18155. //IE 10 and below
  18156. var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100);
  18157. if (zoom !== 100) {
  18158. additionalIEZoom = zoom / 100
  18159. }
  18160. }
  18161. }
  18162. if (additionalIEZoom === 1) {
  18163. a.x = a.x - (corrSVG.e - jQuery("#canvasSection").offset().left);
  18164. a.y = a.y - (corrSVG.f - jQuery("#canvasSection").offset().top);
  18165. b.x = b.x - (corrSVG.e - jQuery("#canvasSection").offset().left);
  18166. b.y = b.y - (corrSVG.f - jQuery("#canvasSection").offset().top);
  18167. } else {
  18168. var canvasOffsetLeft = jQuery("#canvasSection").offset().left;
  18169. var canvasScrollLeft = jQuery("#canvasSection").scrollLeft();
  18170. var canvasScrollTop = jQuery("#canvasSection").scrollTop();
  18171. var offset = a.e - (canvasOffsetLeft * additionalIEZoom);
  18172. var additionaloffset = 0;
  18173. if (offset > 10) {
  18174. additionaloffset = (offset / additionalIEZoom) - offset;
  18175. }
  18176. a.x = a.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));
  18177. a.y = a.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));
  18178. b.x = b.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft));
  18179. b.y = b.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop));
  18180. }
  18181. // Fit to SVG-Coordinates
  18182. a.x /= corrSVG.a; a.y /= corrSVG.d;
  18183. b.x /= corrSVG.a; b.y /= corrSVG.d;
  18184. // Calculate the elements from the childs of the canvas
  18185. var elements = this.facade.getCanvas().getChildShapes(true).findAll(function(value) {
  18186. var absBounds = value.absoluteBounds();
  18187. var bA = absBounds.upperLeft();
  18188. var bB = absBounds.lowerRight();
  18189. if(bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y)
  18190. return true;
  18191. return false;
  18192. });
  18193. // Set the selection
  18194. this.facade.setSelection(elements);
  18195. }
  18196. },
  18197. handleMouseMove: function(event) {
  18198. // Calculate the size
  18199. var size = {
  18200. width : Event.pointerX(event) - this.position.x - jQuery("#canvasSection").offset().left,
  18201. height : Event.pointerY(event) - this.position.y - jQuery("#canvasSection").offset().top + 5
  18202. };
  18203. var scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;
  18204. size.width -= this.offsetScroll.x - scrollNode.scrollLeft;
  18205. size.height -= this.offsetScroll.y - scrollNode.scrollTop;
  18206. // Set the size
  18207. this.resize(size);
  18208. Event.stop(event);
  18209. },
  18210. hide: function() {
  18211. this.node.style.display = "none";
  18212. },
  18213. show: function() {
  18214. this.node.style.display = "";
  18215. },
  18216. setPos: function(pos) {
  18217. // Set the Position
  18218. this.node.style.top = pos.y + "px";
  18219. this.node.style.left = pos.x + "px";
  18220. this.position = pos;
  18221. },
  18222. resize: function(size) {
  18223. // Calculate the negative offset
  18224. this.setPos(this.position);
  18225. this.size = Object.clone(size);
  18226. if(size.width < 0) {
  18227. this.node.style.left = (this.position.x + size.width) + "px";
  18228. size.width = - size.width;
  18229. }
  18230. if(size.height < 0) {
  18231. this.node.style.top = (this.position.y + size.height) + "px";
  18232. size.height = - size.height;
  18233. }
  18234. // Set the size
  18235. this.node.style.width = size.width + "px";
  18236. this.node.style.height = size.height + "px";
  18237. }
  18238. });
  18239. /*
  18240. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  18241. * License rights for this program may be obtained from Alfresco Software, Ltd.
  18242. * pursuant to a written agreement and any use of this program without such an
  18243. * agreement is prohibited.
  18244. */
  18245. /*
  18246. * All code Copyright 2013 KIS Consultancy all rights reserved
  18247. */
  18248. if(!ORYX.Plugins)
  18249. ORYX.Plugins = new Object();
  18250. ORYX.Plugins.ShapeHighlighting = Clazz.extend({
  18251. construct: function(facade) {
  18252. this.parentNode = facade.getCanvas().getSvgContainer();
  18253. // The parent Node
  18254. this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parentNode,
  18255. ['g']);
  18256. this.highlightNodes = {};
  18257. facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this));
  18258. facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this));
  18259. },
  18260. setHighlight: function(options) {
  18261. if(options && options.highlightId){
  18262. var node = this.highlightNodes[options.highlightId];
  18263. if(!node){
  18264. node= ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
  18265. ['path', {
  18266. "stroke-width": 2.0, "fill":"none"
  18267. }]);
  18268. this.highlightNodes[options.highlightId] = node;
  18269. }
  18270. if(options.elements && options.elements.length > 0) {
  18271. this.setAttributesByStyle( node, options );
  18272. this.show(node);
  18273. } else {
  18274. this.hide(node);
  18275. }
  18276. }
  18277. },
  18278. hideHighlight: function(options) {
  18279. if(options && options.highlightId && this.highlightNodes[options.highlightId]){
  18280. this.hide(this.highlightNodes[options.highlightId]);
  18281. }
  18282. },
  18283. hide: function(node) {
  18284. node.setAttributeNS(null, 'display', 'none');
  18285. },
  18286. show: function(node) {
  18287. node.setAttributeNS(null, 'display', '');
  18288. },
  18289. setAttributesByStyle: function( node, options ){
  18290. // If the style say, that it should look like a rectangle
  18291. if( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){
  18292. // Set like this
  18293. var bo = options.elements[0].absoluteBounds();
  18294. var strWidth = options.strokewidth ? options.strokewidth : ORYX.CONFIG.BORDER_OFFSET
  18295. node.setAttributeNS(null, "d", this.getPathRectangle( bo.a, bo.b , strWidth ) );
  18296. node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
  18297. node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
  18298. node.setAttributeNS(null, "stroke-width", strWidth);
  18299. } else if(options.elements.length == 1
  18300. && options.elements[0] instanceof ORYX.Core.Edge &&
  18301. options.highlightId != "selection") {
  18302. /* Highlight containment of edge's childs */
  18303. var path = this.getPathEdge(options.elements[0].dockers);
  18304. if (path && path.length > 0)
  18305. {
  18306. node.setAttributeNS(null, "d", path);
  18307. }
  18308. node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
  18309. node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
  18310. node.setAttributeNS(null, "stroke-width", ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
  18311. }else {
  18312. // If not, set just the corners
  18313. var path = this.getPathByElements(options.elements);
  18314. if (path && path.length > 0)
  18315. {
  18316. node.setAttributeNS(null, "d", path);
  18317. }
  18318. node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
  18319. node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 1.0);
  18320. node.setAttributeNS(null, "stroke-width", options.strokewidth ? options.strokewidth : 2.0);
  18321. }
  18322. },
  18323. getPathByElements: function(elements){
  18324. if(!elements || elements.length <= 0) {return undefined}
  18325. // Get the padding and the size
  18326. var padding = ORYX.CONFIG.SELECTED_AREA_PADDING;
  18327. var path = ""
  18328. // Get thru all Elements
  18329. elements.each((function(element) {
  18330. if(!element) {return}
  18331. // Get the absolute Bounds and the two Points
  18332. var bounds = element.absoluteBounds();
  18333. bounds.widen(padding)
  18334. var a = bounds.upperLeft();
  18335. var b = bounds.lowerRight();
  18336. path = path + this.getPath(a ,b);
  18337. }).bind(this));
  18338. return path;
  18339. },
  18340. getPath: function(a, b){
  18341. return this.getPathCorners(a, b);
  18342. },
  18343. getPathCorners: function(a, b){
  18344. var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
  18345. var path = ""
  18346. // Set: Upper left
  18347. path = path + "M" + a.x + " " + (a.y + size) + " l0 -" + size + " l" + size + " 0 ";
  18348. // Set: Lower left
  18349. path = path + "M" + a.x + " " + (b.y - size) + " l0 " + size + " l" + size + " 0 ";
  18350. // Set: Lower right
  18351. path = path + "M" + b.x + " " + (b.y - size) + " l0 " + size + " l-" + size + " 0 ";
  18352. // Set: Upper right
  18353. path = path + "M" + b.x + " " + (a.y + size) + " l0 -" + size + " l-" + size + " 0 ";
  18354. return path;
  18355. },
  18356. getPathRectangle: function(a, b, strokeWidth){
  18357. var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
  18358. var path = ""
  18359. var offset = strokeWidth / 2.0;
  18360. // Set: Upper left
  18361. path = path + "M" + (a.x + offset) + " " + (a.y);
  18362. path = path + " L" + (a.x + offset) + " " + (b.y - offset);
  18363. path = path + " L" + (b.x - offset) + " " + (b.y - offset);
  18364. path = path + " L" + (b.x - offset) + " " + (a.y + offset);
  18365. path = path + " L" + (a.x + offset) + " " + (a.y + offset);
  18366. return path;
  18367. },
  18368. getPathEdge: function(edgeDockers) {
  18369. var length = edgeDockers.length;
  18370. var path = "M" + edgeDockers[0].bounds.center().x + " "
  18371. + edgeDockers[0].bounds.center().y;
  18372. for(i=1; i<length; i++) {
  18373. var dockerPoint = edgeDockers[i].bounds.center();
  18374. path = path + " L" + dockerPoint.x + " " + dockerPoint.y;
  18375. }
  18376. return path;
  18377. }
  18378. });
  18379. ORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({
  18380. construct: function(facade) {
  18381. this.facade = facade;
  18382. this.opacityFull = 0.9;
  18383. this.opacityLow = 0.4;
  18384. // Register on Dragging-Events for show/hide of ShapeMenu
  18385. //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this));
  18386. //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END, this.show.bind(this));
  18387. },
  18388. /**
  18389. * On the Selection-Changed
  18390. *
  18391. */
  18392. onSelectionChanged: function(event) {
  18393. if(event.elements && event.elements.length > 1) {
  18394. this.facade.raiseEvent({
  18395. type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  18396. highlightId:'selection',
  18397. elements: event.elements.without(event.subSelection),
  18398. color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
  18399. opacity: !event.subSelection ? this.opacityFull : this.opacityLow
  18400. });
  18401. if(event.subSelection){
  18402. this.facade.raiseEvent({
  18403. type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
  18404. highlightId:'subselection',
  18405. elements: [event.subSelection],
  18406. color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
  18407. opacity: this.opacityFull
  18408. });
  18409. } else {
  18410. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
  18411. }
  18412. } else {
  18413. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'selection'});
  18414. this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
  18415. }
  18416. }
  18417. });/*
  18418. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  18419. * License rights for this program may be obtained from Alfresco Software, Ltd.
  18420. * pursuant to a written agreement and any use of this program without such an
  18421. * agreement is prohibited.
  18422. */
  18423. /*
  18424. * All code Copyright 2013 KIS Consultancy all rights reserved
  18425. */
  18426. if (!ORYX.Plugins)
  18427. ORYX.Plugins = new Object();
  18428. ORYX.Plugins.Overlay = Clazz.extend({
  18429. facade: undefined,
  18430. styleNode: undefined,
  18431. construct: function(facade){
  18432. this.facade = facade;
  18433. this.changes = [];
  18434. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this));
  18435. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this));
  18436. this.styleNode = document.createElement('style')
  18437. this.styleNode.setAttributeNS(null, 'type', 'text/css')
  18438. document.getElementsByTagName('head')[0].appendChild( this.styleNode )
  18439. },
  18440. /**
  18441. * Show the overlay for specific nodes
  18442. * @param {Object} options
  18443. *
  18444. * String options.id - MUST - Define the id of the overlay (is needed for the hiding of this overlay)
  18445. * ORYX.Core.Shape[] options.shapes - MUST - Define the Shapes for the changes
  18446. * attr-name:value options.changes - Defines all the changes which should be shown
  18447. *
  18448. *
  18449. */
  18450. show: function( options ){
  18451. // Checks if all arguments are available
  18452. if( !options ||
  18453. !options.shapes || !options.shapes instanceof Array ||
  18454. !options.id || !options.id instanceof String || options.id.length == 0) {
  18455. return
  18456. }
  18457. //if( this.changes[options.id]){
  18458. // this.hide( options )
  18459. //}
  18460. // Checked if attributes are setted
  18461. if( options.attributes ){
  18462. // FOR EACH - Shape
  18463. options.shapes.each(function(el){
  18464. // Checks if the node is a Shape
  18465. if( !el instanceof ORYX.Core.Shape){ return }
  18466. this.setAttributes( el.node , options.attributes )
  18467. }.bind(this))
  18468. }
  18469. var isSVG = true
  18470. try {
  18471. isSVG = options.node && options.node instanceof SVGElement;
  18472. } catch(e){}
  18473. // Checks if node is setted and if this is an SVGElement
  18474. if ( options.node && isSVG) {
  18475. options["_temps"] = []
  18476. // FOR EACH - Node
  18477. options.shapes.each(function(el, index){
  18478. // Checks if the node is a Shape
  18479. if( !el instanceof ORYX.Core.Shape){ return }
  18480. var _temp = {}
  18481. _temp.svg = options.dontCloneNode ? options.node : options.node.cloneNode( true );
  18482. // Add the svg node to the ORYX-Shape
  18483. el.node.firstChild.appendChild( _temp.svg )
  18484. // If
  18485. if (el instanceof ORYX.Core.Edge && !options.nodePosition) {
  18486. options['nodePosition'] = "START"
  18487. }
  18488. // If the node position is setted, it has to be transformed
  18489. if( options.nodePosition ){
  18490. var b = el.bounds;
  18491. var p = options.nodePosition.toUpperCase();
  18492. // Check the values of START and END
  18493. if( el instanceof ORYX.Core.Node && p == "START"){
  18494. p = "NW";
  18495. } else if(el instanceof ORYX.Core.Node && p == "END"){
  18496. p = "SE";
  18497. } else if(el instanceof ORYX.Core.Edge && p == "START"){
  18498. b = el.getDockers().first().bounds
  18499. } else if(el instanceof ORYX.Core.Edge && p == "END"){
  18500. b = el.getDockers().last().bounds
  18501. }
  18502. // Create a callback for the changing the position
  18503. // depending on the position string
  18504. _temp.callback = function(){
  18505. var x = 0; var y = 0;
  18506. if( p == "NW" ){
  18507. // Do Nothing
  18508. } else if( p == "N" ) {
  18509. x = b.width() / 2;
  18510. } else if( p == "NE" ) {
  18511. x = b.width();
  18512. } else if( p == "E" ) {
  18513. x = b.width(); y = b.height() / 2;
  18514. } else if( p == "SE" ) {
  18515. x = b.width(); y = b.height();
  18516. } else if( p == "S" ) {
  18517. x = b.width() / 2; y = b.height();
  18518. } else if( p == "SW" ) {
  18519. y = b.height();
  18520. } else if( p == "W" ) {
  18521. y = b.height() / 2;
  18522. } else if( p == "START" || p == "END") {
  18523. x = b.width() / 2; y = b.height() / 2;
  18524. } else {
  18525. return
  18526. }
  18527. if( el instanceof ORYX.Core.Edge){
  18528. x += b.upperLeft().x ; y += b.upperLeft().y ;
  18529. }
  18530. _temp.svg.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")")
  18531. }.bind(this)
  18532. _temp.element = el;
  18533. _temp.callback();
  18534. b.registerCallback( _temp.callback );
  18535. }
  18536. options._temps.push( _temp )
  18537. }.bind(this))
  18538. }
  18539. // Store the changes
  18540. if( !this.changes[options.id] ){
  18541. this.changes[options.id] = [];
  18542. }
  18543. this.changes[options.id].push( options );
  18544. },
  18545. /**
  18546. * Hide the overlay with the spefic id
  18547. * @param {Object} options
  18548. */
  18549. hide: function( options ){
  18550. // Checks if all arguments are available
  18551. if( !options ||
  18552. !options.id || !options.id instanceof String || options.id.length == 0 ||
  18553. !this.changes[options.id]) {
  18554. return
  18555. }
  18556. // Delete all added attributes
  18557. // FOR EACH - Shape
  18558. this.changes[options.id].each(function(option){
  18559. option.shapes.each(function(el, index){
  18560. // Checks if the node is a Shape
  18561. if( !el instanceof ORYX.Core.Shape){ return }
  18562. this.deleteAttributes( el.node )
  18563. }.bind(this));
  18564. if( option._temps ){
  18565. option._temps.each(function(tmp){
  18566. // Delete the added Node, if there is one
  18567. if( tmp.svg && tmp.svg.parentNode ){
  18568. tmp.svg.parentNode.removeChild( tmp.svg )
  18569. }
  18570. // If
  18571. if( tmp.callback && tmp.element){
  18572. // It has to be unregistered from the edge
  18573. tmp.element.bounds.unregisterCallback( tmp.callback )
  18574. }
  18575. }.bind(this))
  18576. }
  18577. }.bind(this));
  18578. this.changes[options.id] = null;
  18579. },
  18580. /**
  18581. * Set the given css attributes to that node
  18582. * @param {HTMLElement} node
  18583. * @param {Object} attributes
  18584. */
  18585. setAttributes: function( node, attributes ) {
  18586. // Get all the childs from ME
  18587. var childs = this.getAllChilds( node.firstChild.firstChild )
  18588. var ids = []
  18589. // Add all Attributes which have relation to another node in this document and concate the pure id out of it
  18590. // This is for example important for the markers of a edge
  18591. childs.each(function(e){ ids.push( $A(e.attributes).findAll(function(attr){ return attr.nodeValue.startsWith('url(#')}) )})
  18592. ids = ids.flatten().compact();
  18593. ids = ids.collect(function(s){return s.nodeValue}).uniq();
  18594. ids = ids.collect(function(s){return s.slice(5, s.length-1)})
  18595. // Add the node ID to the id
  18596. ids.unshift( node.id + ' .me')
  18597. var attr = $H(attributes);
  18598. var attrValue = attr.toJSON().gsub(',', ';').gsub('"', '');
  18599. var attrMarkerValue = attributes.stroke ? attrValue.slice(0, attrValue.length-1) + "; fill:" + attributes.stroke + ";}" : attrValue;
  18600. var attrTextValue;
  18601. if( attributes.fill ){
  18602. var copyAttr = Object.clone(attributes);
  18603. copyAttr.fill = "black";
  18604. attrTextValue = $H(copyAttr).toJSON().gsub(',', ';').gsub('"', '');
  18605. }
  18606. // Create the CSS-Tags Style out of the ids and the attributes
  18607. csstags = ids.collect(function(s, i){return "#" + s + " * " + (!i? attrValue : attrMarkerValue) + "" + (attrTextValue ? " #" + s + " text * " + attrTextValue : "") })
  18608. // Join all the tags
  18609. var s = csstags.join(" ") + "\n"
  18610. // And add to the end of the style tag
  18611. this.styleNode.appendChild(document.createTextNode(s));
  18612. },
  18613. /**
  18614. * Deletes all attributes which are
  18615. * added in a special style sheet for that node
  18616. * @param {HTMLElement} node
  18617. */
  18618. deleteAttributes: function( node ) {
  18619. // Get all children which contains the node id
  18620. var delEl = $A(this.styleNode.childNodes)
  18621. .findAll(function(e){ return e.textContent.include( '#' + node.id ) });
  18622. // Remove all of them
  18623. delEl.each(function(el){
  18624. el.parentNode.removeChild(el);
  18625. });
  18626. },
  18627. getAllChilds: function( node ){
  18628. var childs = $A(node.childNodes)
  18629. $A(node.childNodes).each(function( e ){
  18630. childs.push( this.getAllChilds( e ) )
  18631. }.bind(this))
  18632. return childs.flatten();
  18633. }
  18634. });
  18635. /*
  18636. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  18637. * License rights for this program may be obtained from Alfresco Software, Ltd.
  18638. * pursuant to a written agreement and any use of this program without such an
  18639. * agreement is prohibited.
  18640. */
  18641. /*
  18642. * All code Copyright 2013 KIS Consultancy all rights reserved
  18643. */
  18644. if (!ORYX.Plugins)
  18645. ORYX.Plugins = new Object();
  18646. ORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({
  18647. facade: undefined,
  18648. construct: function(facade){
  18649. this.facade = facade;
  18650. this.copyElements = [];
  18651. //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));
  18652. // SELECT ALL
  18653. this.facade.offer({
  18654. keyCodes: [{
  18655. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  18656. keyCode: 65,
  18657. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18658. }
  18659. ],
  18660. functionality: this.selectAll.bind(this)
  18661. });
  18662. // MOVE LEFT SMALL
  18663. this.facade.offer({
  18664. keyCodes: [{
  18665. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  18666. keyCode: ORYX.CONFIG.KEY_CODE_LEFT,
  18667. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18668. }
  18669. ],
  18670. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, false)
  18671. });
  18672. // MOVE LEFT
  18673. this.facade.offer({
  18674. keyCodes: [{
  18675. keyCode: ORYX.CONFIG.KEY_CODE_LEFT,
  18676. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18677. }
  18678. ],
  18679. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, true)
  18680. });
  18681. // MOVE RIGHT SMALL
  18682. this.facade.offer({
  18683. keyCodes: [{
  18684. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  18685. keyCode: ORYX.CONFIG.KEY_CODE_RIGHT,
  18686. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18687. }
  18688. ],
  18689. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, false)
  18690. });
  18691. // MOVE RIGHT
  18692. this.facade.offer({
  18693. keyCodes: [{
  18694. keyCode: ORYX.CONFIG.KEY_CODE_RIGHT,
  18695. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18696. }
  18697. ],
  18698. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, true)
  18699. });
  18700. // MOVE UP SMALL
  18701. this.facade.offer({
  18702. keyCodes: [{
  18703. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  18704. keyCode: ORYX.CONFIG.KEY_CODE_UP,
  18705. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18706. }
  18707. ],
  18708. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, false)
  18709. });
  18710. // MOVE UP
  18711. this.facade.offer({
  18712. keyCodes: [{
  18713. keyCode: ORYX.CONFIG.KEY_CODE_UP,
  18714. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18715. }
  18716. ],
  18717. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, true)
  18718. });
  18719. // MOVE DOWN SMALL
  18720. this.facade.offer({
  18721. keyCodes: [{
  18722. metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
  18723. keyCode: ORYX.CONFIG.KEY_CODE_DOWN,
  18724. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18725. }
  18726. ],
  18727. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, false)
  18728. });
  18729. // MOVE DOWN
  18730. this.facade.offer({
  18731. keyCodes: [{
  18732. keyCode: ORYX.CONFIG.KEY_CODE_DOWN,
  18733. keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
  18734. }
  18735. ],
  18736. functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, true)
  18737. });
  18738. },
  18739. /**
  18740. * Select all shapes in the editor
  18741. *
  18742. */
  18743. selectAll: function(e){
  18744. Event.stop(e.event);
  18745. this.facade.setSelection(this.facade.getCanvas().getChildShapes(true))
  18746. },
  18747. move: function(key, far, e) {
  18748. Event.stop(e.event);
  18749. // calculate the distance to move the objects and get the selection.
  18750. var distance = far? 20 : 5;
  18751. var selection = this.facade.getSelection();
  18752. var currentSelection = this.facade.getSelection();
  18753. var p = {x: 0, y: 0};
  18754. // switch on the key pressed and populate the point to move by.
  18755. switch(key) {
  18756. case ORYX.CONFIG.KEY_CODE_LEFT:
  18757. p.x = -1*distance;
  18758. break;
  18759. case ORYX.CONFIG.KEY_CODE_RIGHT:
  18760. p.x = distance;
  18761. break;
  18762. case ORYX.CONFIG.KEY_CODE_UP:
  18763. p.y = -1*distance;
  18764. break;
  18765. case ORYX.CONFIG.KEY_CODE_DOWN:
  18766. p.y = distance;
  18767. break;
  18768. }
  18769. // move each shape in the selection by the point calculated and update it.
  18770. selection = selection.findAll(function(shape){
  18771. // Check if this shape is docked to an shape in the selection
  18772. if(shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include( shape.dockers.first().getDockedShape() )){
  18773. return false
  18774. }
  18775. // Check if any of the parent shape is included in the selection
  18776. var s = shape.parent;
  18777. do{
  18778. if(selection.include(s)){
  18779. return false
  18780. }
  18781. }while(s = s.parent);
  18782. // Otherwise, return true
  18783. return true;
  18784. });
  18785. /* Edges must not be movable, if only edges are selected and at least
  18786. * one of them is docked.
  18787. */
  18788. var edgesMovable = true;
  18789. var onlyEdgesSelected = selection.all(function(shape) {
  18790. if(shape instanceof ORYX.Core.Edge) {
  18791. if(shape.isDocked()) {
  18792. edgesMovable = false;
  18793. }
  18794. return true;
  18795. }
  18796. return false;
  18797. });
  18798. if(onlyEdgesSelected && !edgesMovable) {
  18799. /* Abort moving shapes */
  18800. return;
  18801. }
  18802. selection = selection.map(function(shape){
  18803. if( shape instanceof ORYX.Core.Node ){
  18804. /*if( shape.dockers.length == 1 ){
  18805. return shape.dockers.first()
  18806. } else {*/
  18807. return shape
  18808. //}
  18809. } else if( shape instanceof ORYX.Core.Edge ) {
  18810. var dockers = shape.dockers;
  18811. if( selection.include( shape.dockers.first().getDockedShape() ) ){
  18812. dockers = dockers.without( shape.dockers.first() )
  18813. }
  18814. if( selection.include( shape.dockers.last().getDockedShape() ) ){
  18815. dockers = dockers.without( shape.dockers.last() )
  18816. }
  18817. return dockers
  18818. } else {
  18819. return null
  18820. }
  18821. }).flatten().compact();
  18822. if (selection.size() > 0) {
  18823. //Stop moving at canvas borders
  18824. var selectionBounds = [ this.facade.getCanvas().bounds.lowerRight().x,
  18825. this.facade.getCanvas().bounds.lowerRight().y,
  18826. 0,
  18827. 0 ];
  18828. selection.each(function(s) {
  18829. selectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x);
  18830. selectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y);
  18831. selectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x);
  18832. selectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y);
  18833. });
  18834. if(selectionBounds[0]+p.x < 0)
  18835. p.x = -selectionBounds[0];
  18836. if(selectionBounds[1]+p.y < 0)
  18837. p.y = -selectionBounds[1];
  18838. if(selectionBounds[2]+p.x > this.facade.getCanvas().bounds.lowerRight().x)
  18839. p.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2];
  18840. if(selectionBounds[3]+p.y > this.facade.getCanvas().bounds.lowerRight().y)
  18841. p.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3];
  18842. if(p.x!=0 || p.y!=0) {
  18843. // Instantiate the moveCommand
  18844. var commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)];
  18845. // Execute the commands
  18846. this.facade.executeCommands(commands);
  18847. }
  18848. }
  18849. },
  18850. getUndockedCommant: function(shapes){
  18851. var undockEdgeCommand = ORYX.Core.Command.extend({
  18852. construct: function(moveShapes){
  18853. this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();
  18854. },
  18855. execute: function(){
  18856. this.dockers.each(function(el){
  18857. el.docker.setDockedShape(undefined);
  18858. })
  18859. },
  18860. rollback: function(){
  18861. this.dockers.each(function(el){
  18862. el.docker.setDockedShape(el.dockedShape);
  18863. el.docker.setReferencePoint(el.refPoint);
  18864. //el.docker.update();
  18865. })
  18866. }
  18867. });
  18868. command = new undockEdgeCommand( shapes );
  18869. command.execute();
  18870. return command;
  18871. },
  18872. // /**
  18873. // * The key handler for this plugin. Every action from the set of cut, copy,
  18874. // * paste and delete should be accessible trough simple keyboard shortcuts.
  18875. // * This method checks whether any event triggers one of those actions.
  18876. // *
  18877. // * @param {Object} event The keyboard event that should be analysed for
  18878. // * triggering of this plugin.
  18879. // */
  18880. // keyHandler: function(event){
  18881. // //TODO document what event.which is.
  18882. //
  18883. // ORYX.Log.debug("keysMove.js handles a keyEvent.");
  18884. //
  18885. // // assure we have the current event.
  18886. // if (!event)
  18887. // event = window.event;
  18888. //
  18889. // // get the currently pressed key and state of control key.
  18890. // var pressedKey = event.which || event.keyCode;
  18891. // var ctrlPressed = event.ctrlKey;
  18892. //
  18893. // // if the key is one of the arrow keys, forward to move and return.
  18894. // if ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT,
  18895. // ORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) {
  18896. //
  18897. // this.move(pressedKey, !ctrlPressed);
  18898. // return;
  18899. // }
  18900. //
  18901. // }
  18902. });
  18903. /*
  18904. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  18905. * License rights for this program may be obtained from Alfresco Software, Ltd.
  18906. * pursuant to a written agreement and any use of this program without such an
  18907. * agreement is prohibited.
  18908. */
  18909. /*
  18910. * All code Copyright 2013 KIS Consultancy all rights reserved
  18911. */
  18912. if(!ORYX.Plugins) { ORYX.Plugins = {} }
  18913. if(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} }
  18914. new function(){
  18915. /**
  18916. * Edge layouter is an implementation to layout an edge
  18917. * @class ORYX.Plugins.Layouter.EdgeLayouter
  18918. * @author Willi Tscheschner
  18919. */
  18920. ORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({
  18921. /**
  18922. * Layout only Edges
  18923. */
  18924. layouted : [ "http://b3mn.org/stencilset/bpmn1.1#SequenceFlow",
  18925. "http://b3mn.org/stencilset/bpmn1.1#MessageFlow",
  18926. "http://b3mn.org/stencilset/timjpdl3#SequenceFlow",
  18927. "http://b3mn.org/stencilset/jbpm4#SequenceFlow",
  18928. "http://b3mn.org/stencilset/bpmn2.0#MessageFlow",
  18929. "http://b3mn.org/stencilset/bpmn2.0#SequenceFlow",
  18930. "http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow",
  18931. "http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow",
  18932. "http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink",
  18933. "http://b3mn.org/stencilset/epc#ControlFlow",
  18934. "http://www.signavio.com/stencilsets/processmap#ProcessLink",
  18935. "http://www.signavio.com/stencilsets/organigram#connection"],
  18936. /**
  18937. * Layout a set on edges
  18938. * @param {Object} edges
  18939. */
  18940. layout: function(edges){
  18941. edges.each(function(edge){
  18942. this.doLayout(edge)
  18943. }.bind(this))
  18944. },
  18945. /**
  18946. * Layout one edge
  18947. * @param {Object} edge
  18948. */
  18949. doLayout: function(edge){
  18950. // Get from and to node
  18951. var from = edge.getIncomingNodes()[0];
  18952. var to = edge.getOutgoingNodes()[0];
  18953. // Return if one is null
  18954. if (!from || !to) { return }
  18955. var positions = this.getPositions(from, to, edge);
  18956. if (positions.length > 0){
  18957. this.setDockers(edge, positions[0].a, positions[0].b);
  18958. }
  18959. },
  18960. /**
  18961. * Returns a set on positions which are not containt either
  18962. * in the bounds in from or to.
  18963. * @param {Object} from Shape where the edge is come from
  18964. * @param {Object} to Shape where the edge is leading to
  18965. * @param {Object} edge Edge between from and to
  18966. */
  18967. getPositions : function(from, to, edge){
  18968. // Get absolute bounds
  18969. var ab = from.absoluteBounds();
  18970. var bb = to.absoluteBounds();
  18971. // Get center from and to
  18972. var a = ab.center();
  18973. var b = bb.center();
  18974. var am = ab.midPoint();
  18975. var bm = bb.midPoint();
  18976. // Get first and last reference point
  18977. var first = Object.clone(edge.dockers.first().referencePoint);
  18978. var last = Object.clone(edge.dockers.last().referencePoint);
  18979. // Get the absolute one
  18980. var aFirst = edge.dockers.first().getAbsoluteReferencePoint();
  18981. var aLast = edge.dockers.last().getAbsoluteReferencePoint();
  18982. // IF ------>
  18983. // or |
  18984. // V
  18985. // Do nothing
  18986. if (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) {
  18987. return []
  18988. }
  18989. // Calc center position, between a and b
  18990. // depending on there weight
  18991. var m = {}
  18992. m.x = a.x < b.x ?
  18993. (((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2):
  18994. (((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2);
  18995. m.y = a.y < b.y ?
  18996. (((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2):
  18997. (((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2);
  18998. // Enlarge both bounds with 10
  18999. ab.widen(5); // Wide the from less than
  19000. bb.widen(20);// the to because of the arrow from the edge
  19001. var positions = [];
  19002. var off = this.getOffset.bind(this);
  19003. // Checks ----+
  19004. // |
  19005. // V
  19006. if (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) {
  19007. positions.push({
  19008. a : {x:b.x+off(last,bm,"x"),y:a.y+off(first,am,"y")},
  19009. z : this.getWeight(from, a.x < b.x ? "r" : "l", to, a.y < b.y ? "t" : "b", edge)
  19010. });
  19011. }
  19012. // Checks |
  19013. // +--->
  19014. if (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) {
  19015. positions.push({
  19016. a : {x:a.x+off(first,am,"x"),y:b.y+off(last,bm,"y")},
  19017. z : this.getWeight(from, a.y < b.y ? "b" : "t", to, a.x < b.x ? "l" : "r", edge)
  19018. });
  19019. }
  19020. // Checks --+
  19021. // |
  19022. // +--->
  19023. if (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) {
  19024. positions.push({
  19025. a : {x:m.x,y:a.y+off(first,am,"y")},
  19026. b : {x:m.x,y:b.y+off(last,bm,"y")},
  19027. z : this.getWeight(from, "r", to, "l", edge, a.x > b.x)
  19028. });
  19029. }
  19030. // Checks |
  19031. // +---+
  19032. // |
  19033. // V
  19034. if (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) {
  19035. positions.push({
  19036. a : {x:a.x+off(first,am,"x"),y:m.y},
  19037. b : {x:b.x+off(last,bm,"x"),y:m.y},
  19038. z : this.getWeight(from, "b", to, "t", edge, a.y > b.y)
  19039. });
  19040. }
  19041. // Sort DESC of weights
  19042. return positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)});
  19043. },
  19044. /**
  19045. * Returns a offset for the pos to the center of the bounds
  19046. *
  19047. * @param {Object} val
  19048. * @param {Object} pos2
  19049. * @param {String} dir Direction x|y
  19050. */
  19051. getOffset: function(pos, pos2, dir){
  19052. return pos[dir] - pos2[dir];
  19053. },
  19054. /**
  19055. * Returns a value which shows the weight for this configuration
  19056. *
  19057. * @param {Object} from Shape which is coming from
  19058. * @param {String} d1 Direction where is goes
  19059. * @param {Object} to Shape which goes to
  19060. * @param {String} d2 Direction where it comes to
  19061. * @param {Object} edge Edge between from and to
  19062. * @param {Boolean} reverse Reverse the direction (e.g. "r" -> "l")
  19063. */
  19064. getWeight: function(from, d1, to, d2, edge, reverse){
  19065. d1 = (d1||"").toLowerCase();
  19066. d2 = (d2||"").toLowerCase();
  19067. if (!["t","r","b","l"].include(d1)){ d1 = "r"}
  19068. if (!["t","r","b","l"].include(d2)){ d1 = "l"}
  19069. // If reverse is set
  19070. if (reverse) {
  19071. // Reverse d1 and d2
  19072. d1 = d1=="t"?"b":(d1=="r"?"l":(d1=="b"?"t":(d1=="l"?"r":"r")))
  19073. d2 = d2=="t"?"b":(d2=="r"?"l":(d2=="b"?"t":(d2=="l"?"r":"r")))
  19074. }
  19075. var weight = 0;
  19076. // Get rules for from "out" and to "in"
  19077. var dr1 = this.facade.getRules().getLayoutingRules(from, edge)["out"];
  19078. var dr2 = this.facade.getRules().getLayoutingRules(to, edge)["in"];
  19079. var fromWeight = dr1[d1];
  19080. var toWeight = dr2[d2];
  19081. /**
  19082. * Return a true if the center 1 is in the same direction than center 2
  19083. * @param {Object} direction
  19084. * @param {Object} center1
  19085. * @param {Object} center2
  19086. */
  19087. var sameDirection = function(direction, center1, center2){
  19088. switch(direction){
  19089. case "t": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y
  19090. case "r": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2
  19091. case "b": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y
  19092. case "l": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2
  19093. default: return false;
  19094. }
  19095. }
  19096. // Check if there are same incoming edges from 'from'
  19097. var sameIncomingFrom = from
  19098. .getIncomingShapes()
  19099. .findAll(function(a){ return a instanceof ORYX.Core.Edge})
  19100. .any(function(e){
  19101. return sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center());
  19102. });
  19103. // Check if there are same outgoing edges from 'to'
  19104. var sameOutgoingTo = to
  19105. .getOutgoingShapes()
  19106. .findAll(function(a){ return a instanceof ORYX.Core.Edge})
  19107. .any(function(e){
  19108. return sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center());
  19109. });
  19110. // If there are equivalent edges, set 0
  19111. //fromWeight = sameIncomingFrom ? 0 : fromWeight;
  19112. //toWeight = sameOutgoingTo ? 0 : toWeight;
  19113. // Get the sum of "out" and the direction plus "in" and the direction
  19114. return (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight);
  19115. },
  19116. /**
  19117. * Removes all current dockers from the node
  19118. * (except the start and end) and adds two new
  19119. * dockers, on the position a and b.
  19120. * @param {Object} edge
  19121. * @param {Object} a
  19122. * @param {Object} b
  19123. */
  19124. setDockers: function(edge, a, b){
  19125. if (!edge){ return }
  19126. // Remove all dockers (implicit,
  19127. // start and end dockers will not removed)
  19128. edge.dockers.each(function(r){
  19129. edge.removeDocker(r);
  19130. });
  19131. // For a and b (if exists), create
  19132. // a new docker and set position
  19133. [a, b].compact().each(function(pos){
  19134. var docker = edge.createDocker(undefined, pos);
  19135. docker.bounds.centerMoveTo(pos);
  19136. });
  19137. // Update all dockers from the edge
  19138. edge.dockers.each(function(docker){
  19139. docker.update()
  19140. })
  19141. // Update edge
  19142. //edge.refresh();
  19143. edge._update(true);
  19144. }
  19145. });
  19146. }()
  19147. /*
  19148. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  19149. * License rights for this program may be obtained from Alfresco Software, Ltd.
  19150. * pursuant to a written agreement and any use of this program without such an
  19151. * agreement is prohibited.
  19152. */
  19153. /*
  19154. * All code Copyright 2013 KIS Consultancy all rights reserved
  19155. */
  19156. if(!ORYX.Plugins)
  19157. ORYX.Plugins = new Object();
  19158. new function(){
  19159. ORYX.Plugins.BPMN2_0 = {
  19160. /**
  19161. * Constructor
  19162. * @param {Object} Facade: The Facade of the Editor
  19163. */
  19164. construct: function(facade){
  19165. this.facade = facade;
  19166. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, this.handleDockerDocked.bind(this));
  19167. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED, this.handlePropertyChanged.bind(this));
  19168. this.facade.registerOnEvent('layout.bpmn2_0.pool', this.handleLayoutPool.bind(this));
  19169. this.facade.registerOnEvent('layout.bpmn2_0.subprocess', this.handleSubProcess.bind(this));
  19170. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, this.handleShapeRemove.bind(this));
  19171. this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.afterLoad.bind(this));
  19172. this.namespace = undefined;
  19173. },
  19174. /**
  19175. * Force to update every pool
  19176. */
  19177. afterLoad: function(){
  19178. this.facade.getCanvas().getChildNodes().each(function(shape){
  19179. if (shape.getStencil().id().endsWith("Pool")) {
  19180. this.handleLayoutPool({
  19181. shape: shape
  19182. });
  19183. }
  19184. }.bind(this))
  19185. },
  19186. /**
  19187. * If a pool is selected and contains no lane,
  19188. * a lane is created automagically
  19189. */
  19190. onSelectionChanged: function(event) {
  19191. var selection = event.elements;
  19192. if(selection && selection.length === 1) {
  19193. var namespace = this.getNamespace();
  19194. var shape = selection[0];
  19195. if(shape.getStencil().idWithoutNs() === "Pool") {
  19196. if(shape.getChildNodes().length === 0) {
  19197. // create a lane inside the selected pool
  19198. var option = {
  19199. type:namespace + "Lane",
  19200. position:{x:0,y:0},
  19201. namespace:shape.getStencil().namespace(),
  19202. parent:shape
  19203. };
  19204. this.facade.createShape(option);
  19205. this.facade.getCanvas().update();
  19206. this.facade.setSelection([shape]);
  19207. }
  19208. }
  19209. }
  19210. // Preventing selection of all lanes but not the pool
  19211. if(selection.any(function(s){ return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane")})){
  19212. var lanes = selection.findAll(function(s){
  19213. return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane")
  19214. });
  19215. var pools = [];
  19216. var unselectLanes = [];
  19217. lanes.each(function(lane){
  19218. pools.push(this.getParentPool(lane))
  19219. }.bind(this));
  19220. pools = pools.uniq().findAll(function(pool){
  19221. var childLanes = this.getLanes(pool, true);
  19222. if (childLanes.all(function(lane){ return lanes.include(lane)})){
  19223. unselectLanes = unselectLanes.concat(childLanes);
  19224. return true;
  19225. } else if (selection.include(pool) && childLanes.any(function(lane){ return lanes.include(lane)})) {
  19226. unselectLanes = unselectLanes.concat(childLanes);
  19227. return true;
  19228. } else {
  19229. return false;
  19230. }
  19231. }.bind(this))
  19232. if (unselectLanes.length > 0 && pools.length > 0){
  19233. selection = selection.without.apply(selection, unselectLanes);
  19234. selection = selection.concat(pools);
  19235. this.facade.setSelection(selection.uniq());
  19236. }
  19237. }
  19238. },
  19239. handleShapeRemove: function(option) {
  19240. var sh = option.shape;
  19241. var parent = option.parent;
  19242. if (sh instanceof ORYX.Core.Node && sh.getStencil().idWithoutNs() === "Lane" && this.facade.isExecutingCommands()) {
  19243. var pool = this.getParentPool(parent);
  19244. if (pool&&pool.parent){
  19245. var isLeafFn = function(leaf){
  19246. return !leaf.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === "Lane"});
  19247. }
  19248. var isLeaf = isLeafFn(sh);
  19249. var parentHasMoreLanes = parent.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === "Lane"});
  19250. if (isLeaf && parentHasMoreLanes){
  19251. var command = new ResizeLanesCommand(sh, parent, pool, this);
  19252. this.facade.executeCommands([command]);
  19253. } else if( !isLeaf &&
  19254. !this.facade.getSelection().any(function(select){ // Find one of the selection, which is a lane and child of "sh" and is a leaf lane
  19255. return select instanceof ORYX.Core.Node && select.getStencil().idWithoutNs() === "Lane" &&
  19256. select.isParent(sh) && isLeafFn(select);})) {
  19257. var Command = ORYX.Core.Command.extend({
  19258. construct: function(shape, facade) {
  19259. this.children = shape.getChildNodes(true);
  19260. this.facade = facade;
  19261. },
  19262. execute: function() {
  19263. this.children.each(function(child){
  19264. child.bounds.moveBy(30,0)
  19265. });
  19266. //this.facade.getCanvas().update();
  19267. },
  19268. rollback: function() {
  19269. this.children.each(function(child){
  19270. child.bounds.moveBy(-30,0)
  19271. })
  19272. //this.facade.getCanvas().update();
  19273. }
  19274. });
  19275. this.facade.executeCommands([new Command(sh, this.facade)]);
  19276. } else if (isLeaf&&!parentHasMoreLanes&&parent == pool){
  19277. parent.add(sh);
  19278. }
  19279. }
  19280. }
  19281. },
  19282. hashedSubProcesses: {},
  19283. hashChildShapes: function(shape){
  19284. var children = shape.getChildNodes();
  19285. children.each(function(child){
  19286. if (this.hashedSubProcesses[child.id]){
  19287. this.hashedSubProcesses[child.id] = child.absoluteXY();
  19288. this.hashedSubProcesses[child.id].width = child.bounds.width();
  19289. this.hashedSubProcesses[child.id].height = child.bounds.height();
  19290. this.hashChildShapes(child);
  19291. }
  19292. }.bind(this));
  19293. },
  19294. /**
  19295. * Handle the layouting of a sub process.
  19296. * Mainly to adjust the child dockers of a sub process.
  19297. *
  19298. */
  19299. handleSubProcess : function(option) {
  19300. var sh = option.shape;
  19301. if (!this.hashedSubProcesses[sh.id]) {
  19302. this.hashedSubProcesses[sh.id] = sh.absoluteXY();
  19303. this.hashedSubProcesses[sh.id].width = sh.bounds.width();
  19304. this.hashedSubProcesses[sh.id].height = sh.bounds.height();
  19305. return;
  19306. }
  19307. var offset = sh.absoluteXY();
  19308. offset.x -= this.hashedSubProcesses[sh.id].x;
  19309. offset.y -= this.hashedSubProcesses[sh.id].y;
  19310. var resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height();
  19311. this.hashedSubProcesses[sh.id] = sh.absoluteXY();
  19312. this.hashedSubProcesses[sh.id].width = sh.bounds.width();
  19313. this.hashedSubProcesses[sh.id].height = sh.bounds.height();
  19314. this.hashChildShapes(sh);
  19315. // Move dockers only if currently is not resizing
  19316. if (this.facade.isExecutingCommands()&&!resized) {
  19317. this.moveChildDockers(sh, offset);
  19318. }
  19319. },
  19320. moveChildDockers: function(shape, offset){
  19321. if (!offset.x && !offset.y) {
  19322. return;
  19323. }
  19324. var children = shape.getChildNodes(true);
  19325. // Get all nodes
  19326. var dockers = children
  19327. // Get all incoming and outgoing edges
  19328. .map(function(node){
  19329. return [].concat(node.getIncomingShapes())
  19330. .concat(node.getOutgoingShapes())
  19331. })
  19332. // Flatten all including arrays into one
  19333. .flatten()
  19334. // Get every edge only once
  19335. .uniq()
  19336. // Get all dockers
  19337. .map(function(edge){
  19338. return edge.dockers.length > 2 ?
  19339. edge.dockers.slice(1, edge.dockers.length-1) :
  19340. [];
  19341. })
  19342. // Flatten the dockers lists
  19343. .flatten();
  19344. var abs = shape.absoluteBounds();
  19345. abs.moveBy(-offset.x, -offset.y)
  19346. var obj = {};
  19347. dockers.each(function(docker){
  19348. if (docker.isChanged){
  19349. return;
  19350. }
  19351. var off = Object.clone(offset);
  19352. if (!abs.isIncluded(docker.bounds.center())){
  19353. var index = docker.parent.dockers.indexOf(docker);
  19354. var size = docker.parent.dockers.length;
  19355. var from = docker.parent.getSource();
  19356. var to = docker.parent.getTarget();
  19357. var bothAreIncluded = children.include(from) && children.include(to);
  19358. if (!bothAreIncluded){
  19359. var previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index-1].bounds.center()) : false;
  19360. var nextIsOver = index !== size-1 ? abs.isIncluded(docker.parent.dockers[index+1].bounds.center()) : false;
  19361. if (!previousIsOver && !nextIsOver){ return; }
  19362. var ref = docker.parent.dockers[previousIsOver ? index-1 : index+1];
  19363. if (Math.abs(-Math.abs(ref.bounds.center().x-docker.bounds.center().x)) < 2){
  19364. off.y = 0;
  19365. } else if(Math.abs(-Math.abs(ref.bounds.center().y-docker.bounds.center().y)) < 2){
  19366. off.x = 0;
  19367. } else {
  19368. return;
  19369. }
  19370. }
  19371. }
  19372. obj[docker.getId()] = {
  19373. docker:docker,
  19374. offset:off
  19375. }
  19376. })
  19377. // Set dockers
  19378. this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]);
  19379. },
  19380. /**
  19381. * DragDocker.Docked Handler
  19382. *
  19383. */
  19384. handleDockerDocked: function(options) {
  19385. var namespace = this.getNamespace();
  19386. var edge = options.parent;
  19387. var edgeSource = options.target;
  19388. if(edge.getStencil().id() === namespace + "SequenceFlow") {
  19389. var isGateway = edgeSource.getStencil().groups().find(function(group) {
  19390. if(group == "Gateways")
  19391. return group;
  19392. });
  19393. if(!isGateway && (edge.properties["oryx-conditiontype"] == "Expression"))
  19394. // show diamond on edge source
  19395. edge.setProperty("oryx-showdiamondmarker", true);
  19396. else
  19397. // do not show diamond on edge source
  19398. edge.setProperty("oryx-showdiamondmarker", false);
  19399. // update edge rendering
  19400. //edge.update();
  19401. this.facade.getCanvas().update();
  19402. }
  19403. },
  19404. /**
  19405. * PropertyWindow.PropertyChanged Handler
  19406. */
  19407. handlePropertyChanged: function(option) {
  19408. var namespace = this.getNamespace();
  19409. var shapes = option.elements;
  19410. var propertyKey = option.key;
  19411. var propertyValue = option.value;
  19412. var changed = false;
  19413. shapes.each(function(shape){
  19414. if((shape.getStencil().id() === namespace + "SequenceFlow") &&
  19415. (propertyKey === "oryx-conditiontype")) {
  19416. if(propertyValue != "Expression")
  19417. // Do not show the Diamond
  19418. shape.setProperty("oryx-showdiamondmarker", false);
  19419. else {
  19420. var incomingShapes = shape.getIncomingShapes();
  19421. if(!incomingShapes) {
  19422. shape.setProperty("oryx-showdiamondmarker", true);
  19423. }
  19424. var incomingGateway = incomingShapes.find(function(aShape) {
  19425. var foundGateway = aShape.getStencil().groups().find(function(group) {
  19426. if(group == "Gateways")
  19427. return group;
  19428. });
  19429. if(foundGateway)
  19430. return foundGateway;
  19431. });
  19432. if(!incomingGateway)
  19433. // show diamond on edge source
  19434. shape.setProperty("oryx-showdiamondmarker", true);
  19435. else
  19436. // do not show diamond
  19437. shape.setProperty("oryx-showdiamondmarker", false);
  19438. }
  19439. changed = true;
  19440. }
  19441. }.bind(this));
  19442. if(changed) {this.facade.getCanvas().update();}
  19443. },
  19444. hashedPoolPositions : {},
  19445. hashedLaneDepth : {},
  19446. hashedBounds : {},
  19447. hashedPositions: {},
  19448. /**
  19449. * Handler for layouting event 'layout.bpmn2_0.pool'
  19450. * @param {Object} event
  19451. */
  19452. handleLayoutPool: function(event){
  19453. var pool = event.shape;
  19454. var selection = this.facade.getSelection();
  19455. var currentShape = selection.include(pool) ? pool : selection.first();
  19456. currentShape = currentShape || pool;
  19457. this.currentPool = pool;
  19458. // Check if it is a pool or a lane
  19459. if (!(currentShape.getStencil().id().endsWith("Pool") || currentShape.getStencil().id().endsWith("Lane"))) {
  19460. return;
  19461. }
  19462. // Check if the lane is within the pool and is not removed lately
  19463. if (currentShape !== pool && !currentShape.isParent(pool) && !this.hashedBounds[pool.id][currentShape.id]){
  19464. return;
  19465. }
  19466. if (!this.hashedBounds[pool.id]) {
  19467. this.hashedBounds[pool.id] = {};
  19468. }
  19469. // Find all child lanes
  19470. var lanes = this.getLanes(pool);
  19471. if (lanes.length <= 0) {
  19472. return
  19473. }
  19474. var allLanes = this.getLanes(pool, true), hp;
  19475. var considerForDockers = allLanes.clone();
  19476. var hashedPositions = $H({});
  19477. allLanes.each(function(lane){
  19478. hashedPositions[lane.id] = lane.bounds.upperLeft();
  19479. })
  19480. // Show/hide caption regarding the number of lanes
  19481. if (lanes.length === 1 && this.getLanes(lanes.first()).length <= 0) {
  19482. // TRUE if there is a caption
  19483. lanes.first().setProperty("oryx-showcaption", lanes.first().properties["oryx-name"].trim().length > 0);
  19484. var rect = lanes.first().node.getElementsByTagName("rect");
  19485. rect[0].setAttributeNS(null, "display", "none");
  19486. } else {
  19487. allLanes.invoke("setProperty", "oryx-showcaption", true);
  19488. allLanes.each(function(lane){
  19489. var rect = lane.node.getElementsByTagName("rect");
  19490. rect[0].removeAttributeNS(null, "display");
  19491. })
  19492. }
  19493. var deletedLanes = [];
  19494. var addedLanes = [];
  19495. // Get all new lanes
  19496. var i=-1;
  19497. while (++i<allLanes.length) {
  19498. if (!this.hashedBounds[pool.id][allLanes[i].id]){
  19499. addedLanes.push(allLanes[i])
  19500. }
  19501. }
  19502. if (addedLanes.length > 0){
  19503. currentShape = addedLanes.first();
  19504. }
  19505. // Get all deleted lanes
  19506. var resourceIds = $H(this.hashedBounds[pool.id]).keys();
  19507. var i=-1;
  19508. while (++i<resourceIds.length) {
  19509. if (!allLanes.any(function(lane){ return lane.id == resourceIds[i]})){
  19510. deletedLanes.push(this.hashedBounds[pool.id][resourceIds[i]]);
  19511. selection = selection.without(function(r){ return r.id == resourceIds[i] });
  19512. }
  19513. }
  19514. var height, width, x, y;
  19515. if (deletedLanes.length > 0 || addedLanes.length > 0) {
  19516. if (addedLanes.length === 1 && this.getLanes(addedLanes[0].parent).length === 1){
  19517. // Set height from the pool
  19518. height = this.adjustHeight(lanes, addedLanes[0].parent);
  19519. } else {
  19520. // Set height from the pool
  19521. height = this.updateHeight(pool);
  19522. }
  19523. // Set width from the pool
  19524. width = this.adjustWidth(lanes, pool.bounds.width());
  19525. pool.update();
  19526. }
  19527. /**
  19528. * Set width/height depending on the pool
  19529. */
  19530. else if (pool == currentShape) {
  19531. if (selection.length === 1 && this.isResized(pool, this.hashedPoolPositions[pool.id])) {
  19532. var oldXY = this.hashedPoolPositions[pool.id].upperLeft();
  19533. var xy = pool.bounds.upperLeft();
  19534. var scale = 0;
  19535. if (this.shouldScale(pool)){
  19536. var old = this.hashedPoolPositions[pool.id];
  19537. scale = old.height()/pool.bounds.height();
  19538. }
  19539. this.adjustLanes(pool, allLanes, oldXY.x - xy.x, oldXY.y - xy.y, scale);
  19540. }
  19541. // Set height from the pool
  19542. height = this.adjustHeight(lanes, undefined, pool.bounds.height());
  19543. // Set width from the pool
  19544. width = this.adjustWidth(lanes, pool.bounds.width());
  19545. }
  19546. /**???
  19547. * Set width/height depending on containing lanes
  19548. */
  19549. else {
  19550. // Reposition the pool if one shape is selected and the upperleft has changed
  19551. if (selection.length === 1 && this.isResized(currentShape, this.hashedBounds[pool.id][currentShape.id])){
  19552. var oldXY = this.hashedBounds[pool.id][currentShape.id].upperLeft();
  19553. var xy = currentShape.absoluteXY();
  19554. x = oldXY.x - xy.x;
  19555. y = oldXY.y - xy.y;
  19556. // Adjust all other lanes beneath this lane
  19557. if (x||y){
  19558. considerForDockers = considerForDockers.without(currentShape);
  19559. this.adjustLanes(pool, this.getAllExcludedLanes(pool, currentShape), x, 0);
  19560. }
  19561. // Adjust all child lanes
  19562. var childLanes = this.getLanes(currentShape, true);
  19563. if (childLanes.length > 0){
  19564. if (this.shouldScale(currentShape)){
  19565. var old = this.hashedBounds[pool.id][currentShape.id];
  19566. var scale = old.height()/currentShape.bounds.height();
  19567. this.adjustLanes(pool, childLanes, x, y, scale);
  19568. } else {
  19569. this.adjustLanes(pool, childLanes, x, y, 0);
  19570. }
  19571. }
  19572. }
  19573. // Cache all bounds
  19574. var changes = allLanes.map(function(lane){ return {
  19575. shape: lane,
  19576. bounds: lane.bounds.clone()
  19577. } });
  19578. // Get height and adjust child heights
  19579. height = this.adjustHeight(lanes, currentShape);
  19580. // Check if something has changed and maybe create a command
  19581. this.checkForChanges(allLanes, changes);
  19582. // Set width from the current shape
  19583. width = this.adjustWidth(lanes, currentShape.bounds.width()+(this.getDepth(currentShape,pool)*30));
  19584. }
  19585. this.setDimensions(pool, width, height, x, y);
  19586. if (this.facade.isExecutingCommands() && (deletedLanes.length === 0 || addedLanes.length !== 0)){
  19587. // Update all dockers
  19588. this.updateDockers(considerForDockers, pool);
  19589. // Check if the order has changed
  19590. if (this.hashedPositions[pool.id] && this.hashedPositions[pool.id].keys().any(function(key, i){
  19591. return (allLanes[i]||{}).id !== key;
  19592. })){
  19593. var LanesHasBeenReordered = ORYX.Core.Command.extend({
  19594. construct: function(originPosition, newPosition, lanes, plugin, poolId) {
  19595. this.originPosition = Object.clone(originPosition);
  19596. this.newPosition = Object.clone(newPosition);
  19597. this.lanes = lanes;
  19598. this.plugin = plugin;
  19599. this.pool = poolId;
  19600. },
  19601. execute: function(){
  19602. if (!this.executed){
  19603. this.executed = true;
  19604. this.lanes.each(function(lane){
  19605. if (this.newPosition[lane.id])
  19606. lane.bounds.moveTo(this.newPosition[lane.id])
  19607. }.bind(this));
  19608. this.plugin.hashedPositions[this.pool] = Object.clone(this.newPosition);
  19609. }
  19610. },
  19611. rollback: function(){
  19612. this.lanes.each(function(lane){
  19613. if (this.originPosition[lane.id])
  19614. lane.bounds.moveTo(this.originPosition[lane.id])
  19615. }.bind(this));
  19616. this.plugin.hashedPositions[this.pool] = Object.clone(this.originPosition);
  19617. }
  19618. });
  19619. var hp2 = $H({});
  19620. allLanes.each(function(lane){
  19621. hp2[lane.id] = lane.bounds.upperLeft();
  19622. })
  19623. var command = new LanesHasBeenReordered(hashedPositions, hp2, allLanes, this, pool.id);
  19624. this.facade.executeCommands([command]);
  19625. }
  19626. }
  19627. this.hashedBounds[pool.id] = {};
  19628. this.hashedPositions[pool.id] = hashedPositions;
  19629. var i=-1;
  19630. while (++i < allLanes.length) {
  19631. // Cache positions
  19632. this.hashedBounds[pool.id][allLanes[i].id] = allLanes[i].absoluteBounds();
  19633. // Cache also the bounds of child shapes, mainly for child subprocesses
  19634. this.hashChildShapes(allLanes[i]);
  19635. this.hashedLaneDepth[allLanes[i].id] = this.getDepth(allLanes[i], pool);
  19636. this.forceToUpdateLane(allLanes[i]);
  19637. }
  19638. this.hashedPoolPositions[pool.id] = pool.bounds.clone();
  19639. // Update selection
  19640. //this.facade.setSelection(selection);
  19641. },
  19642. shouldScale: function(element){
  19643. var childLanes = element.getChildNodes().findAll(function(shape){ return shape.getStencil().id().endsWith("Lane") })
  19644. return childLanes.length > 1 || childLanes.any(function(lane){ return this.shouldScale(lane) }.bind(this))
  19645. },
  19646. /**
  19647. * Lookup if some bounds has changed
  19648. * @param {Object} lanes
  19649. * @param {Object} changes
  19650. */
  19651. checkForChanges: function(lanes, changes){
  19652. // Check if something has changed
  19653. if (this.facade.isExecutingCommands() && changes.any(function(change){
  19654. return change.shape.bounds.toString() !== change.bounds.toString();
  19655. })){
  19656. var Command = ORYX.Core.Command.extend({
  19657. construct: function(changes) {
  19658. this.oldState = changes;
  19659. this.newState = changes.map(function(s){ return {shape:s.shape, bounds:s.bounds.clone()}});
  19660. },
  19661. execute: function(){
  19662. if (this.executed){
  19663. this.applyState(this.newState);
  19664. }
  19665. this.executed = true;
  19666. },
  19667. rollback: function(){
  19668. this.applyState(this.oldState);
  19669. },
  19670. applyState: function(state){
  19671. state.each(function(s){
  19672. s.shape.bounds.set(s.bounds.upperLeft(), s.bounds.lowerRight());
  19673. })
  19674. }
  19675. });
  19676. this.facade.executeCommands([new Command(changes)]);
  19677. }
  19678. },
  19679. isResized: function(shape, bounds){
  19680. if (!bounds||!shape){
  19681. return false;
  19682. }
  19683. var oldB = bounds;
  19684. //var oldXY = oldB.upperLeft();
  19685. //var xy = shape.absoluteXY();
  19686. return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0
  19687. },
  19688. adjustLanes: function(pool, lanes, x, y, scale){
  19689. scale = scale || 0;
  19690. // For every lane, adjust the child nodes with the offset
  19691. lanes.each(function(l){
  19692. l.getChildNodes().each(function(child){
  19693. if (!child.getStencil().id().endsWith("Lane")){
  19694. var cy = scale ? child.bounds.center().y - (child.bounds.center().y/scale) : -y;
  19695. child.bounds.moveBy((x||0), -cy);
  19696. if (scale&&child.getStencil().id().endsWith("Subprocess")) {
  19697. this.moveChildDockers(child, {x:(0), y:-cy});
  19698. }
  19699. }
  19700. }.bind(this));
  19701. this.hashedBounds[pool.id][l.id].moveBy(-(x||0), !scale?-y:0);
  19702. if (scale) {
  19703. l.isScaled = true;
  19704. }
  19705. }.bind(this))
  19706. },
  19707. getAllExcludedLanes: function(parent, lane){
  19708. var lanes = [];
  19709. parent.getChildNodes().each(function(shape){
  19710. if ((!lane || shape !== lane) && shape.getStencil().id().endsWith("Lane")){
  19711. lanes.push(shape);
  19712. lanes = lanes.concat(this.getAllExcludedLanes(shape, lane));
  19713. }
  19714. }.bind(this));
  19715. return lanes;
  19716. },
  19717. forceToUpdateLane: function(lane){
  19718. if (lane.bounds.height() !== lane._svgShapes[0].height) {
  19719. lane.isChanged = true;
  19720. lane.isResized = true;
  19721. lane._update();
  19722. }
  19723. },
  19724. getDepth: function(child, parent){
  19725. var i=0;
  19726. while(child && child.parent && child !== parent){
  19727. child = child.parent;
  19728. ++i
  19729. }
  19730. return i;
  19731. },
  19732. updateDepth: function(lane, fromDepth, toDepth){
  19733. var xOffset = (fromDepth - toDepth) * 30;
  19734. lane.getChildNodes().each(function(shape){
  19735. shape.bounds.moveBy(xOffset, 0);
  19736. [].concat(children[j].getIncomingShapes())
  19737. .concat(children[j].getOutgoingShapes())
  19738. })
  19739. },
  19740. setDimensions: function(shape, width, height, x, y){
  19741. var isLane = shape.getStencil().id().endsWith("Lane");
  19742. // Set the bounds
  19743. shape.bounds.set(
  19744. isLane ? 30 : (shape.bounds.a.x - (x || 0)),
  19745. isLane ? shape.bounds.a.y : (shape.bounds.a.y - (y || 0)),
  19746. width ? shape.bounds.a.x + width - (isLane?30:(x||0)) : shape.bounds.b.x,
  19747. height ? shape.bounds.a.y + height - (isLane?0:(y||0)) : shape.bounds.b.y
  19748. );
  19749. },
  19750. setLanePosition: function(shape, y){
  19751. shape.bounds.moveTo(30, y);
  19752. },
  19753. adjustWidth: function(lanes, width) {
  19754. // Set width to each lane
  19755. (lanes||[]).each(function(lane){
  19756. this.setDimensions(lane, width);
  19757. this.adjustWidth(this.getLanes(lane), width-30);
  19758. }.bind(this));
  19759. return width;
  19760. },
  19761. adjustHeight: function(lanes, changedLane, propagateHeight){
  19762. var oldHeight = 0;
  19763. if (!changedLane && propagateHeight){
  19764. var i=-1;
  19765. while (++i<lanes.length){
  19766. oldHeight += lanes[i].bounds.height();
  19767. }
  19768. }
  19769. var i=-1;
  19770. var height = 0;
  19771. // Iterate trough every lane
  19772. while (++i<lanes.length){
  19773. if (lanes[i] === changedLane) {
  19774. // Propagate new height down to the children
  19775. this.adjustHeight(this.getLanes(lanes[i]), undefined, lanes[i].bounds.height());
  19776. lanes[i].bounds.set({x:30, y:height}, {x:lanes[i].bounds.width()+30, y:lanes[i].bounds.height()+height})
  19777. } else if (!changedLane && propagateHeight) {
  19778. var tempHeight = (lanes[i].bounds.height() * propagateHeight) / oldHeight;
  19779. // Propagate height
  19780. this.adjustHeight(this.getLanes(lanes[i]), undefined, tempHeight);
  19781. // Set height propotional to the propagated and old height
  19782. this.setDimensions(lanes[i], null, tempHeight);
  19783. this.setLanePosition(lanes[i], height);
  19784. } else {
  19785. // Get height from children
  19786. var tempHeight = this.adjustHeight(this.getLanes(lanes[i]), changedLane, propagateHeight);
  19787. if (!tempHeight) {
  19788. tempHeight = lanes[i].bounds.height();
  19789. }
  19790. this.setDimensions(lanes[i], null, tempHeight);
  19791. this.setLanePosition(lanes[i], height);
  19792. }
  19793. height += lanes[i].bounds.height();
  19794. }
  19795. return height;
  19796. },
  19797. updateHeight: function(root){
  19798. var lanes = this.getLanes(root);
  19799. if (lanes.length == 0){
  19800. return root.bounds.height();
  19801. }
  19802. var height = 0;
  19803. var i=-1;
  19804. while (++i < lanes.length) {
  19805. this.setLanePosition(lanes[i], height);
  19806. height += this.updateHeight(lanes[i]);
  19807. }
  19808. this.setDimensions(root, null, height);
  19809. return height;
  19810. },
  19811. getOffset: function(lane, includePool, pool){
  19812. var offset = {x:0,y:0};
  19813. /*var parent = lane;
  19814. while(parent) {
  19815. var offParent = this.hashedBounds[pool.id][parent.id] ||(includePool === true ? this.hashedPoolPositions[parent.id] : undefined);
  19816. if (offParent){
  19817. var ul = parent.bounds.upperLeft();
  19818. var ulo = offParent.upperLeft();
  19819. offset.x += ul.x-ulo.x;
  19820. offset.y += ul.y-ulo.y;
  19821. }
  19822. if (parent.getStencil().id().endsWith("Pool")) {
  19823. break;
  19824. }
  19825. parent = parent.parent;
  19826. } */
  19827. var offset = lane.absoluteXY();
  19828. var hashed = this.hashedBounds[pool.id][lane.id] ||(includePool === true ? this.hashedPoolPositions[lane.id] : undefined);
  19829. if (hashed) {
  19830. offset.x -= hashed.upperLeft().x;
  19831. offset.y -= hashed.upperLeft().y;
  19832. } else {
  19833. return {x:0,y:0}
  19834. }
  19835. return offset;
  19836. },
  19837. getNextLane: function(shape){
  19838. while(shape && !shape.getStencil().id().endsWith("Lane")){
  19839. if (shape instanceof ORYX.Core.Canvas) {
  19840. return null;
  19841. }
  19842. shape = shape.parent;
  19843. }
  19844. return shape;
  19845. },
  19846. getParentPool: function(shape){
  19847. while(shape && !shape.getStencil().id().endsWith("Pool")){
  19848. if (shape instanceof ORYX.Core.Canvas) {
  19849. return null;
  19850. }
  19851. shape = shape.parent;
  19852. }
  19853. return shape;
  19854. },
  19855. updateDockers: function(lanes, pool){
  19856. var absPool = pool.absoluteBounds(), movedShapes = [];
  19857. var oldPool = (this.hashedPoolPositions[pool.id]||absPool).clone();
  19858. var i=-1, j=-1, k=-1, l=-1, docker;
  19859. var dockers = {};
  19860. while (++i < lanes.length) {
  19861. if (!this.hashedBounds[pool.id][lanes[i].id]) {
  19862. continue;
  19863. }
  19864. var isScaled = lanes[i].isScaled;
  19865. delete lanes[i].isScaled;
  19866. var children = lanes[i].getChildNodes();
  19867. var absBounds = lanes[i].absoluteBounds();
  19868. var oldBounds = (this.hashedBounds[pool.id][lanes[i].id]||absBounds);
  19869. //oldBounds.moveBy((absBounds.upperLeft().x-lanes[i].bounds.upperLeft().x), (absBounds.upperLeft().y-lanes[i].bounds.upperLeft().y));
  19870. var offset = this.getOffset(lanes[i], true, pool);
  19871. var xOffsetDepth = 0;
  19872. var depth = this.getDepth(lanes[i], pool);
  19873. if ( this.hashedLaneDepth[lanes[i].id] !== undefined && this.hashedLaneDepth[lanes[i].id] !== depth) {
  19874. xOffsetDepth = (this.hashedLaneDepth[lanes[i].id] - depth) * 30;
  19875. offset.x += xOffsetDepth;
  19876. }
  19877. j=-1;
  19878. while (++j < children.length) {
  19879. if (xOffsetDepth && !children[j].getStencil().id().endsWith("Lane")) {
  19880. movedShapes.push({xOffset:xOffsetDepth, shape: children[j]});
  19881. children[j].bounds.moveBy(xOffsetDepth, 0);
  19882. }
  19883. if (children[j].getStencil().id().endsWith("Subprocess")) {
  19884. this.moveChildDockers(children[j], offset);
  19885. }
  19886. var edges = [].concat(children[j].getIncomingShapes())
  19887. .concat(children[j].getOutgoingShapes())
  19888. // Remove all edges which are included in the selection from the list
  19889. .findAll(function(r){ return r instanceof ORYX.Core.Edge })
  19890. k=-1;
  19891. while (++k < edges.length) {
  19892. if (edges[k].getStencil().id().endsWith("MessageFlow")) {
  19893. this.layoutEdges(children[j], [edges[k]], offset);
  19894. continue;
  19895. }
  19896. l=-1;
  19897. while (++l < edges[k].dockers.length) {
  19898. docker = edges[k].dockers[l];
  19899. if (docker.getDockedShape()||docker.isChanged){
  19900. continue;
  19901. }
  19902. pos = docker.bounds.center();
  19903. // Check if the modified center included the new position
  19904. var isOverLane = oldBounds.isIncluded(pos);
  19905. // Check if the original center is over the pool
  19906. var isOutSidePool = !oldPool.isIncluded(pos);
  19907. var previousIsOverLane = l == 0 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l-1].bounds.center());
  19908. var nextIsOverLane = l == edges[k].dockers.length-1 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l+1].bounds.center());
  19909. var off = Object.clone(offset);
  19910. // If the
  19911. if (isScaled && isOverLane && this.isResized(lanes[i], this.hashedBounds[pool.id][lanes[i].id])){
  19912. var relY = (pos.y - absBounds.upperLeft().y + off.y);
  19913. off.y -= (relY - (relY * (absBounds.height()/oldBounds.height())));
  19914. }
  19915. // Check if the previous dockers docked shape is from this lane
  19916. // Otherwise, check if the docker is over the lane OR is outside the lane
  19917. // but the previous/next was over this lane
  19918. if (isOverLane){
  19919. dockers[docker.id] = {docker: docker, offset:off};
  19920. }
  19921. /*else if (l == 1 && edges[k].dockers.length>2 && edges[k].dockers[l-1].isDocked()){
  19922. var dockedLane = this.getNextLane(edges[k].dockers[l-1].getDockedShape());
  19923. if (dockedLane != lanes[i])
  19924. continue;
  19925. dockers[docker.id] = {docker: docker, offset:offset};
  19926. }
  19927. // Check if the next dockers docked shape is from this lane
  19928. else if (l == edges[k].dockers.length-2 && edges[k].dockers.length>2 && edges[k].dockers[l+1].isDocked()){
  19929. var dockedLane = this.getNextLane(edges[k].dockers[l+1].getDockedShape());
  19930. if (dockedLane != lanes[i])
  19931. continue;
  19932. dockers[docker.id] = {docker: docker, offset:offset};
  19933. }
  19934. else if (isOutSidePool) {
  19935. dockers[docker.id] = {docker: docker, offset:this.getOffset(lanes[i], true, pool)};
  19936. }*/
  19937. }
  19938. }
  19939. }
  19940. }
  19941. // Move the moved children
  19942. var MoveChildCommand = ORYX.Core.Command.extend({
  19943. construct: function(state){
  19944. this.state = state;
  19945. },
  19946. execute: function(){
  19947. if (this.executed){
  19948. this.state.each(function(s){
  19949. s.shape.bounds.moveBy(s.xOffset, 0);
  19950. });
  19951. }
  19952. this.executed = true;
  19953. },
  19954. rollback: function(){
  19955. this.state.each(function(s){
  19956. s.shape.bounds.moveBy(-s.xOffset, 0);
  19957. });
  19958. }
  19959. })
  19960. // Set dockers
  19961. this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(dockers), new MoveChildCommand(movedShapes)]);
  19962. },
  19963. moveBy: function(pos, offset){
  19964. pos.x += offset.x;
  19965. pos.y += offset.y;
  19966. return pos;
  19967. },
  19968. getHashedBounds: function(shape){
  19969. return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds();
  19970. },
  19971. /**
  19972. * Returns a set on all child lanes for the given Shape. If recursive is TRUE, also indirect children will be returned (default is FALSE)
  19973. * The set is sorted with first child the lowest y-coordinate and the last one the highest.
  19974. * @param {ORYX.Core.Shape} shape
  19975. * @param {boolean} recursive
  19976. */
  19977. getLanes: function(shape, recursive){
  19978. var namespace = this.getNamespace();
  19979. // Get all the child lanes
  19980. var lanes = shape.getChildNodes(recursive||false).findAll(function(node) { return (node.getStencil().id() === namespace + "Lane"); });
  19981. // Sort all lanes by there y coordinate
  19982. lanes = lanes.sort(function(a, b){
  19983. // Get y coordinates for upper left and lower right
  19984. var auy = Math.round(a.bounds.upperLeft().y);
  19985. var buy = Math.round(b.bounds.upperLeft().y);
  19986. var aly = Math.round(a.bounds.lowerRight().y);
  19987. var bly = Math.round(b.bounds.lowerRight().y);
  19988. var ha = this.getHashedBounds(a);
  19989. var hb = this.getHashedBounds(b);
  19990. // Get the old y coordinates
  19991. var oauy = Math.round(ha.upperLeft().y);
  19992. var obuy = Math.round(hb.upperLeft().y);
  19993. var oaly = Math.round(ha.lowerRight().y);
  19994. var obly = Math.round(hb.lowerRight().y);
  19995. // If equal, than use the old one
  19996. if (auy == buy && aly == bly) {
  19997. auy = oauy; buy = obuy; aly = oaly; bly = obly;
  19998. }
  19999. if (Math.round(a.bounds.height()-ha.height()) === 0 && Math.round(b.bounds.height()-hb.height()) === 0){
  20000. return auy < buy ? -1 : (auy > buy ? 1: 0);
  20001. }
  20002. // Check if upper left and lower right is completely above/below
  20003. var above = auy < buy && aly < bly;
  20004. var below = auy > buy && aly > bly;
  20005. // Check if a is above b including the old values
  20006. var slightlyAboveBottom = auy < buy && aly >= bly && oaly < obly;
  20007. var slightlyAboveTop = auy >= buy && aly < bly && oauy < obuy;
  20008. // Check if a is below b including the old values
  20009. var slightlyBelowBottom = auy > buy && aly <= bly && oaly > obly;
  20010. var slightlyBelowTop = auy <= buy && aly > bly && oauy > obuy;
  20011. // Return -1 if a is above b, 1 if b is above a, or 0 otherwise
  20012. return (above || slightlyAboveBottom || slightlyAboveTop ? -1 : (below || slightlyBelowBottom || slightlyBelowTop ? 1 : 0))
  20013. }.bind(this));
  20014. // Return lanes
  20015. return lanes;
  20016. },
  20017. getNamespace: function() {
  20018. if(!this.namespace) {
  20019. var stencilsets = this.facade.getStencilSets();
  20020. if(stencilsets.keys()) {
  20021. this.namespace = stencilsets.keys()[0];
  20022. } else {
  20023. return undefined;
  20024. }
  20025. }
  20026. return this.namespace;
  20027. }
  20028. };
  20029. var ResizeLanesCommand = ORYX.Core.Command.extend({
  20030. construct: function(shape, parent, pool, plugin) {
  20031. this.facade = plugin.facade;
  20032. this.plugin = plugin;
  20033. this.shape = shape;
  20034. this.changes;
  20035. this.pool = pool;
  20036. this.parent = parent;
  20037. this.shapeChildren = [];
  20038. /*
  20039. * The Bounds have to be stored
  20040. * separate because they would
  20041. * otherwise also be influenced
  20042. */
  20043. this.shape.getChildShapes().each(function(childShape) {
  20044. this.shapeChildren.push({
  20045. shape: childShape,
  20046. bounds: {
  20047. a: {
  20048. x: childShape.bounds.a.x,
  20049. y: childShape.bounds.a.y
  20050. },
  20051. b: {
  20052. x: childShape.bounds.b.x,
  20053. y: childShape.bounds.b.y
  20054. }
  20055. }
  20056. });
  20057. }.bind(this));
  20058. this.shapeUpperLeft = this.shape.bounds.upperLeft();
  20059. // If there is no parent,
  20060. // correct the abs position with the parents abs.
  20061. /*if (!this.shape.parent) {
  20062. var pAbs = parent.absoluteXY();
  20063. this.shapeUpperLeft.x += pAbs.x;
  20064. this.shapeUpperLeft.y += pAbs.y;
  20065. }*/
  20066. this.parentHeight = this.parent.bounds.height();
  20067. },
  20068. getLeafLanes: function(lane){
  20069. var childLanes = this.plugin.getLanes(lane).map(function(child){
  20070. return this.getLeafLanes(child);
  20071. }.bind(this)).flatten();
  20072. return childLanes.length > 0 ? childLanes : [lane];
  20073. },
  20074. findNewLane: function(){
  20075. var lanes = this.plugin.getLanes(this.parent);
  20076. var leafLanes = this.getLeafLanes(this.parent);
  20077. /*leafLanes = leafLanes.sort(function(a,b){
  20078. var aupl = a.absoluteXY().y;
  20079. var bupl = b.absoluteXY().y;
  20080. return aupl < bupl ? -1 : (aupl > bupl ? 1 : 0)
  20081. })*/
  20082. this.lane = leafLanes.find(function(l){ return l.bounds.upperLeft().y >= this.shapeUpperLeft.y }.bind(this)) || leafLanes.last();
  20083. this.laneUpperLeft = this.lane.bounds.upperLeft();
  20084. },
  20085. execute: function() {
  20086. if(this.changes) {
  20087. this.executeAgain();
  20088. return;
  20089. }
  20090. /*
  20091. * Rescue all ChildShapes of the deleted
  20092. * Shape into the lane that takes its
  20093. * place
  20094. */
  20095. if (!this.lane){
  20096. this.findNewLane();
  20097. }
  20098. if(this.lane) {
  20099. var laUpL = this.laneUpperLeft;
  20100. var shUpL = this.shapeUpperLeft;
  20101. var depthChange = this.plugin.getDepth(this.lane, this.parent)-1;
  20102. this.changes = $H({});
  20103. // Selected lane is BELOW the removed lane
  20104. if (laUpL.y >= shUpL.y) {
  20105. this.lane.getChildShapes().each(function(childShape) {
  20106. /*
  20107. * Cache the changes for rollback
  20108. */
  20109. if(!this.changes[childShape.getId()]) {
  20110. this.changes[childShape.getId()] = this.computeChanges(childShape, this.lane, this.lane, this.shape.bounds.height());
  20111. }
  20112. childShape.bounds.moveBy(0, this.shape.bounds.height());
  20113. }.bind(this));
  20114. this.plugin.hashChildShapes(this.lane);
  20115. this.shapeChildren.each(function(shapeChild) {
  20116. shapeChild.shape.bounds.set(shapeChild.bounds);
  20117. shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), 0);
  20118. /*
  20119. * Cache the changes for rollback
  20120. */
  20121. if(!this.changes[shapeChild.shape.getId()]) {
  20122. this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);
  20123. }
  20124. this.lane.add(shapeChild.shape);
  20125. }.bind(this));
  20126. this.lane.bounds.moveBy(0, shUpL.y-laUpL.y);
  20127. // Selected lane is ABOVE the removed lane
  20128. } else if(shUpL.y > laUpL.y){
  20129. this.shapeChildren.each(function(shapeChild) {
  20130. shapeChild.shape.bounds.set(shapeChild.bounds);
  20131. shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), this.lane.bounds.height());
  20132. /*
  20133. * Cache the changes for rollback
  20134. */
  20135. if(!this.changes[shapeChild.shape.getId()]) {
  20136. this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0);
  20137. }
  20138. this.lane.add(shapeChild.shape);
  20139. }.bind(this));
  20140. }
  20141. }
  20142. /*
  20143. * Adjust the height of the lanes
  20144. */
  20145. // Get the height values
  20146. var oldHeight = this.lane.bounds.height();
  20147. var newHeight = this.lane.length === 1 ? this.parentHeight : this.lane.bounds.height() + this.shape.bounds.height();
  20148. // Set height
  20149. this.setHeight(newHeight, oldHeight, this.parent, this.parentHeight, true);
  20150. // Cache all sibling lanes
  20151. //this.changes[this.shape.getId()] = this.computeChanges(this.shape, this.parent, this.parent, 0);
  20152. this.plugin.getLanes(this.parent).each(function(childLane){
  20153. if(!this.changes[childLane.getId()] && childLane !== this.lane && childLane !== this.shape) {
  20154. this.changes[childLane.getId()] = this.computeChanges(childLane, this.parent, this.parent, 0);
  20155. }
  20156. }.bind(this))
  20157. // Update
  20158. this.update();
  20159. },
  20160. setHeight: function(newHeight, oldHeight, parent, parentHeight, store){
  20161. // Set heigh of the lane
  20162. this.plugin.setDimensions(this.lane, this.lane.bounds.width(), newHeight);
  20163. this.plugin.hashedBounds[this.pool.id][this.lane.id] = this.lane.absoluteBounds();
  20164. // Adjust child lanes
  20165. this.plugin.adjustHeight(this.plugin.getLanes(parent), this.lane);
  20166. if (store === true){
  20167. // Store changes
  20168. this.changes[this.shape.getId()] = this.computeChanges(this.shape, parent, parent, 0, oldHeight, newHeight);
  20169. }
  20170. // Set parents height
  20171. this.plugin.setDimensions(parent, parent.bounds.width(), parentHeight);
  20172. if (parent !== this.pool){
  20173. this.plugin.setDimensions(this.pool, this.pool.bounds.width(), this.pool.bounds.height() + (newHeight-oldHeight));
  20174. }
  20175. },
  20176. update: function(){
  20177. // Hack to prevent the updating of the dockers
  20178. this.plugin.hashedBounds[this.pool.id]["REMOVED"] = true;
  20179. // Update
  20180. //this.facade.getCanvas().update();
  20181. },
  20182. rollback: function() {
  20183. var laUpL = this.laneUpperLeft;
  20184. var shUpL = this.shapeUpperLeft;
  20185. this.changes.each(function(pair) {
  20186. var parent = pair.value.oldParent;
  20187. var shape = pair.value.shape;
  20188. var parentHeight = pair.value.parentHeight;
  20189. var oldHeight = pair.value.oldHeight;
  20190. var newHeight = pair.value.newHeight;
  20191. // Move siblings
  20192. if (shape.getStencil().id().endsWith("Lane")){
  20193. shape.bounds.moveTo(pair.value.oldPosition);
  20194. }
  20195. // If lane
  20196. if(oldHeight) {
  20197. this.setHeight(oldHeight, newHeight, parent, parent.bounds.height() + (oldHeight - newHeight));
  20198. if (laUpL.y >= shUpL.y) {
  20199. this.lane.bounds.moveBy(0, this.shape.bounds.height()-1);
  20200. }
  20201. } else {
  20202. parent.add(shape);
  20203. shape.bounds.moveTo(pair.value.oldPosition);
  20204. }
  20205. }.bind(this));
  20206. // Update
  20207. //this.update();
  20208. },
  20209. executeAgain: function() {
  20210. this.changes.each(function(pair) {
  20211. var parent = pair.value.newParent;
  20212. var shape = pair.value.shape;
  20213. var newHeight = pair.value.newHeight;
  20214. var oldHeight = pair.value.oldHeight;
  20215. // If lane
  20216. if(newHeight) {
  20217. var laUpL = this.laneUpperLeft.y;
  20218. var shUpL = this.shapeUpperLeft.y;
  20219. if (laUpL >= shUpL) {
  20220. this.lane.bounds.moveBy(0, shUpL - laUpL);
  20221. }
  20222. this.setHeight(newHeight, oldHeight, parent, parent.bounds.height() + (newHeight-oldHeight));
  20223. } else {
  20224. parent.add(shape);
  20225. shape.bounds.moveTo(pair.value.newPosition);
  20226. }
  20227. }.bind(this));
  20228. // Update
  20229. this.update();
  20230. },
  20231. computeChanges: function(shape, oldParent, parent, yOffset, oldHeight, newHeight) {
  20232. oldParent = this.changes[shape.getId()] ? this.changes[shape.getId()].oldParent : oldParent;
  20233. var oldPosition = this.changes[shape.getId()] ? this.changes[shape.getId()].oldPosition : shape.bounds.upperLeft();
  20234. var sUl = shape.bounds.upperLeft();
  20235. var pos = {x: sUl.x, y: sUl.y + yOffset};
  20236. var changes = {
  20237. shape : shape,
  20238. parentHeight: oldParent.bounds.height(),
  20239. oldParent : oldParent,
  20240. oldPosition : oldPosition,
  20241. oldHeight : oldHeight,
  20242. newParent : parent,
  20243. newPosition : pos,
  20244. newHeight : newHeight
  20245. };
  20246. return changes;
  20247. }
  20248. });
  20249. ORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0);
  20250. }()