12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842 |
- /**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * @namespace Oryx name space for different utility methods
- * @name ORYX.Utils
- */
- ORYX.Utils = {
- /**
- * General helper method for parsing a param out of current location url
- * @example
- * // Current url in Browser => "http://oryx.org?param=value"
- * ORYX.Utils.getParamFromUrl("param") // => "value"
- * @param {Object} name
- */
- getParamFromUrl: function(name){
- name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
- var regexS = "[\\?&]" + name + "=([^&#]*)";
- var regex = new RegExp(regexS);
- var results = regex.exec(window.location.href);
- if (results == null) {
- return null;
- }
- else {
- return results[1];
- }
- },
-
- adjustLightness: function(){
- return arguments[0];
- },
-
- adjustGradient: function(gradient, reference){
-
- if (ORYX.CONFIG.DISABLE_GRADIENT && gradient){
-
- var col = reference.getAttributeNS(null, "stop-color") || "#ffffff";
-
- $A(gradient.getElementsByTagName("stop")).each(function(stop){
- if (stop == reference){ return; }
- stop.setAttributeNS(null, "stop-color", col);
- })
- }
- }
- }
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- XMLNS = {
- ATOM: "http://www.w3.org/2005/Atom",
- XHTML: "http://www.w3.org/1999/xhtml",
- ERDF: "http://purl.org/NET/erdf/profile",
- RDFS: "http://www.w3.org/2000/01/rdf-schema#",
- RDF: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
- RAZIEL: "http://b3mn.org/Raziel",
- SCHEMA: ""
- };
- //TODO kann kickstart sich vielleicht auch um die erzeugung von paketen/
- // namespaces k�mmern? z.b. requireNamespace("ORYX.Core.SVG");
- var Kickstart = {
- started: false,
- callbacks: [],
- alreadyLoaded: [],
- PATH: '',
- load: function() { Kickstart.kick(); },
- kick: function() {
- //console.profile("loading");
- if(!Kickstart.started) {
- Kickstart.started = true;
- Kickstart.callbacks.each(function(callback){
- // call the registered callback asynchronously.
- window.setTimeout(callback, 1);
- });
- }
- },
- register: function(callback) {
- //TODO Add some mutual exclusion between kick and register calls.
- with(Kickstart) {
- if(started) window.setTimeout(callback, 1);
- else Kickstart.callbacks.push(callback)
- }
- },
- /**
- * Loads a js, assuring that it has only been downloaded once.
- * @param {String} url the script to load.
- */
- require: function(url) {
- // if not already loaded, include it.
- if(Kickstart.alreadyLoaded.member(url))
- return false;
- return Kickstart.include(url);
- },
- /**
- * Loads a js, regardless of whether it has only been already downloaded.
- * @param {String} url the script to load.
- */
- include: function(url) {
- // prepare a script tag and place it in html head.
- var head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0];
- var s = document.createElementNS(XMLNS.XHTML, "script");
- s.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript');
- s.src = Kickstart.PATH + url;
- //TODO macht es sinn, dass neue skript als letztes kind in den head
- // einzubinden (stichwort reihenfolge der skript tags)?
- head.appendChild(s);
- // remember this url.
- Kickstart.alreadyLoaded.push(url);
- return true;
- }
- }
- // register kickstart as the new onload event listener on current window.
- // previous listener(s) are triggered to launch with kickstart.
- Event.observe(window, 'load', Kickstart.load);/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- var ERDF = {
- LITERAL: 0x01,
- RESOURCE: 0x02,
- DELIMITERS: ['.', '-'],
- HASH: '#',
- HYPHEN: "-",
- schemas: [],
- callback: undefined,
- log: undefined,
- init: function(callback) {
-
- // init logging.
- //ERDF.log = Log4js.getLogger("oryx");
- //ERDF.log.setLevel(Log4js.Level.ALL);
- //ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false));
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace("ERDF Parser is initialized.");
- // register callbacks and default schemas.
- ERDF.callback = callback;
- ERDF.registerSchema('schema', XMLNS.SCHEMA);
- ERDF.registerSchema('rdfs', XMLNS.RDFS);
- },
- run: function() {
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace("ERDF Parser is running.");
- // do the work.
- return ERDF._checkProfile() && ERDF.parse();
- },
-
- parse: function() {
-
- //(ERDF.log.isDebugEnabled())
- // ERDF.log.debug("Begin parsing document metadata.");
-
- // time measuring
- ERDF.__startTime = new Date();
- var bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body');
- var subject = {type: ERDF.RESOURCE, value: ''};
- var result = ERDF._parseDocumentMetadata() &&
- ERDF._parseFromTag(bodies[0], subject);
-
- // time measuring
- ERDF.__stopTime = new Date();
- var duration = (ERDF.__stopTime - ERDF.__startTime)/1000.;
- //alert('ERDF parsing took ' + duration + ' s.');
-
- return result;
- },
-
- _parseDocumentMetadata: function() {
- // get links from head element.
- var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');
- var links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link');
- var metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta');
- // process links first, since they could contain schema definitions.
- $A(links).each(function(link) {
- var properties = link.getAttribute('rel');
- var reversedProperties = link.getAttribute('rev');
- var value = link.getAttribute('href');
-
- ERDF._parseTriplesFrom(
- ERDF.RESOURCE, '',
- properties,
- ERDF.RESOURCE, value);
-
- ERDF._parseTriplesFrom(
- ERDF.RESOURCE, value,
- reversedProperties,
- ERDF.RESOURCE, '');
- });
- // continue with metas.
- $A(metas).each(function(meta) {
- var property = meta.getAttribute('name');
- var value = meta.getAttribute('content');
-
- ERDF._parseTriplesFrom(
- ERDF.RESOURCE, '',
- property,
- ERDF.LITERAL, value);
- });
- return true;
- },
-
- _parseFromTag: function(node, subject, depth) {
-
- // avoid parsing non-xhtml content.
- if(node.namespaceURI != XMLNS.XHTML) { return; }
-
- // housekeeping.
- if(!depth) depth=0;
- var id = node.getAttribute('id');
- // some logging.
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace(">".times(depth) + " Parsing " + node.nodeName + " ("+node.nodeType+") for data on " +
- // ((subject.type == ERDF.RESOURCE) ? ('<' + subject.value + '>') : '') +
- // ((subject.type == ERDF.LITERAL) ? '"' + subject.value + '"' : ''));
-
- /* triple finding! */
-
- // in a-tags...
- if(node.nodeName.endsWith(':a') || node.nodeName == 'a') {
- var properties = node.getAttribute('rel');
- var reversedProperties = node.getAttribute('rev');
- var value = node.getAttribute('href');
- var title = node.getAttribute('title');
- var content = node.textContent;
- // rel triples
- ERDF._parseTriplesFrom(
- subject.type, subject.value,
- properties,
- ERDF.RESOURCE, value,
- function(triple) {
- var label = title? title : content;
-
- // label triples
- ERDF._parseTriplesFrom(
- triple.object.type, triple.object.value,
- 'rdfs.label',
- ERDF.LITERAL, label);
- });
- // rev triples
- ERDF._parseTriplesFrom(
- subject.type, subject.value,
- reversedProperties,
- ERDF.RESOURCE, '');
-
- // type triples
- ERDF._parseTypeTriplesFrom(
- subject.type, subject.value,
- properties);
- // in img-tags...
- } else if(node.nodeName.endsWith(':img') || node.nodeName == 'img') {
- var properties = node.getAttribute('class');
- var value = node.getAttribute('src');
- var alt = node.getAttribute('alt');
- ERDF._parseTriplesFrom(
- subject.type, subject.value,
- properties,
- ERDF.RESOURCE, value,
- function(triple) {
- var label = alt;
-
- // label triples
- ERDF._parseTriplesFrom(
- triple.object.type, triple.object.value,
- 'rdfs.label',
- ERDF.LITERAL, label);
- });
- }
-
- // in every tag
- var properties = node.getAttribute('class');
- var title = node.getAttribute('title');
- var content = node.textContent;
- var label = title ? title : content;
-
- // regular triples
- ERDF._parseTriplesFrom(
- subject.type, subject.value,
- properties,
- ERDF.LITERAL, label);
- if(id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH+id};
-
- // type triples
- ERDF._parseTypeTriplesFrom(
- subject.type, subject.value,
- properties);
- // parse all children that are element nodes.
- var children = node.childNodes;
- if(children) $A(children).each(function(_node) {
- if(_node.nodeType == _node.ELEMENT_NODE)
- ERDF._parseFromTag(_node, subject, depth+1); });
- },
-
- _parseTriplesFrom: function(subjectType, subject, properties,
- objectType, object, callback) {
-
- if(!properties) return;
- properties.toLowerCase().split(' ').each( function(property) {
-
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace("Going for property " + property);
- var schema = ERDF.schemas.find( function(schema) {
- return false || ERDF.DELIMITERS.find( function(delimiter) {
- return property.startsWith(schema.prefix + delimiter);
- });
- });
-
- if(schema && object) {
- property = property.substring(
- schema.prefix.length+1, property.length);
- var triple = ERDF.registerTriple(
- new ERDF.Resource(subject),
- {prefix: schema.prefix, name: property},
- (objectType == ERDF.RESOURCE) ?
- new ERDF.Resource(object) :
- new ERDF.Literal(object));
-
- if(callback) callback(triple);
- }
- });
- },
-
- _parseTypeTriplesFrom: function(subjectType, subject, properties, callback) {
-
- if(!properties) return;
- properties.toLowerCase().split(' ').each( function(property) {
-
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace("Going for property " + property);
-
- var schema = ERDF.schemas.find( function(schema) {
- return false || ERDF.DELIMITERS.find( function(delimiter) {
- return property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter);
- });
- });
-
- if(schema && subject) {
- property = property.substring(schema.prefix.length+2, property.length);
- var triple = ERDF.registerTriple(
- (subjectType == ERDF.RESOURCE) ?
- new ERDF.Resource(subject) :
- new ERDF.Literal(subject),
- {prefix: 'rdf', name: 'type'},
- new ERDF.Resource(schema.namespace+property));
- if(callback) callback(triple);
- }
- });
- },
-
- /**
- * Checks for ERDF profile declaration in head of document.
- */
- _checkProfile: function() {
- // get profiles from head element.
- var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head');
- var profiles = heads[0].getAttribute("profile");
- var found = false;
- // if erdf profile is contained.
- if(profiles && profiles.split(" ").member(XMLNS.ERDF)) {
- // pass check.
- //if(ERDF.log.isTraceEnabled())
- // ERDF.log.trace("Found ERDF profile " + XMLNS.ERDF);
- return true;
-
- } else {
-
- // otherwise fail check.
- //if(ERDF.log.isFatalEnabled())
- // ERDF.log.fatal("No ERDF profile found.");
- return false;
- }
- },
-
- __stripHashes: function(s) {
- return (s && s.substring(0, 1)=='#') ? s.substring(1, s.length) : s;
- },
-
- registerSchema: function(prefix, namespace) {
-
- // TODO check whether already registered, if so, complain.
- ERDF.schemas.push({
- prefix: prefix,
- namespace: namespace
- });
-
- //if(ERDF.log.isDebugEnabled())
- // ERDF.log.debug("Prefix '"+prefix+"' for '"+namespace+"' registered.");
- },
-
- registerTriple: function(subject, predicate, object) {
-
- // if prefix is schema, this is a schema definition.
- if(predicate.prefix.toLowerCase() == 'schema')
- this.registerSchema(predicate.name, object.value);
-
- var triple = new ERDF.Triple(subject, predicate, object);
- ERDF.callback(triple);
-
- //if(ERDF.log.isInfoEnabled())
- // ERDF.log.info(triple)
-
- // return the registered triple.
- return triple;
- },
-
- __enhanceObject: function() {
-
- /* Resource state querying methods */
- this.isResource = function() {
- return this.type == ERDF.RESOURCE };
- this.isLocal = function() {
- return this.isResource() && this.value.startsWith('#') };
- this.isCurrentDocument = function() {
- return this.isResource() && (this.value == '') };
-
- /* Resource getter methods.*/
- this.getId = function() {
- return this.isLocal() ? ERDF.__stripHashes(this.value) : false; };
- /* Liiteral state querying methods */
- this.isLiteral = function() {
- return this.type == ERDF.LIITERAL };
- },
-
- serialize: function(literal) {
-
- if(!literal){
- return "";
- }else if(literal.constructor == String) {
- return literal;
- } else if(literal.constructor == Boolean) {
- return literal? 'true':'false';
- } else {
- return literal.toString();
- }
- }
- };
- ERDF.Triple = function(subject, predicate, object) {
-
- this.subject = subject;
- this.predicate = predicate;
- this.object = object;
-
- this.toString = function() {
-
- return "[ERDF.Triple] " +
- this.subject.toString() + ' ' +
- this.predicate.prefix + ':' + this.predicate.name + ' ' +
- this.object.toString();
- };
- };
- ERDF.Resource = function(uri) {
-
- this.type = ERDF.RESOURCE;
- this.value = uri;
- ERDF.__enhanceObject.apply(this);
-
- this.toString = function() {
- return '<' + this.value + '>';
- }
-
- };
- ERDF.Literal = function(literal) {
-
- this.type = ERDF.LITERAL;
- this.value = ERDF.serialize(literal);
- ERDF.__enhanceObject.apply(this);
- this.toString = function() {
- return '"' + this.value + '"';
- }
- };/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /*
- * Save and triple generation behaviour. Use this area to configure
- * data management to your needs.
- */
- var USE_ASYNCHRONOUS_REQUESTS = true;
- var DISCARD_UNUSED_TRIPLES = true;
- var PREFER_SPANS_OVER_DIVS = true;
- var PREFER_TITLE_OVER_TEXTNODE = false;
- var RESOURCE_ID_PREFIX = 'resource';
- var SHOW_DEBUG_ALERTS_WHEN_SAVING = false;
- var SHOW_EXTENDED_DEBUG_INFORMATION = false;
- /*
- * Back end specific workarounds.
- */
- var USE_ARESS_WORKAROUNDS = true;
- /*
- * Data management constants. Do not change these, as they are used
- * both internally and externally to communicate on events and to identify
- * command object actions in triple production and embedding rules.
- */
- // Resource constants
- var RESOURCE_CREATED = 0x01;
- var RESOURCE_REMOVED = 0x02;
- var RESOURCE_SAVED = 0x04;
- var RESOURCE_RELOADED = 0x08;
- var RESOURCE_SYNCHRONIZED = 0x10;
- // Triple constants
- var TRIPLE_REMOVE = 0x01;
- var TRIPLE_ADD = 0x02;
- var TRIPLE_RELOAD = 0x04;
- var TRIPLE_SAVE = 0x08;
- var PROCESSDATA_REF = 'processdata';
- // HTTP status code constants
- //
- //// 2xx
- //const 200_OK = 'Ok';
- //const 201_CREATED = 'Created';
- //const 202_ACCEPTED = 'Accepted';
- //const 204_NO_CONTENT = 'No Content';
- //
- //// 3xx
- //const 301_MOVED_PERMANENTLY = 'Moved Permanently';
- //const 302_MOVED_TEMPORARILY = 'Moved Temporarily';
- //const 304_NOT_MODIFIED = 'Not Modified';
- //
- //// 4xx
- //const 400_BAD_REQUEST = 'Bad Request';
- //const 401_UNAUTHORIZED = 'Unauthorized';
- //const 403_FORBIDDEN = 'Forbidden';
- //const 404_NOT_FOUND = 'Not Found';
- //const 409_CONFLICT = 'Conflict';
- //
- //// 5xx
- //const 500_INTERNAL_SERVER_ERROR = 'Internal Server Error';
- //const 501_NOT_IMPLEMENTED = 'Not Implemented';
- //const 502_BAD_GATEWAY = 'Bad Gateway';
- //const 503_SERVICE_UNAVAILABLE = 'Service Unavailable';
- //
- /**
- * The Data Management object. Use this one when interacting with page internal
- * data. Initialize data management by DataManager.init();
- * @class DataManager
- */
- var DataManager = {
-
- /**
- * The init method should be called once in the DataManagers lifetime.
- * It causes the DataManager to initialize itself, the erdf parser, do all
- * neccessary registrations and configurations, to run the parser and
- * from then on deliver all resulting triples.
- * No parameters needed are needed in a call to this method.
- */
- init: function() {
- ERDF.init(DataManager._registerTriple);
- DataManager.__synclocal();
- },
-
- /**
- * This triple array is meant to be the whole knowledge of the DataManager.
- */
- _triples: [],
-
- /**
- * This method is meant for callback from erdf parsing. It is not to be
- * used in another way than to add triples to the triple store.
- * @param {Object} triple the triple to add to the triple store.
- */
- _registerTriple: function(triple) {
- DataManager._triples.push(triple)
- },
-
- /**
- * The __synclocal method is for internal usage only.
- * It performs synchronization with the local document, that is, the triple
- * store is adjustet to the content of the document, which could have been
- * changed by any other applications running on the same page.
- */
- __synclocal: function() {
- DataManager._triples = [];
- ERDF.run();
- },
-
- /**
- * Makes the shape passed into this method synchronize itself with the DOM.
- * This method returns the shapes resource object for further manipulation.
- * @param {Object} shape
- */
- __synchronizeShape: function(shape) {
- var r = ResourceManager.getResource(shape.resourceId);
- var serialize = shape.serialize();
- // store all serialize values
- serialize.each( function(ser) {
-
- var resource = (ser.type == 'resource');
- var _triple = new ERDF.Triple(
- new ERDF.Resource(shape.resourceId),
- {prefix: ser.prefix, name: ser.name},
- resource ?
- new ERDF.Resource(ser.value) :
- new ERDF.Literal(ser.value)
- );
- DataManager.setObject(_triple);
- });
-
- return r;
- },
- __storeShape: function(shape) {
-
- // first synchronize the shape,
- var resource = DataManager.__synchronizeShape(shape);
-
- // then save the synchronized dom.
- resource.save();
- },
-
- __forceExistance: function(shape) {
-
- if(!$(shape.resourceId)) {
-
- if(!$$('.' + PROCESSDATA_REF)[0])
- DataManager.graft(XMLNS.XHTML,
- document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
-
- // object is literal
- DataManager.graft(XMLNS.XHTML,
- $$('.' + PROCESSDATA_REF)[0], [
-
- 'div', {
- 'id': shape.resourceId,
- //This should be done in a more dynamic way!!!!!
- 'class': (shape instanceof ORYX.Core.Canvas) ? "-oryx-canvas" : undefined
- }
- ]);
-
- } else {
- var resource = $(shape.resourceId)
- var children = $A(resource.childNodes)
- children.each( function(child) {
- resource.removeChild(child);
- });
- };
- },
-
- __persistShape: function(shape) {
- // a shape serialization.
- var shapeData = shape.serialize();
-
- // initialize a triple array and construct a shape resource
- // to be used in triple generation.
- var triplesArray = [];
- var shapeResource = new ERDF.Resource(shape.resourceId);
- // remove all triples for this particular shape's resource
- DataManager.removeTriples( DataManager.query(
- shapeResource, undefined, undefined));
- // for each data set in the shape's serialization
- shapeData.each( function(data) {
- // construct a triple's value
- var value = (data.type == 'resource') ?
- new ERDF.Resource(data.value) :
- new ERDF.Literal(data.value);
- // construct triple and add it to the DOM.
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: data.prefix, name: data.name},
- value
- ));
- });
- },
-
- __persistDOM: function(facade) {
- // getChildShapes gets all shapes (nodes AND edges), deep flag
- // makes it return a flattened child hierarchy.
-
- var canvas = facade.getCanvas();
- var shapes = canvas.getChildShapes(true);
- var result = '';
-
- // persist all shapes.
- shapes.each( function(shape) {
- DataManager.__forceExistance(shape);
- });
- //DataManager.__synclocal();
-
- DataManager.__renderCanvas(facade);
- result += DataManager.serialize(
- $(ERDF.__stripHashes(facade.getCanvas().resourceId)), true);
-
- shapes.each( function(shape) {
-
- DataManager.__persistShape(shape);
- result += DataManager.serialize(
- $(ERDF.__stripHashes(shape.resourceId)), true);
- });
-
- //result += DataManager.__renderCanvas(facade);
-
- return result;
- },
- __renderCanvas: function(facade) {
- var canvas = facade.getCanvas();
- var stencilSets = facade.getStencilSets();
- var shapes = canvas.getChildShapes(true);
-
- DataManager.__forceExistance(canvas);
-
- DataManager.__persistShape(canvas);
-
- var shapeResource = new ERDF.Resource(canvas.resourceId);
- // remove all triples for this particular shape's resource
- DataManager.removeTriples( DataManager.query(
- shapeResource, undefined, undefined));
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "mode"},
- new ERDF.Literal("writable")
- ));
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "mode"},
- new ERDF.Literal("fullscreen")
- ));
- stencilSets.values().each(function(stencilset) {
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "stencilset"},
- new ERDF.Resource(stencilset.source().replace(/&/g, "%26"))
- ));
-
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "ssnamespace"},
- new ERDF.Resource(stencilset.namespace())
- ));
-
- stencilset.extensions().keys().each(function(extension) {
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "ssextension"},
- new ERDF.Literal(extension)
- ));
- });
- });
-
- shapes.each(function(shape) {
- DataManager.addTriple( new ERDF.Triple(
- shapeResource,
- {prefix: "oryx", name: "render"},
- new ERDF.Resource("#" + shape.resourceId)
- ));
- });
- },
- __counter: 0,
- __provideId: function() {
-
- while($(RESOURCE_ID_PREFIX+DataManager.__counter))
- DataManager.__counter++;
-
- return RESOURCE_ID_PREFIX+DataManager.__counter;
- },
-
- serializeDOM: function(facade) {
-
- return DataManager.__persistDOM(facade);
- },
-
- syncGlobal: function(facade) {
-
- return DataManager.__syncglobal(facade);
- },
-
- /**
- * This method is used to synchronize local DOM with remote resources.
- * Local changes are commited to the server, and remote changes are
- * performed to the local document.
- * @param {Object} facade The facade of the editor that holds certain
- * resource representations as shapes.
- */
- __syncglobal: function(facade) {
- // getChildShapes gets all shapes (nodes AND edges), deep flag
- // makes it return a flattened child hierarchy.
-
- var canvas = facade.getCanvas();
- var shapes = canvas.getChildShapes(true);
- // create dummy resource representations in the dom
- // for all shapes that were newly created.
- shapes.select( function(shape) {
- // select shapes without resource id.
- return !($(shape.resourceId));
- }).each( function(shape) {
- // create new resources for them.
- if(USE_ARESS_WORKAROUNDS) {
-
- /*
- * This is a workaround due to a bug in aress. Resources are
- * ignoring changes to raziel:type property once they are
- * created. As long as this is not fixed, the resource is now
- * being created using a randomly guessed id, this temporary id
- * is then used in references and the appropriate div is being
- * populated with properties.
- *
- * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT
- * TO IDS THAT ARE UNKNOWN TO THE BACK END.
- *
- * After the resource is actually created in aress, it gets an id
- * that is persistent. All shapes are then being populated with the
- * correct id references and stored on the server.
- *
- * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT
- * REGARDING THE ID REFERENCES AGAIN.
- */
-
- var razielType = shape.properties['raziel-type'];
-
- var div = '<div xmlns="http://www.w3.org/1999/xhtml">' +
- '<span class="raziel-type">'+razielType+'</span></div>';
- var r = ResourceManager.__createResource(div);
- shape.resourceId = r.id();
-
- } else {
-
- var r = ResourceManager.__createResource();
- shape.resourceId = r.id();
- }
- });
- shapes.each( function(shape) {
-
- // store all shapes.
- DataManager.__storeShape(shape);
- });
- },
-
- /**
- * This method serializes a single div into a string that satisfies the
- * client/server communication protocol. It ingnores all elements that have
- * an attribute named class that includes 'transient'.
- * @param {Object} node the element to serialize.
- * @param {Object} preserveNamespace whether to preserve the parent's
- * namespace. If you are not sure about namespaces, provide
- * just the element to be serialized.
- */
- serialize: function(node, preserveNamespace) {
- if (node.nodeType == node.ELEMENT_NODE) {
- // serialize an element node.
-
- var children = $A(node.childNodes);
- var attributes = $A(node.attributes);
- var clazz = new String(node.getAttribute('class'));
- var ignore = clazz.split(' ').member('transient');
- // ignore transients.
- if(ignore)
- return '';
- // start serialization.
-
- var result = '<' + node.nodeName;
-
- // preserve namespace?
- if(!preserveNamespace)
- result += ' xmlns="' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '" xmlns:oryx="http://oryx-editor.org"';
-
- // add all attributes.
-
- attributes.each(function(attribute) {
- result += ' ' + attribute.nodeName + '="' +
- attribute.nodeValue + '"';});
-
- // close if no children.
-
- if(children.length == 0)
- result += '/>';
-
- else {
-
- // serialize all children.
-
- result += '>';
- children.each(function(_node) {
- result += DataManager.serialize(_node, true)});
- result += '</' + node.nodeName + '>'
- }
- return result;
-
- } else if (node.nodeType == node.TEXT_NODE) {
-
- // serialize a text node.
- return node.nodeValue;
- }
-
- //TODO serialize cdata areas also.
- //TODO work on namespace awareness.
- },
- addTriple: function(triple) {
- // assert the subject is a resource
-
- if(!triple.subject.type == ERDF.LITERAL)
- throw 'Cannot add the triple ' + triple.toString() +
- ' because the subject is not a resource.'
-
- // get the element which represents this triple's subject.
- var elementId = ERDF.__stripHashes(triple.subject.value);
- var element = $(elementId);
-
- // assert the subject is inside this document.
- if(!element)
- throw 'Cannot add the triple ' + triple.toString() +
- ' because the subject "'+elementId+'" is not in the document.';
- if(triple.object.type == ERDF.LITERAL)
- // object is literal
- DataManager.graft(XMLNS.XHTML, element, [
- 'span', {'class': (triple.predicate.prefix + "-" +
- triple.predicate.name)}, triple.object.value.escapeHTML()
- ]);
-
- else {
- // object is resource
- DataManager.graft(XMLNS.XHTML, element, [
- 'a', {'rel': (triple.predicate.prefix + "-" +
- triple.predicate.name), 'href': triple.object.value}
- ]);
-
- }
- return true;
- },
-
- removeTriples: function(triples) {
- // alert('Removing ' +triples.length+' triples.');
- // from all the triples select those ...
- var removed = triples.select(
- function(triple) {
-
- // TODO remove also from triple store.
- // ... that were actually removed.
- return DataManager.__removeTriple(triple);
- });
-
- // sync and return removed triples.
- // DataManager.__synclocal();
- return removed;
- },
-
- removeTriple: function(triple) {
-
- // remember whether the triple was actually removed.
- var result = DataManager.__removeTriple(triple);
- // sync and return removed triples.
- // DataManager.__synclocal();
- return result;
- },
- __removeTriple: function(triple) {
-
- // assert the subject is a resource
- if(!triple.subject.type == ERDF.LITERAL)
-
- throw 'Cannot remove the triple ' + triple.toString() +
- ' because the subject is not a resource.';
- // get the element which represents this triple's subject.
- var elementId = ERDF.__stripHashes(triple.subject.value);
- var element = $(elementId);
- // assert the subject is inside this document.
- if(!element)
-
- throw 'Cannot remove the triple ' + triple.toString() +
- ' because the subject is not in the document.';
-
- if(triple.object.type == ERDF.LITERAL) {
-
- // continue searching actively for the triple.
- var result = DataManager.__removeTripleRecursively(triple, element);
- return result;
- }
- },
- __removeTripleRecursively: function(triple, continueFrom) {
- // return when this node is not an element node.
- if(continueFrom.nodeType != continueFrom.ELEMENT_NODE)
- return false;
-
- var classes = new String(continueFrom.getAttribute('class'));
- var children = $A(continueFrom.childNodes);
-
- if(classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) {
-
- var content = continueFrom.textContent;
- if( (triple.object.type == ERDF.LITERAL) &&
- (triple.object.value == content))
- continueFrom.parentNode.removeChild(continueFrom);
-
- return true;
-
- } else {
-
- children.each(function(_node) {
- DataManager.__removeTripleRecursively(triple, _node)});
- return false;
- }
- },
- /**
- * graft() function
- * Originally by Sean M. Burke from interglacial.com, altered for usage with
- * SVG and namespace (xmlns) support. Be sure you understand xmlns before
- * using this funtion, as it creates all grafted elements in the xmlns
- * provided by you and all element's attribures in default xmlns. If you
- * need to graft elements in a certain xmlns and wish to assign attributes
- * in both that and another xmlns, you will need to do stepwise grafting,
- * adding non-default attributes yourself or you'll have to enhance this
- * function. Latter, I would appreciate: martin�apfelfabrik.de
- * @param {Object} namespace The namespace in which
- * elements should be grafted.
- * @param {Object} parent The element that should contain the grafted
- * structure after the function returned.
- * @param {Object} t the crafting structure.
- * @param {Object} doc the document in which grafting is performed.
- */
- graft: function(namespace, parent, t, doc) {
-
- doc = (doc || (parent && parent.ownerDocument) || document);
- var e;
- if(t === undefined) {
- echo( "Can't graft an undefined value");
- } else if(t.constructor == String) {
- e = doc.createTextNode( t );
- } else {
- for(var i = 0; i < t.length; i++) {
- if( i === 0 && t[i].constructor == String ) {
- var snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i );
- if( snared ) {
- e = doc.createElementNS(namespace, snared[1]);
- e.setAttributeNS(null, 'class', snared[2] );
- continue;
- }
- snared = t[i].match( /^([a-z][a-z0-9]*)$/i );
- if( snared ) {
- e = doc.createElementNS(namespace, snared[1]); // but no class
- continue;
- }
-
- // Otherwise:
- e = doc.createElementNS(namespace, "span");
- e.setAttribute(null, "class", "namelessFromLOL" );
- }
-
- if( t[i] === undefined ) {
- echo("Can't graft an undefined value in a list!");
- } else if( t[i].constructor == String || t[i].constructor == Array) {
- this.graft(namespace, e, t[i], doc );
- } else if( t[i].constructor == Number ) {
- this.graft(namespace, e, t[i].toString(), doc );
- } else if( t[i].constructor == Object ) {
- // hash's properties => element's attributes
- for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }
- } else if( t[i].constructor == Boolean ) {
- this.graft(namespace, e, t[i] ? 'true' : 'false', doc );
- } else
- throw "Object " + t[i] + " is inscrutable as an graft arglet.";
- }
- }
-
- if(parent) parent.appendChild(e);
-
- return Element.extend(e); // return the topmost created node
- },
- setObject: function(triple) {
- /**
- * Erwartungen von Arvid an diese Funktion:
- * - Es existiert genau ein triple mit dem Subjekt und Praedikat,
- * das uebergeben wurde, und dieses haelt uebergebenes Objekt.
- */
- var triples = DataManager.query(
- triple.subject,
- triple.predicate,
- undefined
- );
-
- DataManager.removeTriples(triples);
- DataManager.addTriple(triple);
- return true;
- },
-
- query: function(subject, predicate, object) {
- /*
- * Typical triple.
- * {value: subject, type: subjectType},
- * {prefix: schema.prefix, name: property},
- * {value: object, type: objectType});
- */
-
- return DataManager._triples.select(function(triple) {
-
- var select = ((subject) ?
- (triple.subject.type == subject.type) &&
- (triple.subject.value == subject.value) : true);
- if(predicate) {
- select = select && ((predicate.prefix) ?
- (triple.predicate.prefix == predicate.prefix) : true);
- select = select && ((predicate.name) ?
- (triple.predicate.name == predicate.name) : true);
- }
- select = select && ((object) ?
- (triple.object.type == object.type) &&
- (triple.object.value == object.value) : true);
- return select;
- });
- }
- }
- Kickstart.register(DataManager.init);
- function assert(expr, m) { if(!expr) throw m; };
- function DMCommand(action, triple) {
-
- // store action and triple.
- this.action = action;
- this.triple = triple;
-
- this.toString = function() {
- return 'Command('+action+', '+triple+')';
- };
- }
- function DMCommandHandler(nextHandler) {
-
- /**
- * Private method to set the next handler in the Chain of Responsibility
- * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for
- * details).
- * @param {DMCommandHandler} handler The handler that is next in the chain.
- */
- this.__setNext = function(handler) {
- var _next = this.__next;
- this.__next = nextHandler;
- return _next ? _next : true;
- };
- this.__setNext(nextHandler);
- /**
- * Invokes the next handler. If there is no next handler, this method
- * returns false, otherwise it forwards the result of the handling.
- * @param {Object} command The command object to be processed.
- */
- this.__invokeNext = function(command) {
- return this.__next ? this.__next.handle(command) : false;
- };
-
- /**
- * Handles a command. The abstract method process() is called with the
- * command object that has been passed. If the process method catches the
- * command (returns true on completion), the handle() method returns true.
- * If the process() method doesn't catch the command, the next handler will
- * be invoked.
- * @param {Object} command The command object to be processed.
- */
- this.handle = function(command) {
- return this.process(command) ? true : this.__invokeNext(command);
- }
-
- /**
- * Empty process() method returning false. If javascript knew abstract
- * class members, this would be one.
- * @param {Object} command The command object to process.
- */
- this.process = function(command) { return false; };
- };
- /**
- * This Handler manages the addition and the removal of meta elements in the
- * head of the document.
- * @param {DMCommandHandler} next The handler that is next in the chain.
- */
- function MetaTagHandler(next) {
-
- DMCommandHandler.apply(this, [next]);
- this.process = function(command) {
-
- with(command.triple) {
-
- /* assert prerequisites */
- if( !(
- (subject instanceof ERDF.Resource) &&
- (subject.isCurrentDocument()) &&
- (object instanceof ERDF.Literal)
- )) return false;
- }
-
- };
- };
- var chain = new MetaTagHandler();
- var command = new DMCommand(TRIPLE_ADD, new ERDF.Triple(
- new ERDF.Resource(''),
- 'rdf:tool',
- new ERDF.Literal('')
- ));
- /*
- if(chain.handle(command))
- alert('Handled!');
- */
- ResourceManager = {
-
- __corrupt: false,
- __latelyCreatedResource: undefined,
- __listeners: $H(),
- __token: 1,
-
- addListener: function(listener, mask) {
- if(!(listener instanceof Function))
- throw 'Resource event listener is not a function!';
- if(!(mask))
- throw 'Invalid mask for resource event listener registration.';
- // construct controller and token.
- var controller = {listener: listener, mask: mask};
- var token = ResourceManager.__token++;
-
- // add new listener.
- ResourceManager.__listeners[token] = controller;
-
- // return the token generated.
- return token;
- },
-
- removeListener: function(token) {
-
- // remove the listener with the token and return it.
- return ResourceManager.__listners.remove(token);
- },
-
- __Event: function(action, resourceId) {
- this.action = action;
- this.resourceId = resourceId;
- },
-
- __dispatchEvent: function(event) {
-
- // get all listeners. for each listener, ...
- ResourceManager.__listeners.values().each(function(controller) {
-
- // .. if listener subscribed to this type of event ...
- if(event.action & controller.mask)
- return controller.listener(event);
- });
- },
- getResource: function(id) {
- // get all possible resources for this.
- id = ERDF.__stripHashes(id);
- var resources = DataManager.query(
- new ERDF.Resource('#'+id),
- {prefix: 'raziel', name: 'entry'},
- undefined
- );
- // check for consistency.
- if((resources.length == 1) && (resources[0].object.isResource())) {
- var entryUrl = resources[0].object.value;
- return new ResourceManager.__Resource(id, entryUrl);
- }
- // else throw an error message.
- throw ('Resource with id ' +id+ ' not recognized as such. ' +
- ((resources.length > 1) ?
- ' There is more than one raziel:entry URL.' :
- ' There is no raziel:entry URL.'));
- return false;
- },
- __createResource: function(alternativeDiv) {
-
- var collectionUrls = DataManager.query(
- new ERDF.Resource(''),
- // TODO This will become raziel:collection in near future.
- {prefix: 'raziel', name: 'collection'},
- undefined
- );
- // check for consistency.
-
- if( (collectionUrls.length == 1) &&
- (collectionUrls[0].object.isResource())) {
- // get the collection url.
-
- var collectionUrl = collectionUrls[0].object.value;
- var resource = undefined;
-
- // if there is an old id, serialize the dummy div from there,
- // otherwise create a dummy div on the fly.
-
- var serialization = alternativeDiv? alternativeDiv :
- '<div xmlns="http://www.w3.org/1999/xhtml"></div>';
-
- ResourceManager.__request(
- 'POST', collectionUrl, serialization,
- // on success
- function() {
-
- // get div and id that have been generated by the server.
-
- var response = (this.responseXML);
- var div = response.childNodes[0];
- var id = div.getAttribute('id');
-
- // store div in DOM
- if(!$$('.' + PROCESSDATA_REF)[0])
- DataManager.graft(XMLNS.XHTML,
- document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
-
- $$('.' + PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));
- // parse local erdf data once more.
-
- DataManager.__synclocal();
-
- // get new resource object.
- resource = new ResourceManager.getResource(id);
- // set up an action informing of the creation.
-
- ResourceManager.__resourceActionSucceeded(
- this, RESOURCE_CREATED, undefined);
- },
- function() { ResourceManager.__resourceActionFailed(
- this, RESOURCE_CREATED, undefined);},
- false
- );
-
- return resource;
- }
-
- // else
- throw 'Could not create resource! raziel:collection URL is missing!';
- return false;
- },
-
- __Resource: function(id, url) {
-
- this.__id = id;
- this.__url = url;
-
- /*
- * Process URL is no longer needed to refer to the shape element on the
- * canvas. AReSS uses the id's to gather information on fireing
- * behaviour now.
- */
-
- // // find the process url.
- // var processUrl = undefined;
- //
- // var urls = DataManager.query(
- // new ERDF.Resource('#'+this.__id),
- // {prefix: 'raziel', name: 'process'},
- // undefined
- // );
- //
- // if(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'};
- //
- // urls.each( function(triple) {
- //
- // // if there are more urls, use the last one.
- // processUrl = triple.object.value;
- // });
- //
- // this.__processUrl = processUrl;
- //
- // // convenience function for getting the process url.
- // this.processUrl = function() {
- // return this.__processUrl;
- // }
- // convenience finction for getting the id.
- this.id = function() {
- return this.__id;
- }
- // convenience finction for getting the entry url.
- this.url = function() {
- return this.__url;
- }
-
- this.reload = function() {
- var _url = this.__url;
- var _id = this.__id;
- ResourceManager.__request(
- 'GET', _url, null,
- function() { ResourceManager.__resourceActionSucceeded(
- this, RESOURCE_RELOADED, _id); },
- function() { ResourceManager.__resourceActionFailed(
- this, RESURCE_RELOADED, _id); },
- USE_ASYNCHRONOUS_REQUESTS
- );
- };
-
- this.save = function(synchronize) {
- var _url = this.__url;
- var _id = this.__id;
- data = DataManager.serialize($(_id));
- ResourceManager.__request(
- 'PUT', _url, data,
- function() { ResourceManager.__resourceActionSucceeded(
- this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); },
- function() { ResourceManager.__resourceActionFailed(
- this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); },
- USE_ASYNCHRONOUS_REQUESTS
- );
- };
-
- this.remove = function() {
- var _url = this.__url;
- var _id = this.__id;
- ResourceManager.__request(
- 'DELETE', _url, null,
- function() { ResourceManager.__resourceActionSucceeded(
- this, RESOURCE_REMOVED, _id); },
- function() { ResourceManager.__resourceActionFailed(
- this, RESOURCE_REMOVED, _id);},
- USE_ASYNCHRONOUS_REQUESTS
- );
- };
- },
- request: function(url, requestOptions) {
- var options = {
- method: 'get',
- asynchronous: true,
- parameters: {}
- };
- Object.extend(options, requestOptions || {});
-
- var params = Hash.toQueryString(options.parameters);
- if (params)
- url += (url.include('?') ? '&' : '?') + params;
-
- return ResourceManager.__request(
- options.method,
- url,
- options.data,
- (options.onSuccess instanceof Function ? function() { options.onSuccess(this); } : undefined ),
- (options.onFailure instanceof Function ? function() { options.onFailure(this); } : undefined ),
- options.asynchronous && USE_ASYNCHRONOUS_REQUESTS,
- options.headers);
- },
-
- __request: function(method, url, data, success, error, async, headers) {
-
- // get a request object
- var httpRequest = Try.these(
- /* do the Mozilla/Safari/Opera stuff */
- function() { return new XMLHttpRequest(); },
-
- /* do the IE stuff */
- function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
- function() { return new ActiveXObject("Microsoft.XMLHTTP") }
- );
- // if there is no request object ...
- if (!httpRequest) {
- if(!this.__corrupt)
- 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.';
- this.__corrupt = true;
- return false;
- }
-
- if(success instanceof Function)
- httpRequest.onload = success;
- if(error instanceof Function) {
- httpRequest.onerror = error;
- }
-
- var h = $H(headers)
- h.keys().each(function(key) {
-
- httpRequest.setRequestHeader(key, h[key]);
- });
-
- try {
- if(SHOW_DEBUG_ALERTS_WHEN_SAVING)
-
- alert(method + ' ' + url + '\n' +
- SHOW_EXTENDED_DEBUG_INFORMATION ? data : '');
- // TODO Remove synchronous calls to the server as soon as xenodot
- // handles asynchronous requests without failure.
- httpRequest.open(method, url, !async?false:true);
- httpRequest.send(data);
-
- } catch(e) {
- return false;
- }
- return true;
- },
- __resourceActionSucceeded: function(transport, action, id) {
-
- var status = transport.status;
- var response = transport.responseText;
-
- if(SHOW_DEBUG_ALERTS_WHEN_SAVING)
- alert(status + ' ' + url + '\n' +
- SHOW_EXTENDED_DEBUG_INFORMATION ? data : '');
- // if the status code is not in 2xx, throw an error.
- if(status >= 300)
- 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.');
- switch(action) {
-
- case RESOURCE_REMOVED:
- // get div and id
- var response = (transport.responseXML);
- var div = response.childNodes[0];
- var id = div.getAttribute('id');
-
- // remove the resource from DOM
- var localDiv = document.getElementById(id);
- localDiv.parentNode.removeChild(localDiv);
- break;
- case RESOURCE_CREATED:
- // nothing remains to be done.
- break;
-
- case RESOURCE_SAVED | RESOURCE_SYNCHRONIZED:
- DataManager.__synclocal();
- case RESOURCE_SAVED:
- // nothing remains to be done.
- break;
- case RESOURCE_RELOADED:
-
- // get div and id
- var response = (transport.responseXML);
- var div = response.childNodes[0];
- var id = div.getAttribute('id');
-
- // remove the local resource representation from DOM
- var localDiv = document.getElementById(id)
- localDiv.parentNode.removeChild(localDiv);
-
- // store div in DOM
- if(!$$(PROCESSDATA_REF)[0])
- DataManager.graft(XMLNS.XHTML,
- document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]);
-
- $$(PROCESSDATA_REF)[0].appendChild(div.cloneNode(true));
- DataManager.__synclocal();
- break;
- default:
- DataManager.__synclocal();
- }
-
- // dispatch to all listeners ...
- ResourceManager.__dispatchEvent(
- // ... an event describing the change that happened here.
- new ResourceManager.__Event(action, id)
- );
- },
- __resourceActionFailed: function(transport, action, id) {
- throw "Fatal: Resource action failed. There is something horribly " +
- "wrong with either the server, the transport protocol or your " +
- "online status. Sure you're online?";
- }
- }/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * The super class for all classes in ORYX. Adds some OOP feeling to javascript.
- * See article "Object Oriented Super Class Method Calling with JavaScript" on
- * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html
- * for a documentation on this. Fairly good article that points out errors in
- * Douglas Crockford's inheritance and super method calling approach.
- * Worth reading.
- * @class Clazz
- */
- var Clazz = function() {};
- /**
- * Empty constructor.
- * @methodOf Clazz.prototype
- */
- Clazz.prototype.construct = function() {};
- /**
- * Can be used to build up inheritances of classes.
- * @example
- * var MyClass = Clazz.extend({
- * construct: function(myParam){
- * // Do sth.
- * }
- * });
- * var MySubClass = MyClass.extend({
- * construct: function(myParam){
- * // Use this to call constructor of super class
- * arguments.callee.$.construct.apply(this, arguments);
- * // Do sth.
- * }
- * });
- * @param {Object} def The definition of the new class.
- */
- Clazz.extend = function(def) {
- var classDef = function() {
- if (arguments[0] !== Clazz) { this.construct.apply(this, arguments); }
- };
-
- var proto = new this(Clazz);
- var superClass = this.prototype;
-
- for (var n in def) {
- var item = def[n];
- if (item instanceof Function) item.$ = superClass;
- proto[n] = item;
- }
- classDef.prototype = proto;
-
- //Give this new class the same static extend method
- classDef.extend = this.extend;
- return classDef;
- };/**
- * Copyright (c) 2010
- * Signavio GmbH
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX) var ORYX = {};
- if(!ORYX.CONFIG) ORYX.CONFIG = {};
- /**
- * This file contains URI constants that may be used for XMLHTTPRequests.
- */
- ORYX.CONFIG.ROOT_PATH = "../editor/"; //TODO: Remove last slash!!
- ORYX.CONFIG.EXPLORER_PATH = "../explorer";
- ORYX.CONFIG.LIBS_PATH = "../libs";
- /**
- * Regular Config
- */
- ORYX.CONFIG.SERVER_HANDLER_ROOT = "../service";
- ORYX.CONFIG.SERVER_EDITOR_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor";
- ORYX.CONFIG.SERVER_MODEL_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/model";
- ORYX.CONFIG.STENCILSET_HANDLER = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_stencilset?embedsvg=true&url=true&namespace=";
- ORYX.CONFIG.STENCIL_SETS_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_stencilset";
- ORYX.CONFIG.PLUGINS_CONFIG = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor/plugins";
- ORYX.CONFIG.SYNTAXCHECKER_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/syntaxchecker";
- ORYX.CONFIG.DEPLOY_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/model/deploy";
- ORYX.CONFIG.MODEL_LIST_URL = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/models";
- ORYX.CONFIG.SS_EXTENSIONS_FOLDER = ORYX.CONFIG.ROOT_PATH + "stencilsets/extensions/";
- ORYX.CONFIG.SS_EXTENSIONS_CONFIG = ORYX.CONFIG.SERVER_HANDLER_ROOT + "/editor_ssextensions";
- ORYX.CONFIG.ORYX_NEW_URL = "/new";
- ORYX.CONFIG.BPMN_LAYOUTER = ORYX.CONFIG.ROOT_PATH + "bpmnlayouter";/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX) var ORYX = {};
- if(!ORYX.CONFIG) ORYX.CONFIG = {};
- /**
- * Signavio specific variables
- */
- ORYX.CONFIG.BACKEND_SWITCH = true;
- ORYX.CONFIG.PANEL_LEFT_WIDTH = 250;
- ORYX.CONFIG.PANEL_RIGHT_COLLAPSED = true;
- ORYX.CONFIG.PANEL_RIGHT_WIDTH = 300;
- ORYX.CONFIG.APPNAME = 'Activiti BPM suite';
- ORYX.CONFIG.WEB_URL = "../";
- ORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif';
- /* Show grid line while dragging */
- ORYX.CONFIG.SHOW_GRIDLINE = true;
- /* Editor-Mode */
- ORYX.CONFIG.MODE_READONLY = "readonly";
- ORYX.CONFIG.MODE_FULLSCREEN = "fullscreen";
- ORYX.CONFIG.WINDOW_HEIGHT = 400;
- ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false;
- /* Plugins */
- ORYX.CONFIG.PLUGINS_ENABLED = true;
- ORYX.CONFIG.PLUGINS_FOLDER = "Plugins/";
- ORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true;
- /* Namespaces */
- ORYX.CONFIG.NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
- ORYX.CONFIG.NAMESPACE_SVG = "http://www.w3.org/2000/svg";
- /* UI */
- ORYX.CONFIG.CANVAS_WIDTH = 1485;
- ORYX.CONFIG.CANVAS_HEIGHT = 1050;
- ORYX.CONFIG.CANVAS_RESIZE_INTERVAL = 300;
- ORYX.CONFIG.SELECTED_AREA_PADDING = 4;
- ORYX.CONFIG.CANVAS_BACKGROUND_COLOR = "none";
- ORYX.CONFIG.GRID_DISTANCE = 30;
- ORYX.CONFIG.GRID_ENABLED = true;
- ORYX.CONFIG.ZOOM_OFFSET = 0.1;
- ORYX.CONFIG.DEFAULT_SHAPE_MARGIN = 60;
- ORYX.CONFIG.SCALERS_SIZE = 7;
- ORYX.CONFIG.MINIMUM_SIZE = 20;
- ORYX.CONFIG.MAXIMUM_SIZE = 10000;
- ORYX.CONFIG.OFFSET_MAGNET = 15;
- ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP = 8;
- ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM = 8;
- ORYX.CONFIG.OFFSET_EDGE_BOUNDS = 5;
- ORYX.CONFIG.COPY_MOVE_OFFSET = 30;
-
- ORYX.CONFIG.BORDER_OFFSET = 14;
- ORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP = 12;
- ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30;
- ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45;
- /* Shape-Menu Align */
- ORYX.CONFIG.SHAPEMENU_RIGHT = "Oryx_Right";
- ORYX.CONFIG.SHAPEMENU_BOTTOM = "Oryx_Bottom";
- ORYX.CONFIG.SHAPEMENU_LEFT = "Oryx_Left";
- ORYX.CONFIG.SHAPEMENU_TOP = "Oryx_Top";
- /* Morph-Menu Item */
- ORYX.CONFIG.MORPHITEM_DISABLED = "Oryx_MorphItem_disabled";
- /* Property type names */
- ORYX.CONFIG.TYPE_STRING = "string";
- ORYX.CONFIG.TYPE_BOOLEAN = "boolean";
- ORYX.CONFIG.TYPE_INTEGER = "integer";
- ORYX.CONFIG.TYPE_FLOAT = "float";
- ORYX.CONFIG.TYPE_COLOR = "color";
- ORYX.CONFIG.TYPE_DATE = "date";
- ORYX.CONFIG.TYPE_CHOICE = "choice";
- ORYX.CONFIG.TYPE_URL = "url";
- ORYX.CONFIG.TYPE_DIAGRAM_LINK = "diagramlink";
- ORYX.CONFIG.TYPE_COMPLEX = "complex";
- ORYX.CONFIG.TYPE_MULTIPLECOMPLEX = "multiplecomplex";
- ORYX.CONFIG.TYPE_TEXT = "text";
- ORYX.CONFIG.TYPE_MODEL_LINK = "modellink";
- ORYX.CONFIG.TYPE_LISTENER = "listener";
- ORYX.CONFIG.TYPE_EPC_FREQ = "epcfrequency";
- ORYX.CONFIG.TYPE_GLOSSARY_LINK = "glossarylink";
-
- /* Vertical line distance of multiline labels */
- ORYX.CONFIG.LABEL_LINE_DISTANCE = 2;
- ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT = 12;
- /* Open Morph Menu with Hover */
- ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false;
- /* Editor constants come here */
- ORYX.CONFIG.EDITOR_ALIGN_BOTTOM = 0x01;
- ORYX.CONFIG.EDITOR_ALIGN_MIDDLE = 0x02;
- ORYX.CONFIG.EDITOR_ALIGN_TOP = 0x04;
- ORYX.CONFIG.EDITOR_ALIGN_LEFT = 0x08;
- ORYX.CONFIG.EDITOR_ALIGN_CENTER = 0x10;
- ORYX.CONFIG.EDITOR_ALIGN_RIGHT = 0x20;
- ORYX.CONFIG.EDITOR_ALIGN_SIZE = 0x30;
- /* Event types */
- ORYX.CONFIG.EVENT_MOUSEDOWN = "mousedown";
- ORYX.CONFIG.EVENT_MOUSEUP = "mouseup";
- ORYX.CONFIG.EVENT_MOUSEOVER = "mouseover";
- ORYX.CONFIG.EVENT_MOUSEOUT = "mouseout";
- ORYX.CONFIG.EVENT_MOUSEMOVE = "mousemove";
- ORYX.CONFIG.EVENT_DBLCLICK = "dblclick";
- ORYX.CONFIG.EVENT_KEYDOWN = "keydown";
- ORYX.CONFIG.EVENT_KEYUP = "keyup";
- ORYX.CONFIG.EVENT_LOADED = "editorloaded";
-
- ORYX.CONFIG.EVENT_EXECUTE_COMMANDS = "executeCommands";
- ORYX.CONFIG.EVENT_STENCIL_SET_LOADED = "stencilSetLoaded";
- ORYX.CONFIG.EVENT_SELECTION_CHANGED = "selectionchanged";
- ORYX.CONFIG.EVENT_SHAPEADDED = "shapeadded";
- ORYX.CONFIG.EVENT_SHAPEREMOVED = "shaperemoved";
- ORYX.CONFIG.EVENT_PROPERTY_CHANGED = "propertyChanged";
- ORYX.CONFIG.EVENT_DRAGDROP_START = "dragdrop.start";
- ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE = "shape.menu.close";
- ORYX.CONFIG.EVENT_DRAGDROP_END = "dragdrop.end";
- ORYX.CONFIG.EVENT_RESIZE_START = "resize.start";
- ORYX.CONFIG.EVENT_RESIZE_END = "resize.end";
- ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED = "dragDocker.docked";
- ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW = "highlight.showHighlight";
- ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE = "highlight.hideHighlight";
- ORYX.CONFIG.EVENT_LOADING_ENABLE = "loading.enable";
- ORYX.CONFIG.EVENT_LOADING_DISABLE = "loading.disable";
- ORYX.CONFIG.EVENT_LOADING_STATUS = "loading.status";
- ORYX.CONFIG.EVENT_OVERLAY_SHOW = "overlay.show";
- ORYX.CONFIG.EVENT_OVERLAY_HIDE = "overlay.hide";
- ORYX.CONFIG.EVENT_ARRANGEMENT_TOP = "arrangement.setToTop";
- ORYX.CONFIG.EVENT_ARRANGEMENT_BACK = "arrangement.setToBack";
- ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD = "arrangement.setForward";
- ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD = "arrangement.setBackward";
- ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED = "propertyWindow.propertyChanged";
- ORYX.CONFIG.EVENT_LAYOUT_ROWS = "layout.rows";
- ORYX.CONFIG.EVENT_LAYOUT_BPEL = "layout.BPEL";
- ORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL = "layout.BPEL.vertical";
- ORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL = "layout.BPEL.horizontal";
- ORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = "layout.BPEL.singlechild";
- ORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE = "layout.BPEL.autoresize";
- ORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT = "autolayout.layout";
- ORYX.CONFIG.EVENT_UNDO_EXECUTE = "undo.execute";
- ORYX.CONFIG.EVENT_UNDO_ROLLBACK = "undo.rollback";
- ORYX.CONFIG.EVENT_BUTTON_UPDATE = "toolbar.button.update";
- ORYX.CONFIG.EVENT_LAYOUT = "layout.dolayout";
- ORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = "glossary.link.edit";
- ORYX.CONFIG.EVENT_GLOSSARY_SHOW = "glossary.show.info";
- ORYX.CONFIG.EVENT_GLOSSARY_NEW = "glossary.show.new";
- ORYX.CONFIG.EVENT_DOCKERDRAG = "dragTheDocker";
-
- ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW = "propertywindow.show";
- ORYX.CONFIG.EVENT_ABOUT_TO_SAVE = "file.aboutToSave";
-
- /* Selection Shapes Highlights */
- ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE = 5;
- ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR = "#4444FF";
- ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR2 = "#9999FF";
-
- ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_CORNER = "corner";
- ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE = "rectangle";
-
- ORYX.CONFIG.SELECTION_VALID_COLOR = "#00FF00";
- ORYX.CONFIG.SELECTION_INVALID_COLOR = "#FF0000";
- ORYX.CONFIG.DOCKER_DOCKED_COLOR = "#00FF00";
- ORYX.CONFIG.DOCKER_UNDOCKED_COLOR = "#FF0000";
- ORYX.CONFIG.DOCKER_SNAP_OFFSET = 10;
-
- /* Copy & Paste */
- ORYX.CONFIG.EDIT_OFFSET_PASTE = 10;
- /* Key-Codes */
- ORYX.CONFIG.KEY_CODE_X = 88;
- ORYX.CONFIG.KEY_CODE_C = 67;
- ORYX.CONFIG.KEY_CODE_V = 86;
- ORYX.CONFIG.KEY_CODE_DELETE = 46;
- ORYX.CONFIG.KEY_CODE_META = 224;
- ORYX.CONFIG.KEY_CODE_BACKSPACE = 8;
- ORYX.CONFIG.KEY_CODE_LEFT = 37;
- ORYX.CONFIG.KEY_CODE_RIGHT = 39;
- ORYX.CONFIG.KEY_CODE_UP = 38;
- ORYX.CONFIG.KEY_CODE_DOWN = 40;
- // TODO Determine where the lowercase constants are still used and remove them from here.
- ORYX.CONFIG.KEY_Code_enter = 12;
- ORYX.CONFIG.KEY_Code_left = 37;
- ORYX.CONFIG.KEY_Code_right = 39;
- ORYX.CONFIG.KEY_Code_top = 38;
- ORYX.CONFIG.KEY_Code_bottom = 40;
- /* Supported Meta Keys */
-
- ORYX.CONFIG.META_KEY_META_CTRL = "metactrl";
- ORYX.CONFIG.META_KEY_ALT = "alt";
- ORYX.CONFIG.META_KEY_SHIFT = "shift";
- /* Key Actions */
- ORYX.CONFIG.KEY_ACTION_DOWN = "down";
- ORYX.CONFIG.KEY_ACTION_UP = "up";
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- function printf() {
-
- var result = arguments[0];
- for (var i=1; i<arguments.length; i++)
- result = result.replace('%' + (i-1), arguments[i]);
- return result;
- }
- // oryx constants.
- var ORYX_LOGLEVEL_TRACE = 5;
- var ORYX_LOGLEVEL_DEBUG = 4;
- var ORYX_LOGLEVEL_INFO = 3;
- var ORYX_LOGLEVEL_WARN = 2;
- var ORYX_LOGLEVEL_ERROR = 1;
- var ORYX_LOGLEVEL_FATAL = 0;
- var ORYX_LOGLEVEL = 3;
- var ORYX_CONFIGURATION_DELAY = 100;
- var ORYX_CONFIGURATION_WAIT_ATTEMPTS = 10;
- if(!ORYX) var ORYX = {};
- ORYX = Object.extend(ORYX, {
- //set the path in the config.js file!!!!
- PATH: ORYX.CONFIG.ROOT_PATH,
- //CONFIGURATION: "config.js",
- URLS: [
-
- /*
- * No longer needed, since compiled into one source file that
- * contains all of this files concatenated in the exact order
- * as defined in build.xml.
- */
-
- /*
- "scripts/Core/SVG/editpathhandler.js",
- "scripts/Core/SVG/minmaxpathhandler.js",
- "scripts/Core/SVG/pointspathhandler.js",
- "scripts/Core/SVG/svgmarker.js",
- "scripts/Core/SVG/svgshape.js",
- "scripts/Core/SVG/label.js",
- "scripts/Core/Math/math.js",
- "scripts/Core/StencilSet/stencil.js",
- "scripts/Core/StencilSet/property.js",
- "scripts/Core/StencilSet/propertyitem.js",
- "scripts/Core/StencilSet/rules.js",
- "scripts/Core/StencilSet/stencilset.js",
- "scripts/Core/StencilSet/stencilsets.js",
- "scripts/Core/bounds.js",
- "scripts/Core/uiobject.js",
- "scripts/Core/abstractshape.js",
- "scripts/Core/canvas.js",
- "scripts/Core/main.js",
- "scripts/Core/svgDrag.js",
- "scripts/Core/shape.js",
- "scripts/Core/Controls/control.js",
- "scripts/Core/Controls/docker.js",
- "scripts/Core/Controls/magnet.js",
- "scripts/Core/node.js",
- "scripts/Core/edge.js"
- */ ],
- alreadyLoaded: [],
- configrationRetries: 0,
- Version: '0.1.1',
- availablePlugins: [],
- /**
- * The ORYX.Log logger.
- */
- Log: {
-
- __appenders: [
- { append: function(message) {
- console.log(message); }}
- ],
-
- trace: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_TRACE)
- ORYX.Log.__log('TRACE', arguments); },
- debug: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_DEBUG)
- ORYX.Log.__log('DEBUG', arguments); },
- info: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_INFO)
- ORYX.Log.__log('INFO', arguments); },
- warn: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_WARN)
- ORYX.Log.__log('WARN', arguments); },
- error: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_ERROR)
- ORYX.Log.__log('ERROR', arguments); },
- fatal: function() { if(ORYX_LOGLEVEL >= ORYX_LOGLEVEL_FATAL)
- ORYX.Log.__log('FATAL', arguments); },
-
- __log: function(prefix, messageParts) {
-
- messageParts[0] = (new Date()).getTime() + " "
- + prefix + " " + messageParts[0];
- var message = printf.apply(null, messageParts);
-
- ORYX.Log.__appenders.each(function(appender) {
- appender.append(message);
- });
- },
-
- addAppender: function(appender) {
- ORYX.Log.__appenders.push(appender);
- }
- },
- /**
- * First bootstrapping layer. The Oryx loading procedure begins. In this
- * step, all preliminaries that are not in the responsibility of Oryx to be
- * met have to be checked here, such as the existance of the prototpe
- * library in the current execution environment. After that, the second
- * bootstrapping layer is being invoked. Failing to ensure that any
- * preliminary condition is not met has to fail with an error.
- */
- load: function() {
-
- if (ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY !== true) {
- var waitingpanel = new Ext.Window({renderTo:Ext.getBody(),id:'oryx-loading-panel',bodyStyle:'padding: 8px;background:white',title:ORYX.I18N.Oryx.title,width:'auto',height:'auto',modal:true,resizable:false,closable:false,html:'<span style="font-size:11px;">' + ORYX.I18N.Oryx.pleaseWait + '</span>'})
- waitingpanel.show()
- }
-
- ORYX.Log.debug("Oryx begins loading procedure.");
-
- // check for prototype
- if( (typeof Prototype=='undefined') ||
- (typeof Element == 'undefined') ||
- (typeof Element.Methods=='undefined') ||
- parseFloat(Prototype.Version.split(".")[0] + "." +
- Prototype.Version.split(".")[1]) < 1.5)
- throw("Application requires the Prototype JavaScript framework >= 1.5.3");
-
- ORYX.Log.debug("Prototype > 1.5 found.");
- // continue loading.
- ORYX._load();
- },
- /**
- * Second bootstrapping layer. The oryx configuration is checked. When not
- * yet loaded, config.js is being requested from the server. A repeated
- * error in retrieving the configuration will result in an error to be
- * thrown after a certain time of retries. Once the configuration is there,
- * all urls that are registered with oryx loading are being requested from
- * the server. Once everything is loaded, the third layer is being invoked.
- */
- _load: function() {
- /*
- // if configuration not there already,
- if(!(ORYX.CONFIG)) {
-
- // if this is the first attempt...
- if(ORYX.configrationRetries == 0) {
-
- // get the path and filename.
- var configuration = ORYX.PATH + ORYX.CONFIGURATION;
-
- ORYX.Log.debug("Configuration not found, loading from '%0'.",
- configuration);
-
- // require configuration file.
- Kickstart.require(configuration);
-
- // else if attempts exceeded ...
- } else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) {
-
- throw "Tried to get configuration" +
- ORYX_CONFIGURATION_WAIT_ATTEMPTS +
- " times from '" + configuration + "'. Giving up."
-
- } else if(ORYX.configrationRetries > 0){
-
- // point out how many attempts are left...
- ORYX.Log.debug("Waiting once more (%0 attempts left)",
- (ORYX_CONFIGURATION_WAIT_ATTEMPTS -
- ORYX.configrationRetries));
- }
-
- // any case: continue in a moment with increased retry count.
- ORYX.configrationRetries++;
- window.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY);
- return;
- }
-
- ORYX.Log.info("Configuration loaded.");
-
- // load necessary scripts.
- ORYX.URLS.each(function(url) {
- ORYX.Log.debug("Requireing '%0'", url);
- Kickstart.require(ORYX.PATH + url) });
- */
- // configurate logging and load plugins.
- ORYX.loadPlugins();
- },
- /**
- * Third bootstrapping layer. This is where first the plugin coniguration
- * file is loaded into oryx, analyzed, and where all plugins are being
- * requested by the server. Afterwards, all editor instances will be
- * initialized.
- */
- loadPlugins: function() {
-
- // load plugins if enabled.
- if(ORYX.CONFIG.PLUGINS_ENABLED)
- ORYX._loadPlugins()
- else
- ORYX.Log.warn("Ignoring plugins, loading Core only.");
- // init the editor instances.
- init();
- },
-
- _loadPlugins: function() {
- // load plugin configuration file.
- var source = ORYX.CONFIG.PLUGINS_CONFIG;
- ORYX.Log.debug("Loading plugin configuration from '%0'.", source);
-
- new Ajax.Request(source, {
- asynchronous: false,
- method: 'get',
- onSuccess: function(result) {
- /*
- * This is the method that is being called when the plugin
- * configuration was successfully loaded from the server. The
- * file has to be processed and the contents need to be
- * considered for further plugin requireation.
- */
-
- ORYX.Log.info("Plugin configuration file loaded.");
-
- // get plugins.xml content
- var resultXml = result.responseXML;
-
- // TODO: Describe how properties are handled.
- // Get the globale Properties
- var globalProperties = [];
- var preferences = $A(resultXml.getElementsByTagName("properties"));
- preferences.each( function(p) {
- var props = $A(p.childNodes);
- props.each( function(prop) {
- var property = new Hash();
-
- // get all attributes from the node and set to global properties
- var attributes = $A(prop.attributes)
- attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});
- if(attributes.length > 0) { globalProperties.push(property) };
- });
- });
-
- // TODO Why are we using XML if we don't respect structure anyway?
- // for each plugin element in the configuration..
- var plugin = resultXml.getElementsByTagName("plugin");
- $A(plugin).each( function(node) {
-
- // get all element's attributes.
- // TODO: What about: var pluginData = $H(node.attributes) !?
- var pluginData = new Hash();
- $A(node.attributes).each( function(attr){
- pluginData[attr.nodeName] = attr.nodeValue});
-
- // ensure there's a name attribute.
- if(!pluginData['name']) {
- ORYX.Log.error("A plugin is not providing a name. Ingnoring this plugin.");
- return;
- }
- // ensure there's a source attribute.
- if(!pluginData['source']) {
- ORYX.Log.error("Plugin with name '%0' doesn't provide a source attribute.", pluginData['name']);
- return;
- }
-
- // Get all private Properties
- var propertyNodes = node.getElementsByTagName("property");
- var properties = [];
- $A(propertyNodes).each(function(prop) {
- var property = new Hash();
-
- // Get all Attributes from the Node
- var attributes = $A(prop.attributes)
- attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue});
- if(attributes.length > 0) { properties.push(property) };
-
- });
-
- // Set all Global-Properties to the Properties
- properties = properties.concat(globalProperties);
-
- // Set Properties to Plugin-Data
- pluginData['properties'] = properties;
-
- // Get the RequieredNodes
- var requireNodes = node.getElementsByTagName("requires");
- var requires;
- $A(requireNodes).each(function(req) {
- var namespace = $A(req.attributes).find(function(attr){ return attr.name == "namespace"})
- if( namespace && namespace.nodeValue ){
- if( !requires ){
- requires = {namespaces:[]}
- }
-
- requires.namespaces.push(namespace.nodeValue)
- }
- });
-
- // Set Requires to the Plugin-Data, if there is one
- if( requires ){
- pluginData['requires'] = requires;
- }
- // Get the RequieredNodes
- var notUsesInNodes = node.getElementsByTagName("notUsesIn");
- var notUsesIn;
- $A(notUsesInNodes).each(function(not) {
- var namespace = $A(not.attributes).find(function(attr){ return attr.name == "namespace"})
- if( namespace && namespace.nodeValue ){
- if( !notUsesIn ){
- notUsesIn = {namespaces:[]}
- }
-
- notUsesIn.namespaces.push(namespace.nodeValue)
- }
- });
-
- // Set Requires to the Plugin-Data, if there is one
- if( notUsesIn ){
- pluginData['notUsesIn'] = notUsesIn;
- }
-
-
- var url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source'];
-
- ORYX.Log.debug("Requireing '%0'", url);
-
- // Add the Script-Tag to the Site
- //Kickstart.require(url);
-
- ORYX.Log.info("Plugin '%0' successfully loaded.", pluginData['name']);
-
- // Add the Plugin-Data to all available Plugins
- ORYX.availablePlugins.push(pluginData);
-
- });
-
- },
- onFailure:this._loadPluginsOnFails
- });
- },
- _loadPluginsOnFails: function(result) {
- ORYX.Log.error("Plugin configuration file not available.");
- }
- });
- ORYX.Log.debug('Registering Oryx with Kickstart');
- Kickstart.register(ORYX.load);
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- /**
- * EditPathHandler
- *
- * Edit SVG paths' coordinates according to specified from-to movement and
- * horizontal and vertical scaling factors.
- * The resulting path's d attribute is stored in instance variable d.
- *
- * @constructor
- */
- ORYX.Core.SVG.EditPathHandler = Clazz.extend({
-
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
-
- this.x = 0;
- this.y = 0;
- this.oldX = 0;
- this.oldY = 0;
- this.deltaWidth = 1;
- this.deltaHeight = 1;
-
- this.d = "";
- },
-
- /**
- * init
- *
- * @param {float} x Target point's x-coordinate
- * @param {float} y Target point's y-coordinate
- * @param {float} oldX Reference point's x-coordinate
- * @param {float} oldY Reference point's y-coordinate
- * @param {float} deltaWidth Horizontal scaling factor
- * @param {float} deltaHeight Vertical scaling factor
- */
- init: function(x, y, oldX, oldY, deltaWidth, deltaHeight) {
- this.x = x;
- this.y = y;
- this.oldX = oldX;
- this.oldY = oldY;
- this.deltaWidth = deltaWidth;
- this.deltaHeight = deltaHeight;
-
- this.d = "";
- },
- /**
- * editPointsAbs
- *
- * @param {Array} points Array of absolutePoints
- */
- editPointsAbs: function(points) {
- if(points instanceof Array) {
- var newPoints = [];
- var x, y;
- for(var i = 0; i < points.length; i++) {
- x = (parseFloat(points[i]) - this.oldX)*this.deltaWidth + this.x;
- i++;
- y = (parseFloat(points[i]) - this.oldY)*this.deltaHeight + this.y;
- newPoints.push(x);
- newPoints.push(y);
- }
-
- return newPoints;
- } else {
- //TODO error
- }
- },
-
- /**
- * editPointsRel
- *
- * @param {Array} points Array of absolutePoints
- */
- editPointsRel: function(points) {
- if(points instanceof Array) {
- var newPoints = [];
- var x, y;
- for(var i = 0; i < points.length; i++) {
- x = parseFloat(points[i])*this.deltaWidth;
- i++;
- y = parseFloat(points[i])*this.deltaHeight;
- newPoints.push(x);
- newPoints.push(y);
- }
-
- return newPoints;
- } else {
- //TODO error
- }
- },
- /**
- * arcAbs - A
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- var pointsAbs = this.editPointsAbs([x, y]);
- var pointsRel = this.editPointsRel([rx, ry]);
-
- this.d = this.d.concat(" A" + pointsRel[0] + " " + pointsRel[1] +
- " " + xAxisRotation + " " + largeArcFlag +
- " " + sweepFlag + " " + pointsAbs[0] + " " +
- pointsAbs[1] + " ");
- },
- /**
- * arcRel - a
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- var pointsRel = this.editPointsRel([rx, ry, x, y]);
-
- this.d = this.d.concat(" a" + pointsRel[0] + " " + pointsRel[1] +
- " " + xAxisRotation + " " + largeArcFlag +
- " " + sweepFlag + " " + pointsRel[2] + " " +
- pointsRel[3] + " ");
- },
- /**
- * curvetoCubicAbs - C
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
- var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]);
-
- this.d = this.d.concat(" C" + pointsAbs[0] + " " + pointsAbs[1] +
- " " + pointsAbs[2] + " " + pointsAbs[3] +
- " " + pointsAbs[4] + " " + pointsAbs[5] + " ");
- },
- /**
- * curvetoCubicRel - c
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
- var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]);
-
- this.d = this.d.concat(" c" + pointsRel[0] + " " + pointsRel[1] +
- " " + pointsRel[2] + " " + pointsRel[3] +
- " " + pointsRel[4] + " " + pointsRel[5] + " ");
- },
- /**
- * linetoHorizontalAbs - H
- *
- * @param {Number} x
- */
- linetoHorizontalAbs: function(x) {
- var pointsAbs = this.editPointsAbs([x, 0]);
-
- this.d = this.d.concat(" H" + pointsAbs[0] + " ");
- },
- /**
- * linetoHorizontalRel - h
- *
- * @param {Number} x
- */
- linetoHorizontalRel: function(x) {
- var pointsRel = this.editPointsRel([x, 0]);
-
- this.d = this.d.concat(" h" + pointsRel[0] + " ");
- },
- /**
- * linetoAbs - L
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoAbs: function(x, y) {
- var pointsAbs = this.editPointsAbs([x, y]);
-
- this.d = this.d.concat(" L" + pointsAbs[0] + " " + pointsAbs[1] + " ");
- },
- /**
- * linetoRel - l
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoRel: function(x, y) {
- var pointsRel = this.editPointsRel([x, y]);
-
- this.d = this.d.concat(" l" + pointsRel[0] + " " + pointsRel[1] + " ");
- },
- /**
- * movetoAbs - M
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoAbs: function(x, y) {
- var pointsAbs = this.editPointsAbs([x, y]);
-
- this.d = this.d.concat(" M" + pointsAbs[0] + " " + pointsAbs[1] + " ");
- },
- /**
- * movetoRel - m
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoRel: function(x, y) {
- var pointsRel;
- if(this.d === "") {
- pointsRel = this.editPointsAbs([x, y]);
- } else {
- pointsRel = this.editPointsRel([x, y]);
- }
-
- this.d = this.d.concat(" m" + pointsRel[0] + " " + pointsRel[1] + " ");
- },
- /**
- * curvetoQuadraticAbs - Q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticAbs: function(x1, y1, x, y) {
- var pointsAbs = this.editPointsAbs([x1, y1, x, y]);
-
- this.d = this.d.concat(" Q" + pointsAbs[0] + " " + pointsAbs[1] + " " +
- pointsAbs[2] + " " + pointsAbs[3] + " ");
- },
- /**
- * curvetoQuadraticRel - q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticRel: function(x1, y1, x, y) {
- var pointsRel = this.editPointsRel([x1, y1, x, y]);
-
- this.d = this.d.concat(" q" + pointsRel[0] + " " + pointsRel[1] + " " +
- pointsRel[2] + " " + pointsRel[3] + " ");
- },
- /**
- * curvetoCubicSmoothAbs - S
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothAbs: function(x2, y2, x, y) {
- var pointsAbs = this.editPointsAbs([x2, y2, x, y]);
-
- this.d = this.d.concat(" S" + pointsAbs[0] + " " + pointsAbs[1] + " " +
- pointsAbs[2] + " " + pointsAbs[3] + " ");
- },
- /**
- * curvetoCubicSmoothRel - s
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothRel: function(x2, y2, x, y) {
- var pointsRel = this.editPointsRel([x2, y2, x, y]);
-
- this.d = this.d.concat(" s" + pointsRel[0] + " " + pointsRel[1] + " " +
- pointsRel[2] + " " + pointsRel[3] + " ");
- },
- /**
- * curvetoQuadraticSmoothAbs - T
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothAbs: function(x, y) {
- var pointsAbs = this.editPointsAbs([x, y]);
-
- this.d = this.d.concat(" T" + pointsAbs[0] + " " + pointsAbs[1] + " ");
- },
- /**
- * curvetoQuadraticSmoothRel - t
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothRel: function(x, y) {
- var pointsRel = this.editPointsRel([x, y]);
-
- this.d = this.d.concat(" t" + pointsRel[0] + " " + pointsRel[1] + " ");
- },
- /**
- * linetoVerticalAbs - V
- *
- * @param {Number} y
- */
- linetoVerticalAbs: function(y) {
- var pointsAbs = this.editPointsAbs([0, y]);
-
- this.d = this.d.concat(" V" + pointsAbs[1] + " ");
- },
- /**
- * linetoVerticalRel - v
- *
- * @param {Number} y
- */
- linetoVerticalRel: function(y) {
- var pointsRel = this.editPointsRel([0, y]);
-
- this.d = this.d.concat(" v" + pointsRel[1] + " ");
- },
- /**
- * closePath - z or Z
- */
- closePath: function() {
- this.d = this.d.concat(" z");
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- /**
- * MinMaxPathHandler
- *
- * Determine the minimum and maximum of a SVG path's absolute coordinates.
- * For relative coordinates the absolute value is computed for consideration.
- * The values are stored in attributes minX, minY, maxX, and maxY.
- *
- * @constructor
- */
- ORYX.Core.SVG.MinMaxPathHandler = Clazz.extend({
-
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
-
- this.minX = undefined;
- this.minY = undefined;
- this.maxX = undefined;
- this.maxY = undefined;
-
- this._lastAbsX = undefined;
- this._lastAbsY = undefined;
- },
- /**
- * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY
- *
- * @param {Array} points Array of absolutePoints
- */
- calculateMinMax: function(points) {
- if(points instanceof Array) {
- var x, y;
- for(var i = 0; i < points.length; i++) {
- x = parseFloat(points[i]);
- i++;
- y = parseFloat(points[i]);
-
- this.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x;
- this.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x;
- this.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y;
- this.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y;
-
- this._lastAbsX = x;
- this._lastAbsY = y;
- }
- } else {
- //TODO error
- }
- },
- /**
- * arcAbs - A
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- this.calculateMinMax([x, y]);
- },
- /**
- * arcRel - a
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoCubicAbs - C
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
- this.calculateMinMax([x1, y1, x2, y2, x, y]);
- },
- /**
- * curvetoCubicRel - c
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
- this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1,
- this._lastAbsX + x2, this._lastAbsY + y2,
- this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * linetoHorizontalAbs - H
- *
- * @param {Number} x
- */
- linetoHorizontalAbs: function(x) {
- this.calculateMinMax([x, this._lastAbsY]);
- },
- /**
- * linetoHorizontalRel - h
- *
- * @param {Number} x
- */
- linetoHorizontalRel: function(x) {
- this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]);
- },
- /**
- * linetoAbs - L
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoAbs: function(x, y) {
- this.calculateMinMax([x, y]);
- },
- /**
- * linetoRel - l
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoRel: function(x, y) {
- this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * movetoAbs - M
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoAbs: function(x, y) {
- this.calculateMinMax([x, y]);
- },
- /**
- * movetoRel - m
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoRel: function(x, y) {
- if(this._lastAbsX && this._lastAbsY) {
- this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
- } else {
- this.calculateMinMax([x, y]);
- }
- },
- /**
- * curvetoQuadraticAbs - Q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticAbs: function(x1, y1, x, y) {
- this.calculateMinMax([x1, y1, x, y]);
- },
- /**
- * curvetoQuadraticRel - q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticRel: function(x1, y1, x, y) {
- this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoCubicSmoothAbs - S
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothAbs: function(x2, y2, x, y) {
- this.calculateMinMax([x2, y2, x, y]);
- },
- /**
- * curvetoCubicSmoothRel - s
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothRel: function(x2, y2, x, y) {
- this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoQuadraticSmoothAbs - T
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothAbs: function(x, y) {
- this.calculateMinMax([x, y]);
- },
- /**
- * curvetoQuadraticSmoothRel - t
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothRel: function(x, y) {
- this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * linetoVerticalAbs - V
- *
- * @param {Number} y
- */
- linetoVerticalAbs: function(y) {
- this.calculateMinMax([this._lastAbsX, y]);
- },
- /**
- * linetoVerticalRel - v
- *
- * @param {Number} y
- */
- linetoVerticalRel: function(y) {
- this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]);
- },
- /**
- * closePath - z or Z
- */
- closePath: function() {
- return;// do nothing
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- /**
- * PathHandler
- *
- * Determine absolute points of a SVG path. The coordinates are stored
- * sequentially in the attribute points (x-coordinates at even indices,
- * y-coordinates at odd indices).
- *
- * @constructor
- */
- ORYX.Core.SVG.PointsPathHandler = Clazz.extend({
-
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
-
- this.points = [];
-
- this._lastAbsX = undefined;
- this._lastAbsY = undefined;
- },
- /**
- * addPoints
- *
- * @param {Array} points Array of absolutePoints
- */
- addPoints: function(points) {
- if(points instanceof Array) {
- var x, y;
- for(var i = 0; i < points.length; i++) {
- x = parseFloat(points[i]);
- i++;
- y = parseFloat(points[i]);
-
- this.points.push(x);
- this.points.push(y);
- //this.points.push({x:x, y:y});
-
- this._lastAbsX = x;
- this._lastAbsY = y;
- }
- } else {
- //TODO error
- }
- },
- /**
- * arcAbs - A
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- this.addPoints([x, y]);
- },
- /**
- * arcRel - a
- *
- * @param {Number} rx
- * @param {Number} ry
- * @param {Number} xAxisRotation
- * @param {Boolean} largeArcFlag
- * @param {Boolean} sweepFlag
- * @param {Number} x
- * @param {Number} y
- */
- arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoCubicAbs - C
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicAbs: function(x1, y1, x2, y2, x, y) {
- this.addPoints([x, y]);
- },
- /**
- * curvetoCubicRel - c
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicRel: function(x1, y1, x2, y2, x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * linetoHorizontalAbs - H
- *
- * @param {Number} x
- */
- linetoHorizontalAbs: function(x) {
- this.addPoints([x, this._lastAbsY]);
- },
- /**
- * linetoHorizontalRel - h
- *
- * @param {Number} x
- */
- linetoHorizontalRel: function(x) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY]);
- },
- /**
- * linetoAbs - L
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoAbs: function(x, y) {
- this.addPoints([x, y]);
- },
- /**
- * linetoRel - l
- *
- * @param {Number} x
- * @param {Number} y
- */
- linetoRel: function(x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * movetoAbs - M
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoAbs: function(x, y) {
- this.addPoints([x, y]);
- },
- /**
- * movetoRel - m
- *
- * @param {Number} x
- * @param {Number} y
- */
- movetoRel: function(x, y) {
- if(this._lastAbsX && this._lastAbsY) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- } else {
- this.addPoints([x, y]);
- }
- },
- /**
- * curvetoQuadraticAbs - Q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticAbs: function(x1, y1, x, y) {
- this.addPoints([x, y]);
- },
- /**
- * curvetoQuadraticRel - q
- *
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticRel: function(x1, y1, x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoCubicSmoothAbs - S
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothAbs: function(x2, y2, x, y) {
- this.addPoints([x, y]);
- },
- /**
- * curvetoCubicSmoothRel - s
- *
- * @param {Number} x2
- * @param {Number} y2
- * @param {Number} x
- * @param {Number} y
- */
- curvetoCubicSmoothRel: function(x2, y2, x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * curvetoQuadraticSmoothAbs - T
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothAbs: function(x, y) {
- this.addPoints([x, y]);
- },
- /**
- * curvetoQuadraticSmoothRel - t
- *
- * @param {Number} x
- * @param {Number} y
- */
- curvetoQuadraticSmoothRel: function(x, y) {
- this.addPoints([this._lastAbsX + x, this._lastAbsY + y]);
- },
- /**
- * linetoVerticalAbs - V
- *
- * @param {Number} y
- */
- linetoVerticalAbs: function(y) {
- this.addPoints([this._lastAbsX, y]);
- },
- /**
- * linetoVerticalRel - v
- *
- * @param {Number} y
- */
- linetoVerticalRel: function(y) {
- this.addPoints([this._lastAbsX, this._lastAbsY + y]);
- },
- /**
- * closePath - z or Z
- */
- closePath: function() {
- return;// do nothing
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- *
- * Config variables
- */
- NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
- NAMESPACE_SVG = "http://www.w3.org/2000/svg/";
- /**
- * @classDescription This class wraps the manipulation of a SVG marker.
- * @namespace ORYX.Core.SVG
- * uses Inheritance (Clazz)
- * uses Prototype 1.5.0
- *
- */
- /**
- * Init package
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- ORYX.Core.SVG.SVGMarker = Clazz.extend({
- /**
- * Constructor
- * @param markerElement {SVGMarkerElement}
- */
- construct: function(markerElement) {
- arguments.callee.$.construct.apply(this, arguments);
- this.id = undefined;
- this.element = markerElement;
- this.refX = undefined;
- this.refY = undefined;
- this.markerWidth = undefined;
- this.markerHeight = undefined;
- this.oldRefX = undefined;
- this.oldRefY = undefined;
- this.oldMarkerWidth = undefined;
- this.oldMarkerHeight = undefined;
- this.optional = false;
- this.enabled = true;
- this.minimumLength = undefined;
- this.resize = false;
- this.svgShapes = [];
- this._init(); //initialisation of all the properties declared above.
- },
- /**
- * Initializes the values that are defined in the constructor.
- */
- _init: function() {
- //check if this.element is a SVGMarkerElement
- if(!( this.element == "[object SVGMarkerElement]")) {
- throw "SVGMarker: Argument is not an instance of SVGMarkerElement.";
- }
- this.id = this.element.getAttributeNS(null, "id");
-
- //init svg marker attributes
- var refXValue = this.element.getAttributeNS(null, "refX");
- if(refXValue) {
- this.refX = parseFloat(refXValue);
- } else {
- this.refX = 0;
- }
- var refYValue = this.element.getAttributeNS(null, "refY");
- if(refYValue) {
- this.refY = parseFloat(refYValue);
- } else {
- this.refY = 0;
- }
- var markerWidthValue = this.element.getAttributeNS(null, "markerWidth");
- if(markerWidthValue) {
- this.markerWidth = parseFloat(markerWidthValue);
- } else {
- this.markerWidth = 3;
- }
- var markerHeightValue = this.element.getAttributeNS(null, "markerHeight");
- if(markerHeightValue) {
- this.markerHeight = parseFloat(markerHeightValue);
- } else {
- this.markerHeight = 3;
- }
- this.oldRefX = this.refX;
- this.oldRefY = this.refY;
- this.oldMarkerWidth = this.markerWidth;
- this.oldMarkerHeight = this.markerHeight;
- //init oryx attributes
- var optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "optional");
- if(optionalAttr) {
- optionalAttr = optionalAttr.strip();
- this.optional = (optionalAttr.toLowerCase() === "yes");
- } else {
- this.optional = false;
- }
- var enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "enabled");
- if(enabledAttr) {
- enabledAttr = enabledAttr.strip();
- this.enabled = !(enabledAttr.toLowerCase() === "no");
- } else {
- this.enabled = true;
- }
- var minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "minimumLength");
- if(minLengthAttr) {
- this.minimumLength = parseFloat(minLengthAttr);
- }
- var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize");
- if(resizeAttr) {
- resizeAttr = resizeAttr.strip();
- this.resize = (resizeAttr.toLowerCase() === "yes");
- } else {
- this.resize = false;
- }
- //init SVGShape objects
- //this.svgShapes = this._getSVGShapes(this.element);
- },
- /**
- *
- */
- _getSVGShapes: function(svgElement) {
- if(svgElement.hasChildNodes) {
- var svgShapes = [];
- var me = this;
- $A(svgElement.childNodes).each(function(svgChild) {
- try {
- var svgShape = new ORYX.Core.SVG.SVGShape(svgChild);
- svgShapes.push(svgShape);
- } catch (e) {
- svgShapes = svgShapes.concat(me._getSVGShapes(svgChild));
- }
- });
- return svgShapes;
- }
- },
- /**
- * Writes the changed values into the SVG marker.
- */
- update: function() {
- //TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt!
- // //update marker attributes
- // if(this.refX != this.oldRefX) {
- // this.element.setAttributeNS(null, "refX", this.refX);
- // }
- // if(this.refY != this.oldRefY) {
- // this.element.setAttributeNS(null, "refY", this.refY);
- // }
- // if(this.markerWidth != this.oldMarkerWidth) {
- // this.element.setAttributeNS(null, "markerWidth", this.markerWidth);
- // }
- // if(this.markerHeight != this.oldMarkerHeight) {
- // this.element.setAttributeNS(null, "markerHeight", this.markerHeight);
- // }
- //
- // //update SVGShape objects
- // var widthDelta = this.markerWidth / this.oldMarkerWidth;
- // var heightDelta = this.markerHeight / this.oldMarkerHeight;
- // if(widthDelta != 1 && heightDelta != 1) {
- // this.svgShapes.each(function(svgShape) {
- //
- // });
- // }
- //update old values to prepare the next update
- this.oldRefX = this.refX;
- this.oldRefY = this.refY;
- this.oldMarkerWidth = this.markerWidth;
- this.oldMarkerHeight = this.markerHeight;
- },
-
- toString: function() { return (this.element) ? "SVGMarker " + this.element.id : "SVGMarker " + this.element;}
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- *
- * Config variables
- */
- NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
- NAMESPACE_SVG = "http://www.w3.org/2000/svg/";
- /**
- * @classDescription This class wraps the manipulation of a SVG basic shape or a path.
- * @namespace ORYX.Core.SVG
- * uses Inheritance (Clazz)
- * uses Prototype 1.5.0
- * uses PathParser by Kevin Lindsey (http://kevlindev.com/)
- * uses MinMaxPathHandler
- * uses EditPathHandler
- *
- */
- //init package
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- ORYX.Core.SVG.SVGShape = Clazz.extend({
- /**
- * Constructor
- * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path.
- */
- construct: function(svgElem) {
- arguments.callee.$.construct.apply(this, arguments);
- this.type;
- this.element = svgElem;
- this.x = undefined;
- this.y = undefined;
- this.width = undefined;
- this.height = undefined;
- this.oldX = undefined;
- this.oldY = undefined;
- this.oldWidth = undefined;
- this.oldHeight = undefined;
- this.radiusX = undefined;
- this.radiusY = undefined;
- this.isHorizontallyResizable = false;
- this.isVerticallyResizable = false;
- //this.anchors = [];
- this.anchorLeft = false;
- this.anchorRight = false;
- this.anchorTop = false;
- this.anchorBottom = false;
-
- //attributes of path elements of edge objects
- this.allowDockers = true;
- this.resizeMarkerMid = false;
- this.editPathParser;
- this.editPathHandler;
- this.init(); //initialisation of all the properties declared above.
- },
- /**
- * Initializes the values that are defined in the constructor.
- */
- init: function() {
- /**initialize position and size*/
- if(ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) {
- this.type = "Rect";
-
- var xAttr = this.element.getAttributeNS(null, "x");
- if(xAttr) {
- this.oldX = parseFloat(xAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var yAttr = this.element.getAttributeNS(null, "y");
- if(yAttr) {
- this.oldY = parseFloat(yAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var widthAttr = this.element.getAttributeNS(null, "width");
- if(widthAttr) {
- this.oldWidth = parseFloat(widthAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var heightAttr = this.element.getAttributeNS(null, "height");
- if(heightAttr) {
- this.oldHeight = parseFloat(heightAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- } else if(ORYX.Editor.checkClassType(this.element, SVGCircleElement)) {
- this.type = "Circle";
-
- var cx = undefined;
- var cy = undefined;
- //var r = undefined;
- var cxAttr = this.element.getAttributeNS(null, "cx");
- if(cxAttr) {
- cx = parseFloat(cxAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var cyAttr = this.element.getAttributeNS(null, "cy");
- if(cyAttr) {
- cy = parseFloat(cyAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var rAttr = this.element.getAttributeNS(null, "r");
- if(rAttr) {
- //r = parseFloat(rAttr);
- this.radiusX = parseFloat(rAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- this.oldX = cx - this.radiusX;
- this.oldY = cy - this.radiusX;
- this.oldWidth = 2*this.radiusX;
- this.oldHeight = 2*this.radiusX;
- } else if(ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) {
- this.type = "Ellipse";
-
- var cx = undefined;
- var cy = undefined;
- //var rx = undefined;
- //var ry = undefined;
- var cxAttr = this.element.getAttributeNS(null, "cx");
- if(cxAttr) {
- cx = parseFloat(cxAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var cyAttr = this.element.getAttributeNS(null, "cy");
- if(cyAttr) {
- cy = parseFloat(cyAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var rxAttr = this.element.getAttributeNS(null, "rx");
- if(rxAttr) {
- this.radiusX = parseFloat(rxAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var ryAttr = this.element.getAttributeNS(null, "ry");
- if(ryAttr) {
- this.radiusY = parseFloat(ryAttr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- this.oldX = cx - this.radiusX;
- this.oldY = cy - this.radiusY;
- this.oldWidth = 2*this.radiusX;
- this.oldHeight = 2*this.radiusY;
- } else if(ORYX.Editor.checkClassType(this.element, SVGLineElement)) {
- this.type = "Line";
-
- var x1 = undefined;
- var y1 = undefined;
- var x2 = undefined;
- var y2 = undefined;
- var x1Attr = this.element.getAttributeNS(null, "x1");
- if(x1Attr) {
- x1 = parseFloat(x1Attr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var y1Attr = this.element.getAttributeNS(null, "y1");
- if(y1Attr) {
- y1 = parseFloat(y1Attr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var x2Attr = this.element.getAttributeNS(null, "x2");
- if(x2Attr) {
- x2 = parseFloat(x2Attr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- var y2Attr = this.element.getAttributeNS(null, "y2");
- if(y2Attr) {
- y2 = parseFloat(y2Attr);
- } else {
- throw "Missing attribute in element " + this.element;
- }
- this.oldX = Math.min(x1,x2);
- this.oldY = Math.min(y1,y2);
- this.oldWidth = Math.abs(x1-x2);
- this.oldHeight = Math.abs(y1-y2);
- } else if(ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) {
- this.type = "Polyline";
-
- var pointsArray = [];
- if (this.element.points&&this.element.points.numberOfItems){
- for(var i=0, size=this.element.points.numberOfItems; i<size; i++){
- pointsArray.push(this.element.points.getItem(i).x)
- pointsArray.push(this.element.points.getItem(i).y)
- }
- } else {
- var points = this.element.getAttributeNS(null, "points");
- if(points) {
- points = points.replace(/,/g , " ");
- pointsArray = points.split(" ");
- pointsArray = pointsArray.without("");
- } else {
- throw "Missing attribute in element " + this.element;
- }
- }
-
- if(pointsArray && pointsArray.length && pointsArray.length > 1) {
- var minX = parseFloat(pointsArray[0]);
- var minY = parseFloat(pointsArray[1]);
- var maxX = parseFloat(pointsArray[0]);
- var maxY = parseFloat(pointsArray[1]);
- for(var i = 0; i < pointsArray.length; i++) {
- minX = Math.min(minX, parseFloat(pointsArray[i]));
- maxX = Math.max(maxX, parseFloat(pointsArray[i]));
- i++;
- minY = Math.min(minY, parseFloat(pointsArray[i]));
- maxY = Math.max(maxY, parseFloat(pointsArray[i]));
- }
- this.oldX = minX;
- this.oldY = minY;
- this.oldWidth = maxX-minX;
- this.oldHeight = maxY-minY;
- } else {
- throw "Missing attribute in element " + this.element;
- }
- } else if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {
- this.type = "Path";
-
- this.editPathParser = new PathParser();
- this.editPathHandler = new ORYX.Core.SVG.EditPathHandler();
- this.editPathParser.setHandler(this.editPathHandler);
-
- var parser = new PathParser();
- var handler = new ORYX.Core.SVG.MinMaxPathHandler();
- parser.setHandler(handler);
- parser.parsePath(this.element);
- this.oldX = handler.minX;
- this.oldY = handler.minY;
- this.oldWidth = handler.maxX - handler.minX;
- this.oldHeight = handler.maxY - handler.minY;
- delete parser;
- delete handler;
- } else {
- throw "Element is not a shape.";
- }
- /** initialize attributes of oryx namespace */
- //resize
- var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize");
- if(resizeAttr) {
- resizeAttr = resizeAttr.toLowerCase();
- if(resizeAttr.match(/horizontal/)) {
- this.isHorizontallyResizable = true;
- } else {
- this.isHorizontallyResizable = false;
- }
- if(resizeAttr.match(/vertical/)) {
- this.isVerticallyResizable = true;
- } else {
- this.isVerticallyResizable = false;
- }
- } else {
- this.isHorizontallyResizable = false;
- this.isVerticallyResizable = false;
- }
- //anchors
- var anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "anchors");
- if(anchorAttr) {
- anchorAttr = anchorAttr.replace("/,/g", " ");
- var anchors = anchorAttr.split(" ").without("");
-
- for(var i = 0; i < anchors.length; i++) {
- switch(anchors[i].toLowerCase()) {
- case "left":
- this.anchorLeft = true;
- break;
- case "right":
- this.anchorRight = true;
- break;
- case "top":
- this.anchorTop = true;
- break;
- case "bottom":
- this.anchorBottom = true;
- break;
- }
- }
- }
-
- //allowDockers and resizeMarkerMid
- if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) {
- var allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "allowDockers");
- if(allowDockersAttr) {
- if(allowDockersAttr.toLowerCase() === "no") {
- this.allowDockers = false;
- } else {
- this.allowDockers = true;
- }
- }
-
- var resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resizeMarker-mid");
- if(resizeMarkerMidAttr) {
- if(resizeMarkerMidAttr.toLowerCase() === "yes") {
- this.resizeMarkerMid = true;
- } else {
- this.resizeMarkerMid = false;
- }
- }
- }
-
- this.x = this.oldX;
- this.y = this.oldY;
- this.width = this.oldWidth;
- this.height = this.oldHeight;
- },
- /**
- * Writes the changed values into the SVG element.
- */
- update: function() {
-
- if(this.x !== this.oldX || this.y !== this.oldY || this.width !== this.oldWidth || this.height !== this.oldHeight) {
- switch(this.type) {
- case "Rect":
- if(this.x !== this.oldX) this.element.setAttributeNS(null, "x", this.x);
- if(this.y !== this.oldY) this.element.setAttributeNS(null, "y", this.y);
- if(this.width !== this.oldWidth) this.element.setAttributeNS(null, "width", this.width);
- if(this.height !== this.oldHeight) this.element.setAttributeNS(null, "height", this.height);
- break;
- case "Circle":
- //calculate the radius
- //var r;
- // if(this.width/this.oldWidth <= this.height/this.oldHeight) {
- // this.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0;
- // } else {
- this.radiusX = ((this.width < this.height) ? this.width : this.height)/2.0;
- //}
-
- this.element.setAttributeNS(null, "cx", this.x + this.width/2.0);
- this.element.setAttributeNS(null, "cy", this.y + this.height/2.0);
- this.element.setAttributeNS(null, "r", this.radiusX);
- break;
- case "Ellipse":
- this.radiusX = this.width/2;
- this.radiusY = this.height/2;
-
- this.element.setAttributeNS(null, "cx", this.x + this.radiusX);
- this.element.setAttributeNS(null, "cy", this.y + this.radiusY);
- this.element.setAttributeNS(null, "rx", this.radiusX);
- this.element.setAttributeNS(null, "ry", this.radiusY);
- break;
- case "Line":
- if(this.x !== this.oldX)
- this.element.setAttributeNS(null, "x1", this.x);
-
- if(this.y !== this.oldY)
- this.element.setAttributeNS(null, "y1", this.y);
-
- if(this.x !== this.oldX || this.width !== this.oldWidth)
- this.element.setAttributeNS(null, "x2", this.x + this.width);
-
- if(this.y !== this.oldY || this.height !== this.oldHeight)
- this.element.setAttributeNS(null, "y2", this.y + this.height);
- break;
- case "Polyline":
- var points = this.element.getAttributeNS(null, "points");
- if(points) {
- points = points.replace(/,/g, " ").split(" ").without("");
-
- if(points && points.length && points.length > 1) {
-
- //TODO what if oldWidth == 0?
- var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;
- var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;
-
- var updatedPoints = "";
- for(var i = 0; i < points.length; i++) {
- var x = (parseFloat(points[i])-this.oldX)*widthDelta + this.x;
- i++;
- var y = (parseFloat(points[i])-this.oldY)*heightDelta + this.y;
- updatedPoints += x + " " + y + " ";
- }
- this.element.setAttributeNS(null, "points", updatedPoints);
- } else {
- //TODO error
- }
- } else {
- //TODO error
- }
- break;
- case "Path":
- //calculate scaling delta
- //TODO what if oldWidth == 0?
- var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth;
- var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight;
-
- //use path parser to edit each point of the path
- this.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta);
- this.editPathParser.parsePath(this.element);
-
- //change d attribute of path
- this.element.setAttributeNS(null, "d", this.editPathHandler.d);
- break;
- }
- this.oldX = this.x;
- this.oldY = this.y;
- this.oldWidth = this.width;
- this.oldHeight = this.height;
- }
-
- // Remove cached variables
- delete this.visible;
- delete this.handler;
- },
-
- isPointIncluded: function(pointX, pointY) {
- // Check if there are the right arguments and if the node is visible
- if(!pointX || !pointY || !this.isVisible()) {
- return false;
- }
- switch(this.type) {
- case "Rect":
- return (pointX >= this.x && pointX <= this.x + this.width &&
- pointY >= this.y && pointY <= this.y+this.height);
- break;
- case "Circle":
- //calculate the radius
- // var r;
- // if(this.width/this.oldWidth <= this.height/this.oldHeight) {
- // r = ((this.width > this.height) ? this.width : this.height)/2.0;
- // } else {
- // r = ((this.width < this.height) ? this.width : this.height)/2.0;
- // }
- return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width/2.0, this.y + this.height/2.0, this.radiusX, this.radiusX);
- break;
- case "Ellipse":
- return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY);
- break;
- case "Line":
- return ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height);
- break;
- case "Polyline":
- var points = this.element.getAttributeNS(null, "points");
-
- if(points) {
- points = points.replace(/,/g , " ").split(" ").without("");
-
- points = points.collect(function(n) {
- return parseFloat(n);
- });
-
- return ORYX.Core.Math.isPointInPolygone(pointX, pointY, points);
- } else {
- return false;
- }
- break;
- case "Path":
-
- // Cache Path handler
- if (!this.handler) {
- var parser = new PathParser();
- this.handler = new ORYX.Core.SVG.PointsPathHandler();
- parser.setHandler(this.handler);
- parser.parsePath(this.element);
- }
-
- return ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points);
- break;
- default:
- return false;
- }
- },
- /**
- * Returns true if the element is visible
- * @param {SVGElement} elem
- * @return boolean
- */
- isVisible: function(elem) {
-
- if (this.visible !== undefined){
- return this.visible;
- }
-
- if (!elem) {
- elem = this.element;
- }
- var hasOwnerSVG = false;
- try {
- hasOwnerSVG = !!elem.ownerSVGElement;
- } catch(e){}
-
- // Is SVG context
- if ( hasOwnerSVG ) {
- // IF G-Element
- if (ORYX.Editor.checkClassType(elem, SVGGElement)) {
- if (elem.className && elem.className.baseVal == "me") {
- this.visible = true;
- return this.visible;
- }
- }
- // Check if fill or stroke is set
- var fill = elem.getAttributeNS(null, "fill");
- var stroke = elem.getAttributeNS(null, "stroke");
- if (fill && fill == "none" && stroke && stroke == "none") {
- this.visible = false;
- } else {
- // Check if displayed
- var attr = elem.getAttributeNS(null, "display");
- if(!attr)
- this.visible = this.isVisible(elem.parentNode);
- else if (attr == "none")
- this.visible = false;
- else
- this.visible = true;
- }
- } else {
- this.visible = true;
- }
-
- return this.visible;
- },
- toString: function() { return (this.element) ? "SVGShape " + this.element.id : "SVGShape " + this.element;}
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};}
- /**
- * @classDescription Class for adding text to a shape.
- *
- */
- ORYX.Core.SVG.Label = Clazz.extend({
-
- _characterSets:[
- "%W",
- "@",
- "m",
- "wDGMOQÖ#+=<>~^",
- "ABCHKNRSUVXZÜÄ&",
- "bdghnopquxöüETY1234567890ß_§${}*´`µ€",
- "aeksvyzäFLP?°²³",
- "c-",
- "rtJ\"/()[]:;!|\\",
- "fjI., ",
- "'",
- "il"
- ],
- _characterSetValues:[15,14,13,11,10,9,8,7,6,5,4,3],
- /**
- * Constructor
- * @param options {Object} :
- * textElement
- *
- */
- construct: function(options) {
- arguments.callee.$.construct.apply(this, arguments);
-
- if(!options.textElement) {
- throw "Label: No parameter textElement."
- } else if (!ORYX.Editor.checkClassType( options.textElement, SVGTextElement ) ) {
- throw "Label: Parameter textElement is not an SVGTextElement."
- }
-
- this.invisibleRenderPoint = -5000;
-
- this.node = options.textElement;
-
-
- this.node.setAttributeNS(null, 'stroke-width', '0pt');
- this.node.setAttributeNS(null, 'letter-spacing', '-0.01px');
-
- this.shapeId = options.shapeId;
-
- this.id;
-
- this.fitToElemId;
-
- this.edgePosition;
-
- this.x;
- this.y;
- this.oldX;
- this.oldY;
-
- this.isVisible = true;
-
- this._text;
- this._verticalAlign;
- this._horizontalAlign;
- this._rotate;
- this._rotationPoint;
-
- //this.anchors = [];
- this.anchorLeft;
- this.anchorRight;
- this.anchorTop;
- this.anchorBottom;
-
- this._isChanged = true;
- //if the text element already has an id, don't change it.
- var _id = this.node.getAttributeNS(null, 'id');
- if(_id) {
- this.id = _id;
- }
-
- //initialization
-
- //set referenced element the text is fit to
- this.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem');
- if(this.fitToElemId)
- this.fitToElemId = this.shapeId + this.fitToElemId;
-
- //set alignment
- var alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align');
- if(alignValues) {
- alignValues = alignValues.replace(/,/g, " ");
- alignValues = alignValues.split(" ");
- alignValues = alignValues.without("");
-
- alignValues.each((function(alignValue) {
- switch (alignValue) {
- case 'top':
- case 'middle':
- case 'bottom':
- if(!this._verticalAlign){this._originVerticalAlign = this._verticalAlign = alignValue;}
- break;
- case 'left':
- case 'center':
- case 'right':
- if(!this._horizontalAlign){this._originHorizontalAlign = this._horizontalAlign = alignValue;}
- break;
- }
- }).bind(this));
- }
-
- //set edge position (only in case the label belongs to an edge)
- this.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition');
- if(this.edgePosition) {
- this.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase();
- }
-
-
- //get offset top
- this.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP;
- if(this.offsetTop) {
- this.offsetTop = parseInt(this.offsetTop);
- }
-
- //get offset top
- this.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM;
- if(this.offsetBottom) {
- this.offsetBottom = parseInt(this.offsetBottom);
- }
-
-
- //set rotation
- var rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate');
- if(rotateValue) {
- try {
- this._rotate = parseFloat(rotateValue);
- } catch (e) {
- this._rotate = 0;
- }
- } else {
- this._rotate = 0;
- }
-
- //anchors
- var anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
- if(anchorAttr) {
- anchorAttr = anchorAttr.replace("/,/g", " ");
- var anchors = anchorAttr.split(" ").without("");
-
- for(var i = 0; i < anchors.length; i++) {
- switch(anchors[i].toLowerCase()) {
- case "left":
- this.originAnchorLeft = this.anchorLeft = true;
- break;
- case "right":
- this.originAnchorRight = this.anchorRight = true;
- break;
- case "top":
- this.originAnchorTop = this.anchorTop = true;
- break;
- case "bottom":
- this.originAnchorBottom = this.anchorBottom = true;
- break;
- }
- }
- }
-
- //if no alignment defined, set default alignment
- if(!this._verticalAlign) { this._verticalAlign = 'bottom'; }
- if(!this._horizontalAlign) { this._horizontalAlign = 'left'; }
- var xValue = this.node.getAttributeNS(null, 'x');
- if(xValue) {
- this.oldX = this.x = parseFloat(xValue);
- } else {
- //TODO error
- }
-
- var yValue = this.node.getAttributeNS(null, 'y');
- if(yValue) {
- this.oldY = this.y = parseFloat(yValue);
- } else {
- //TODO error
- }
-
- //set initial text
- this.text(this.node.textContent);
- },
-
- /**
- * Reset the anchor position to the original value
- * which was specified in the stencil set
- *
- */
- resetAnchorPosition: function(){
- this.anchorLeft = this.originAnchorLeft || false;
- this.anchorRight = this.originAnchorRight || false;
- this.anchorTop = this.originAnchorTop || false;
- this.anchorBottom = this.originAnchorBottom || false;
- },
-
- isOriginAnchorLeft: function(){ return this.originAnchorLeft || false; },
- isOriginAnchorRight: function(){ return this.originAnchorRight || false; },
- isOriginAnchorTop: function(){ return this.originAnchorTop || false; },
- isOriginAnchorBottom: function(){ return this.originAnchorBottom || false; },
-
-
- isAnchorLeft: function(){ return this.anchorLeft || false; },
- isAnchorRight: function(){ return this.anchorRight || false; },
- isAnchorTop: function(){ return this.anchorTop || false; },
- isAnchorBottom: function(){ return this.anchorBottom || false; },
-
- /**
- * Returns the x coordinate
- * @return {number}
- */
- getX: function(){
- try {
- var x = this.node.x.baseVal.getItem(0).value;
- switch(this.horizontalAlign()){
- case "left": return x;
- case "center": return x - (this.getWidth()/2);
- case "right": return x - this.getWidth();
- }
- return this.node.getBBox().x;
- } catch(e){
- return this.x;
- }
- },
-
- setX: function(x){
- if (this.position)
- this.position.x = x;
- else
- this.setOriginX(x);
- },
-
-
- /**
- * Returns the y coordinate
- * @return {number}
- */
- getY: function(){
- try {
- return this.node.getBBox().y;
- } catch(e){
- return this.y;
- }
- },
-
- setY: function(y){
- if (this.position)
- this.position.y = y;
- else
- this.setOriginY(y);
- },
-
- setOriginX: function(x){
- this.x = x;
- },
-
- setOriginY: function(y){
- this.y = y;
- },
-
- /**
- * Returns the width of the label
- * @return {number}
- */
- getWidth: function(){
- try {
- try {
- var width, cn = this.node.childNodes;
- if (cn.length == 0 || !Ext.isGecko) {
- width = this.node.getBBox().width;
- } else {
- for (var i = 0, size = cn.length; i < size; ++i) {
- var w = cn[i].getComputedTextLength();
- if ("undefined" == typeof width || width < w) {
- width = w;
- }
- }
- }
- return width+(width%2==0?0:1);
- } catch (ee) {
- return this.node.getBBox().width;
- }
- } catch(e){
- return 0;
- }
- },
-
- getOriginUpperLeft: function(){
- var x = this.x, y = this.y;
- switch (this._horizontalAlign){
- case 'center' :
- x -= this.getWidth()/2;
- break;
- case 'right' :
- x -= this.getWidth();
- break;
- }
- switch (this._verticalAlign){
- case 'middle' :
- y -= this.getHeight()/2;
- break;
- case 'bottom' :
- y -= this.getHeight();
- break;
- }
- return {x:x, y:y};
- },
-
- /**
- * Returns the height of the label
- * @return {number}
- */
- getHeight: function(){
- try {
- return this.node.getBBox().height;
- } catch(e){
- return 0;
- }
- },
-
- /**
- * Returns the relative center position of the label
- * to its parent shape.
- * @return {Object}
- */
- getCenter: function(){
- var up = {x: this.getX(), y: this.getY()};
- up.x += this.getWidth()/2;
- up.y += this.getHeight()/2;
- return up;
- },
-
- /**
- * Sets the position of a label relative to the parent.
- * @param {Object} position
- */
- setPosition: function(position){
- if (!position || position.x === undefined || position.y === undefined) {
- delete this.position;
- } else {
- this.position = position;
- }
-
- if (this.position){
- delete this._referencePoint;
- delete this.edgePosition;
- }
-
- this._isChanged = true;
- this.update();
- },
-
- /**
- * Return the position
- */
- getPosition: function(){
- return this.position;
- },
-
- setReferencePoint: function(ref){
- if (ref) {
- this._referencePoint = ref;
- } else {
- delete this._referencePoint;
- }
- if (this._referencePoint){
- delete this.position;
- }
- },
-
- getReferencePoint: function(){
- return this._referencePoint || undefined;
- },
-
- changed: function() {
- this._isChanged = true;
- },
-
- /**
- * Register a callback which will be called if the label
- * was rendered.
- * @param {Object} fn
- */
- registerOnChange: function(fn){
- if (!this.changeCallbacks){
- this.changeCallbacks = [];
- }
- if (fn instanceof Function && !this.changeCallbacks.include(fn)){
- this.changeCallbacks.push(fn);
- }
- },
-
- /**
- * Unregister the callback for changes.
- * @param {Object} fn
- */
- unregisterOnChange: function(fn){
- if (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)){
- this.changeCallbacks = this.changeCallbacks.without(fn);
- }
- },
-
- /**
- * Returns TRUE if the labe is currently in
- * the update mechanism.
- * @return {Boolean}
- */
- isUpdating: function(){
- return !!this._isUpdating;
- },
-
-
- getOriginEdgePosition: function(){
- return this.originEdgePosition;
- },
-
- /**
- * Returns the edgeposition.
- *
- * @return {String} "starttop", "startmiddle", "startbottom",
- * "midtop", "midbottom", "endtop", "endbottom" or null
- */
- getEdgePosition: function(){
- return this.edgePosition || null;
- },
-
- /**
- * Set the edge position, must be one of the valid
- * edge positions (see getEdgePosition).
- * Removes the reference point and the absolute position as well.
- *
- * @param {Object} position
- */
- setEdgePosition: function(position){
- if (["starttop", "startmiddle", "startbottom",
- "midtop", "midbottom", "endtop", "endbottom"].include(position)){
- this.edgePosition = position;
- delete this.position;
- delete this._referencePoint;
- } else {
- delete this.edgePosition;
- }
- },
-
- /**
- * Update the SVG text element.
- */
- update: function(force) {
-
- var x = this.x, y = this.y;
- if (this.position){
- x = this.position.x;
- y = this.position.y;
- }
- x = Math.floor(x); y = Math.floor(y);
-
- if(this._isChanged || x !== this.oldX || y !== this.oldY || force === true) {
- if (this.isVisible) {
- this._isChanged = false;
- this._isUpdating = true;
-
- this.node.setAttributeNS(null, 'x', x);
- this.node.setAttributeNS(null, 'y', y);
- this.node.removeAttributeNS(null, "fill-opacity");
-
- //this.node.setAttributeNS(null, 'font-size', this._fontSize);
- //this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + " " + this._verticalAlign);
-
- this.oldX = x;
- this.oldY = y;
-
- //set rotation
- if (!this.position && !this.getReferencePoint()) {
- if (this._rotate !== undefined) {
- if (this._rotationPoint)
- this.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(this._rotationPoint.x) + ' ' + Math.floor(this._rotationPoint.y) + ')');
- else
- this.node.setAttributeNS(null, 'transform', 'rotate(' + this._rotate + ' ' + Math.floor(x) + ' ' + Math.floor(y) + ')');
- }
- } else {
- this.node.removeAttributeNS(null, 'transform');
- }
-
- var textLines = this._text.split("\n");
- while (textLines.last() == "")
- textLines.pop();
-
-
- if (this.node.ownerDocument) {
- // Only reset the tspans if the text
- // has changed or has to be wrapped
- if (this.fitToElemId || this._textHasChanged){
- this.node.textContent = ""; // Remove content
- textLines.each((function(textLine, index){
- var tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
- tspan.textContent = textLine.trim();
- if (this.fitToElemId) {
- tspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);
- tspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);
- }
-
- /*
- * Chrome's getBBox() method fails, if a text node contains an empty tspan element.
- * So, we add a whitespace to such a tspan element.
- */
- if(tspan.textContent === "") {
- tspan.textContent = " ";
- }
-
- //append tspan to text node
- this.node.appendChild(tspan);
- }).bind(this));
- delete this._textHasChanged;
- delete this.indices;
- }
-
- //Work around for Mozilla bug 293581
- if (this.isVisible && this.fitToElemId) {
- this.node.setAttributeNS(null, 'visibility', 'hidden');
- }
-
- if (this.fitToElemId) {
- window.setTimeout(this._checkFittingToReferencedElem.bind(this), 0);
- } else {
- window.setTimeout(this._positionText.bind(this), 0);
- //this._positionText();
- }
- }
- } else {
- this.node.textContent = "";
- //this.node.setAttributeNS(null, "fill-opacity", "0.2");
- }
- }
- },
-
- _checkFittingToReferencedElem: function() {
- try {
- var tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'));
-
- //only do this in firefox 3. all other browsers do not support word wrapping!!!!!
- //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) {
- var newtspans = [];
-
- var refNode = this.node.ownerDocument.getElementById(this.fitToElemId);
-
- if (refNode) {
-
- var refbb = refNode.getBBox();
-
- var fontSize = this.getFontSize();
-
- for (var j = 0; j < tspans.length; j++) {
- var tspan = tspans[j];
-
- var textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize);
-
- var refBoxLength = (this._rotate != 0
- && this._rotate % 180 != 0
- && this._rotate % 90 == 0 ?
- refbb.height : refbb.width);
-
- if (textLength > refBoxLength) {
-
- var startIndex = 0;
- var lastSeperatorIndex = 0;
-
- var numOfChars = this.getTrimmedTextLength(tspan.textContent);
- for (var i = 0; i < numOfChars; i++) {
- var sslength = this._getRenderedTextLength(tspan, startIndex, i-startIndex, fontSize);
-
- if (sslength > refBoxLength - 2) {
- var newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
- if (lastSeperatorIndex <= startIndex) {
- lastSeperatorIndex = (i == 0) ? i : i-1;
- newtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim();
- //lastSeperatorIndex = i;
- }
- else {
- newtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim();
- }
-
- newtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint);
- newtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint);
-
- //insert tspan to text node
- //this.node.insertBefore(newtspan, tspan);
- newtspans.push(newtspan);
-
- startIndex = lastSeperatorIndex;
-
- }
- else {
- var curChar = tspan.textContent.charAt(i);
- if (curChar == ' ' ||
- curChar == '-' ||
- curChar == "." ||
- curChar == "," ||
- curChar == ";" ||
- curChar == ":") {
- lastSeperatorIndex = i;
- }
- }
- }
-
- tspan.textContent = tspan.textContent.slice(startIndex).trim();
- }
-
- newtspans.push(tspan);
- }
-
- while (this.node.hasChildNodes())
- this.node.removeChild(this.node.childNodes[0]);
-
- while (newtspans.length > 0) {
- this.node.appendChild(newtspans.shift());
- }
- }
- //}
- } catch (e) {
- ORYX.Log.fatal("Error " + e);
- }
-
- window.setTimeout(this._positionText.bind(this), 0);
- },
-
- /**
- * This is a work around method for Mozilla bug 293581.
- * Before the method getComputedTextLength works, the text has to be rendered.
- */
- _positionText: function() {
- try {
- //var tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
- var tspans = this.node.childNodes;
-
- var fontSize = this.getFontSize(this.node);
-
- var invalidTSpans = [];
-
- var x = this.x, y = this.y;
- if (this.position){
- x = this.position.x;
- y = this.position.y;
- }
- x = Math.floor(x); y = Math.floor(y);
-
- var i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called
- var is =(this.indices || $R(0,tspans.length-1).toArray());
- var length = is.length;
- is.each((function(index){
- if ("undefined" == typeof index){
- return;
- }
-
- var tspan = tspans[i++];
-
- if(tspan.textContent.trim() === "") {
- invalidTSpans.push(tspan);
- } else {
- //set vertical position
- var dy = 0;
- switch (this._verticalAlign) {
- case 'bottom':
- dy = -(length - index - 1) * (fontSize);
- break;
- case 'middle':
- dy = -(length / 2.0 - index - 1) * (fontSize);
- dy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2;
- break;
- case 'top':
- dy = index * (fontSize);
- dy += fontSize;
- break;
- }
-
- tspan.setAttributeNS(null, 'dy', Math.floor(dy));
-
- tspan.setAttributeNS(null, 'x', x);
- tspan.setAttributeNS(null, 'y', y);
- indic.push(index);
- }
-
- }).bind(this));
-
- indic.length = tspans.length;
- this.indices = this.indices || indic;
-
- invalidTSpans.each(function(tspan) {
- this.node.removeChild(tspan)
- }.bind(this));
-
- //set horizontal alignment
- switch (this._horizontalAlign) {
- case 'left':
- this.node.setAttributeNS(null, 'text-anchor', 'start');
- break;
- case 'center':
- this.node.setAttributeNS(null, 'text-anchor', 'middle');
- break;
- case 'right':
- this.node.setAttributeNS(null, 'text-anchor', 'end');
- break;
- }
-
- } catch(e) {
- //console.log(e);
- this._isChanged = true;
- }
-
-
- if(this.isVisible) {
- this.node.removeAttributeNS(null, 'visibility');
- }
-
-
- // Finished
- delete this._isUpdating;
-
- // Raise change event
- (this.changeCallbacks||[]).each(function(fn){
- fn.apply(fn);
- })
-
- },
-
- /**
- * Returns the text length of the text content of an SVG tspan element.
- * For all browsers but Firefox 3 the values are estimated.
- * @param {TSpanSVGElement} tspan
- * @param {int} startIndex Optional, for sub strings
- * @param {int} endIndex Optional, for sub strings
- */
- _getRenderedTextLength: function(tspan, startIndex, endIndex, fontSize) {
- //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {
- if(startIndex === undefined) {
- //test string: abcdefghijklmnopqrstuvwxyzöäü,.-#+ 1234567890ßABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*ÜÄÖ!"§$%&/()=?[]{}|<>'~´`\^°µ@€²³
- // for(var i = 0; i < tspan.textContent.length; i++) {
- // console.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0));
- // }
- return tspan.getComputedTextLength();
- } else {
- return tspan.getSubStringLength(startIndex, endIndex);
- }
- /*} else {
- if(startIndex === undefined) {
- return this._estimateTextWidth(tspan.textContent, fontSize);
- } else {
- return this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize);
- }
- }*/
- },
-
- /**
- * Estimates the text width for a string.
- * Used for word wrapping in all browser but FF3.
- * @param {Object} text
- */
- _estimateTextWidth: function(text, fontSize) {
- var sum = 0.0;
- for(var i = 0; i < text.length; i++) {
- sum += this._estimateCharacterWidth(text.charAt(i));
- }
-
- return sum*(fontSize/14.0);
- },
-
- /**
- * Estimates the width of a single character for font size 14.
- * Used for word wrapping in all browser but FF3.
- * @param {Object} character
- */
- _estimateCharacterWidth: function(character) {
- for(var i = 0; i < this._characterSets.length; i++) {
- if(this._characterSets[i].indexOf(character) >= 0) {
- return this._characterSetValues[i];
- }
- }
- return 9;
- },
-
- getReferencedElementWidth: function() {
- var refNode = this.node.ownerDocument.getElementById(this.fitToElemId);
-
- if(refNode) {
- var refbb = refNode.getBBox();
-
- if(refbb) {
- return (this._rotate != 0
- && this._rotate % 180 != 0
- && this._rotate % 90 == 0 ?
- refbb.height : refbb.width);
- }
- }
-
- return undefined;
- },
-
- /**
- * If no parameter is provided, this method returns the current text.
- * @param text {String} Optional. Replaces the old text with this one.
- */
- text: function() {
- switch (arguments.length) {
- case 0:
- return this._text
- break;
-
- case 1:
- var oldText = this._text;
- if(arguments[0]) {
- this._text = arguments[0].toString();
- } else {
- this._text = "";
- }
- if(oldText !== this._text) {
- this._isChanged = true;
- this._textHasChanged = true;
- }
- break;
-
- default:
- //TODO error
- break;
- }
- },
-
- getOriginVerticalAlign: function(){
- return this._originVerticalAlign;
- },
-
- verticalAlign: function() {
- switch(arguments.length) {
- case 0:
- return this._verticalAlign;
- case 1:
- if(['top', 'middle', 'bottom'].member(arguments[0])) {
- var oldValue = this._verticalAlign;
- this._verticalAlign = arguments[0];
- if(this._verticalAlign !== oldValue) {
- this._isChanged = true;
- }
- }
- break;
-
- default:
- //TODO error
- break;
- }
- },
-
- getOriginHorizontalAlign: function(){
- return this._originHorizontalAlign;
- },
-
- horizontalAlign: function() {
- switch(arguments.length) {
- case 0:
- return this._horizontalAlign;
- case 1:
- if(['left', 'center', 'right'].member(arguments[0])) {
- var oldValue = this._horizontalAlign;
- this._horizontalAlign = arguments[0];
- if(this._horizontalAlign !== oldValue) {
- this._isChanged = true;
- }
- }
- break;
-
- default:
- //TODO error
- break;
- }
- },
-
- rotate: function() {
- switch(arguments.length) {
- case 0:
- return this._rotate;
- case 1:
- if (this._rotate != arguments[0]) {
- this._rotate = arguments[0];
- this._rotationPoint = undefined;
- this._isChanged = true;
- }
- case 2:
- if(this._rotate != arguments[0] ||
- !this._rotationPoint ||
- this._rotationPoint.x != arguments[1].x ||
- this._rotationPoint.y != arguments[1].y) {
- this._rotate = arguments[0];
- this._rotationPoint = arguments[1];
- this._isChanged = true;
- }
-
- }
- },
-
- hide: function() {
- if(this.isVisible) {
- this.isVisible = false;
- this._isChanged = true;
- }
- },
-
- show: function() {
- if(!this.isVisible) {
- this.isVisible = true;
- this._isChanged = true;
- }
- },
-
- /**
- * iterates parent nodes till it finds a SVG font-size
- * attribute.
- * @param {SVGElement} node
- */
- getInheritedFontSize: function(node) {
- if(!node || !node.getAttributeNS)
- return;
-
- var attr = node.getAttributeNS(null, "font-size");
- if(attr) {
- return parseFloat(attr);
- } else if(!ORYX.Editor.checkClassType(node, SVGSVGElement)) {
- return this.getInheritedFontSize(node.parentNode);
- }
- },
-
- getFontSize: function(node) {
- var tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan');
-
- //trying to get an inherited font-size attribute
- //NO CSS CONSIDERED!
- var fontSize = this.getInheritedFontSize(this.node);
-
- if (!fontSize) {
- //because this only works in firefox 3, all other browser use the default line height
- if (tspans[0] && /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) {
- fontSize = tspans[0].getExtentOfChar(0).height;
- }
- else {
- fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;
- }
-
- //handling of unsupported method in webkit
- if (fontSize <= 0) {
- fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT;
- }
- }
-
- if(fontSize)
- this.node.setAttribute("oryx:fontSize", fontSize);
-
- return fontSize;
- },
-
- /**
- * Get trimmed text length for use with
- * getExtentOfChar and getSubStringLength.
- * @param {String} text
- */
- getTrimmedTextLength: function(text) {
- text = text.strip().gsub(' ', ' ');
-
- var oldLength;
- do {
- oldLength = text.length;
- text = text.gsub(' ', ' ');
- } while (oldLength > text.length);
- return text.length;
- },
-
- /**
- * Returns the offset from
- * edge to the label which is
- * positioned under the edge
- * @return {int}
- */
- getOffsetBottom: function(){
- return this.offsetBottom;
- },
-
-
- /**
- * Returns the offset from
- * edge to the label which is
- * positioned over the edge
- * @return {int}
- */
- getOffsetTop: function(){
- return this.offsetTop;
- },
-
- /**
- *
- * @param {Object} obj
- */
- deserialize: function(obj, shape){
- if (obj && "undefined" != typeof obj.x && "undefined" != typeof obj.y){
- this.setPosition({x:obj.x, y:obj.y});
-
- if ("undefined" != typeof obj.distance){
- var from = shape.dockers[obj.from];
- var to = shape.dockers[obj.to];
- if (from && to){
- this.setReferencePoint({
- dirty : true,
- distance : obj.distance,
- intersection : {x: obj.x, y: obj.y},
- orientation : obj.orientation,
- segment: {
- from: from,
- fromIndex: obj.from,
- fromPosition: from.bounds.center(),
- to: to,
- toIndex: obj.to,
- toPosition: to.bounds.center()
- }
- })
- }
- }
-
- if (obj.left) this.anchorLeft = true;
- if (obj.right) this.anchorRight = true;
- if (obj.top) this.anchorTop = true;
- if (obj.bottom) this.anchorBottom = true;
- if (obj.valign) this.verticalAlign(obj.valign);
- if (obj.align) this.horizontalAlign(obj.align);
-
- } else if (obj && "undefined" != typeof obj.edge){
- this.setEdgePosition(obj.edge);
- }
- },
- /**
- *
- * @return {Object}
- */
- serialize: function(){
-
- // On edge position
- if (this.getEdgePosition()){
- if (this.getOriginEdgePosition() !== this.getEdgePosition()){
- return {edge: this.getEdgePosition()};
- } else {
- return null;
- }
- }
-
- // On self defined position
- if (this.position){
- var pos = {x: this.position.x, y: this.position.y};
- if (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()){
- pos.left = true;
- }
- if (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()){
- pos.right = true;
- }
- if (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()){
- pos.top = true;
- }
- if (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()){
- pos.bottom = true;
- }
-
- if (this.getOriginVerticalAlign() !== this.verticalAlign()){
- pos.valign = this.verticalAlign();
- }
- if (this.getOriginHorizontalAlign() !== this.horizontalAlign()){
- pos.align = this.horizontalAlign();
- }
-
- return pos;
- }
-
- // On reference point which is interesting for edges
- if (this.getReferencePoint()){
- var ref = this.getReferencePoint();
- return {
- distance : ref.distance,
- x : ref.intersection.x,
- y : ref.intersection.y,
- from : ref.segment.fromIndex,
- to : ref.segment.toIndex,
- orientation : ref.orientation,
- valign : this.verticalAlign(),
- align : this.horizontalAlign()
- }
- }
- return null;
- },
-
- toString: function() { return "Label " + this.id }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.Math) {ORYX.Core.Math = {};}
-
- /**
- * Calculate the middle point between two given points
- * @param {x:double, y:double} point1
- * @param {x:double, y:double} point2
- * @return the middle point
- */
- ORYX.Core.Math.midPoint = function(point1, point2) {
- return {
- x: (point1.x + point2.x) / 2.0,
- y: (point1.y + point2.y) / 2.0
- }
- }
-
- /**
- * Returns a TRUE if the point is over a line (defined by
- * point1 and point 2). In Addition a threshold can be set,
- * which defines the weight of those line.
- *
- * @param {int} pointX - Point X
- * @param {int} pointY - Point Y
- * @param {int} lPoint1X - Line first Point X
- * @param {int} lPoint1Y - Line first Point Y
- * @param {int} lPoint2X - Line second Point X
- * @param {int} lPoint2Y - Line second Point y
- * @param {int} offset {optional} - maximal distance to line
- * @class ORYX.Core.Math.prototype
- */
- ORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) {
- offset = offset ? Math.abs(offset) : 1;
-
- // Check if the edge is vertical
- if(Math.abs(lPoint1X-lPoint2X)<=offset && Math.abs(pointX-lPoint1X)<=offset && pointY-Math.max(lPoint1Y, lPoint2Y)<=offset && Math.min(lPoint1Y, lPoint2Y)-pointY<=offset) {
- return true
- }
- // Check if the edge is horizontal
- if(Math.abs(lPoint1Y-lPoint2Y)<=offset && Math.abs(pointY-lPoint1Y)<=offset && pointX-Math.max(lPoint1X, lPoint2X)<=offset && Math.min(lPoint1X, lPoint2X)-pointX<=offset) {
- return true
- }
- if(pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) {
- return false
- }
- if(pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) {
- return false
- }
-
- var s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X);
-
- return Math.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset
- }
- /**
- * Get a boolean if the point is in the polygone
- *
- */
- ORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) {
- if(cx === undefined || cy === undefined || rx === undefined || ry === undefined) {
- throw "ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY"
- }
-
- var tx = (pointX - cx) / rx;
- var ty = (pointY - cy) / ry;
-
- return tx * tx + ty * ty < 1.0;
- }
-
- /**
- * Get a boolean if the point is in the polygone
- * @param {int} pointX
- * @param {int} pointY
- * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...)
- */
- ORYX.Core.Math.isPointInPolygone = function(pointX, pointY, polygone){
- if (arguments.length < 3) {
- throw "ORYX.Core.Math.isPointInPolygone needs two arguments"
- }
-
- var lastIndex = polygone.length-1;
-
- if (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) {
- polygone.push(polygone[0]);
- polygone.push(polygone[1]);
- }
-
- var crossings = 0;
- var x1, y1, x2, y2, d;
-
- for (var i = 0; i < polygone.length - 3; ) {
- x1=polygone[i];
- y1=polygone[++i];
- x2=polygone[++i];
- y2=polygone[i+1];
- d=(pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1);
- if ((y1 >= pointY) != (y2 >= pointY)) {
- crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0;
- }
- if (!d && Math.min(x1,x2) <= pointX && pointX <= Math.max(x1,x2)
- && Math.min(y1,y2) <= pointY && pointY <= Math.max(y1,y2)) {
- return true;
- }
- }
- return (crossings%2)?true:false;
- }
- /**
- * Calculates the distance between a point and a line. It is also testable, if
- * the distance orthogonal to the line, matches the segment of the line.
- *
- * @param {float} lineP1
- * The starting point of the line segment
- * @param {float} lineP2
- * The end point of the line segment
- * @param {Point} point
- * The point to calculate the distance to.
- * @param {boolean} toSegmentOnly
- * Flag to signal if only the segment of the line shell be evaluated.
- */
- ORYX.Core.Math.distancePointLinie = function(
- lineP1,
- lineP2,
- point,
- toSegmentOnly) {
-
- var intersectionPoint =
- ORYX.Core.Math.getPointOfIntersectionPointLine(lineP1,
- lineP2,
- point,
- toSegmentOnly);
-
- if(!intersectionPoint) {
- return null;
- }
-
- return ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint);
- };
- /**
- * Calculates the distance between two points.
- *
- * @param {point} point1
- * @param {point} point2
- */
- ORYX.Core.Math.getDistancePointToPoint = function(point1, point2) {
- return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
- };
- /**
- * Calculates the relative distance of a point which is between two other points.
- *
- * @param {point} between1
- * @param {point} between2
- * @param {point} point
- */
- ORYX.Core.Math.getDistanceBetweenTwoPoints = function(between1, between2, point) {
- return ORYX.Core.Math.getDistancePointToPoint(point, between1) /
- ORYX.Core.Math.getDistancePointToPoint(between1, between2);
- };
- /**
- * Returns true, if the point is of the left hand
- * side of the regarding the line.
- *
- * @param {point} lineP1 Line first point
- * @param {point} lineP2 Line second point
- * @param {point} point
- */
- ORYX.Core.Math.pointIsLeftOfLine = function(lineP1, lineP2, point){
-
- var vec1 = ORYX.Core.Math.getVector(lineP1, lineP2);
- var vec2 = ORYX.Core.Math.getVector(lineP1, point);
- // if the cross produkt is more than 0
- return ((vec1.x*vec2.y) - (vec2.x*vec1.y)) > 0
- };
- /**
- * Calculates the a point which is relatively between two other points.
- *
- * @param {point} point1
- * @param {point} point2
- * @param {number} relative Relative which is between 0 and 1
- */
- ORYX.Core.Math.getPointBetweenTwoPoints = function(point1, point2, relative) {
- relative = Math.max(Math.min(relative || 0, 1), 0);
-
- if (relative === 0){
- return point1;
- } else if (relative === 1){
- return point2;
- }
-
- return {
- x: point1.x + ((point2.x - point1.x) * relative),
- y: point1.y + ((point2.y - point1.y) * relative)
- }
- };
- /**
- * Returns the vector of the both points
- *
- * @param {point} point1
- * @param {point} point2
- */
- ORYX.Core.Math.getVector = function(point1, point2){
- return {
- x: point2.x - point1.x,
- y: point2.y - point1.y
- }
- }
- /**
- * Returns the an identity vector of the given vector,
- * which has the length ot one.
- *
- * @param {point} vector
- * or
- * @param {point} point1
- * @param {point} point2
- */
- ORYX.Core.Math.getIdentityVector = function(vector){
-
- if (arguments.length == 2){
- vector = ORYX.Core.Math.getVector(arguments[0], arguments[1]);
- }
-
- var length = Math.sqrt((vector.x*vector.x)+(vector.y*vector.y))
- return {
- x: vector.x / (length || 1),
- y: vector.y / (length || 1)
- }
- }
- ORYX.Core.Math.getOrthogonalIdentityVector = function(point1, point2){
- var vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2);
- return {
- x: vec.y,
- y: -vec.x
- }
- }
- /**
- * Returns the intersection point of a line and a point that defines a line
- * orthogonal to the given line.
- *
- * @param {float} lineP1
- * The starting point of the line segment
- * @param {float} lineP2
- * The end point of the line segment
- * @param {Point} point
- * The point to calculate the distance to.
- * @param {boolean} onSegmentOnly
- * Flag to signal if only the segment of the line shell be evaluated.
- */
- ORYX.Core.Math.getPointOfIntersectionPointLine = function(
- lineP1,
- lineP2,
- point,
- onSegmentOnly) {
- /*
- * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0
- * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)²
- */
- var denominator = Math.pow(lineP2.x - lineP1.x, 2)
- + Math.pow(lineP2.y - lineP1.y, 2);
- if(denominator == 0) {
- return undefined;
- }
-
- var u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x)
- + (point.y - lineP1.y) * (lineP2.y - lineP1.y))
- / denominator;
-
- if(onSegmentOnly) {
- if (!(0 <= u && u <= 1)) {
- return undefined;
- }
- }
-
- pointOfIntersection = new Object();
- pointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x);
- pointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y);
-
- return pointOfIntersection;
- };
- /**
- * Translated the point with the given matrix.
- * @param {Point} point
- * @param {Matrix} matrix
- * @return {Object} Includes x, y
- */
- ORYX.Core.Math.getTranslatedPoint = function(point, matrix){
- var x = matrix.a*point.x+matrix.c*point.y+matrix.e*1;
- var y = matrix.b*point.x+matrix.d*point.y+matrix.f*1;
- return {x:x, y:y}
- }
- /**
- * Returns the inverse matrix of the given SVG transformation matrix
- * @param {SVGTransformationMatrix} matrix
- * @return {Matrix}
- */
- ORYX.Core.Math.getInverseMatrix = function(matrix){
- var det = ORYX.Core.Math.getDeterminant(matrix), m = matrix;
- // +- -+
- // | a c e |
- // | b d f |
- // | 0 0 1 |
- // +- -+
- return {
- a: det * ((m.d*1)-(m.f*0)),
- b: det * ((m.f*0)-(m.b*1)),
- c: det * ((m.e*0)-(m.c*1)),
- d: det * ((m.a*1)-(m.e*0)),
- e: det * ((m.c*m.f)-(m.e*m.d)),
- f: det * ((m.e*m.b)-(m.a*m.f))
- }
- }
- /**
- * Returns the determinant of the svg transformation matrix
- * @param {SVGTranformationMatrix} matrix
- * @return {Number}
- *
- */
- ORYX.Core.Math.getDeterminant = function(m){
- // a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32
- 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);
- }
- /**
- * Returns the bounding box of the given node. Translates the
- * origin bounding box with the tranlation matrix.
- * @param {SVGElement} node
- * @return {Object} Includes x, y, width, height
- */
- ORYX.Core.Math.getTranslatedBoundingBox = function(node){
- var matrix = node.getCTM();
- var bb = node.getBBox();
- var ul = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y}, matrix);
- var ll = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y+bb.height}, matrix);
- var ur = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y}, matrix);
- var lr = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y+bb.height}, matrix);
-
- var minPoint = {
- x: Math.min(ul.x, ll.x, ur.x, lr.x),
- y: Math.min(ul.y, ll.y, ur.y, lr.y)
- }
- var maxPoint = {
- x: Math.max(ul.x, ll.x, ur.x, lr.x),
- y: Math.max(ul.y, ll.y, ur.y, lr.y)
- }
- return {
- x: minPoint.x,
- y: minPoint.y,
- width: maxPoint.x - minPoint.x,
- height: maxPoint.y - minPoint.y
- }
- };
- /**
- * Returns the angle of the given line, which is representated by the two points
- * @param {Point} p1
- * @param {Point} p2
- * @return {Number} 0 <= x <= 359.99999
- */
- ORYX.Core.Math.getAngle = function(p1, p2){
- if(p1.x == p2.x && p1.y == p2.y)
- return 0;
- var angle = Math.asin(Math.sqrt(Math.pow(p1.y-p2.y, 2))
- /(Math.sqrt(Math.pow(p2.x-p1.x, 2)+Math.pow(p1.y-p2.y, 2))))
- *180/Math.PI;
-
- if(p2.x >= p1.x && p2.y <= p1.y)
- return angle;
- else if(p2.x < p1.x && p2.y <= p1.y)
- return 180 - angle;
- else if(p2.x < p1.x && p2.y > p1.y)
- return 180 + angle;
- else
- return 360 - angle;
- };
- /**
- * Implementation of the cohen-sutherland algorithm
- */
- new function(){
-
- var RIGHT = 2, TOP = 8, BOTTOM = 4, LEFT = 1;
-
- function computeOutCode (x, y, xmin, ymin, xmax, ymax) {
- var code = 0;
- if (y > ymax)
- code |= TOP;
- else if (y < ymin)
- code |= BOTTOM;
- if (x > xmax)
- code |= RIGHT;
- else if (x < xmin)
- code |= LEFT;
- return code;
- }
-
- /**
- * Returns TRUE if the rectangle is over the edge and has intersection points or includes it
- * @param {Object} x1 Point A of the line
- * @param {Object} y1
- * @param {Object} x2 Point B of the line
- * @param {Object} y2
- * @param {Object} xmin Point A of the rectangle
- * @param {Object} ymin
- * @param {Object} xmax Point B of the rectangle
- * @param {Object} ymax
- */
- ORYX.Core.Math.isRectOverLine = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){
- return !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments);
- }
-
- /**
- * Returns the clipped line on the given rectangle. If there is
- * no intersection, it will return NULL.
- *
- * @param {Object} x1 Point A of the line
- * @param {Object} y1
- * @param {Object} x2 Point B of the line
- * @param {Object} y2
- * @param {Object} xmin Point A of the rectangle
- * @param {Object} ymin
- * @param {Object} xmax Point B of the rectangle
- * @param {Object} ymax
- */
- ORYX.Core.Math.clipLineOnRect = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){
- //Outcodes for P0, P1, and whatever point lies outside the clip rectangle
- var outcode0, outcode1, outcodeOut, hhh = 0;
- var accept = false, done = false;
-
- //compute outcodes
- outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax);
- outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax);
-
- do {
- if ((outcode0 | outcode1) == 0 ){
- accept = true;
- done = true;
- } else if ( (outcode0 & outcode1) > 0 ) {
- done = true;
- } else {
- //failed both tests, so calculate the line segment to clip
- //from an outside point to an intersection with clip edge
- var x = 0, y = 0;
- //At least one endpoint is outside the clip rectangle; pick it.
- outcodeOut = outcode0 != 0 ? outcode0: outcode1;
- //Now find the intersection point;
- //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0)
- if ( (outcodeOut & TOP) > 0 ) {
- x = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1);
- y = ymax;
- } else if ((outcodeOut & BOTTOM) > 0 ) {
- x = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1);
- y = ymin;
- } else if ((outcodeOut & RIGHT)> 0) {
- y = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1);
- x = xmax;
- } else if ((outcodeOut & LEFT) > 0) {
- y = y1 + (y2 - y1) * (xmin - x1)/(x2 - x1);
- x = xmin;
- }
-
- //Now we move outside point to intersection point to clip
- //and get ready for next pass.
- if (outcodeOut == outcode0) {
- x1 = x;
- y1 = y;
- outcode0 = computeOutCode (x1, y1, xmin, ymin, xmax, ymax);
- } else {
- x2 = x;
- y2 = y;
- outcode1 = computeOutCode (x2, y2, xmin, ymin, xmax, ymax);
- }
- }
- hhh ++;
- } while (done != true && hhh < 5000);
-
- if(accept) {
- return {a:{x:x1, y:y1}, b:{x:x2, y:y2}};
- }
- return null;
- }
- }();
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespace
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
- /**
- * Class Stencil
- * uses Prototpye 1.5.0
- * uses Inheritance
- *
- * This class represents one stencil of a stencil set.
- */
- ORYX.Core.StencilSet.Stencil = {
- /**
- * Constructor
- */
- construct: function(jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) {
- arguments.callee.$.construct.apply(this, arguments); // super();
-
- // check arguments and set defaults.
- if(!jsonStencil) throw "Stencilset seems corrupt.";
- if(!namespace) throw "Stencil does not provide namespace.";
- if(!source) throw "Stencil does not provide SVG source.";
- if(!stencilSet) throw "Fatal internal error loading stencilset.";
- //if(!propertyPackages) throw "Fatal internal error loading stencilset.";
-
- this._source = source;
- this._jsonStencil = jsonStencil;
- this._stencilSet = stencilSet;
- this._namespace = namespace;
- this._propertyPackages = propertyPackages;
-
- if(defaultPosition && !this._jsonStencil.position)
- this._jsonStencil.position = defaultPosition;
-
- this._view;
- this._properties = new Hash();
- // check stencil consistency and set defaults.
- /*with(this._jsonStencil) {
-
- if(!type) throw "Stencil does not provide type.";
- if((type != "edge") && (type != "node"))
- throw "Stencil type must be 'edge' or 'node'.";
- if(!id || id == "") throw "Stencil does not provide valid id.";
- if(!title || title == "")
- throw "Stencil does not provide title";
- if(!description) { description = ""; };
- if(!groups) { groups = []; }
- if(!roles) { roles = []; }
- // add id of stencil to its roles
- roles.push(id);
- }*/
-
- //init all JSON values
- if(!this._jsonStencil.type || !(this._jsonStencil.type === "edge" || this._jsonStencil.type === "node")) {
- throw "ORYX.Core.StencilSet.Stencil(construct): Type is not defined.";
- }
- if(!this._jsonStencil.id || this._jsonStencil.id === "") {
- throw "ORYX.Core.StencilSet.Stencil(construct): Id is not defined.";
- }
- if(!this._jsonStencil.title || this._jsonStencil.title === "") {
- throw "ORYX.Core.StencilSet.Stencil(construct): Title is not defined.";
- }
- if(!this._jsonStencil.description) { this._jsonStencil.description = ""; };
- if(!this._jsonStencil.groups) { this._jsonStencil.groups = []; }
- if(!this._jsonStencil.roles) { this._jsonStencil.roles = []; }
-
- //add id of stencil to its roles
- this._jsonStencil.roles.push(this._jsonStencil.id);
- //prepend namespace to each role
- this._jsonStencil.roles.each((function(role, index) {
- this._jsonStencil.roles[index] = namespace + role;
- }).bind(this));
- //delete duplicate roles
- this._jsonStencil.roles = this._jsonStencil.roles.uniq();
- //make id unique by prepending namespace of stencil set
- this._jsonStencil.id = namespace + this._jsonStencil.id;
- this.postProcessProperties();
-
- // init serialize callback
- if(!this._jsonStencil.serialize) {
- this._jsonStencil.serialize = {};
- //this._jsonStencil.serialize = function(shape, data) { return data;};
- }
-
- // init deserialize callback
- if(!this._jsonStencil.deserialize) {
- this._jsonStencil.deserialize = {};
- //this._jsonStencil.deserialize = function(shape, data) { return data;};
- }
-
- // init layout callback
- if(!this._jsonStencil.layout) {
- this._jsonStencil.layout = []
- //this._jsonStencil.layout = function() {return true;}
- }
-
- //TODO does not work correctly, if the url does not exist
- //How to guarantee that the view is loaded correctly before leaving the constructor???
- var url = source + "view/" + jsonStencil.view;
- // override content type when this is webkit.
-
- /*
- if(Prototype.Browser.WebKit) {
-
- var req = new XMLHttpRequest;
- req.open("GET", url, false);
- req.overrideMimeType('text/xml');
- req.send(null);
- req.onload = (function() { _loadSVGOnSuccess(req.responseXML); }).bind(this);
- // else just do it.
- } else
- */
-
- if(this._jsonStencil.view.trim().match(/</)) {
- var parser = new DOMParser();
- var xml = parser.parseFromString( this._jsonStencil.view ,"text/xml");
-
- //check if result is a SVG document
- if( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {
-
- this._view = xml.documentElement;
-
- //updating link to images
- var imageElems = this._view.getElementsByTagNameNS("http://www.w3.org/2000/svg", "image");
- $A(imageElems).each((function(imageElem) {
- var link = imageElem.getAttributeNodeNS("http://www.w3.org/1999/xlink", "href");
- if(link && link.value.indexOf("://") == -1) {
- link.textContent = this._source + "view/" + link.value;
- }
- }).bind(this));
- } else {
- throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document."
- }
- } else {
- new Ajax.Request(
- url, {
- asynchronous:false, method:'get',
- onSuccess:this._loadSVGOnSuccess.bind(this),
- onFailure:this._loadSVGOnFailure.bind(this)
- });
- }
- },
- postProcessProperties: function() {
- // add image path to icon
- if(this._jsonStencil.icon && this._jsonStencil.icon.indexOf("://") === -1) {
- this._jsonStencil.icon = this._source + "icons/" + this._jsonStencil.icon;
- } else {
- this._jsonStencil.icon = "";
- }
-
- // init property packages
- if(this._jsonStencil.propertyPackages && this._jsonStencil.propertyPackages instanceof Array) {
- this._jsonStencil.propertyPackages.each((function(ppId) {
- var pp = this._propertyPackages[ppId];
-
- if(pp) {
- pp.each((function(prop){
- var oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);
- this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
- }).bind(this));
- }
- }).bind(this));
- }
-
- // init properties
- if(this._jsonStencil.properties && this._jsonStencil.properties instanceof Array) {
- this._jsonStencil.properties.each((function(prop) {
- var oProp = new ORYX.Core.StencilSet.Property(prop, this._namespace, this);
- this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
- }).bind(this));
- }
-
- },
- /**
- * @param {ORYX.Core.StencilSet.Stencil} stencil
- * @return {Boolean} True, if stencil has the same namespace and type.
- */
- equals: function(stencil) {
- return (this.id() === stencil.id());
- },
- stencilSet: function() {
- return this._stencilSet;
- },
- type: function() {
- return this._jsonStencil.type;
- },
- namespace: function() {
- return this._namespace;
- },
- id: function() {
- return this._jsonStencil.id;
- },
-
- idWithoutNs: function(){
- return this.id().replace(this.namespace(),"");
- },
- title: function() {
- return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "title");
- },
- description: function() {
- return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "description");
- },
-
- groups: function() {
- return ORYX.Core.StencilSet.getTranslation(this._jsonStencil, "groups");
- },
-
- position: function() {
- return (isNaN(this._jsonStencil.position) ? 0 : this._jsonStencil.position);
- },
- view: function() {
- return this._view.cloneNode(true) || this._view;
- },
- icon: function() {
- return this._jsonStencil.icon;
- },
-
- fixedAspectRatio: function() {
- return this._jsonStencil.fixedAspectRatio === true;
- },
-
- hasMultipleRepositoryEntries: function() {
- return (this.getRepositoryEntries().length > 0);
- },
-
- getRepositoryEntries: function() {
- return (this._jsonStencil.repositoryEntries) ?
- $A(this._jsonStencil.repositoryEntries) : $A([]);
- },
-
- properties: function() {
- return this._properties.values();
- },
- property: function(id) {
- return this._properties[id];
- },
- roles: function() {
- return this._jsonStencil.roles;
- },
-
- defaultAlign: function() {
- if(!this._jsonStencil.defaultAlign)
- return "east";
- return this._jsonStencil.defaultAlign;
- },
- serialize: function(shape, data) {
- return this._jsonStencil.serialize;
- //return this._jsonStencil.serialize(shape, data);
- },
-
- deserialize: function(shape, data) {
- return this._jsonStencil.deserialize;
- //return this._jsonStencil.deserialize(shape, data);
- },
-
- // in which case is targetShape used?
- // layout: function(shape, targetShape) {
- // return this._jsonStencil.layout(shape, targetShape);
- // },
- // layout property to store events for layouting in plugins
- layout: function(shape) {
- return this._jsonStencil.layout
- },
-
- addProperty: function(property, namespace) {
- if(property && namespace) {
- var oProp = new ORYX.Core.StencilSet.Property(property, namespace, this);
- this._properties[oProp.prefix() + "-" + oProp.id()] = oProp;
- }
- },
-
- removeProperty: function(propertyId) {
- if(propertyId) {
- var oProp = this._properties.values().find(function(prop) {
- return (propertyId == prop.id());
- });
- if(oProp)
- delete this._properties[oProp.prefix() + "-" + oProp.id()];
- }
- },
- _loadSVGOnSuccess: function(result) {
-
- var xml = null;
-
- /*
- * We want to get a dom object for the requested file. Unfortunately,
- * safari has some issues here. this is meant as a fallback for all
- * browsers that don't recognize the svg mimetype as XML but support
- * data: urls on Ajax calls.
- */
-
- // responseXML != undefined.
- // if(!(result.responseXML))
-
- // get the dom by data: url.
- // xml = _evenMoreEvilHack(result.responseText, 'text/xml');
-
- // else
-
- // get it the usual way.
- xml = result.responseXML;
- //check if result is a SVG document
- if( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) {
- this._view = xml.documentElement;
-
- //updating link to images
- var imageElems = this._view.getElementsByTagNameNS("http://www.w3.org/2000/svg", "image");
- $A(imageElems).each((function(imageElem) {
- var link = imageElem.getAttributeNodeNS("http://www.w3.org/1999/xlink", "href");
- if(link && link.value.indexOf("://") == -1) {
- link.textContent = this._source + "view/" + link.value;
- }
- }).bind(this));
- } else {
- throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document."
- }
- },
- _loadSVGOnFailure: function(result) {
- throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed."
- },
- toString: function() { return "Stencil " + this.title() + " (" + this.id() + ")"; }
- };
- ORYX.Core.StencilSet.Stencil = Clazz.extend(ORYX.Core.StencilSet.Stencil);
- /**
- * Transform a string into an xml document, the Safari way, as long as
- * the nightlies are broken. Even more evil version.
- * @param {Object} str
- * @param {Object} contentType
- */
- function _evenMoreEvilHack(str, contentType) {
-
- /*
- * This even more evil hack was taken from
- * http://web-graphics.com/mtarchive/001606.php#chatty004999
- */
-
- if (window.ActiveXObject) {
- var d = new ActiveXObject("MSXML.DomDocument");
- d.loadXML(str);
- return d;
- } else if (window.XMLHttpRequest) {
- var req = new XMLHttpRequest;
- req.open("GET", "data:" + (contentType || "application/xml") +
- ";charset=utf-8," + encodeURIComponent(str), false);
- if (req.overrideMimeType) {
- req.overrideMimeType(contentType);
- }
- req.send(null);
- return req.responseXML;
- }
- }
- /**
- * Transform a string into an xml document, the Safari way, as long as
- * the nightlies are broken.
- * @param {Object} result the xml document object.
- */
- function _evilSafariHack(serializedXML) {
-
- /*
- * The Dave way. Taken from:
- * http://web-graphics.com/mtarchive/001606.php
- *
- * There is another possibility to parse XML in Safari, by implementing
- * the DOMParser in javascript. However, in the latest nightlies of
- * WebKit, DOMParser is already available, but still buggy. So, this is
- * the best compromise for the time being.
- */
-
- var xml = serializedXML;
- var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xml);
- var dom = null;
-
- // your standard AJAX stuff
- var req = new XMLHttpRequest();
- req.open("GET", url);
- req.onload = function() { dom = req.responseXML; }
- req.send(null);
-
- return dom;
- }
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespace
- */
- if (!ORYX) {
- var ORYX = {};
- }
- if (!ORYX.Core) {
- ORYX.Core = {};
- }
- if (!ORYX.Core.StencilSet) {
- ORYX.Core.StencilSet = {};
- }
- /**
- * Class Property
- * uses Prototpye 1.5.0
- * uses Inheritance
- */
- ORYX.Core.StencilSet.Property = Clazz.extend({
- /**
- * Constructor
- */
- construct: function(jsonProp, namespace, stencil){
- arguments.callee.$.construct.apply(this, arguments);
-
- this._jsonProp = jsonProp || ORYX.Log.error("Parameter jsonProp is not defined.");
- this._namespace = namespace || ORYX.Log.error("Parameter namespace is not defined.");
- this._stencil = stencil || ORYX.Log.error("Parameter stencil is not defined.");
-
- this._items = {};
- this._complexItems = {};
-
- jsonProp.id = jsonProp.id || ORYX.Log.error("ORYX.Core.StencilSet.Property(construct): Id is not defined.");
- jsonProp.id = jsonProp.id.toLowerCase();
-
- if (!jsonProp.type) {
- ORYX.Log.info("Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.", stencil, jsonProp.id);
- jsonProp.type = "string";
- }
- else {
- jsonProp.type = jsonProp.type.toLowerCase();
- }
-
- jsonProp.prefix = jsonProp.prefix || "oryx";
- jsonProp.title = jsonProp.title || "";
- jsonProp.value = jsonProp.value || "";
- jsonProp.description = jsonProp.description || "";
- jsonProp.readonly = jsonProp.readonly || false;
- jsonProp.optional = jsonProp.optional !== false;
-
- //init refToView
- if (this._jsonProp.refToView) {
- if (!(this._jsonProp.refToView instanceof Array)) {
- this._jsonProp.refToView = [this._jsonProp.refToView];
- }
- }
- else {
- this._jsonProp.refToView = [];
- }
-
- var globalMin = this.getMinForType(jsonProp.type);
- if (jsonProp.min === undefined || jsonProp.min === null) {
- jsonProp.min =globalMin;
- } else if (jsonProp.min < globalMin) {
- jsonProp.min = globalMin;
- }
-
- var globalMax = this.getMaxForType(jsonProp.type);
- if (jsonProp.max === undefined || jsonProp.max === null) {
- jsonProp.max = globalMax;
- } else if (jsonProp.max > globalMax) {
- jsonProp.min = globalMax;
- }
-
- if (!jsonProp.fillOpacity) {
- jsonProp.fillOpacity = false;
- }
-
- if ("number" != typeof jsonProp.lightness) {
- jsonProp.lightness = 1
- } else {
- jsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness))
- }
-
- if (!jsonProp.strokeOpacity) {
- jsonProp.strokeOpacity = false;
- }
-
- if (jsonProp.length === undefined || jsonProp.length === null) {
- jsonProp.length = Number.MAX_VALUE;
- }
-
- if (!jsonProp.wrapLines) {
- jsonProp.wrapLines = false;
- }
-
- if (!jsonProp.dateFormat) {
- jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || "m/d/y";
- }
-
- if (!jsonProp.fill) {
- jsonProp.fill = false;
- }
-
- if (!jsonProp.stroke) {
- jsonProp.stroke = false;
- }
-
- if(!jsonProp.inverseBoolean) {
- jsonProp.inverseBoolean = false;
- }
-
- if(!jsonProp.directlyEditable && jsonProp.directlyEditable != false) {
- jsonProp.directlyEditable = true;
- }
-
- if(jsonProp.visible !== false) {
- jsonProp.visible = true;
- }
-
- if(jsonProp.isList !== true) {
- jsonProp.isList = false;
-
- if(!jsonProp.list || !(jsonProp.list instanceof Array)) {
- jsonProp.list = [];
- }
- }
-
- if(!jsonProp.category) {
- if (jsonProp.popular) {
- jsonProp.category = "popular";
- } else {
- jsonProp.category = "others";
- }
- }
-
- if(!jsonProp.alwaysAppearInMultiselect) {
- jsonProp.alwaysAppearInMultiselect = false;
- }
-
- if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) {
- if (jsonProp.items && jsonProp.items instanceof Array) {
- jsonProp.items.each((function(jsonItem){
- // why is the item's value used as the key???
- this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this);
- }).bind(this));
- }
- else {
- throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
- }
- // extended by Kerstin (start)
- }
- else
- if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) {
- if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) {
- jsonProp.complexItems.each((function(jsonComplexItem){
- this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this);
- }).bind(this));
- }
- else {
- throw "ORYX.Core.StencilSet.Property(construct): No complex property items defined."
- }
- }
- // extended by Kerstin (end)
- },
-
- getMinForType : function(type) {
- if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {
- return -Math.pow(2,31)
- } else {
- return -Number.MAX_VALUE+1;
- }
- },
- getMaxForType : function(type) {
- if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) {
- return Math.pow(2,31)-1
- } else {
- return Number.MAX_VALUE;
- }
- },
-
- /**
- * @param {ORYX.Core.StencilSet.Property} property
- * @return {Boolean} True, if property has the same namespace and id.
- */
- equals: function(property){
- return (this._namespace === property.namespace() &&
- this.id() === property.id()) ? true : false;
- },
-
- namespace: function(){
- return this._namespace;
- },
-
- stencil: function(){
- return this._stencil;
- },
-
- id: function(){
- return this._jsonProp.id;
- },
-
- prefix: function(){
- return this._jsonProp.prefix;
- },
-
- type: function(){
- return this._jsonProp.type;
- },
-
- inverseBoolean: function() {
- return this._jsonProp.inverseBoolean;
- },
-
- category: function() {
- return this._jsonProp.category;
- },
-
- setCategory: function(value) {
- this._jsonProp.category = value;
- },
-
- directlyEditable: function() {
- return this._jsonProp.directlyEditable;
- },
-
- visible: function() {
- return this._jsonProp.visible;
- },
-
- title: function(){
- return ORYX.Core.StencilSet.getTranslation(this._jsonProp, "title");
- },
-
- value: function(){
- return this._jsonProp.value;
- },
-
- readonly: function(){
- return this._jsonProp.readonly;
- },
-
- optional: function(){
- return this._jsonProp.optional;
- },
-
- description: function(){
- return ORYX.Core.StencilSet.getTranslation(this._jsonProp, "description");
- },
-
- /**
- * An optional link to a SVG element so that the property affects the
- * graphical representation of the stencil.
- */
- refToView: function(){
- return this._jsonProp.refToView;
- },
-
- /**
- * If type is integer or float, min is the lower bounds of value.
- */
- min: function(){
- return this._jsonProp.min;
- },
-
- /**
- * If type ist integer or float, max is the upper bounds of value.
- */
- max: function(){
- return this._jsonProp.max;
- },
-
- /**
- * If type is float, this method returns if the fill-opacity property should
- * be set.
- * @return {Boolean}
- */
- fillOpacity: function(){
- return this._jsonProp.fillOpacity;
- },
-
- /**
- * If type is float, this method returns if the stroke-opacity property should
- * be set.
- * @return {Boolean}
- */
- strokeOpacity: function(){
- return this._jsonProp.strokeOpacity;
- },
-
- /**
- * If type is string or richtext, length is the maximum length of the text.
- * TODO how long can a string be.
- */
- length: function(){
- return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE;
- },
-
- wrapLines: function(){
- return this._jsonProp.wrapLines;
- },
-
- /**
- * If type is date, dateFormat specifies the format of the date. The format
- * specification of the ext library is used:
- *
- * Format Output Description
- * ------ ---------- --------------------------------------------------------------
- * d 10 Day of the month, 2 digits with leading zeros
- * D Wed A textual representation of a day, three letters
- * j 10 Day of the month without leading zeros
- * l Wednesday A full textual representation of the day of the week
- * S th English ordinal day of month suffix, 2 chars (use with j)
- * w 3 Numeric representation of the day of the week
- * z 9 The julian date, or day of the year (0-365)
- * W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
- * F January A full textual representation of the month
- * m 01 Numeric representation of a month, with leading zeros
- * M Jan Month name abbreviation, three letters
- * n 1 Numeric representation of a month, without leading zeros
- * t 31 Number of days in the given month
- * L 0 Whether its a leap year (1 if it is a leap year, else 0)
- * Y 2007 A full numeric representation of a year, 4 digits
- * y 07 A two digit representation of a year
- * a pm Lowercase Ante meridiem and Post meridiem
- * A PM Uppercase Ante meridiem and Post meridiem
- * g 3 12-hour format of an hour without leading zeros
- * G 15 24-hour format of an hour without leading zeros
- * h 03 12-hour format of an hour with leading zeros
- * H 15 24-hour format of an hour with leading zeros
- * i 05 Minutes with leading zeros
- * s 01 Seconds, with leading zeros
- * O -0600 Difference to Greenwich time (GMT) in hours
- * T CST Timezone setting of the machine running the code
- * Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
- *
- * Example:
- * F j, Y, g:i a -> January 10, 2007, 3:05 pm
- */
- dateFormat: function(){
- return this._jsonProp.dateFormat;
- },
-
- /**
- * If type is color, this method returns if the fill property should
- * be set.
- * @return {Boolean}
- */
- fill: function(){
- return this._jsonProp.fill;
- },
-
- /**
- * Lightness defines the satiation of the color
- * 0 is the pure color
- * 1 is white
- * @return {Integer} lightness
- */
- lightness: function(){
- return this._jsonProp.lightness;
- },
-
- /**
- * If type is color, this method returns if the stroke property should
- * be set.
- * @return {Boolean}
- */
- stroke: function(){
- return this._jsonProp.stroke;
- },
-
- /**
- * If type is choice, items is a hash map with all alternative values
- * (PropertyItem objects) with id as keys.
- */
- items: function(){
- return $H(this._items).values();
- },
-
- item: function(value){
- if (value) {
- return this._items[value.toLowerCase()];
- } else {
- return null;
- }
- },
-
- toString: function(){
- return "Property " + this.title() + " (" + this.id() + ")";
- },
-
- complexItems: function(){
- return $H(this._complexItems).values();
- },
-
- complexItem: function(id){
- if(id) {
- return this._complexItems[id.toLowerCase()];
- } else {
- return null;
- }
-
- },
-
- complexAttributeToView: function(){
- return this._jsonProp.complexAttributeToView || "";
- },
-
- isList: function() {
- return !!this._jsonProp.isList;
- },
-
- getListItems: function() {
- return this._jsonProp.list;
- },
-
- /**
- * If type is glossary link, the
- * type of category can be defined where
- * the link only can go to.
- * @return {String} The glossary category id
- */
- linkableType: function(){
- return this._jsonProp.linkableType || "";
- },
-
- alwaysAppearInMultiselect : function() {
- return this._jsonProp.alwaysAppearInMultiselect;
- },
-
- popular: function() {
- return this._jsonProp.popular || false;
- },
-
- setPopular: function() {
- this._jsonProp.popular = true;
- }
-
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespace
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
- /**
- * Class Stencil
- * uses Prototpye 1.5.0
- * uses Inheritance
- */
- ORYX.Core.StencilSet.PropertyItem = Clazz.extend({
- /**
- * Constructor
- */
- construct: function(jsonItem, namespace, property) {
- arguments.callee.$.construct.apply(this, arguments);
- if(!jsonItem) {
- throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined.";
- }
- if(!namespace) {
- throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined.";
- }
- if(!property) {
- throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined.";
- }
-
- this._jsonItem = jsonItem;
- this._namespace = namespace;
- this._property = property;
-
- //init all values
- if(!jsonItem.value) {
- throw "ORYX.Core.StencilSet.PropertyItem(construct): Value is not defined.";
- }
-
- if(this._jsonItem.refToView) {
- if(!(this._jsonItem.refToView instanceof Array)) {
- this._jsonItem.refToView = [this._jsonItem.refToView];
- }
- } else {
- this._jsonItem.refToView = [];
- }
- },
- /**
- * @param {ORYX.Core.StencilSet.PropertyItem} item
- * @return {Boolean} True, if item has the same namespace and id.
- */
- equals: function(item) {
- return (this.property().equals(item.property()) &&
- this.value() === item.value());
- },
- namespace: function() {
- return this._namespace;
- },
- property: function() {
- return this._property;
- },
- value: function() {
- return this._jsonItem.value;
- },
-
- title: function() {
- return ORYX.Core.StencilSet.getTranslation(this._jsonItem, "title");
- },
- refToView: function() {
- return this._jsonItem.refToView;
- },
-
- icon: function() {
- return (this._jsonItem.icon) ? this.property().stencil()._source + "icons/" + this._jsonItem.icon : "";
- },
- toString: function() { return "PropertyItem " + this.property() + " (" + this.value() + ")"; }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
- /**
- * Class Stencil
- * uses Prototpye 1.5.0
- * uses Inheritance
- */
- ORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({
- /**
- * Constructor
- */
- construct: function(jsonItem, namespace, property) {
- arguments.callee.$.construct.apply(this, arguments);
- if(!jsonItem) {
- throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined.";
- }
- if(!namespace) {
- throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined.";
- }
- if(!property) {
- throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined.";
- }
-
- this._jsonItem = jsonItem;
- this._namespace = namespace;
- this._property = property;
- this._items = new Hash();
- this._complexItems = new Hash();
-
- //init all values
- if(!jsonItem.name) {
- throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined.";
- }
-
- if(!jsonItem.type) {
- throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined.";
- } else {
- jsonItem.type = jsonItem.type.toLowerCase();
- }
-
- if(jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) {
- if(jsonItem.items && jsonItem.items instanceof Array) {
- jsonItem.items.each((function(item) {
- this._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this);
- }).bind(this));
- } else {
- throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
- }
- } else if(jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) {
- if(jsonItem.complexItems && jsonItem.complexItems instanceof Array) {
- jsonItem.complexItems.each((function(complexItem) {
- this._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this);
- }).bind(this));
- } else {
- throw "ORYX.Core.StencilSet.Property(construct): No property items defined."
- }
- }
- },
- /**
- * @param {ORYX.Core.StencilSet.PropertyItem} item
- * @return {Boolean} True, if item has the same namespace and id.
- */
- equals: function(item) {
- return (this.property().equals(item.property()) &&
- this.name() === item.name());
- },
- namespace: function() {
- return this._namespace;
- },
- property: function() {
- return this._property;
- },
- name: function() {
- return ORYX.Core.StencilSet.getTranslation(this._jsonItem, "name");
- },
-
- id: function() {
- return this._jsonItem.id;
- },
-
- type: function() {
- return this._jsonItem.type;
- },
-
- optional: function() {
- return this._jsonItem.optional;
- },
-
- width: function() {
- return this._jsonItem.width;
- },
-
- value: function() {
- return this._jsonItem.value;
- },
-
- items: function() {
- return this._items.values();
- },
-
- complexItems: function() {
- return this._complexItems.values();
- },
-
- disable: function() {
- return this._jsonItem.disable;
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
- /**
- * Class Rules uses Prototpye 1.5.0 uses Inheritance
- *
- * This class implements the API to check the stencil sets' rules.
- */
- ORYX.Core.StencilSet.Rules = {
- /**
- * Constructor
- */
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
- this._stencilSets = [];
- this._stencils = [];
- this._containerStencils = [];
-
- this._cachedConnectSET = new Hash();
- this._cachedConnectSE = new Hash();
- this._cachedConnectTE = new Hash();
- this._cachedCardSE = new Hash();
- this._cachedCardTE = new Hash();
- this._cachedContainPC = new Hash();
- this._cachedMorphRS = new Hash();
-
- this._connectionRules = new Hash();
- this._cardinalityRules = new Hash();
- this._containmentRules = new Hash();
- this._morphingRules = new Hash();
- this._layoutRules = new Hash();
- },
-
- /**
- * Call this method to initialize the rules for a stencil set and all of its
- * active extensions.
- *
- * @param {Object}
- * stencilSet
- */
- initializeRules: function(stencilSet) {
-
- var existingSS = this._stencilSets.find(function(ss) {
- return (ss.namespace() == stencilSet.namespace());
- });
- if (existingSS) {
- // reinitialize all rules
- var stencilsets = this._stencilSets.clone();
- stencilsets = stencilsets.without(existingSS);
- stencilsets.push(stencilSet);
-
- this._stencilSets = [];
- this._stencils = [];
- this._containerStencils = [];
-
- this._cachedConnectSET = new Hash();
- this._cachedConnectSE = new Hash();
- this._cachedConnectTE = new Hash();
- this._cachedCardSE = new Hash();
- this._cachedCardTE = new Hash();
- this._cachedContainPC = new Hash();
- this._cachedMorphRS = new Hash();
-
- this._connectionRules = new Hash();
- this._cardinalityRules = new Hash();
- this._containmentRules = new Hash();
- this._morphingRules = new Hash();
- this._layoutRules = new Hash();
-
- stencilsets.each(function(ss){
- this.initializeRules(ss);
- }.bind(this));
- return;
- }
- else {
- this._stencilSets.push(stencilSet);
-
- var jsonRules = new Hash(stencilSet.jsonRules());
- var namespace = stencilSet.namespace();
- var stencils = stencilSet.stencils();
-
- stencilSet.extensions().values().each(function(extension) {
- if(extension.rules) {
- if(extension.rules.connectionRules)
- jsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules);
- if(extension.rules.cardinalityRules)
- jsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules);
- if(extension.rules.containmentRules)
- jsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules);
- if(extension.rules.morphingRules)
- jsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules);
- }
- if(extension.stencils)
- stencils = stencils.concat(extension.stencils);
- });
-
- this._stencils = this._stencils.concat(stencilSet.stencils());
-
- // init connection rules
- var cr = this._connectionRules;
- if (jsonRules.connectionRules) {
- jsonRules.connectionRules.each((function(rules){
- if (this._isRoleOfOtherNamespace(rules.role)) {
- if (!cr[rules.role]) {
- cr[rules.role] = new Hash();
- }
- }
- else {
- if (!cr[namespace + rules.role])
- cr[namespace + rules.role] = new Hash();
- }
-
- rules.connects.each((function(connect){
- var toRoles = [];
- if (connect.to) {
- if (!(connect.to instanceof Array)) {
- connect.to = [connect.to];
- }
- connect.to.each((function(to){
- if (this._isRoleOfOtherNamespace(to)) {
- toRoles.push(to);
- }
- else {
- toRoles.push(namespace + to);
- }
- }).bind(this));
- }
-
- var role, from;
- if (this._isRoleOfOtherNamespace(rules.role))
- role = rules.role;
- else
- role = namespace + rules.role;
-
- if (this._isRoleOfOtherNamespace(connect.from))
- from = connect.from;
- else
- from = namespace + connect.from;
-
- if (!cr[role][from])
- cr[role][from] = toRoles;
- else
- cr[role][from] = cr[role][from].concat(toRoles);
-
- }).bind(this));
- }).bind(this));
- }
-
- // init cardinality rules
- var cardr = this._cardinalityRules;
- if (jsonRules.cardinalityRules) {
- jsonRules.cardinalityRules.each((function(rules){
- var cardrKey;
- if (this._isRoleOfOtherNamespace(rules.role)) {
- cardrKey = rules.role;
- }
- else {
- cardrKey = namespace + rules.role;
- }
-
- if (!cardr[cardrKey]) {
- cardr[cardrKey] = {};
- for (i in rules) {
- cardr[cardrKey][i] = rules[i];
- }
- }
-
- var oe = new Hash();
- if (rules.outgoingEdges) {
- rules.outgoingEdges.each((function(rule){
- if (this._isRoleOfOtherNamespace(rule.role)) {
- oe[rule.role] = rule;
- }
- else {
- oe[namespace + rule.role] = rule;
- }
- }).bind(this));
- }
- cardr[cardrKey].outgoingEdges = oe;
- var ie = new Hash();
- if (rules.incomingEdges) {
- rules.incomingEdges.each((function(rule){
- if (this._isRoleOfOtherNamespace(rule.role)) {
- ie[rule.role] = rule;
- }
- else {
- ie[namespace + rule.role] = rule;
- }
- }).bind(this));
- }
- cardr[cardrKey].incomingEdges = ie;
- }).bind(this));
- }
-
- // init containment rules
- var conr = this._containmentRules;
- if (jsonRules.containmentRules) {
- jsonRules.containmentRules.each((function(rules){
- var conrKey;
- if (this._isRoleOfOtherNamespace(rules.role)) {
- conrKey = rules.role;
- }
- else {
- this._containerStencils.push(namespace + rules.role);
- conrKey = namespace + rules.role;
- }
- if (!conr[conrKey]) {
- conr[conrKey] = [];
- }
- (rules.contains||[]).each((function(containRole){
- if (this._isRoleOfOtherNamespace(containRole)) {
- conr[conrKey].push(containRole);
- }
- else {
- conr[conrKey].push(namespace + containRole);
- }
- }).bind(this));
- }).bind(this));
- }
-
- // init morphing rules
- var morphr = this._morphingRules;
- if (jsonRules.morphingRules) {
- jsonRules.morphingRules.each((function(rules){
- var morphrKey;
- if (this._isRoleOfOtherNamespace(rules.role)) {
- morphrKey = rules.role;
- }
- else {
- morphrKey = namespace + rules.role;
- }
- if (!morphr[morphrKey]) {
- morphr[morphrKey] = [];
- }
- if(!rules.preserveBounds) {
- rules.preserveBounds = false;
- }
- rules.baseMorphs.each((function(baseMorphStencilId){
- var morphStencil = this._getStencilById(namespace + baseMorphStencilId);
- if(morphStencil) {
- morphr[morphrKey].push(morphStencil);
- }
- }).bind(this));
- }).bind(this));
- }
-
- // init layouting rules
- var layoutRules = this._layoutRules;
- if (jsonRules.layoutRules) {
-
- var getDirections = function(o){
- return {
- "edgeRole":o.edgeRole||undefined,
- "t": o["t"]||1,
- "r": o["r"]||1,
- "b": o["b"]||1,
- "l": o["l"]||1
- }
- }
-
- jsonRules.layoutRules.each(function(rules){
- var layoutKey;
- if (this._isRoleOfOtherNamespace(rules.role)) {
- layoutKey = rules.role;
- }
- else {
- layoutKey = namespace + rules.role;
- }
- if (!layoutRules[layoutKey]) {
- layoutRules[layoutKey] = {};
- }
- if (rules["in"]){
- layoutRules[layoutKey]["in"] = getDirections(rules["in"]);
- }
- if (rules["ins"]){
- layoutRules[layoutKey]["ins"] = (rules["ins"]||[]).map(function(e){ return getDirections(e) })
- }
- if (rules["out"]) {
- layoutRules[layoutKey]["out"] = getDirections(rules["out"]);
- }
- if (rules["outs"]){
- layoutRules[layoutKey]["outs"] = (rules["outs"]||[]).map(function(e){ return getDirections(e) })
- }
- }.bind(this));
- }
- }
- },
-
- _getStencilById: function(id) {
- return this._stencils.find(function(stencil) {
- return stencil.id()==id;
- });
- },
-
- _cacheConnect: function(args) {
- result = this._canConnect(args);
-
- if (args.sourceStencil && args.targetStencil) {
- var source = this._cachedConnectSET[args.sourceStencil.id()];
-
- if(!source) {
- source = new Hash();
- this._cachedConnectSET[args.sourceStencil.id()] = source;
- }
-
- var edge = source[args.edgeStencil.id()];
-
- if(!edge) {
- edge = new Hash();
- source[args.edgeStencil.id()] = edge;
- }
-
- edge[args.targetStencil.id()] = result;
-
- } else if (args.sourceStencil) {
- var source = this._cachedConnectSE[args.sourceStencil.id()];
-
- if(!source) {
- source = new Hash();
- this._cachedConnectSE[args.sourceStencil.id()] = source;
- }
-
- source[args.edgeStencil.id()] = result;
- } else {
- var target = this._cachedConnectTE[args.targetStencil.id()];
-
- if(!target) {
- target = new Hash();
- this._cachedConnectTE[args.targetStencil.id()] = target;
- }
-
- target[args.edgeStencil.id()] = result;
- }
-
- return result;
- },
-
- _cacheCard: function(args) {
-
- if(args.sourceStencil) {
- var source = this._cachedCardSE[args.sourceStencil.id()]
-
- if(!source) {
- source = new Hash();
- this._cachedCardSE[args.sourceStencil.id()] = source;
- }
-
- var max = this._getMaximumNumberOfOutgoingEdge(args);
- if(max == undefined)
- max = -1;
-
- source[args.edgeStencil.id()] = max;
- }
-
- if(args.targetStencil) {
- var target = this._cachedCardTE[args.targetStencil.id()]
-
- if(!target) {
- target = new Hash();
- this._cachedCardTE[args.targetStencil.id()] = target;
- }
-
- var max = this._getMaximumNumberOfIncomingEdge(args);
- if(max == undefined)
- max = -1;
-
- target[args.edgeStencil.id()] = max;
- }
- },
-
- _cacheContain: function(args) {
-
- var result = [this._canContain(args),
- this._getMaximumOccurrence(args.containingStencil, args.containedStencil)]
-
- if(result[1] == undefined)
- result[1] = -1;
-
- var children = this._cachedContainPC[args.containingStencil.id()];
-
- if(!children) {
- children = new Hash();
- this._cachedContainPC[args.containingStencil.id()] = children;
- }
-
- children[args.containedStencil.id()] = result;
-
- return result;
- },
-
- /**
- * Returns all stencils belonging to a morph group. (calculation result is
- * cached)
- */
- _cacheMorph: function(role) {
-
- var morphs = this._cachedMorphRS[role];
-
- if(!morphs) {
- morphs = [];
-
- if(this._morphingRules.keys().include(role)) {
- morphs = this._stencils.select(function(stencil) {
- return stencil.roles().include(role);
- });
- }
-
- this._cachedMorphRS[role] = morphs;
- }
- return morphs;
- },
-
- /** Begin connection rules' methods */
-
- /**
- *
- * @param {Object}
- * args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined
- * sourceShape: ORYX.Core.Shape | undefined
- *
- * At least sourceStencil or sourceShape has to be specified
- *
- * @return {Array} Array of stencils of edges that can be outgoing edges of
- * the source.
- */
- outgoingEdgeStencils: function(args) {
- // check arguments
- if(!args.sourceShape && !args.sourceStencil) {
- return [];
- }
-
- // init arguments
- if(args.sourceShape) {
- args.sourceStencil = args.sourceShape.getStencil();
- }
-
- var _edges = [];
-
- // test each edge, if it can connect to source
- this._stencils.each((function(stencil) {
- if(stencil.type() === "edge") {
- var newArgs = Object.clone(args);
- newArgs.edgeStencil = stencil;
- if(this.canConnect(newArgs)) {
- _edges.push(stencil);
- }
- }
- }).bind(this));
- return _edges;
- },
- /**
- *
- * @param {Object}
- * args targetStencil: ORYX.Core.StencilSet.Stencil | undefined
- * targetShape: ORYX.Core.Shape | undefined
- *
- * At least targetStencil or targetShape has to be specified
- *
- * @return {Array} Array of stencils of edges that can be incoming edges of
- * the target.
- */
- incomingEdgeStencils: function(args) {
- // check arguments
- if(!args.targetShape && !args.targetStencil) {
- return [];
- }
-
- // init arguments
- if(args.targetShape) {
- args.targetStencil = args.targetShape.getStencil();
- }
-
- var _edges = [];
-
- // test each edge, if it can connect to source
- this._stencils.each((function(stencil) {
- if(stencil.type() === "edge") {
- var newArgs = Object.clone(args);
- newArgs.edgeStencil = stencil;
- if(this.canConnect(newArgs)) {
- _edges.push(stencil);
- }
- }
- }).bind(this));
- return _edges;
- },
-
- /**
- *
- * @param {Object}
- * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined
- * edgeShape: ORYX.Core.Edge | undefined targetStencil:
- * ORYX.Core.StencilSet.Stencil | undefined targetShape:
- * ORYX.Core.Node | undefined
- *
- * At least edgeStencil or edgeShape has to be specified!!!
- *
- * @return {Array} Returns an array of stencils that can be source of the
- * specified edge.
- */
- sourceStencils: function(args) {
- // check arguments
- if(!args ||
- !args.edgeShape && !args.edgeStencil) {
- return [];
- }
-
- // init arguments
- if(args.targetShape) {
- args.targetStencil = args.targetShape.getStencil();
- }
-
- if(args.edgeShape) {
- args.edgeStencil = args.edgeShape.getStencil();
- }
-
- var _sources = [];
-
- // check each stencil, if it can be a source
- this._stencils.each((function(stencil) {
- var newArgs = Object.clone(args);
- newArgs.sourceStencil = stencil;
- if(this.canConnect(newArgs)) {
- _sources.push(stencil);
- }
- }).bind(this));
- return _sources;
- },
-
- /**
- *
- * @param {Object}
- * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined
- * edgeShape: ORYX.Core.Edge | undefined sourceStencil:
- * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
- * ORYX.Core.Node | undefined
- *
- * At least edgeStencil or edgeShape has to be specified!!!
- *
- * @return {Array} Returns an array of stencils that can be target of the
- * specified edge.
- */
- targetStencils: function(args) {
- // check arguments
- if(!args ||
- !args.edgeShape && !args.edgeStencil) {
- return [];
- }
-
- // init arguments
- if(args.sourceShape) {
- args.sourceStencil = args.sourceShape.getStencil();
- }
-
- if(args.edgeShape) {
- args.edgeStencil = args.edgeShape.getStencil();
- }
-
- var _targets = [];
-
- // check stencil, if it can be a target
- this._stencils.each((function(stencil) {
- var newArgs = Object.clone(args);
- newArgs.targetStencil = stencil;
- if(this.canConnect(newArgs)) {
- _targets.push(stencil);
- }
- }).bind(this));
- return _targets;
- },
- /**
- *
- * @param {Object}
- * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:
- * ORYX.Core.Edge |undefined sourceStencil:
- * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
- * ORYX.Core.Node |undefined targetStencil:
- * ORYX.Core.StencilSet.Stencil | undefined targetShape:
- * ORYX.Core.Node |undefined
- *
- * At least source or target has to be specified!!!
- *
- * @return {Boolean} Returns, if the edge can connect source and target.
- */
- canConnect: function(args) {
- // check arguments
- if(!args ||
- (!args.sourceShape && !args.sourceStencil &&
- !args.targetShape && !args.targetStencil) ||
- !args.edgeShape && !args.edgeStencil) {
- return false;
- }
-
- // init arguments
- if(args.sourceShape) {
- args.sourceStencil = args.sourceShape.getStencil();
- }
- if(args.targetShape) {
- args.targetStencil = args.targetShape.getStencil();
- }
- if(args.edgeShape) {
- args.edgeStencil = args.edgeShape.getStencil();
- }
-
- var result;
-
- if(args.sourceStencil && args.targetStencil) {
- var source = this._cachedConnectSET[args.sourceStencil.id()];
-
- if(!source)
- result = this._cacheConnect(args);
- else {
- var edge = source[args.edgeStencil.id()];
- if(!edge)
- result = this._cacheConnect(args);
- else {
- var target = edge[args.targetStencil.id()];
- if(target == undefined)
- result = this._cacheConnect(args);
- else
- result = target;
- }
- }
- } else if (args.sourceStencil) {
- var source = this._cachedConnectSE[args.sourceStencil.id()];
-
- if(!source)
- result = this._cacheConnect(args);
- else {
- var edge = source[args.edgeStencil.id()];
-
- if(edge == undefined)
- result = this._cacheConnect(args);
- else
- result = edge;
- }
- } else { // args.targetStencil
- var target = this._cachedConnectTE[args.targetStencil.id()];
-
- if(!target)
- result = this._cacheConnect(args);
- else {
- var edge = target[args.edgeStencil.id()];
-
- if(edge == undefined)
- result = this._cacheConnect(args);
- else
- result = edge;
- }
- }
-
- // check cardinality
- if (result) {
- if(args.sourceShape) {
- var source = this._cachedCardSE[args.sourceStencil.id()];
-
- if(!source) {
- this._cacheCard(args);
- source = this._cachedCardSE[args.sourceStencil.id()];
- }
-
- var max = source[args.edgeStencil.id()];
-
- if(max == undefined) {
- this._cacheCard(args);
- }
-
- max = source[args.edgeStencil.id()];
-
- if(max != -1) {
- result = args.sourceShape.getOutgoingShapes().all(function(cs) {
- if((cs.getStencil().id() === args.edgeStencil.id()) &&
- ((args.edgeShape) ? cs !== args.edgeShape : true)) {
- max--;
- return (max > 0) ? true : false;
- } else {
- return true;
- }
- });
- }
- }
-
- if (args.targetShape) {
- var target = this._cachedCardTE[args.targetStencil.id()];
-
- if(!target) {
- this._cacheCard(args);
- target = this._cachedCardTE[args.targetStencil.id()];
- }
-
- var max = target[args.edgeStencil.id()];
-
- if(max == undefined) {
- this._cacheCard(args);
- }
-
- max = target[args.edgeStencil.id()];
-
- if(max != -1) {
- result = args.targetShape.getIncomingShapes().all(function(cs){
- if ((cs.getStencil().id() === args.edgeStencil.id()) &&
- ((args.edgeShape) ? cs !== args.edgeShape : true)) {
- max--;
- return (max > 0) ? true : false;
- }
- else {
- return true;
- }
- });
- }
- }
- }
-
- return result;
- },
-
- /**
- *
- * @param {Object}
- * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape:
- * ORYX.Core.Edge |undefined sourceStencil:
- * ORYX.Core.StencilSet.Stencil | undefined sourceShape:
- * ORYX.Core.Node |undefined targetStencil:
- * ORYX.Core.StencilSet.Stencil | undefined targetShape:
- * ORYX.Core.Node |undefined
- *
- * At least source or target has to be specified!!!
- *
- * @return {Boolean} Returns, if the edge can connect source and target.
- */
- _canConnect: function(args) {
- // check arguments
- if(!args ||
- (!args.sourceShape && !args.sourceStencil &&
- !args.targetShape && !args.targetStencil) ||
- !args.edgeShape && !args.edgeStencil) {
- return false;
- }
-
- // init arguments
- if(args.sourceShape) {
- args.sourceStencil = args.sourceShape.getStencil();
- }
- if(args.targetShape) {
- args.targetStencil = args.targetShape.getStencil();
- }
- if(args.edgeShape) {
- args.edgeStencil = args.edgeShape.getStencil();
- }
- // 1. check connection rules
- var resultCR;
-
- // get all connection rules for this edge
- var edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil);
- // check connection rules, if the source can be connected to the target
- // with the specified edge.
- if(edgeRules.keys().length === 0) {
- resultCR = false;
- } else {
- if(args.sourceStencil) {
- resultCR = args.sourceStencil.roles().any(function(sourceRole) {
- var targetRoles = edgeRules[sourceRole];
- if(!targetRoles) {return false;}
-
- if(args.targetStencil) {
- return (targetRoles.any(function(targetRole) {
- return args.targetStencil.roles().member(targetRole);
- }));
- } else {
- return true;
- }
- });
- } else { // !args.sourceStencil -> there is args.targetStencil
- resultCR = edgeRules.values().any(function(targetRoles) {
- return args.targetStencil.roles().any(function(targetRole) {
- return targetRoles.member(targetRole);
- });
- });
- }
- }
-
- return resultCR;
- },
- /** End connection rules' methods */
- /** Begin containment rules' methods */
- isContainer: function(shape) {
- return this._containerStencils.member(shape.getStencil().id());
- },
- /**
- *
- * @param {Object}
- * args containingStencil: ORYX.Core.StencilSet.Stencil
- * containingShape: ORYX.Core.AbstractShape containedStencil:
- * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape
- */
- canContain: function(args) {
- if(!args ||
- !args.containingStencil && !args.containingShape ||
- !args.containedStencil && !args.containedShape) {
- return false;
- }
-
- // init arguments
- if(args.containedShape) {
- args.containedStencil = args.containedShape.getStencil();
- }
-
- if(args.containingShape) {
- args.containingStencil = args.containingShape.getStencil();
- }
-
- //if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge')
- // return false;
- if(args.containedStencil.type() == 'edge')
- return false;
-
- var childValues;
-
- var parent = this._cachedContainPC[args.containingStencil.id()];
-
- if(!parent)
- childValues = this._cacheContain(args);
- else {
- childValues = parent[args.containedStencil.id()];
-
- if(!childValues)
- childValues = this._cacheContain(args);
- }
- if(!childValues[0])
- return false;
- else if (childValues[1] == -1)
- return true;
- else {
- if(args.containingShape) {
- var max = childValues[1];
- return args.containingShape.getChildShapes(false).all(function(as) {
- if(as.getStencil().id() === args.containedStencil.id()) {
- max--;
- return (max > 0) ? true : false;
- } else {
- return true;
- }
- });
- } else {
- return true;
- }
- }
- },
-
- /**
- *
- * @param {Object}
- * args containingStencil: ORYX.Core.StencilSet.Stencil
- * containingShape: ORYX.Core.AbstractShape containedStencil:
- * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape
- */
- _canContain: function(args) {
- if(!args ||
- !args.containingStencil && !args.containingShape ||
- !args.containedStencil && !args.containedShape) {
- return false;
- }
-
- // init arguments
- if(args.containedShape) {
- args.containedStencil = args.containedShape.getStencil();
- }
-
- if(args.containingShape) {
- args.containingStencil = args.containingShape.getStencil();
- }
-
- // if(args.containingShape) {
- // if(args.containingShape instanceof ORYX.Core.Edge) {
- // // edges cannot contain other shapes
- // return false;
- // }
- // }
-
- var result;
-
- // check containment rules
- result = args.containingStencil.roles().any((function(role) {
- var roles = this._containmentRules[role];
- if(roles) {
- return roles.any(function(role) {
- return args.containedStencil.roles().member(role);
- });
- } else {
- return false;
- }
- }).bind(this));
-
- return result;
- },
-
- /** End containment rules' methods */
-
-
- /** Begin morphing rules' methods */
-
- /**
- *
- * @param {Object}
- * args
- * stencil: ORYX.Core.StencilSet.Stencil | undefined
- * shape: ORYX.Core.Shape | undefined
- *
- * At least stencil or shape has to be specified
- *
- * @return {Array} Array of stencils that the passed stencil/shape can be
- * transformed to (including the current stencil itself)
- */
- morphStencils: function(args) {
- // check arguments
- if(!args.stencil && !args.shape) {
- return [];
- }
-
- // init arguments
- if(args.shape) {
- args.stencil = args.shape.getStencil();
- }
-
- var _morphStencils = [];
- args.stencil.roles().each(function(role) {
- this._cacheMorph(role).each(function(stencil) {
- _morphStencils.push(stencil);
- })
- }.bind(this));
- var baseMorphs = this.baseMorphs();
- // BaseMorphs should be in the front of the array
- _morphStencils = _morphStencils.uniq().sort(function(a,b){ return baseMorphs.include(a)&&!baseMorphs.include(b) ? -1 : (baseMorphs.include(b)&&!baseMorphs.include(a) ? 1 : 0)})
- return _morphStencils;
- },
-
- /**
- * @return {Array} An array of all base morph stencils
- */
- baseMorphs: function() {
- var _baseMorphs = [];
- this._morphingRules.each(function(pair) {
- pair.value.each(function(baseMorph) {
- _baseMorphs.push(baseMorph);
- });
- });
- return _baseMorphs;
- },
-
- /**
- * Returns true if there are morphing rules defines
- * @return {boolean}
- */
- containsMorphingRules: function(){
- return this._stencilSets.any(function(ss){ return !!ss.jsonRules().morphingRules});
- },
-
- /**
- *
- * @param {Object}
- * args
- * sourceStencil:
- * ORYX.Core.StencilSet.Stencil | undefined
- * sourceShape:
- * ORYX.Core.Node |undefined
- * targetStencil:
- * ORYX.Core.StencilSet.Stencil | undefined
- * targetShape:
- * ORYX.Core.Node |undefined
- *
- *
- * @return {Stencil} Returns, the stencil for the connecting edge
- * or null if connection is not possible
- */
- connectMorph: function(args) {
- // check arguments
- if(!args ||
- (!args.sourceShape && !args.sourceStencil &&
- !args.targetShape && !args.targetStencil)) {
- return false;
- }
-
- // init arguments
- if(args.sourceShape) {
- args.sourceStencil = args.sourceShape.getStencil();
- }
- if(args.targetShape) {
- args.targetStencil = args.targetShape.getStencil();
- }
-
- var incoming = this.incomingEdgeStencils(args);
- var outgoing = this.outgoingEdgeStencils(args);
-
- var edgeStencils = incoming.select(function(e) { return outgoing.member(e); }); // intersection of sets
- var baseEdgeStencils = this.baseMorphs().select(function(e) { return edgeStencils.member(e); }); // again: intersection of sets
-
- if(baseEdgeStencils.size()>0)
- return baseEdgeStencils[0]; // return any of the possible base morphs
- else if(edgeStencils.size()>0)
- return edgeStencils[0]; // return any of the possible stencils
-
- return null; //connection not possible
- },
-
- /**
- * Return true if the stencil should be located in the shape menu
- * @param {ORYX.Core.StencilSet.Stencil} morph
- * @return {Boolean} Returns true if the morphs in the morph group of the
- * specified morph shall be displayed in the shape menu
- */
- showInShapeMenu: function(stencil) {
- return this._stencilSets.any(function(ss){
- return ss.jsonRules().morphingRules
- .any(function(r){
- return stencil.roles().include(ss.namespace() + r.role)
- && r.showInShapeMenu !== false;
- })
- });
- },
-
- preserveBounds: function(stencil) {
- return this._stencilSets.any(function(ss) {
- return ss.jsonRules().morphingRules.any(function(r) {
-
-
- return stencil.roles().include(ss.namespace() + r.role)
- && r.preserveBounds;
- })
- })
- },
-
- /** End morphing rules' methods */
- /** Begin layouting rules' methods */
-
- /**
- * Returns a set on "in" and "out" layouting rules for a given shape
- * @param {Object} shape
- * @param {Object} edgeShape (Optional)
- * @return {Object} "in" and "out" with a default value of {"t":1, "r":1, "b":1, "r":1} if not specified in the json
- */
- getLayoutingRules : function(shape, edgeShape){
-
- if (!shape||!(shape instanceof ORYX.Core.Shape)){ return }
-
- var layout = {"in":{},"out":{}};
-
- var parseValues = function(o, v){
- if (o && o[v]){
- ["t","r","b","l"].each(function(d){
- layout[v][d]=Math.max(o[v][d],layout[v][d]||0);
- });
- }
- if (o && o[v+"s"] instanceof Array){
- ["t","r","b","l"].each(function(d){
- var defaultRule = o[v+"s"].find(function(e){ return !e.edgeRole });
- var edgeRule;
- if (edgeShape instanceof ORYX.Core.Edge) {
- edgeRule = o[v + "s"].find(function(e){return this._hasRole(edgeShape, e.edgeRole) }.bind(this));
- }
- layout[v][d]=Math.max(edgeRule?edgeRule[d]:defaultRule[d],layout[v][d]||0);
- }.bind(this));
- }
- }.bind(this)
-
- // For each role
- shape.getStencil().roles().each(function(role) {
- // check if there are layout information
- if (this._layoutRules[role]){
- // if so, parse those information to the 'layout' variable
- parseValues(this._layoutRules[role], "in");
- parseValues(this._layoutRules[role], "out");
- }
- }.bind(this));
-
- // Make sure, that every attribute has an value,
- // otherwise set 1
- ["in","out"].each(function(v){
- ["t","r","b","l"].each(function(d){
- layout[v][d]=layout[v][d]!==undefined?layout[v][d]:1;
- });
- })
-
- return layout;
- },
-
- /** End layouting rules' methods */
-
- /** Helper methods */
- /**
- * Checks wether a shape contains the given role or the role is equal the stencil id
- * @param {ORYX.Core.Shape} shape
- * @param {String} role
- */
- _hasRole: function(shape, role){
- if (!(shape instanceof ORYX.Core.Shape)||!role){ return }
- var isRole = shape.getStencil().roles().any(function(r){ return r == role});
-
- return isRole || shape.getStencil().id() == (shape.getStencil().namespace()+role);
- },
- /**
- *
- * @param {String}
- * role
- *
- * @return {Array} Returns an array of stencils that can act as role.
- */
- _stencilsWithRole: function(role) {
- return this._stencils.findAll(function(stencil) {
- return (stencil.roles().member(role)) ? true : false;
- });
- },
-
- /**
- *
- * @param {String}
- * role
- *
- * @return {Array} Returns an array of stencils that can act as role and
- * have the type 'edge'.
- */
- _edgesWithRole: function(role) {
- return this._stencils.findAll(function(stencil) {
- return (stencil.roles().member(role) && stencil.type() === "edge") ? true : false;
- });
- },
-
- /**
- *
- * @param {String}
- * role
- *
- * @return {Array} Returns an array of stencils that can act as role and
- * have the type 'node'.
- */
- _nodesWithRole: function(role) {
- return this._stencils.findAll(function(stencil) {
- return (stencil.roles().member(role) && stencil.type() === "node") ? true : false;
- });
- },
- /**
- *
- * @param {ORYX.Core.StencilSet.Stencil}
- * parent
- * @param {ORYX.Core.StencilSet.Stencil}
- * child
- *
- * @returns {Boolean} Returns the maximum occurrence of shapes of the
- * stencil's type inside the parent.
- */
- _getMaximumOccurrence: function(parent, child) {
- var max;
- child.roles().each((function(role) {
- var cardRule = this._cardinalityRules[role];
- if(cardRule && cardRule.maximumOccurrence) {
- if(max) {
- max = Math.min(max, cardRule.maximumOccurrence);
- } else {
- max = cardRule.maximumOccurrence;
- }
- }
- }).bind(this));
- return max;
- },
- /**
- *
- * @param {Object}
- * args sourceStencil: ORYX.Core.Node edgeStencil:
- * ORYX.Core.StencilSet.Stencil
- *
- * @return {Boolean} Returns, the maximum number of outgoing edges of the
- * type specified by edgeStencil of the sourceShape.
- */
- _getMaximumNumberOfOutgoingEdge: function(args) {
- if(!args ||
- !args.sourceStencil ||
- !args.edgeStencil) {
- return false;
- }
-
- var max;
- args.sourceStencil.roles().each((function(role) {
- var cardRule = this._cardinalityRules[role];
- if(cardRule && cardRule.outgoingEdges) {
- args.edgeStencil.roles().each(function(edgeRole) {
- var oe = cardRule.outgoingEdges[edgeRole];
- if(oe && oe.maximum) {
- if(max) {
- max = Math.min(max, oe.maximum);
- } else {
- max = oe.maximum;
- }
- }
- });
- }
- }).bind(this));
- return max;
- },
-
- /**
- *
- * @param {Object}
- * args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil:
- * ORYX.Core.StencilSet.Stencil
- *
- * @return {Boolean} Returns the maximum number of incoming edges of the
- * type specified by edgeStencil of the targetShape.
- */
- _getMaximumNumberOfIncomingEdge: function(args) {
- if(!args ||
- !args.targetStencil ||
- !args.edgeStencil) {
- return false;
- }
-
- var max;
- args.targetStencil.roles().each((function(role) {
- var cardRule = this._cardinalityRules[role];
- if(cardRule && cardRule.incomingEdges) {
- args.edgeStencil.roles().each(function(edgeRole) {
- var ie = cardRule.incomingEdges[edgeRole];
- if(ie && ie.maximum) {
- if(max) {
- max = Math.min(max, ie.maximum);
- } else {
- max = ie.maximum;
- }
- }
- });
- }
- }).bind(this));
- return max;
- },
-
- /**
- *
- * @param {ORYX.Core.StencilSet.Stencil}
- * edgeStencil
- *
- * @return {Hash} Returns a hash map of all connection rules for
- * edgeStencil.
- */
- _getConnectionRulesOfEdgeStencil: function(edgeStencil) {
- var edgeRules = new Hash();
- edgeStencil.roles().each((function(role) {
- if(this._connectionRules[role]) {
- this._connectionRules[role].each(function(cr) {
- if(edgeRules[cr.key]) {
- edgeRules[cr.key] = edgeRules[cr.key].concat(cr.value);
- } else {
- edgeRules[cr.key] = cr.value;
- }
- });
- }
- }).bind(this));
-
- return edgeRules;
- },
-
- _isRoleOfOtherNamespace: function(role) {
- return (role.indexOf("#") > 0);
- },
- toString: function() { return "Rules"; }
- }
- ORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules);
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespace
- */
- if (!ORYX) {
- var ORYX = {};
- }
- if (!ORYX.Core) {
- ORYX.Core = {};
- }
- if (!ORYX.Core.StencilSet) {
- ORYX.Core.StencilSet = {};
- }
- /**
- * This class represents a stencil set. It offers methods for accessing
- * the attributes of the stencil set description JSON file and the stencil set's
- * stencils.
- */
- ORYX.Core.StencilSet.StencilSet = Clazz.extend({
- /**
- * Constructor
- * @param source {URL} A reference to the stencil set specification.
- *
- */
- construct: function(source){
- arguments.callee.$.construct.apply(this, arguments);
-
- if (!source) {
- throw "ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined.";
- }
-
- if (source.endsWith("/")) {
- source = source.substr(0, source.length - 1);
- }
-
- this._extensions = new Hash();
-
- this._source = source;
- this._baseUrl = source.substring(0, source.lastIndexOf("/") + 1);
-
- this._jsonObject = {};
-
- this._stencils = new Hash();
- this._availableStencils = new Hash();
-
- if(ORYX.CONFIG.BACKEND_SWITCH) {
- this._baseUrl = "../editor/stencilsets/bpmn2.0/";
- this._source = "../stencilsets/bpmn2.0/bpmn2.0.json";
- new Ajax.Request("../service/editor/stencilset", {
- asynchronous: false,
- method: 'get',
- onSuccess: this._init.bind(this),
- onFailure: this._cancelInit.bind(this)
- });
-
- } else {
- new Ajax.Request(source, {
- asynchronous: false,
- method: 'get',
- onSuccess: this._init.bind(this),
- onFailure: this._cancelInit.bind(this)
- });
- }
-
- if (this.errornous)
- throw "Loading stencil set " + source + " failed.";
- },
-
- /**
- * Finds a root stencil in this stencil set. There may be many of these. If
- * there are, the first one found will be used. In Firefox, this is the
- * topmost definition in the stencil set description file.
- */
- findRootStencilName: function(){
-
- // find any stencil that may be root.
- var rootStencil = this._stencils.values().find(function(stencil){
- return stencil._jsonStencil.mayBeRoot
- });
-
- // if there is none, just guess the first.
- if (!rootStencil) {
- ORYX.Log.warn("Did not find any stencil that may be root. Taking a guess.");
- rootStencil = this._stencils.values()[0];
- }
- // return its id.
- return rootStencil.id();
- },
-
- /**
- * @param {ORYX.Core.StencilSet.StencilSet} stencilSet
- * @return {Boolean} True, if stencil set has the same namespace.
- */
- equals: function(stencilSet){
- return (this.namespace() === stencilSet.namespace());
- },
-
- /**
- *
- * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils
- * that could be (in)direct child of that stencil.
- */
- stencils: function(rootStencil, rules, sortByGroup){
- if(rootStencil && rules) {
- var stencils = this._availableStencils.values();
- var containers = [rootStencil];
- var checkedContainers = [];
-
- var result = [];
-
- while (containers.size() > 0) {
- var container = containers.pop();
- checkedContainers.push(container);
- var children = stencils.findAll(function(stencil){
- var args = {
- containingStencil: container,
- containedStencil: stencil
- };
- return rules.canContain(args);
- });
- for(var i = 0; i < children.size(); i++) {
- if (!checkedContainers.member(children[i])) {
- containers.push(children[i]);
- }
- }
- result = result.concat(children).uniq();
- }
-
- // Sort the result to the origin order
- result = result.sortBy(function(stencil) {
- return stencils.indexOf(stencil);
- });
-
-
- if(sortByGroup) {
- result = result.sortBy(function(stencil) {
- return stencil.groups().first();
- });
- }
-
- var edges = stencils.findAll(function(stencil) {
- return stencil.type() == "edge";
- });
- result = result.concat(edges);
-
- return result;
-
- } else {
- if(sortByGroup) {
- return this._availableStencils.values().sortBy(function(stencil) {
- return stencil.groups().first();
- });
- } else {
- return this._availableStencils.values();
- }
- }
- },
-
- nodes: function(){
- return this._availableStencils.values().findAll(function(stencil){
- return (stencil.type() === 'node')
- });
- },
-
- edges: function(){
- return this._availableStencils.values().findAll(function(stencil){
- return (stencil.type() === 'edge')
- });
- },
-
- stencil: function(id){
- return this._stencils[id];
- },
-
- title: function(){
- return ORYX.Core.StencilSet.getTranslation(this._jsonObject, "title");
- },
-
- description: function(){
- return ORYX.Core.StencilSet.getTranslation(this._jsonObject, "description");
- },
-
- namespace: function(){
- return this._jsonObject ? this._jsonObject.namespace : null;
- },
-
- jsonRules: function(){
- return this._jsonObject ? this._jsonObject.rules : null;
- },
-
- source: function(){
- return this._source;
- },
-
- extensions: function() {
- return this._extensions;
- },
-
- addExtension: function(url) {
-
- new Ajax.Request(url, {
- method: 'GET',
- asynchronous: false,
- onSuccess: (function(transport) {
- this.addExtensionDirectly(transport.responseText);
- }).bind(this),
- onFailure: (function(transport) {
- ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport);
- }).bind(this),
- onException: (function(transport) {
- ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport);
- }).bind(this)
-
- });
- },
-
- addExtensionDirectly: function(str){
- try {
- eval("var jsonExtension = " + str);
- if(!(jsonExtension["extends"].endsWith("#")))
- jsonExtension["extends"] += "#";
-
- if(jsonExtension["extends"] == this.namespace()) {
- this._extensions[jsonExtension.namespace] = jsonExtension;
-
- var defaultPosition = this._stencils.keys().size();
- //load new stencils
- if(jsonExtension.stencils) {
- $A(jsonExtension.stencils).each(function(stencil) {
- defaultPosition++;
- var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition);
- this._stencils[oStencil.id()] = oStencil;
- this._availableStencils[oStencil.id()] = oStencil;
- }.bind(this));
- }
-
- //load additional properties
- if (jsonExtension.properties) {
- var stencils = this._stencils.values();
-
- stencils.each(function(stencil){
- var roles = stencil.roles();
-
- jsonExtension.properties.each(function(prop){
- prop.roles.any(function(role){
- role = jsonExtension["extends"] + role;
- if (roles.member(role)) {
- prop.properties.each(function(property){
- stencil.addProperty(property, jsonExtension.namespace);
- });
-
- return true;
- }
- else
- return false;
- })
- })
- }.bind(this));
- }
-
- //remove stencil properties
- if(jsonExtension.removeproperties) {
- jsonExtension.removeproperties.each(function(remprop) {
- var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil);
- if(stencil) {
- remprop.properties.each(function(propId) {
- stencil.removeProperty(propId);
- });
- }
- }.bind(this));
- }
-
- //remove stencils
- if(jsonExtension.removestencils) {
- $A(jsonExtension.removestencils).each(function(remstencil) {
- delete this._availableStencils[jsonExtension["extends"] + remstencil];
- }.bind(this));
- }
- }
- } catch (e) {
- ORYX.Log.debug("StencilSet.addExtension: Something went wrong when initialising the stencil set extension. " + e);
- }
- },
-
- removeExtension: function(namespace) {
- var jsonExtension = this._extensions[namespace];
- if(jsonExtension) {
-
- //unload extension's stencils
- if(jsonExtension.stencils) {
- $A(jsonExtension.stencils).each(function(stencil) {
- var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this);
- delete this._stencils[oStencil.id()]; // maybe not ??
- delete this._availableStencils[oStencil.id()];
- }.bind(this));
- }
-
- //unload extension's properties
- if (jsonExtension.properties) {
- var stencils = this._stencils.values();
-
- stencils.each(function(stencil){
- var roles = stencil.roles();
-
- jsonExtension.properties.each(function(prop){
- prop.roles.any(function(role){
- role = jsonExtension["extends"] + role;
- if (roles.member(role)) {
- prop.properties.each(function(property){
- stencil.removeProperty(property.id);
- });
-
- return true;
- }
- else
- return false;
- })
- })
- }.bind(this));
- }
-
- //restore removed stencil properties
- if(jsonExtension.removeproperties) {
- jsonExtension.removeproperties.each(function(remprop) {
- var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil);
- if(stencil) {
- var stencilJson = $A(this._jsonObject.stencils).find(function(s) { return s.id == stencil.id() });
- remprop.properties.each(function(propId) {
- var propertyJson = $A(stencilJson.properties).find(function(p) { return p.id == propId });
- stencil.addProperty(propertyJson, this.namespace());
- }.bind(this));
- }
- }.bind(this));
- }
-
- //restore removed stencils
- if(jsonExtension.removestencils) {
- $A(jsonExtension.removestencils).each(function(remstencil) {
- var sId = jsonExtension["extends"] + remstencil;
- this._availableStencils[sId] = this._stencils[sId];
- }.bind(this));
- }
- }
- delete this._extensions[namespace];
- },
-
- __handleStencilset: function(response){
-
- try {
- // using eval instead of prototype's parsing,
- // since there are functions in this JSON.
- eval("this._jsonObject =" + response.responseText);
- }
- catch (e) {
- throw "Stenciset corrupt: " + e;
- }
-
- // assert it was parsed.
- if (!this._jsonObject) {
- throw "Error evaluating stencilset. It may be corrupt.";
- }
-
- with (this._jsonObject) {
-
- // assert there is a namespace.
- if (!namespace || namespace === "")
- throw "Namespace definition missing in stencilset.";
-
- if (!(stencils instanceof Array))
- throw "Stencilset corrupt.";
-
- // assert namespace ends with '#'.
- if (!namespace.endsWith("#"))
- namespace = namespace + "#";
-
- // assert title and description are strings.
- if (!title)
- title = "";
- if (!description)
- description = "";
- }
- },
-
- /**
- * This method is called when the HTTP request to get the requested stencil
- * set succeeds. The response is supposed to be a JSON representation
- * according to the stencil set specification.
- * @param {Object} response The JSON representation according to the
- * stencil set specification.
- */
- _init: function(response){
-
- // init and check consistency.
- this.__handleStencilset(response);
-
- var pps = new Hash();
-
- // init property packages
- if(this._jsonObject.propertyPackages) {
- $A(this._jsonObject.propertyPackages).each((function(pp) {
- pps[pp.name] = pp.properties;
- }).bind(this));
- }
-
- var defaultPosition = 0;
-
- // init each stencil
- $A(this._jsonObject.stencils).each((function(stencil){
- defaultPosition++;
-
- // instantiate normally.
- var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition);
- this._stencils[oStencil.id()] = oStencil;
- this._availableStencils[oStencil.id()] = oStencil;
-
- }).bind(this));
- },
-
- _cancelInit: function(response){
- this.errornous = true;
- },
-
- toString: function(){
- return "StencilSet " + this.title() + " (" + this.namespace() + ")";
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespace
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};}
- /**
- * Class StencilSets
- * uses Prototpye 1.5.0
- * uses Inheritance
- *
- * Singleton
- */
- //storage for loaded stencil sets by namespace
- ORYX.Core.StencilSet._stencilSetsByNamespace = new Hash();
- //storage for stencil sets by url
- ORYX.Core.StencilSet._stencilSetsByUrl = new Hash();
- //storage for stencil set namespaces by editor instances
- ORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash();
- //storage for rules by editor instances
- ORYX.Core.StencilSet._rulesByEditorInstance = new Hash();
- /**
- *
- * @param {String} editorId
- *
- * @return {Hash} Returns a hash map with all stencil sets that are loaded by
- * the editor with the editorId.
- */
- ORYX.Core.StencilSet.stencilSets = function(editorId) {
- var stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId];
- var stencilSets = new Hash();
- if(stencilSetNSs) {
- stencilSetNSs.each(function(stencilSetNS) {
- var stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS)
- stencilSets[stencilSet.namespace()] = stencilSet;
- });
- }
- return stencilSets;
- };
- /**
- *
- * @param {String} namespace
- *
- * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified
- * namespace.
- *
- * The method can handle namespace strings like
- * http://www.example.org/stencilset
- * http://www.example.org/stencilset#
- * http://www.example.org/stencilset#ANode
- */
- ORYX.Core.StencilSet.stencilSet = function(namespace) {
- ORYX.Log.trace("Getting stencil set %0", namespace);
- var splitted = namespace.split("#", 1);
- if(splitted.length === 1) {
- ORYX.Log.trace("Getting stencil set %0", splitted[0]);
- return ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + "#"];
- } else {
- return undefined;
- }
- };
- /**
- *
- * @param {String} id
- *
- * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id.
- *
- * The id must be unique and contains the namespace of the stencil's stencil set.
- * e.g. http://www.example.org/stencilset#ANode
- */
- ORYX.Core.StencilSet.stencil = function(id) {
- ORYX.Log.trace("Getting stencil for %0", id);
- var ss = ORYX.Core.StencilSet.stencilSet(id);
- if(ss) {
- return ss.stencil(id);
- } else {
- ORYX.Log.trace("Cannot fild stencil for %0", id);
- return undefined;
- }
- };
- /**
- *
- * @param {String} editorId
- *
- * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor
- * specified by its editor id.
- */
- ORYX.Core.StencilSet.rules = function(editorId) {
- if(!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {
- ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules();;
- }
- return ORYX.Core.StencilSet._rulesByEditorInstance[editorId];
- };
- /**
- *
- * @param {String} url
- * @param {String} editorId
- *
- * Loads a stencil set from url, if it is not already loaded.
- * It also stores which editor instance loads the stencil set and
- * initializes the Rules object for the editor instance.
- */
- ORYX.Core.StencilSet.loadStencilSet = function(url, editorId) {
- var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url];
- if(!stencilSet) {
- //load stencil set
- stencilSet = new ORYX.Core.StencilSet.StencilSet(url);
-
- //store stencil set
- ORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet;
-
- //store stencil set by url
- ORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet;
- }
-
- var namespace = stencilSet.namespace();
-
- //store which editorInstance loads the stencil set
- if(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) {
- ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace);
- } else {
- ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace];
- }
- //store the rules for the editor instance
- if(ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) {
- ORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet);
- } else {
- var rules = new ORYX.Core.StencilSet.Rules();
- rules.initializeRules(stencilSet);
- ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules;
- }
- };
- /**
- * Returns the translation of an attribute in jsonObject specified by its name
- * according to navigator.language
- */
- ORYX.Core.StencilSet.getTranslation = function(jsonObject, name) {
- var lang = ORYX.I18N.Language.toLowerCase();
-
- var result = jsonObject[name + "_" + lang];
-
- if(result)
- return result;
-
- result = jsonObject[name + "_" + lang.substr(0, 2)];
-
- if(result)
- return result;
-
- return jsonObject[name];
- };
- /**
- * Copyright (c) 2006
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * @classDescription With Bounds you can set and get position and size of UIObjects.
- */
- ORYX.Core.Command = Clazz.extend({
- /**
- * Constructor
- */
- construct: function() {
- },
-
- execute: function(){
- throw "Command.execute() has to be implemented!"
- },
-
- rollback: function(){
- throw "Command.rollback() has to be implemented!"
- }
-
-
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * @classDescription With Bounds you can set and get position and size of UIObjects.
- */
- ORYX.Core.Bounds = {
- /**
- * Constructor
- */
- construct: function() {
- this._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this));
- this.a = {};
- this.b = {};
- this.set.apply(this, arguments);
- this.suspendChange = false;
- this.changedWhileSuspend = false;
- },
-
- /**
- * Calls all registered callbacks.
- */
- _changed: function(sizeChanged) {
- if(!this.suspendChange) {
- this._changedCallbacks.each(function(callback) {
- callback(this, sizeChanged);
- }.bind(this));
- this.changedWhileSuspend = false;
- } else
- this.changedWhileSuspend = true;
- },
-
- /**
- * Registers a callback that is called, if the bounds changes.
- * @param callback {Function} The callback function.
- */
- registerCallback: function(callback) {
- if(!this._changedCallbacks.member(callback)) {
- this._changedCallbacks.push(callback);
- }
- },
-
- /**
- * Unregisters a callback.
- * @param callback {Function} The callback function.
- */
- unregisterCallback: function(callback) {
- this._changedCallbacks = this._changedCallbacks.without(callback);
- },
-
- /**
- * Sets position and size of the shape dependent of four coordinates
- * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});)
- * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});).
- */
- set: function() {
-
- var changed = false;
-
- switch (arguments.length) {
-
- case 1:
- if(this.a.x !== arguments[0].a.x) {
- changed = true;
- this.a.x = arguments[0].a.x;
- }
- if(this.a.y !== arguments[0].a.y) {
- changed = true;
- this.a.y = arguments[0].a.y;
- }
- if(this.b.x !== arguments[0].b.x) {
- changed = true;
- this.b.x = arguments[0].b.x;
- }
- if(this.b.y !== arguments[0].b.y) {
- changed = true;
- this.b.y = arguments[0].b.y;
- }
- break;
-
- case 2:
- var ax = Math.min(arguments[0].x, arguments[1].x);
- var ay = Math.min(arguments[0].y, arguments[1].y);
- var bx = Math.max(arguments[0].x, arguments[1].x);
- var by = Math.max(arguments[0].y, arguments[1].y);
- if(this.a.x !== ax) {
- changed = true;
- this.a.x = ax;
- }
- if(this.a.y !== ay) {
- changed = true;
- this.a.y = ay;
- }
- if(this.b.x !== bx) {
- changed = true;
- this.b.x = bx;
- }
- if(this.b.y !== by) {
- changed = true;
- this.b.y = by;
- }
- break;
-
- case 4:
- var ax = Math.min(arguments[0], arguments[2]);
- var ay = Math.min(arguments[1], arguments[3]);
- var bx = Math.max(arguments[0], arguments[2]);
- var by = Math.max(arguments[1], arguments[3]);
- if(this.a.x !== ax) {
- changed = true;
- this.a.x = ax;
- }
- if(this.a.y !== ay) {
- changed = true;
- this.a.y = ay;
- }
- if(this.b.x !== bx) {
- changed = true;
- this.b.x = bx;
- }
- if(this.b.y !== by) {
- changed = true;
- this.b.y = by;
- }
- break;
- }
-
- if(changed) {
- this._changed(true);
- }
- },
-
- /**
- * Moves the bounds so that the point p will be the new upper left corner.
- * @param {Point} p
- * or
- * @param {Number} x
- * @param {Number} y
- */
- moveTo: function() {
-
- var currentPosition = this.upperLeft();
- switch (arguments.length) {
- case 1:
- this.moveBy({
- x: arguments[0].x - currentPosition.x,
- y: arguments[0].y - currentPosition.y
- });
- break;
- case 2:
- this.moveBy({
- x: arguments[0] - currentPosition.x,
- y: arguments[1] - currentPosition.y
- });
- break;
- default:
- //TODO error
- }
-
- },
-
- /**
- * Moves the bounds relatively by p.
- * @param {Point} p
- * or
- * @param {Number} x
- * @param {Number} y
- *
- */
- moveBy: function() {
- var changed = false;
-
- switch (arguments.length) {
- case 1:
- var p = arguments[0];
- if(p.x !== 0 || p.y !== 0) {
- changed = true;
- this.a.x += p.x;
- this.b.x += p.x;
- this.a.y += p.y;
- this.b.y += p.y;
- }
- break;
- case 2:
- var x = arguments[0];
- var y = arguments[1];
- if(x !== 0 || y !== 0) {
- changed = true;
- this.a.x += x;
- this.b.x += x;
- this.a.y += y;
- this.b.y += y;
- }
- break;
- default:
- //TODO error
- }
-
- if(changed) {
- this._changed();
- }
- },
-
- /***
- * Includes the bounds b into the current bounds.
- * @param {Bounds} b
- */
- include: function(b) {
-
- if( (this.a.x === undefined) && (this.a.y === undefined) &&
- (this.b.x === undefined) && (this.b.y === undefined)) {
- return b;
- };
-
- var cx = Math.min(this.a.x,b.a.x);
- var cy = Math.min(this.a.y,b.a.y);
-
- var dx = Math.max(this.b.x,b.b.x);
- var dy = Math.max(this.b.y,b.b.y);
-
- this.set(cx, cy, dx, dy);
- },
-
- /**
- * Relatively extends the bounds by p.
- * @param {Point} p
- */
- extend: function(p) {
-
- if(p.x !== 0 || p.y !== 0) {
- // this is over cross for the case that a and b have same coordinates.
- //((this.a.x > this.b.x) ? this.a : this.b).x += p.x;
- //((this.b.y > this.a.y) ? this.b : this.a).y += p.y;
- this.b.x += p.x;
- this.b.y += p.y;
-
- this._changed(true);
- }
- },
-
- /**
- * Widens the scope of the bounds by x.
- * @param {Number} x
- */
- widen: function(x) {
- if (x !== 0) {
- this.suspendChange = true;
- this.moveBy({x: -x, y: -x});
- this.extend({x: 2*x, y: 2*x});
- this.suspendChange = false;
- if(this.changedWhileSuspend) {
- this._changed(true);
- }
- }
- },
-
- /**
- * Returns the upper left corner's point regardless of the
- * bound delimiter points.
- */
- upperLeft: function() {
-
- return {x:this.a.x, y:this.a.y};
- },
-
- /**
- * Returns the lower Right left corner's point regardless of the
- * bound delimiter points.
- */
- lowerRight: function() {
-
- return {x:this.b.x, y:this.b.y};
- },
-
- /**
- * @return {Number} Width of bounds.
- */
- width: function() {
- return this.b.x - this.a.x;
- },
-
- /**
- * @return {Number} Height of bounds.
- */
- height: function() {
- return this.b.y - this.a.y;
- },
-
- /**
- * @return {Point} The center point of this bounds.
- */
- center: function() {
- return {
- x: (this.a.x + this.b.x)/2.0,
- y: (this.a.y + this.b.y)/2.0
- };
- },
-
- /**
- * @return {Point} The center point of this bounds relative to upperLeft.
- */
- midPoint: function() {
- return {
- x: (this.b.x - this.a.x)/2.0,
- y: (this.b.y - this.a.y)/2.0
- };
- },
-
- /**
- * Moves the center point of this bounds to the new position.
- * @param p {Point}
- * or
- * @param x {Number}
- * @param y {Number}
- */
- centerMoveTo: function() {
- var currentPosition = this.center();
-
- switch (arguments.length) {
-
- case 1:
- this.moveBy(arguments[0].x - currentPosition.x,
- arguments[0].y - currentPosition.y);
- break;
-
- case 2:
- this.moveBy(arguments[0] - currentPosition.x,
- arguments[1] - currentPosition.y);
- break;
- }
- },
-
- isIncluded: function(point, offset) {
-
- var pointX, pointY, offset;
- // Get the the two Points
- switch(arguments.length) {
- case 1:
- pointX = arguments[0].x;
- pointY = arguments[0].y;
- offset = 0;
-
- break;
- case 2:
- if(arguments[0].x && arguments[0].y) {
- pointX = arguments[0].x;
- pointY = arguments[0].y;
- offset = Math.abs(arguments[1]);
- } else {
- pointX = arguments[0];
- pointY = arguments[1];
- offset = 0;
- }
- break;
- case 3:
- pointX = arguments[0];
- pointY = arguments[1];
- offset = Math.abs(arguments[2]);
- break;
- default:
- throw "isIncluded needs one, two or three arguments";
- }
-
- var ul = this.upperLeft();
- var lr = this.lowerRight();
-
- if(pointX >= ul.x - offset
- && pointX <= lr.x + offset && pointY >= ul.y - offset
- && pointY <= lr.y + offset)
- return true;
- else
- return false;
- },
-
- /**
- * @return {Bounds} A copy of this bounds.
- */
- clone: function() {
-
- //Returns a new bounds object without the callback
- // references of the original bounds
- return new ORYX.Core.Bounds(this);
- },
-
- toString: function() {
-
- return "( "+this.a.x+" | "+this.a.y+" )/( "+this.b.x+" | "+this.b.y+" )";
- },
-
- serializeForERDF: function() {
- return this.a.x+","+this.a.y+","+this.b.x+","+this.b.y;
- }
- };
-
- ORYX.Core.Bounds = Clazz.extend(ORYX.Core.Bounds);/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * @classDescription Abstract base class for all objects that have a graphical representation
- * within the editor.
- * @extends Clazz
- */
- ORYX.Core.UIObject = {
- /**
- * Constructor of the UIObject class.
- */
- construct: function(options) {
-
- this.isChanged = true; //Flag, if UIObject has been changed since last update.
- this.isResized = true;
- this.isVisible = true; //Flag, if UIObject's display attribute is set to 'inherit' or 'none'
- this.isSelectable = false; //Flag, if UIObject is selectable.
- this.isResizable = false; //Flag, if UIObject is resizable.
- this.isMovable = false; //Flag, if UIObject is movable.
-
- this.id = ORYX.Editor.provideId(); //get unique id
- this.parent = undefined; //parent is defined, if this object is added to another uiObject.
- this.node = undefined; //this is a reference to the SVG representation, either locally or in DOM.
- this.children = []; //array for all add uiObjects
-
- this.bounds = new ORYX.Core.Bounds(); //bounds with undefined values
- this._changedCallback = this._changed.bind(this); //callback reference for calling _changed
- this.bounds.registerCallback(this._changedCallback); //set callback in bounds
-
- if(options && options.eventHandlerCallback) {
- this.eventHandlerCallback = options.eventHandlerCallback;
- }
- },
-
- /**
- * Sets isChanged flag to true. Callback for the bounds object.
- */
- _changed: function(bounds, isResized) {
- this.isChanged = true;
- if(this.bounds == bounds)
- this.isResized = isResized || this.isResized;
- },
-
- /**
- * If something changed, this method calls the refresh method that must be implemented by subclasses.
- */
- update: function() {
- if(this.isChanged) {
- this.refresh();
- this.isChanged = false;
-
- //call update of all children
- this.children.each(function(value) {
- value.update();
- });
- }
- },
-
- /**
- * Is called in update method, if isChanged is set to true. Sub classes should call the super class method.
- */
- refresh: function() {
-
- },
-
- /**
- * @return {Array} Array of all child UIObjects.
- */
- getChildren: function() {
- return this.children.clone();
- },
-
- /**
- * @return {Array} Array of all parent UIObjects.
- */
- getParents: function(){
- var parents = [];
- var parent = this.parent;
- while(parent){
- parents.push(parent);
- parent = parent.parent;
- }
- return parents;
- },
-
- /**
- * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE.
- * @param {UIObject} parent
- * @return {Boolean}
- */
- isParent: function(parent){
- var cparent = this;
- while(cparent){
- if (cparent === parent){
- return true;
- }
- cparent = cparent.parent;
- }
- return false;
- },
-
- /**
- * @return {String} Id of this UIObject
- */
- getId: function() {
- return this.id;
- },
-
- /**
- * Method for accessing child uiObjects by id.
- * @param {String} id
- * @param {Boolean} deep
- *
- * @return {UIObject} If found, it returns the UIObject with id.
- */
- getChildById: function(id, deep) {
- return this.children.find(function(uiObj) {
- if(uiObj.getId() === id) {
- return uiObj;
- } else {
- if(deep) {
- var obj = uiObj.getChildById(id, deep);
- if(obj) {
- return obj;
- }
- }
- }
- });
- },
-
- /**
- * Adds an UIObject to this UIObject and sets the parent of the
- * added UIObject. It is also added to the SVG representation of this
- * UIObject.
- * @param {UIObject} uiObject
- */
- add: function(uiObject) {
- //add uiObject, if it is not already a child of this object
- if (!(this.children.member(uiObject))) {
- //if uiObject is child of another parent, remove it from that parent.
- if(uiObject.parent) {
- uiObject.remove(uiObject);
- }
-
- //add uiObject to children
- this.children.push(uiObject);
-
- //set parent reference
- uiObject.parent = this;
-
- //add uiObject.node to this.node
- uiObject.node = this.node.appendChild(uiObject.node);
-
- //register callback to get informed, if child is changed
- uiObject.bounds.registerCallback(this._changedCallback);
- //uiObject.update();
- } else {
- ORYX.Log.info("add: ORYX.Core.UIObject is already a child of this object.");
- }
- },
-
- /**
- * Removes UIObject from this UIObject. The SVG representation will also
- * be removed from this UIObject's SVG representation.
- * @param {UIObject} uiObject
- */
- remove: function(uiObject) {
- //if uiObject is a child of this object, remove it.
- if (this.children.member(uiObject)) {
- //remove uiObject from children
- this.children = this._uiObjects.without(uiObject);
-
- //delete parent reference of uiObject
- uiObject.parent = undefined;
-
- //delete uiObject.node from this.node
- uiObject.node = this.node.removeChild(uiObject.node);
-
- //unregister callback to get informed, if child is changed
- uiObject.bounds.unregisterCallback(this._changedCallback);
- } else {
- ORYX.Log.info("remove: ORYX.Core.UIObject is not a child of this object.");
- }
-
- },
-
- /**
- * Calculates absolute bounds of this UIObject.
- */
- absoluteBounds: function() {
- if(this.parent) {
- var absUL = this.absoluteXY();
- return new ORYX.Core.Bounds(absUL.x, absUL.y,
- absUL.x + this.bounds.width(),
- absUL.y + this.bounds.height());
- } else {
- return this.bounds.clone();
- }
- },
- /**
- * @return {Point} The absolute position of this UIObject.
- */
- absoluteXY: function() {
- if(this.parent) {
- var pXY = this.parent.absoluteXY();
- return {x: pXY.x + this.bounds.upperLeft().x , y: pXY.y + this.bounds.upperLeft().y};
-
- } else {
- return {x: this.bounds.upperLeft().x , y: this.bounds.upperLeft().y};
- }
- },
- /**
- * @return {Point} The absolute position from the Center of this UIObject.
- */
- absoluteCenterXY: function() {
- if(this.parent) {
- var pXY = this.parent.absoluteXY();
- return {x: pXY.x + this.bounds.center().x , y: pXY.y + this.bounds.center().y};
-
- } else {
- return {x: this.bounds.center().x , y: this.bounds.center().y};
- }
- },
-
- /**
- * Hides this UIObject and all its children.
- */
- hide: function() {
- this.node.setAttributeNS(null, 'display', 'none');
- this.isVisible = false;
- this.children.each(function(uiObj) {
- uiObj.hide();
- });
- },
-
- /**
- * Enables visibility of this UIObject and all its children.
- */
- show: function() {
- this.node.setAttributeNS(null, 'display', 'inherit');
- this.isVisible = true;
- this.children.each(function(uiObj) {
- uiObj.show();
- });
- },
-
- addEventHandlers: function(node) {
-
- node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false);
- node.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false);
- node.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false);
- node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false);
- node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false);
- node.addEventListener('click', this._delegateEvent.bind(this), false);
- node.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false);
-
- },
-
- _delegateEvent: function(event) {
- if(this.eventHandlerCallback) {
- this.eventHandlerCallback(event, this);
- }
- },
-
- toString: function() { return "UIObject " + this.id }
- };
- ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * Top Level uiobject.
- * @class ORYX.Core.AbstractShape
- * @extends ORYX.Core.UIObject
- */
- ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(
- /** @lends ORYX.Core.AbstractShape.prototype */
- {
- /**
- * Constructor
- */
- construct: function(options, stencil) {
-
- arguments.callee.$.construct.apply(this, arguments);
-
- this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM
-
- // stencil reference
- this._stencil = stencil;
- // if the stencil defines a super stencil that should be used for its instances, set it.
- if (this._stencil._jsonStencil.superId){
- stencilId = this._stencil.id()
- superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId;
- stencilSet = this._stencil.stencilSet();
- this._stencil = stencilSet.stencil(superStencilId);
- }
-
- //Hash map for all properties. Only stores the values of the properties.
- this.properties = new Hash();
- this.propertiesChanged = new Hash();
- // List of properties which are not included in the stencilset,
- // but which gets (de)serialized
- this.hiddenProperties = new Hash();
-
-
- //Initialization of property map and initial value.
- this._stencil.properties().each((function(property) {
- var key = property.prefix() + "-" + property.id();
- this.properties[key] = property.value();
- this.propertiesChanged[key] = true;
- }).bind(this));
-
- // if super stencil was defined, also regard stencil's properties:
- if (stencil._jsonStencil.superId) {
- stencil.properties().each((function(property) {
- var key = property.prefix() + "-" + property.id();
- var value = property.value();
- var oldValue = this.properties[key];
- this.properties[key] = value;
- this.propertiesChanged[key] = true;
- // Raise an event, to show that the property has changed
- // required for plugins like processLink.js
- //window.setTimeout( function(){
- this._delegateEvent({
- type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
- name : key,
- value : value,
- oldValue: oldValue
- });
- //}.bind(this), 10)
- }).bind(this));
- }
- },
- layout: function() {
- },
-
- /**
- * Returns the stencil object specifiing the type of the shape.
- */
- getStencil: function() {
- return this._stencil;
- },
-
- /**
- *
- * @param {Object} resourceId
- */
- getChildShapeByResourceId: function(resourceId) {
- resourceId = ERDF.__stripHashes(resourceId);
-
- return this.getChildShapes(true).find(function(shape) {
- return shape.resourceId == resourceId
- });
- },
- /**
- *
- * @param {Object} deep
- * @param {Object} iterator
- */
- getChildShapes: function(deep, iterator) {
- var result = [];
- this.children.each(function(uiObject) {
- if(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {
- if(iterator) {
- iterator(uiObject);
- }
- result.push(uiObject);
- if(deep) {
- result = result.concat(uiObject.getChildShapes(deep, iterator));
- }
- }
- });
- return result;
- },
-
- /**
- * @param {Object} shape
- * @return {boolean} true if any of shape's childs is given shape
- */
- hasChildShape: function(shape){
- return this.getChildShapes().any(function(child){
- return (child === shape) || child.hasChildShape(shape);
- });
- },
-
- /**
- *
- * @param {Object} deep
- * @param {Object} iterator
- */
- getChildNodes: function(deep, iterator) {
- var result = [];
- this.children.each(function(uiObject) {
- if(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {
- if(iterator) {
- iterator(uiObject);
- }
- result.push(uiObject);
- }
- if(uiObject instanceof ORYX.Core.Shape) {
- if(deep) {
- result = result.concat(uiObject.getChildNodes(deep, iterator));
- }
- }
- });
- return result;
- },
-
- /**
- *
- * @param {Object} deep
- * @param {Object} iterator
- */
- getChildEdges: function(deep, iterator) {
- var result = [];
- this.children.each(function(uiObject) {
- if(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {
- if(iterator) {
- iterator(uiObject);
- }
- result.push(uiObject);
- }
- if(uiObject instanceof ORYX.Core.Shape) {
- if(deep) {
- result = result.concat(uiObject.getChildEdges(deep, iterator));
- }
- }
- });
- return result;
- },
-
- /**
- * Returns a sorted array of ORYX.Core.Node objects.
- * Ordered in z Order, the last object has the highest z Order.
- */
- //TODO deep iterator
- getAbstractShapesAtPosition: function() {
- var x, y;
- switch (arguments.length) {
- case 1:
- x = arguments[0].x;
- y = arguments[0].y;
- break;
- case 2: //two or more arguments
- x = arguments[0];
- y = arguments[1];
- break;
- default:
- throw "getAbstractShapesAtPosition needs 1 or 2 arguments!"
- }
- if(this.isPointIncluded(x, y)) {
- var result = [];
- result.push(this);
- //check, if one child is at that position
-
-
- var childNodes = this.getChildNodes();
- var childEdges = this.getChildEdges();
-
- [childNodes, childEdges].each(function(ne){
- var nodesAtPosition = new Hash();
-
- ne.each(function(node) {
- if(!node.isVisible){ return }
- var candidates = node.getAbstractShapesAtPosition( x , y );
- if(candidates.length > 0) {
- var nodesInZOrder = $A(node.node.parentNode.childNodes);
- var zOrderIndex = nodesInZOrder.indexOf(node.node);
- nodesAtPosition[zOrderIndex] = candidates;
- }
- });
-
- nodesAtPosition.keys().sort().each(function(key) {
- result = result.concat(nodesAtPosition[key]);
- });
- });
-
- return result;
-
- } else {
- return [];
- }
- },
-
- /**
- *
- * @param key {String} Must be 'prefix-id' of property
- * @param value {Object} Can be of type String or Number according to property type.
- */
- setProperty: function(key, value, force) {
- var oldValue = this.properties[key];
- if(oldValue !== value || force === true) {
- this.properties[key] = value;
- this.propertiesChanged[key] = true;
- this._changed();
-
- // Raise an event, to show that the property has changed
- //window.setTimeout( function(){
- if (!this._isInSetProperty) {
- this._isInSetProperty = true;
-
- this._delegateEvent({
- type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
- elements : [this],
- name : key,
- value : value,
- oldValue: oldValue
- });
-
- delete this._isInSetProperty;
- }
- //}.bind(this), 10)
- }
- },
-
- /**
- * Returns TRUE if one of the properties is flagged as dirty
- * @return {boolean}
- */
- isPropertyChanged: function(){
- return this.propertiesChanged.any(function(property){ return property.value });
- },
- /**
- *
- * @param {String} Must be 'prefix-id' of property
- * @param {Object} Can be of type String or Number according to property type.
- */
- setHiddenProperty: function(key, value) {
- // IF undefined, Delete
- if (value === undefined) {
- delete this.hiddenProperties[key];
- return;
- }
- var oldValue = this.hiddenProperties[key];
- if (oldValue !== value) {
- this.hiddenProperties[key] = value;
- }
- },
- /**
- * Calculate if the point is inside the Shape
- * @param {Point}
- */
- isPointIncluded: function(pointX, pointY, absoluteBounds) {
- var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();
- return absBounds.isIncluded(pointX, pointY);
-
- },
-
- /**
- * Get the serialized object
- * return Array with hash-entrees (prefix, name, value)
- * Following values will given:
- * Type
- * Properties
- */
- serialize: function() {
- var serializedObject = [];
-
- // Add the type
- serializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});
-
- // Add hidden properties
- this.hiddenProperties.each(function(prop){
- serializedObject.push({name: prop.key.replace("oryx-", ""), prefix: "oryx", value: prop.value, type: 'literal'});
- }.bind(this));
-
- // Add all properties
- this.getStencil().properties().each((function(property){
-
- var prefix = property.prefix(); // Get prefix
- var name = property.id(); // Get name
-
- //if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "")
- serializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});
- }).bind(this));
-
- return serializedObject;
- },
-
-
- deserialize: function(serialize){
- // Search in Serialize
- var initializedDocker = 0;
-
- // Sort properties so that the hidden properties are first in the list
- 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));
-
- serialize.each((function(obj){
-
- var name = obj.name;
- var prefix = obj.prefix;
- var value = obj.value;
-
- // Complex properties can be real json objects, encode them to a string
- if(Ext.type(value) === "object") value = Ext.encode(value);
- switch(prefix + "-" + name){
- case 'raziel-parent':
- // Set parent
- if(!this.parent) {break};
-
- // Set outgoing Shape
- var parent = this.getCanvas().getChildShapeByResourceId(value);
- if(parent) {
- parent.add(this);
- }
-
- break;
- default:
- // If list, eval as an array
- var prop = this.getStencil().property(prefix+"-"+name);
- if (prop && prop.isList() && typeof value === "string"){
- if ((value||"").strip()&&!value.startsWith("[")&&!value.startsWith("]"))
- value = "[\""+value.strip()+"\"]";
- value = ((value||"").strip()||"[]").evalJSON();
- }
-
- // Set property
- if(this.properties.keys().member(prefix+"-"+name)) {
- this.setProperty(prefix+"-"+name, value);
- } else if(!(name === "bounds"||name === "parent"||name === "target"||name === "dockers"||name === "docker"||name === "outgoing"||name === "incoming")) {
- this.setHiddenProperty(prefix+"-"+name, value);
- }
-
- }
- }).bind(this));
- },
-
- toString: function() { return "ORYX.Core.AbstractShape " + this.id },
-
- /**
- * Converts the shape to a JSON representation.
- * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.
- */
- toJSON: function(){
- var json = {
- resourceId: this.resourceId,
- properties: Ext.apply({}, this.properties, this.hiddenProperties).inject({}, function(props, prop){
- var key = prop[0];
- var value = prop[1];
-
- //If complex property, value should be a json object
- if ( this.getStencil().property(key)
- && this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX
- && Ext.type(value) === "string"){
-
- try {value = Ext.decode(value);} catch(error){}
-
- // Parse date
- } else if (value instanceof Date&&this.getStencil().property(key)){
- try {
- value = value.format(this.getStencil().property(key).dateFormat());
- } catch(e){}
- }
-
- //Takes "my_property" instead of "oryx-my_property" as key
- key = key.replace(/^[\w_]+-/, "");
- props[key] = value;
-
- return props;
- }.bind(this)),
- stencil: {
- id: this.getStencil().idWithoutNs()
- },
- childShapes: this.getChildShapes().map(function(shape){
- return shape.toJSON()
- })
- };
-
- if(this.getOutgoingShapes){
- json.outgoing = this.getOutgoingShapes().map(function(shape){
- return {
- resourceId: shape.resourceId
- };
- });
- }
-
- if(this.bounds){
- json.bounds = {
- lowerRight: this.bounds.lowerRight(),
- upperLeft: this.bounds.upperLeft()
- };
- }
-
- if(this.dockers){
- json.dockers = this.dockers.map(function(docker){
- var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
- d.getDocker = function(){return docker;};
- return d;
- })
- }
-
- Ext.apply(json, ORYX.Core.AbstractShape.JSONHelper);
-
- // do not pollute the json attributes (for serialization), so put the corresponding
- // shape is encapsulated in a method
- json.getShape = function(){
- return this;
- }.bind(this);
-
- return json;
- }
- });
-
- /**
- * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).
- * @example
- * Ext.apply(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);
- */
- ORYX.Core.AbstractShape.JSONHelper = {
- /**
- * Iterates over each child shape.
- * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.
- * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)
- * @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.
- * @example
- * // Increases the lowerRight x value of each direct child shape by one.
- * myShapeAsJson.eachChild(function(shape, parentShape){
- * shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;
- * return shape;
- * }, false, true);
- */
- eachChild: function(iterator, deep, modify){
- if(!this.childShapes) return;
-
- var newChildShapes = []; //needed if modify = true
-
- this.childShapes.each(function(shape){
- if (!(shape.eachChild instanceof Function)){
- Ext.apply(shape, ORYX.Core.AbstractShape.JSONHelper);
- }
- var res = iterator(shape, this);
- if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.
-
- if(deep) shape.eachChild(iterator, deep, modify);
- }.bind(this));
-
- if(modify) this.childShapes = newChildShapes;
- },
-
- getShape: function(){
- return null;
- },
- getChildShapes: function(deep){
- var allShapes = this.childShapes;
-
- if(deep){
- this.eachChild(function(shape){
- if (!(shape.getChildShapes instanceof Function)){
- Ext.apply(shape, ORYX.Core.AbstractShape.JSONHelper);
- }
- allShapes = allShapes.concat(shape.getChildShapes(deep));
- }, true);
- }
-
- return allShapes;
- },
-
- /**
- * @return {String} Serialized JSON object
- */
- serialize: function(){
- return Ext.encode(this);
- }
- }
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- /**
- @namespace Namespace for the Oryx core elements.
- @name ORYX.Core
- */
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * @class Oryx canvas.
- * @extends ORYX.Core.AbstractShape
- *
- */
- ORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({
- /** @lends ORYX.Core.Canvas.prototype */
- /**
- * Defines the current zoom level
- */
- zoomLevel:1,
- /**
- * Constructor
- */
- construct: function(options) {
- arguments.callee.$.construct.apply(this, arguments);
- if(!(options && options.width && options.height)) {
-
- ORYX.Log.fatal("Canvas is missing mandatory parameters options.width and options.height.");
- return;
- }
-
- //TODO: set document resource id
- this.resourceId = options.id;
- this.nodes = [];
-
- this.edges = [];
-
- //init svg document
- this.rootNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", options.parentNode,
- ['svg', {id: this.id, width: options.width, height: options.height},
- ['defs', {}]
- ]);
-
- this.rootNode.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
- this.rootNode.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg");
- this._htmlContainer = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", options.parentNode,
- ['div', {id: "oryx_canvas_htmlContainer", style:"position:absolute; top:5px"}]);
-
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.rootNode,
- ['g', {},
- ['g', {"class": "stencils"},
- ['g', {"class": "me"}],
- ['g', {"class": "children"}],
- ['g', {"class": "edge"}]
- ],
- ['g', {"class":"svgcontainer"}]
- ]);
-
- /*
- var off = 2 * ORYX.CONFIG.GRID_DISTANCE;
- var size = 3;
- var d = "";
- for(var i = 0; i <= options.width; i += off)
- for(var j = 0; j <= options.height; j += off)
- d = d + "M" + (i - size) + " " + j + " l" + (2*size) + " 0 m" + (-size) + " " + (-size) + " l0 " + (2*size) + " m0" + (-size) + " ";
-
- ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node.firstChild.firstChild,
- ['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]);
- */
-
- //Global definition of default font for shapes
- //Definitions in the SVG definition of a stencil will overwrite these settings for
- // that stencil.
- /*if(navigator.platform.indexOf("Mac") > -1) {
- this.node.setAttributeNS(null, 'stroke', 'black');
- this.node.setAttributeNS(null, 'stroke-width', '0.5px');
- this.node.setAttributeNS(null, 'font-family', 'Skia');
- //this.node.setAttributeNS(null, 'letter-spacing', '2px');
- this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
- } else {
- this.node.setAttributeNS(null, 'stroke', 'none');
- this.node.setAttributeNS(null, 'font-family', 'Verdana');
- this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
- }*/
-
- this.node.setAttributeNS(null, 'stroke', 'black');
- this.node.setAttributeNS(null, 'font-family', 'Verdana, sans-serif');
- this.node.setAttributeNS(null, 'font-size-adjust', 'none');
- this.node.setAttributeNS(null, 'font-style', 'normal');
- this.node.setAttributeNS(null, 'font-variant', 'normal');
- this.node.setAttributeNS(null, 'font-weight', 'normal');
- this.node.setAttributeNS(null, 'line-heigth', 'normal');
-
- this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT);
-
- this.bounds.set(0,0,options.width, options.height);
-
- this.addEventHandlers(this.rootNode.parentNode);
-
- //disable context menu
- this.rootNode.oncontextmenu = function() {return false;};
- },
-
- getScrollNode: function(){
- return Ext.get(this.rootNode).parent("div{overflow=auto}", true);
- },
-
- focus: function(){
-
- try {
- // Get a href
- if (!this.focusEl) {
- this.focusEl = Ext.getBody().createChild({
- tag: "a",
- href: "#",
- cls: "x-grid3-focus x-grid3-focus-canvas",
- tabIndex: "-1"
- });
- this.focusEl.swallowEvent("click", true);
- }
-
- // Focus it
- if (Ext.isGecko) {
- this.focusEl.focus();
- }
- else {
- this.focusEl.focus.defer(1, this.focusEl);
- }
- this.focusEl.blur.defer(3, this.focusEl);
-
- } catch(e){}
- },
-
- update: function() {
-
- this.nodes.each(function(node) {
- this._traverseForUpdate(node);
- }.bind(this));
-
- // call stencil's layout callback
- // (needed for row layouting of xforms)
- //this.getStencil().layout(this);
-
- var layoutEvents = this.getStencil().layout();
-
- if(layoutEvents) {
- layoutEvents.each(function(event) {
-
- // setup additional attributes
- event.shape = this;
- event.forceExecution = true;
- event.target = this.rootNode;
-
- // do layouting
-
- this._delegateEvent(event);
- }.bind(this))
- }
-
- this.nodes.invoke("_update");
-
- this.edges.invoke("_update", true);
-
- /*this.children.each(function(child) {
- child._update();
- });*/
- },
-
- _traverseForUpdate: function(shape) {
- var childRet = shape.isChanged;
- shape.getChildNodes(false, function(child) {
- if(this._traverseForUpdate(child)) {
- childRet = true;
- }
- }.bind(this));
-
- if(childRet) {
- shape.layout();
- return true;
- } else {
- return false;
- }
- },
-
- layout: function() {
-
-
-
- },
-
- /**
- *
- * @param {Object} deep
- * @param {Object} iterator
- */
- getChildNodes: function(deep, iterator) {
- if(!deep && !iterator) {
- return this.nodes.clone();
- } else {
- var result = [];
- this.nodes.each(function(uiObject) {
- if(iterator) {
- iterator(uiObject);
- }
- result.push(uiObject);
-
- if(deep && uiObject instanceof ORYX.Core.Shape) {
- result = result.concat(uiObject.getChildNodes(deep, iterator));
- }
- });
-
- return result;
- }
- },
-
- /**
- * buggy crap! use base class impl instead!
- * @param {Object} iterator
- */
- /* getChildEdges: function(iterator) {
- if(iterator) {
- this.edges.each(function(edge) {
- iterator(edge);
- });
- }
-
- return this.edges.clone();
- },
- */
- /**
- * Overrides the UIObject.add method. Adds uiObject to the correct sub node.
- * @param {UIObject} uiObject
- */
- add: function(uiObject, index, silent) {
- //if uiObject is child of another UIObject, remove it.
- if(uiObject instanceof ORYX.Core.UIObject) {
- if (!(this.children.member(uiObject))) {
- //if uiObject is child of another parent, remove it from that parent.
- if(uiObject.parent) {
- uiObject.parent.remove(uiObject, true);
- }
- //add uiObject to the Canvas
- //add uiObject to this Shape
- if(index != undefined)
- this.children.splice(index, 0, uiObject);
- else
- this.children.push(uiObject);
- //set parent reference
- uiObject.parent = this;
- //add uiObject.node to this.node depending on the type of uiObject
- if(uiObject instanceof ORYX.Core.Shape) {
- if(uiObject instanceof ORYX.Core.Edge) {
- uiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, "defs")[0]);
- uiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node);
- this.edges.push(uiObject);
- } else {
- uiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node);
- this.nodes.push(uiObject);
- }
- } else { //UIObject
- uiObject.node = this.node.appendChild(uiObject.node);
- }
- uiObject.bounds.registerCallback(this._changedCallback);
-
- if(this.eventHandlerCallback && silent !== true)
- this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})
- } else {
-
- ORYX.Log.warn("add: ORYX.Core.UIObject is already a child of this object.");
- }
- } else {
- ORYX.Log.fatal("add: Parameter is not of type ORYX.Core.UIObject.");
- }
- },
- /**
- * Overrides the UIObject.remove method. Removes uiObject.
- * @param {UIObject} uiObject
- */
- remove: function(uiObject, silent) {
- //if uiObject is a child of this object, remove it.
- if (this.children.member(uiObject)) {
- //remove uiObject from children
- var parent = uiObject.parent;
-
- this.children = this.children.without(uiObject);
- //delete parent reference of uiObject
- uiObject.parent = undefined;
- //delete uiObject.node from this.node
- if(uiObject instanceof ORYX.Core.Shape) {
- if(uiObject instanceof ORYX.Core.Edge) {
- uiObject.removeMarkers();
- uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);
- this.edges = this.edges.without(uiObject);
- } else {
- uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);
- this.nodes = this.nodes.without(uiObject);
- }
- } else { //UIObject
- uiObject.node = this.node.removeChild(uiObject.node);
- }
- if(this.eventHandlerCallback && silent !== true)
- this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:uiObject, parent:parent});
-
- uiObject.bounds.unregisterCallback(this._changedCallback);
- } else {
- ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object.");
- }
- },
-
- /**
- * Creates shapes out of the given collection of shape objects and adds them to the canvas.
- * @example
- * canvas.addShapeObjects({
- bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },
- resourceId:"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD",
- childShapes:[],
- properties:{},
- stencil:{
- id:"Subprocess"
- },
- outgoing:[{resourceId: 'aShape'}],
- target: {resourceId: 'aShape'}
- });
- * @param {Object} shapeObjects
- * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback)
- * @return {Array} A collection of ORYX.Core.Shape
- * @methodOf ORYX.Core.Canvas.prototype
- */
- addShapeObjects: function(shapeObjects, eventHandler){
- if(!shapeObjects) return;
-
- this.initializingShapes = true;
-
- /*FIXME This implementation is very evil! At first, all shapes are created on
- canvas. In a second step, the attributes are applied. There must be a distinction
- between the configuration phase (where the outgoings, for example, are just named),
- and the creation phase (where the outgoings are evaluated). This must be reflected
- in code to provide a nicer API/ implementation!!! */
-
- var addShape = function(shape, parent){
- // Create a new Stencil
- var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id );
- // Create a new Shape
- var ShapeClass = (stencil.type() == "node") ? ORYX.Core.Node : ORYX.Core.Edge;
- var newShape = new ShapeClass(
- {'eventHandlerCallback': eventHandler},
- stencil);
-
- // Set the resource id
- newShape.resourceId = shape.resourceId;
- newShape.node.id = "svg-" + shape.resourceId;
-
- // Set parent to json object to be used later
- // Due to the nested json structure, normally shape.parent is not set/ must not be set.
- // In special cases, it can be easier to set this directly instead of a nested structure.
- shape.parent = "#" + ((shape.parent && shape.parent.resourceId) || parent.resourceId);
-
- // Add the shape to the canvas
- this.add( newShape );
- return {
- json: shape,
- object: newShape
- };
- }.bind(this);
-
- /** Builds up recursively a flatted array of shapes, including a javascript object and json representation
- * @param {Object} shape Any object that has Object#childShapes
- */
- var addChildShapesRecursively = function(shape){
- var addedShapes = [];
-
- shape.childShapes.each(function(childShape){
- addedShapes.push(addShape(childShape, shape));
- addedShapes = addedShapes.concat(addChildShapesRecursively(childShape));
- });
-
- return addedShapes;
- }.bind(this);
- var shapes = addChildShapesRecursively({
- childShapes: shapeObjects,
- resourceId: this.resourceId
- });
-
- // prepare deserialisation parameter
- shapes.each(
- function(shape){
- var properties = [];
- for(field in shape.json.properties){
- properties.push({
- prefix: 'oryx',
- name: field,
- value: shape.json.properties[field]
- });
- }
-
- // Outgoings
- shape.json.outgoing.each(function(out){
- properties.push({
- prefix: 'raziel',
- name: 'outgoing',
- value: "#"+out.resourceId
- });
- });
-
- // Target
- // (because of a bug, the first outgoing is taken when there is no target,
- // can be removed after some time)
- if(shape.object instanceof ORYX.Core.Edge) {
- var target = shape.json.target || shape.json.outgoing[0];
- if(target){
- properties.push({
- prefix: 'raziel',
- name: 'target',
- value: "#"+target.resourceId
- });
- }
- }
-
- // Bounds
- if (shape.json.bounds) {
- properties.push({
- prefix: 'oryx',
- name: 'bounds',
- value: shape.json.bounds.upperLeft.x + "," + shape.json.bounds.upperLeft.y + "," + shape.json.bounds.lowerRight.x + "," + shape.json.bounds.lowerRight.y
- });
- }
-
- //Dockers [{x:40, y:50}, {x:30, y:60}] => "40 50 30 60 #"
- if(shape.json.dockers){
- properties.push({
- prefix: 'oryx',
- name: 'dockers',
- value: shape.json.dockers.inject("", function(dockersStr, docker){
- return dockersStr + docker.x + " " + docker.y + " ";
- }) + " #"
- });
- }
-
- //Parent
- properties.push({
- prefix: 'raziel',
- name: 'parent',
- value: shape.json.parent
- });
-
- shape.__properties = properties;
- }.bind(this)
- );
-
- // Deserialize the properties from the shapes
- // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there
-
- // first, deserialize all nodes
- shapes.each(function(shape) {
- if(shape.object instanceof ORYX.Core.Node) {
- shape.object.deserialize(shape.__properties, shape.json);
- }
- });
-
- // second, deserialize all edges
- shapes.each(function(shape) {
- if(shape.object instanceof ORYX.Core.Edge) {
- shape.object.deserialize(shape.__properties, shape.json);
- shape.object._oldBounds = shape.object.bounds.clone();
- shape.object._update();
- }
- });
-
- delete this.initializingShapes;
- return shapes.pluck("object");
- },
-
- /**
- * Updates the size of the canvas, regarding to the containg shapes.
- */
- updateSize: function(){
- // Check the size for the canvas
- var maxWidth = 0;
- var maxHeight = 0;
- var offset = 100;
- this.getChildShapes(true, function(shape){
- var b = shape.bounds;
- maxWidth = Math.max( maxWidth, b.lowerRight().x + offset)
- maxHeight = Math.max( maxHeight, b.lowerRight().y + offset)
- });
-
- if( this.bounds.width() < maxWidth || this.bounds.height() < maxHeight ){
- this.setSize({width: Math.max(this.bounds.width(), maxWidth), height: Math.max(this.bounds.height(), maxHeight)})
- }
- },
- getRootNode: function() {
- return this.rootNode;
- },
-
- getSvgContainer: function() {
- return this.node.childNodes[1];
- },
-
- getHTMLContainer: function() {
- return this._htmlContainer;
- },
- /**
- * Return all elements of the same highest level
- * @param {Object} elements
- */
- getShapesWithSharedParent: function(elements) {
- // If there is no elements, return []
- if(!elements || elements.length < 1) { return [] }
- // If there is one element, return this element
- if(elements.length == 1) { return elements}
- return elements.findAll(function(value){
- var parentShape = value.parent;
- while(parentShape){
- if(elements.member(parentShape)) return false;
- parentShape = parentShape.parent
- }
- return true;
- });
- },
- setSize: function(size, dontSetBounds) {
- if(!size || !size.width || !size.height){return}
-
- if(this.rootNode.parentNode){
- this.rootNode.parentNode.style.width = size.width + 'px';
- this.rootNode.parentNode.style.height = size.height + 'px';
- }
-
- this.rootNode.setAttributeNS(null, 'width', size.width);
- this.rootNode.setAttributeNS(null, 'height', size.height);
- //this._htmlContainer.style.top = "-" + (size.height + 4) + 'px';
- if( !dontSetBounds ){
- this.bounds.set({a:{x:0,y:0},b:{x:size.width/this.zoomLevel,y:size.height/this.zoomLevel}})
- }
- },
-
- /**
- * Returns an SVG document of the current process.
- * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser,
- * false, if you want to use the SVG document in browser on client side.
- */
- getSVGRepresentation: function(escapeText) {
- // Get the serialized svg image source
- var svgClone = this.getRootNode().cloneNode(true);
-
- this._removeInvisibleElements(svgClone);
-
- var x1, y1, x2, y2;
- try {
- var bb = this.getRootNode().childNodes[1].getBBox();
- x1 = bb.x;
- y1 = bb.y;
- x2 = bb.x + bb.width;
- y2 = bb.y + bb.height;
- } catch(e) {
- this.getChildShapes(true).each(function(shape) {
- var absBounds = shape.absoluteBounds();
- var ul = absBounds.upperLeft();
- var lr = absBounds.lowerRight();
- if(x1 == undefined) {
- x1 = ul.x;
- y1 = ul.y;
- x2 = lr.x;
- y2 = lr.y;
- } else {
- x1 = Math.min(x1, ul.x);
- y1 = Math.min(y1, ul.y);
- x2 = Math.max(x2, lr.x);
- y2 = Math.max(y2, lr.y);
- }
- });
- }
-
- var margin = 50;
-
- var width, height, tx, ty;
- if(x1 == undefined) {
- width = 0;
- height = 0;
- tx = 0;
- ty = 0;
- } else {
- width = x2 - x1;
- height = y2 - y1;
- tx = -x1+margin/2;
- ty = -y1+margin/2;
- }
-
-
-
- // Set the width and height
- svgClone.setAttributeNS(null, 'width', width + margin);
- svgClone.setAttributeNS(null, 'height', height + margin);
-
- svgClone.childNodes[1].firstChild.setAttributeNS(null, 'transform', 'translate(' + tx + ", " + ty + ')');
-
- //remove scale factor
- svgClone.childNodes[1].removeAttributeNS(null, 'transform');
-
- try{
- var svgCont = svgClone.childNodes[1].childNodes[1];
- svgCont.parentNode.removeChild(svgCont);
- } catch(e) {}
- if(escapeText) {
- $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function(elem) {
- elem.textContent = elem.textContent.escapeHTML();
- });
-
- $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function(elem) {
- if(elem.childNodes.length == 0)
- elem.textContent = elem.textContent.escapeHTML();
- });
- }
-
- // generating absolute urls for the pdf-exporter
- $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function(elem) {
- var href = elem.getAttributeNS("http://www.w3.org/1999/xlink","href");
-
- if(!href.match("^(http|https)://")) {
- href = window.location.protocol + "//" + window.location.host + href;
- elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href);
- }
- });
-
-
- // escape all links
- $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function(elem) {
- elem.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", (elem.getAttributeNS("http://www.w3.org/1999/xlink","href")||"").escapeHTML());
- });
-
- return svgClone;
- },
-
- /**
- * Removes all nodes (and its children) that has the
- * attribute visibility set to "hidden"
- */
- _removeInvisibleElements: function(element) {
- var index = 0;
- while(index < element.childNodes.length) {
- var child = element.childNodes[index];
- if(child.getAttributeNS &&
- child.getAttributeNS(null, "visibility") === "hidden") {
- element.removeChild(child);
- } else {
- this._removeInvisibleElements(child);
- index++;
- }
- }
-
- },
-
- /**
- * This method checks all shapes on the canvas and removes all shapes that
- * contain invalid bounds values or dockers values(NaN)
- */
- /*cleanUp: function(parent) {
- if (!parent) {
- parent = this;
- }
- parent.getChildShapes().each(function(shape){
- var a = shape.bounds.a;
- var b = shape.bounds.b;
- if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
- parent.remove(shape);
- }
- else {
- shape.getDockers().any(function(docker) {
- a = docker.bounds.a;
- b = docker.bounds.b;
- if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
- parent.remove(shape);
- return true;
- }
- return false;
- });
- shape.getMagnets().any(function(magnet) {
- a = magnet.bounds.a;
- b = magnet.bounds.b;
- if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) {
- parent.remove(shape);
- return true;
- }
- return false;
- });
- this.cleanUp(shape);
- }
- }.bind(this));
- },*/
- _delegateEvent: function(event) {
- if(this.eventHandlerCallback && ( event.target == this.rootNode || event.target == this.rootNode.parentNode )) {
- this.eventHandlerCallback(event, this);
- }
- },
-
- toString: function() { return "Canvas " + this.id },
-
- /**
- * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information.
- */
- toJSON: function() {
- var json = arguments.callee.$.toJSON.apply(this, arguments);
-
- // if(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) {
- // json.stencilset = {
- // url: this.getStencil().stencilSet().namespace()
- // };
- // } else {
- json.stencilset = {
- url: this.getStencil().stencilSet().source(),
- namespace: this.getStencil().stencilSet().namespace()
- };
- // }
-
-
- return json;
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- var idCounter = 0;
- var ID_PREFIX = "resource";
- /**
- * Main initialization method. To be called when loading
- * of the document, including all scripts, is completed.
- */
- function init() {
- /* When the blank image url is not set programatically to a local
- * representation, a spacer gif on the site of ext is loaded from the
- * internet. This causes problems when internet or the ext site are not
- * available. */
- Ext.BLANK_IMAGE_URL = (ORYX.CONFIG.BLANK_IMAGE) || (ORYX.PATH + 'libs/ext-2.0.2/resources/images/default/s.gif');
-
- ORYX.Log.debug("Querying editor instances");
- // Hack for WebKit to set the SVGElement-Classes
- ORYX.Editor.setMissingClasses();
-
- // If someone wants to create the editor instance himself
- if (window.onOryxResourcesLoaded) {
- window.onOryxResourcesLoaded();
- }
- // Else if this is a newly created model
- else if(window.location.pathname.include(ORYX.CONFIG.ORYX_NEW_URL)){
- new ORYX.Editor({
- id: 'oryx-canvas123',
- fullscreen: true,
- stencilset: {
- url: "/oryx" + ORYX.Utils.getParamFromUrl("stencilset")
- }
- });
- }
- // Else fetch the model from server and display editor
- else {
- //HACK for distinguishing between different backends
- // Backend of 2008 uses /self URL ending
- var modelUrl = window.location.href.replace(/#.*/g, "");
- if(modelUrl.endsWith("/self")) {
- modelUrl = modelUrl.replace("/self","/json");
- } else {
- var modelId = window.location.search.substring(4);
- modelUrl = "../service/model/" + modelId + "/json";
- }
- ORYX.Editor.createByUrl(modelUrl, {
- id: modelUrl
- });
- }
- }
- /**
- @namespace Global Oryx name space
- @name ORYX
- */
- if(!ORYX) {var ORYX = {};}
- /**
- * The Editor class.
- * @class ORYX.Editor
- * @extends Clazz
- * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized}
- * @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.
- * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not.
- * @param {String} config.stencilset.url Stencil set URL.
- * @param {String} [config.stencil.id] Stencil type used for creating the canvas.
- * @param {Object} config.properties Any properties applied to the canvas.
- */
- ORYX.Editor = {
- /** @lends ORYX.Editor.prototype */
- // Defines the global dom event listener
- DOMEventListeners: new Hash(),
- // Defines the selection
- selection: [],
-
- // Defines the current zoom level
- zoomLevel:1.0,
- construct: function(config) {
-
- // initialization.
- this._eventsQueue = [];
- this.loadedPlugins = [];
- this.pluginsData = [];
-
-
- //meta data about the model for the signavio warehouse
- //directory, new, name, description, revision, model (the model data)
-
- this.modelMetaData = config;
-
- var model = config;
- if(config.model) {
- model = config.model;
- }
-
- this.id = model.resourceId;
- if(!this.id) {
- this.id = model.id;
- if(!this.id) {
- this.id = ORYX.Editor.provideId();
- }
- }
-
-
- // Defines if the editor should be fullscreen or not
- this.fullscreen = config.fullscreen !== false;
-
- if (Signavio&&Signavio.Helper&&Signavio.Helper.ShowMask instanceof Function) {
- Signavio.Helper.ShowMask(true, !this.fullscreen ? this.id : Ext.getBody());
- }
-
- // Initialize the eventlistener
- this._initEventListener();
- // Load particular stencilset
- if(ORYX.CONFIG.BACKEND_SWITCH) {
- var ssUrl = (model.stencilset.namespace||model.stencilset.url).replace("#", "%23");
- ORYX.Core.StencilSet.loadStencilSet(ORYX.CONFIG.STENCILSET_HANDLER + ssUrl, this.id);
- } else {
- var ssUrl = model.stencilset.url;
- ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.id);
- }
- // CREATES the canvas
- this._createCanvas(model.stencil ? model.stencil.id : null, model.properties);
- // GENERATES the whole EXT.VIEWPORT
- this._generateGUI();
- // Initializing of a callback to check loading ends
- var loadPluginFinished = false;
- var loadContentFinished = false;
- var initFinished = function(){
- if( !loadPluginFinished || !loadContentFinished ){ return }
- this._finishedLoading();
- }.bind(this)
-
- // disable key events when Ext modal window is active
- ORYX.Editor.makeExtModalWindowKeysave(this._getPluginFacade());
-
- // LOAD the plugins
- window.setTimeout(function(){
- this.loadPlugins();
- loadPluginFinished = true;
- initFinished();
- }.bind(this), 100);
- // LOAD the content of the current editor instance
- window.setTimeout(function(){
- this.loadSerialized(model, true); // Request the meta data as well
- this.getCanvas().update();
- loadContentFinished = true;
- initFinished();
- }.bind(this), 200);
- },
-
- _finishedLoading: function() {
- if(Ext.getCmp('oryx-loading-panel')){
- Ext.getCmp('oryx-loading-panel').hide()
- }
-
- // Do Layout for viewport
- this.layout.doLayout();
- // Generate a drop target
- new Ext.dd.DropTarget(this.getCanvas().rootNode.parentNode);
-
- // Fixed the problem that the viewport can not
- // start with collapsed panels correctly
- if (ORYX.CONFIG.PANEL_RIGHT_COLLAPSED === true){
- this.layout_regions.east.collapse();
- }
- if (ORYX.CONFIG.PANEL_LEFT_COLLAPSED === true){
- this.layout_regions.west.collapse();
- }
-
- // Raise Loaded Event
- this.handleEvents( {type:ORYX.CONFIG.EVENT_LOADED} )
-
- },
-
- _initEventListener: function(){
- // Register on Events
-
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false);
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false);
- // Enable Key up and down Event
- this._keydownEnabled = true;
- this._keyupEnabled = true;
- this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = [];
- this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] = [];
- this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = [];
- this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] = [];
- this.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = [];
- this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = [];
-
- },
-
- /**
- * Generate the whole viewport of the
- * Editor and initialized the Ext-Framework
- *
- */
- _generateGUI: function() {
- //TODO make the height be read from eRDF data from the canvas.
- // default, a non-fullscreen editor shall define its height by layout.setHeight(int)
-
- // Defines the layout hight if it's NOT fullscreen
- var layoutHeight = ORYX.CONFIG.WINDOW_HEIGHT;
-
- var canvasParent = this.getCanvas().rootNode.parentNode;
- /**
- * Extend the Region implementation so that,
- * the clicking area can be extend to the whole collapse area and
- * an title can now be shown.
- *
- */
- var oldGetCollapsedEl = Ext.layout.BorderLayout.Region.prototype.getCollapsedEl;
- Ext.layout.BorderLayout.Region.prototype.getCollapsedEl = function(){
- oldGetCollapsedEl.apply(this, arguments);
-
- if(this.collapseMode !== 'mini' && this.floatable === false && this.expandTriggerAll === true){
- this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
- this.collapsedEl.on("mouseover", this.collapsedEl.addClass.bind(this.collapsedEl, "x-layout-collapsed-over"));
- this.collapsedEl.on("click", this.onExpandClick, this);
- }
-
-
- if (this.collapseTitle){
- /* // Use CSS3 Attribute
- this.collapsedEl.createChild({
- cls: "x-collapse-text", html: this.collapseTitle
- });*/
-
- // Use SVG to rotate text
- var svg = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.collapsedEl.dom,
- ['svg', {style:"position:relative;left:"+(this.position === "west" ? 4 : 6)+"px;top:"+(this.position === "west" ? 2 : 5)+"px;"},
- ['text', {transform:"rotate(90)", x:0, y:0, "stroke-width":"0px", fill:"#EEEEEE", style:"font-weight:bold;", "font-size":"11"}, this.collapseTitle]
- ]);
- var text = svg.childNodes[0];
- svg.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg");
-
- // Rotate the west into the other side
- if (this.position === "west" && text.getComputedTextLength instanceof Function){
- // Wait till rendered
- window.setTimeout(function(){
- var length = text.getComputedTextLength();
- text.setAttributeNS(null, "transform", "rotate(-90, " + ((length / 2) + 7) + ", " + ((length / 2) - 3) + ")");;
- }, 1)
- }
- delete this.collapseTitle;
- }
- return this.collapsedEl;
- }
- // DEFINITION OF THE VIEWPORT AREAS
- this.layout_regions = {
-
- // DEFINES TOP-AREA
- north : new Ext.Panel({ //TOOO make a composite of the oryx header and addable elements (for toolbar), second one should contain margins
- region : 'north',
- cls : 'x-panel-editor-north',
- autoEl : 'div',
- border : false
- }),
-
- // DEFINES RIGHT-AREA
- east : new Ext.Panel({
- region : 'east',
- layout : 'fit',
- cls : 'x-panel-editor-east',
- /*layout: 'accordion',
- layoutConfig: {
- // layout-specific configs go here
- titleCollapse: true,
- animate: true,
- activeOnTop: true
- },*/
- autoEl : 'div',
- collapseTitle : ORYX.I18N.View.East,
- border :false,
- cmargins: {left:0, right:0},
- floatable: false,
- expandTriggerAll:true,
- collapsible : true,
- width : ORYX.CONFIG.PANEL_RIGHT_WIDTH || 200,
- split : true,
- title : "East"
- }),
-
-
- // DEFINES BOTTOM-AREA
- south : new Ext.Panel({
- region : 'south',
- cls : 'x-panel-editor-south',
- autoEl : 'div',
- border : false
- }),
-
-
- // DEFINES LEFT-AREA
- west : new Ext.Panel({
- region : 'west',
- layout : 'anchor',
- autoEl : 'div',
- cls : 'x-panel-editor-west',
- collapsible : true,
- collapseTitle : ORYX.I18N.View.West,
- width : ORYX.CONFIG.PANEL_LEFT_WIDTH || 200,
- autoScroll:true,
- cmargins: {left:0, right:0},
- floatable: false,
- expandTriggerAll:true,
- split : true,
- title : "West"
- }),
-
-
- // DEFINES CENTER-AREA (FOR THE EDITOR)
- center : new Ext.Panel({
- region : 'center',
- cls : 'x-panel-editor-center',
- autoScroll: true,
- items : {
- layout : "fit",
- autoHeight: true,
- el : canvasParent
- }
- })
- }
-
- // Hide every region except the center
- for (region in this.layout_regions) {
- if ( region != "center" ) {
- //this.layout_regions[ region ].hide();
- }
- }
-
- // Config for the Ext.Viewport
- var layout_config = {
- layout: 'border',
- items: [
- this.layout_regions.north,
- this.layout_regions.east,
- this.layout_regions.south,
- this.layout_regions.west,
- this.layout_regions.center
- ]
- }
- // IF Fullscreen, use a viewport
- if (this.fullscreen) {
- this.layout = new Ext.Viewport( layout_config )
-
- // IF NOT, use a panel and render it to the given id
- } else {
- layout_config.renderTo = this.id;
- layout_config.height = layoutHeight;
- this.layout = new Ext.Panel( layout_config )
- }
-
- //Generates the ORYX-Header
- //this._generateHeader();
-
-
- // Set the editor to the center, and refresh the size
- canvasParent.parentNode.setAttributeNS(null, 'align', 'center');
- canvasParent.setAttributeNS(null, 'align', 'left');
- this.getCanvas().setSize({
- width : ORYX.CONFIG.CANVAS_WIDTH,
- height : ORYX.CONFIG.CANVAS_HEIGHT
- });
-
- },
-
- _generateHeader: function(){
-
- var headerPanel = new Ext.Panel({
- height : 30,
- autoHeight : false,
- border : false,
- html : "<div id='oryx_editor_header'><a href=\""+ORYX.CONFIG.WEB_URL+"\" target=\"_self\"><img src='"+ORYX.PATH+"images/oryx.small.gif' border=\"0\" /></a><div style='clear: both;'></div><div id='close_editor'></div></div>"
- });
- var maActive = ORYX.MashupAPI && ORYX.MashupAPI.isUsed;
- var maKey = maActive ? ORYX.MashupAPI.key : "";
- var maCanRun = maActive ? ORYX.MashupAPI.canRun : false;
- var maIsRemoteM = maActive ? ORYX.MashupAPI.isModelRemote : true;
-
- var maModelImage= maIsRemoteM ? "<img src='"+ORYX.PATH+"images/page_white_put.png'/>" : "";
- var maModelAuthI= maActive ? "<span class='mashupinfo'><img src='"+ORYX.PATH+"images/" +( maCanRun ? "plugin_error" : "plugin") +".png'/>" + maModelImage + "</span>" : "";
-
-
- // Callback if the user changes
- var fn = function(val){
-
- var publicText = ORYX.I18N.Oryx.notLoggedOn;
- var user = val && val.identifier && val.identifier != "public" ? decodeURI(val.identifier.gsub('"', "")).replace(/\+/g," ") : "";
-
- if( user.length <= 0 ){
- user = publicText;
- }
-
- var content = "<div id='editor_header'>" +
- "<div id='header_logo_image'>" +
- "<img src='../explorer/src/img/signavio/smoky/logo2.png' border=\"0\" usemap=\"#kisbpmmap\"/>" +
- "<map id=\"kisbpmmap\" name=\"kisbpmmap\"><area shape=\"rect\" alt=\"kisbpm.com\" title=\"kisbpm.com\" coords=\"15,2,322,44\" href=\"http://kisbpm.com\" target=\"_blank\" /></map>" +
- "</div>" +
- "<span class='openid " + (publicText == user ? "not" : "") + "'>" +
- (unescape(user)) +
- maModelAuthI +
- "</span>" +
- // "<div id='header_close_image'>" +
- // "<a href=\""+ORYX.CONFIG.WEB_URL+"\" target=\"_self\" title=\"close modeler\">" +
- // "<img src='../editor/images/close_button.png' border=\"0\" />" +
- // "</a>" +
- // "</div>" +
- "</div>";
-
- if( headerPanel.body ){
- headerPanel.body.dom.innerHTML = content;
- } else {
- headerPanel.html = content
- }
- };
-
- ORYX.Editor.Cookie.onChange(fn);
- fn(ORYX.Editor.Cookie.getParams());
-
- // The oryx header
- this.addToRegion("north", headerPanel );
- },
-
- /**
- * adds a component to the specified region
- *
- * @param {String} region
- * @param {Ext.Component} component
- * @param {String} title, optional
- * @return {Ext.Component} dom reference to the current region or null if specified region is unknown
- */
- addToRegion: function(region, component, title) {
-
- if (region.toLowerCase && this.layout_regions[region.toLowerCase()]) {
- var current_region = this.layout_regions[region.toLowerCase()];
- current_region.add(component);
- /*if( (region.toLowerCase() == 'east' || region.toLowerCase() == 'west') && current_region.items.length == 2){ //!current_region.getLayout() instanceof Ext.layout.Accordion ){
- var layout = new Ext.layout.Accordion( current_region.layoutConfig );
- current_region.setLayout( layout );
-
- var items = current_region.items.clone();
-
- current_region.items.each(function(item){ current_region.remove( item )})
- items.each(function(item){ current_region.add( item )})
-
- } */
- ORYX.Log.debug("original dimensions of region %0: %1 x %2", current_region.region, current_region.width, current_region.height)
- // update dimensions of region if required.
- if (!current_region.width && component.initialConfig && component.initialConfig.width) {
- ORYX.Log.debug("resizing width of region %0: %1", current_region.region, component.initialConfig.width)
- current_region.setWidth(component.initialConfig.width)
- }
- if (component.initialConfig && component.initialConfig.height) {
- ORYX.Log.debug("resizing height of region %0: %1", current_region.region, component.initialConfig.height)
- var current_height = current_region.height || 0;
- current_region.height = component.initialConfig.height + current_height;
- current_region.setHeight(component.initialConfig.height + current_height)
- }
-
- // set title if provided as parameter.
- if (typeof title == "string") {
- current_region.setTitle(title);
- }
-
- // trigger doLayout() and show the pane
- current_region.ownerCt.doLayout();
- current_region.show();
- if(Ext.isMac)
- ORYX.Editor.resizeFix();
-
- return current_region;
- }
-
- return null;
- },
- getAvailablePlugins: function(){
- var curAvailablePlugins=ORYX.availablePlugins.clone();
- curAvailablePlugins.each(function(plugin){
- if(this.loadedPlugins.find(function(loadedPlugin){
- return loadedPlugin.type==this.name;
- }.bind(plugin))){
- plugin.engaged=true;
- }else{
- plugin.engaged=false;
- }
- }.bind(this));
- return curAvailablePlugins;
- },
- loadScript: function (url, callback){
- var script = document.createElement("script")
- script.type = "text/javascript";
- if (script.readyState){ //IE
- script.onreadystatechange = function(){
- if (script.readyState == "loaded" || script.readyState == "complete"){
- script.onreadystatechange = null;
- callback();
- }
- };
- } else { //Others
- script.onload = function(){
- callback();
- };
- }
- script.src = url;
- document.getElementsByTagName("head")[0].appendChild(script);
- },
- /**
- * activate Plugin
- *
- * @param {String} name
- * @param {Function} callback
- * callback(sucess, [errorCode])
- * errorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED
- */
- activatePluginByName: function(name, callback, loadTry){
- var match=this.getAvailablePlugins().find(function(value){return value.name==name});
- if(match && (!match.engaged || (match.engaged==='false'))){
- var loadedStencilSetsNamespaces = this.getStencilSets().keys();
- var facade = this._getPluginFacade();
- var newPlugin;
- var me=this;
- ORYX.Log.debug("Initializing plugin '%0'", match.name);
-
- if (!match.requires || !match.requires.namespaces || match.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ){
- if(!match.notUsesIn || !match.notUsesIn.namespaces || !match.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 })){
-
- try {
-
- var className = eval(match.name);
- var newPlugin = new className(facade, match);
- newPlugin.type = match.name;
-
- // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data
- if (newPlugin.registryChanged)
- newPlugin.registryChanged(me.pluginsData);
-
- // If there have an onSelection-Method it will pushed to the Editor Event-Handler
- if (newPlugin.onSelectionChanged)
- me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, newPlugin.onSelectionChanged.bind(newPlugin));
- this.loadedPlugins.push(newPlugin);
- this.loadedPlugins.each(function(loaded){
- if(loaded.registryChanged)
- loaded.registryChanged(this.pluginsData);
- }.bind(me));
- callback(true);
-
- } catch(e) {
- ORYX.Log.warn("Plugin %0 is not available", match.name);
- if(!!loadTry){
- callback(false,"INITFAILED");
- return;
- }
- this.loadScript("plugins/scripts/"+match.source, this.activatePluginByName.bind(this,match.name,callback,true));
- }
- }else{
- callback(false,"NOTUSEINSTENCILSET");
- ORYX.Log.info("Plugin need a stencilset which is not loaded'", match.name);
- }
-
- } else {
- callback(false,"REQUIRESTENCILSET");
- ORYX.Log.info("Plugin need a stencilset which is not loaded'", match.name);
- }
-
- }else{
- callback(false, match?"NOTFOUND":"YETACTIVATED");
- //TODO error handling
- }
- },
- /**
- * Laden der Plugins
- */
- loadPlugins: function() {
-
- // if there should be plugins but still are none, try again.
- // TODO this should wait for every plugin respectively.
- /*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) {
- window.setTimeout(this.loadPlugins.bind(this), 100);
- return;
- }*/
-
- var me = this;
- var newPlugins = [];
- var loadedStencilSetsNamespaces = this.getStencilSets().keys();
- // Available Plugins will be initalize
- var facade = this._getPluginFacade();
-
- // If there is an Array where all plugins are described, than only take those
- // (that comes from the usage of oryx with a mashup api)
- if( ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array ){
-
- // Get the plugins from the available plugins (those who are in the plugins.xml)
- ORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function(value){
- return ORYX.MashupAPI.loadablePlugins.include( value.name )
- })
-
- // Add those plugins to the list, which are only in the loadablePlugins list
- ORYX.MashupAPI.loadablePlugins.each(function( className ){
- if( !(ORYX.availablePlugins.find(function(val){ return val.name == className }))){
- ORYX.availablePlugins.push( {name: className } );
- }
- })
- }
-
-
- ORYX.availablePlugins.each(function(value) {
- ORYX.Log.debug("Initializing plugin '%0'", value.name);
- if( (!value.requires || !value.requires.namespaces || value.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) &&
- (!value.notUsesIn || !value.notUsesIn.namespaces || !value.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&&
- /*only load activated plugins or undefined */
- (value.engaged || (value.engaged===undefined)) ){
- try {
- var className = eval(value.name);
- if( className ){
- var plugin = new className(facade, value);
- plugin.type = value.name;
- newPlugins.push( plugin );
- plugin.engaged=true;
- }
- } catch(e) {
- ORYX.Log.warn("Plugin %0 is not available %1", value.name, e);
- }
-
- } else {
- ORYX.Log.info("Plugin need a stencilset which is not loaded'", value.name);
- }
-
- });
- newPlugins.each(function(value) {
- // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data
- if(value.registryChanged)
- value.registryChanged(me.pluginsData);
- // If there have an onSelection-Method it will pushed to the Editor Event-Handler
- if(value.onSelectionChanged)
- me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value));
- });
- this.loadedPlugins = newPlugins;
-
- // Hack for the Scrollbars
- if(Ext.isMac) {
- ORYX.Editor.resizeFix();
- }
-
- this.registerPluginsOnKeyEvents();
-
- this.setSelection();
-
- },
- /**
- * Creates the Canvas
- * @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.
- * @param {Object} [canvasConfig] Any canvas properties (like language).
- */
- _createCanvas: function(stencilType, canvasConfig) {
- if (stencilType) {
- // Add namespace to stencilType
- if (stencilType.search(/^http/) === -1) {
- stencilType = this.getStencilSets().values()[0].namespace() + stencilType;
- }
- }
- else {
- // Get any root stencil type
- stencilType = this.getStencilSets().values()[0].findRootStencilName();
- }
-
- // get the stencil associated with the type
- var canvasStencil = ORYX.Core.StencilSet.stencil(stencilType);
-
- if (!canvasStencil)
- ORYX.Log.fatal("Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.", stencilType);
-
- // create all dom
- // TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars
- var div = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", null, ['div']);
- // set class for custom styling
- div.addClassName("ORYX_Editor");
-
- // create the canvas
- this._canvas = new ORYX.Core.Canvas({
- width : ORYX.CONFIG.CANVAS_WIDTH,
- height : ORYX.CONFIG.CANVAS_HEIGHT,
- 'eventHandlerCallback' : this.handleEvents.bind(this),
- id : this.id,
- parentNode : div
- }, canvasStencil);
-
- if (canvasConfig) {
- // Migrate canvasConfig to an RDF-like structure
- //FIXME this isn't nice at all because we don't want rdf any longer
- var properties = [];
- for(field in canvasConfig){
- properties.push({
- prefix: 'oryx',
- name: field,
- value: canvasConfig[field]
- });
- }
-
- this._canvas.deserialize(properties);
- }
-
- },
- /**
- * Returns a per-editor singleton plugin facade.
- * To be used in plugin initialization.
- */
- _getPluginFacade: function() {
- // if there is no pluginfacade already created:
- if(!(this._pluginFacade))
- // create it.
- this._pluginFacade = {
- activatePluginByName: this.activatePluginByName.bind(this),
- //deactivatePluginByName: this.deactivatePluginByName.bind(this),
- getAvailablePlugins: this.getAvailablePlugins.bind(this),
- offer: this.offer.bind(this),
- getStencilSets: this.getStencilSets.bind(this),
- getStencilSetExtensionDefinition:function(){ return Object.clone(this.ss_extensions_def||{})}.bind(this),
- getRules: this.getRules.bind(this),
- loadStencilSet: this.loadStencilSet.bind(this),
- createShape: this.createShape.bind(this),
- deleteShape: this.deleteShape.bind(this),
- getSelection: this.getSelection.bind(this),
- setSelection: this.setSelection.bind(this),
- updateSelection: this.updateSelection.bind(this),
- getCanvas: this.getCanvas.bind(this),
-
- importJSON: this.importJSON.bind(this),
- importERDF: this.importERDF.bind(this),
- getERDF: this.getERDF.bind(this),
- getJSON: this.getJSON.bind(this),
- getSerializedJSON: this.getSerializedJSON.bind(this),
-
- executeCommands: this.executeCommands.bind(this),
- isExecutingCommands: this.isExecutingCommands.bind(this),
-
- registerOnEvent: this.registerOnEvent.bind(this),
- unregisterOnEvent: this.unregisterOnEvent.bind(this),
- raiseEvent: this.handleEvents.bind(this),
- enableEvent: this.enableEvent.bind(this),
- disableEvent: this.disableEvent.bind(this),
-
- eventCoordinates: this.eventCoordinates.bind(this),
- addToRegion: this.addToRegion.bind(this),
-
- getModelMetaData: this.getModelMetaData.bind(this)
- };
- // return it.
- return this._pluginFacade;
- },
- isExecutingCommands: function(){
- return !!this.commandExecuting;
- },
- /**
- * Implementes the command pattern
- * (The real usage of the command pattern
- * is implemented and shown in the Plugins/undo.js)
- *
- * @param <Oryx.Core.Command>[] Array of commands
- */
- executeCommands: function(commands){
-
- if (!this.commandStack){
- this.commandStack = [];
- }
- if (!this.commandStackExecuted){
- this.commandStackExecuted = [];
- }
-
-
- this.commandStack = [].concat(this.commandStack)
- .concat(commands);
-
- // Check if already executes
- if (this.commandExecuting){ return; }
-
- // Start execution
- this.commandExecuting = true;
-
- // Iterate over all commands
- while(this.commandStack.length > 0){
- var command = this.commandStack.shift();
- // and execute it
- command.execute();
- this.commandStackExecuted.push(command);
- }
-
- // Raise event for executing commands
- this.handleEvents({
- type : ORYX.CONFIG.EVENT_EXECUTE_COMMANDS,
- commands : this.commandStackExecuted
- });
-
- // Remove temporary vars
- delete this.commandStack;
- delete this.commandStackExecuted;
- delete this.commandExecuting;
-
-
- this.updateSelection();
- },
-
- /**
- * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()).
- * @return {Object} Returns JSON representation as JSON object.
- */
- getJSON: function(){
- var canvas = this.getCanvas().toJSON();
- canvas.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function(sse){ return !sse.endsWith('/meta#') });
- return canvas;
- },
-
- /**
- * Serializes a call to toJSON().
- * @return {String} Returns JSON representation as string.
- */
- getSerializedJSON: function(){
- return Ext.encode(this.getJSON());
- },
-
- /**
- * @return {String} Returns eRDF representation.
- * @deprecated Use ORYX.Editor#getJSON instead, if possible.
- */
- getERDF:function(){
- // Get the serialized dom
- var serializedDOM = DataManager.serializeDOM( this._getPluginFacade() );
-
- // Add xml definition if there is no
- serializedDOM = '<?xml version="1.0" encoding="utf-8"?>' +
- '<html xmlns="http://www.w3.org/1999/xhtml" ' +
- 'xmlns:b3mn="http://b3mn.org/2007/b3mn" ' +
- 'xmlns:ext="http://b3mn.org/2007/ext" ' +
- 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ' +
- 'xmlns:atom="http://b3mn.org/2007/atom+xhtml">' +
- '<head profile="http://purl.org/NET/erdf/profile">' +
- '<link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" />' +
- '<link rel="schema.dcTerms" href="http://purl.org/dc/terms/ " />' +
- '<link rel="schema.b3mn" href="http://b3mn.org" />' +
- '<link rel="schema.oryx" href="http://oryx-editor.org/" />' +
- '<link rel="schema.raziel" href="http://raziel.org/" />' +
- '<base href="' +
- location.href.split("?")[0] +
- '" />' +
- '</head><body>' +
- serializedDOM +
- '</body></html>';
-
- return serializedDOM;
- },
-
- /**
- * Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized}
- * @param {Object|String} jsonObject The (serialized) json object to be imported
- * @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import
- * @throws {SyntaxError} If the serialized json object contains syntax errors
- */
- importJSON: function(jsonObject, noSelectionAfterImport) {
-
- try {
- jsonObject = this.renewResourceIds(jsonObject);
- } catch(error){
- throw error;
- }
- //check, if the imported json model can be loaded in this editor
- // (stencil set has to fit)
- if(jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) {
- Ext.Msg.alert(ORYX.I18N.JSONImport.title, String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace()));
- return null;
- } else {
- var commandClass = ORYX.Core.Command.extend({
- construct: function(jsonObject, loadSerializedCB, noSelectionAfterImport, facade){
- this.jsonObject = jsonObject;
- this.noSelection = noSelectionAfterImport;
- this.facade = facade;
- this.shapes;
- this.connections = [];
- this.parents = new Hash();
- this.selection = this.facade.getSelection();
- this.loadSerialized = loadSerializedCB;
- },
- execute: function(){
-
- if (!this.shapes) {
- // Import the shapes out of the serialization
- this.shapes = this.loadSerialized( this.jsonObject );
-
- //store all connections
- this.shapes.each(function(shape) {
-
- if (shape.getDockers) {
- var dockers = shape.getDockers();
- if (dockers) {
- if (dockers.length > 0) {
- this.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]);
- }
- if (dockers.length > 1) {
- this.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]);
- }
- }
- }
-
- //store parents
- this.parents[shape.id] = shape.parent;
- }.bind(this));
- } else {
- this.shapes.each(function(shape) {
- this.parents[shape.id].add(shape);
- }.bind(this));
-
- this.connections.each(function(con) {
- con[0].setDockedShape(con[1]);
- con[0].setReferencePoint(con[2]);
- con[0].update();
- });
- }
-
- //this.parents.values().uniq().invoke("update");
- this.facade.getCanvas().update();
-
- if(!this.noSelection)
- this.facade.setSelection(this.shapes);
- else
- this.facade.updateSelection();
-
- // call updateSize again, because during loadSerialized the edges' bounds
- // are not yet initialized properly
- this.facade.getCanvas().updateSize();
-
- },
- rollback: function(){
- var selection = this.facade.getSelection();
-
- this.shapes.each(function(shape) {
- selection = selection.without(shape);
- this.facade.deleteShape(shape);
- }.bind(this));
-
- /*this.parents.values().uniq().each(function(parent) {
- if(!this.shapes.member(parent))
- parent.update();
- }.bind(this));*/
-
- this.facade.getCanvas().update();
-
- this.facade.setSelection(selection);
- }
- })
-
- var command = new commandClass(jsonObject,
- this.loadSerialized.bind(this),
- noSelectionAfterImport,
- this._getPluginFacade());
-
- this.executeCommands([command]);
-
- return command.shapes.clone();
- }
- },
-
- /**
- * This method renew all resource Ids and according references.
- * Warning: The implementation performs a substitution on the serialized object for
- * easier implementation. This results in a low performance which is acceptable if this
- * is only used when importing models.
- * @param {Object|String} jsonObject
- * @throws {SyntaxError} If the serialized json object contains syntax errors.
- * @return {Object} The jsonObject with renewed ids.
- * @private
- */
- renewResourceIds: function(jsonObject){
- // For renewing resource ids, a serialized and object version is needed
- if(Ext.type(jsonObject) === "string"){
- try {
- var serJsonObject = jsonObject;
- jsonObject = Ext.decode(jsonObject);
- } catch(error){
- throw new SyntaxError(error.message);
- }
- } else {
- var serJsonObject = Ext.encode(jsonObject);
- }
-
- // collect all resourceIds recursively
- var collectResourceIds = function(shapes){
- if(!shapes) return [];
-
- return shapes.map(function(shape){
- return collectResourceIds(shape.childShapes).concat(shape.resourceId);
- }).flatten();
- }
- var resourceIds = collectResourceIds(jsonObject.childShapes);
-
- // Replace each resource id by a new one
- resourceIds.each(function(oldResourceId){
- var newResourceId = ORYX.Editor.provideId();
- serJsonObject = serJsonObject.gsub('"'+oldResourceId+'"', '"'+newResourceId+'"')
- });
-
- return Ext.decode(serJsonObject);
- },
-
- /**
- * Import erdf structure to the editor
- *
- */
- importERDF: function( erdfDOM ){
- var serialized = this.parseToSerializeObjects( erdfDOM );
-
- if(serialized)
- return this.importJSON(serialized, true);
- },
- /**
- * Parses one model (eRDF) to the serialized form (JSON)
- *
- * @param {Object} oneProcessData
- * @return {Object} The JSON form of given eRDF model, or null if it couldn't be extracted
- */
- parseToSerializeObjects: function( oneProcessData ){
-
- // Firefox splits a long text node into chunks of 4096 characters.
- // To prevent truncation of long property values the normalize method must be called
- if(oneProcessData.normalize) oneProcessData.normalize();
- try {
- var xsl = "";
- var source=ORYX.PATH + "lib/extract-rdf.xsl";
- new Ajax.Request(source, {
- asynchronous: false,
- method: 'get',
- onSuccess: function(transport){
- xsl = transport.responseText
- }.bind(this),
- onFailure: (function(transport){
- ORYX.Log.error("XSL load failed" + transport);
- }).bind(this)
- });
- var domParser = new DOMParser();
- var xmlObject = oneProcessData;
- var xslObject = domParser.parseFromString(xsl, "text/xml");
- var xsltProcessor = new XSLTProcessor();
- var xslRef = document.implementation.createDocument("", "", null);
- xsltProcessor.importStylesheet(xslObject);
-
- var new_rdf = xsltProcessor.transformToFragment(xmlObject, document);
- var serialized_rdf = (new XMLSerializer()).serializeToString(new_rdf);
- }catch(e){
- Ext.Msg.alert("Oryx", error);
- var serialized_rdf = "";
- }
-
- // Firefox 2 to 3 problem?!
- serialized_rdf = !serialized_rdf.startsWith("<?xml") ? "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serialized_rdf : serialized_rdf;
- var req = new Ajax.Request(ORYX.CONFIG.ROOT_PATH+"rdf2json", {
- method: 'POST',
- asynchronous: false,
- onSuccess: function(transport) {
- Ext.decode(transport.responseText);
- },
- parameters: {
- rdf: serialized_rdf
- }
- });
-
- return Ext.decode(req.transport.responseText);
- },
- /**
- * Loads serialized model to the oryx.
- * @example
- * editor.loadSerialized({
- * resourceId: "mymodel1",
- * childShapes: [
- * {
- * stencil:{ id:"Subprocess" },
- * outgoing:[{resourceId: 'aShape'}],
- * target: {resourceId: 'aShape'},
- * bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } },
- * resourceId: "myshape1",
- * childShapes:[],
- * properties:{},
- * }
- * ],
- * properties:{
- * language: "English"
- * },
- * stencilset:{
- * url:"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json"
- * },
- * stencil:{
- * id:"BPMNDiagram"
- * }
- * });
- * @param {Object} model Description of the model to load.
- * @param {Array} [model.ssextensions] List of stenctil set extensions.
- * @param {String} model.stencilset.url
- * @param {String} model.stencil.id
- * @param {Array} model.childShapes
- * @param {Array} [model.properties]
- * @param {String} model.resourceId
- * @return {ORYX.Core.Shape[]} List of created shapes
- * @methodOf ORYX.Editor.prototype
- */
- loadSerialized: function(model, requestMeta){
- var canvas = this.getCanvas();
-
- // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240)
- // Deserialize the canvas' stencil set extensions properties first!
- this.loadSSExtensions(model.ssextensions);
-
- // Load Meta Data Extension if available
- // #Signavio
- if (requestMeta === true) {
- var metaDataExtension = this.getExtensionForMetaData();
- if (metaDataExtension) {
- this.loadSSExtension(metaDataExtension);
- }
- }
-
- var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this));
-
- if(model.properties) {
- for(key in model.properties) {
- var value = model.properties[key];
- var prop = this.getCanvas().getStencil().property("oryx-"+key);
- if (!(typeof value === "string") && (!prop || !prop.isList())) {
- value = Ext.encode(value);
- }
- this.getCanvas().setProperty("oryx-" + key, value);
- }
- }
-
-
- this.getCanvas().updateSize();
-
- // Force to update the selection
- this.selection = [null];
- this.setSelection([]);
-
- return shapes;
- },
-
- /**
- * Return the namespace of the extension which
- * provided all the self defined meta data
- * @return {String} Returns null if no extension is defined, otherwise the namespace
- *
- */
- getExtensionForMetaData: function(){
- if (!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){
- return null;
- }
-
- var stencilsets = this.getStencilSets();
- var extension = this.ss_extensions_def.extensions.find(function(ex){
- return !!stencilsets[ex["extends"]] && ex.namespace.endsWith("/meta#");
- });
-
- return extension ? extension.namespace || null : null;
- },
-
- /**
- * Calls ORYX.Editor.prototype.ss_extension_namespace for each element
- * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces.
- */
- loadSSExtensions: function(ss_extension_namespaces){
- if(!ss_extension_namespaces) return;
- ss_extension_namespaces.each(function(ss_extension_namespace){
- this.loadSSExtension(ss_extension_namespace);
- }.bind(this));
- },
-
- /**
- * Loads a stencil set extension.
- * The stencil set extensions definiton file must already
- * be loaded when the editor is initialized.
- */
- loadSSExtension: function(ss_extension_namespace) {
-
- if (this.ss_extensions_def) {
- var extension = this.ss_extensions_def.extensions.find(function(ex){
- return (ex.namespace == ss_extension_namespace);
- });
-
- if (!extension) {
- return;
- }
-
- var stencilset = this.getStencilSets()[extension["extends"]];
-
- if (!stencilset) {
- return;
- }
-
- // Check if absolute or relative url
- if ((extension["definition"]||"").startsWith("/")){
- stencilset.addExtension(extension["definition"])
- } else {
- stencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension["definition"])
- }
-
- //stencilset.addExtension("/oryx/build/stencilsets/extensions/" + extension["definition"])
- this.getRules().initializeRules(stencilset);
-
- this._getPluginFacade().raiseEvent({
- type: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED
- });
- }
-
- },
- disableEvent: function(eventType){
- if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {
- this._keydownEnabled = false;
- }
- if(eventType == ORYX.CONFIG.EVENT_KEYUP) {
- this._keyupEnabled = false;
- }
- if(this.DOMEventListeners.keys().member(eventType)) {
- var value = this.DOMEventListeners.remove(eventType);
- this.DOMEventListeners['disable_' + eventType] = value;
- }
- },
- enableEvent: function(eventType){
- if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) {
- this._keydownEnabled = true;
- }
-
- if(eventType == ORYX.CONFIG.EVENT_KEYUP) {
- this._keyupEnabled = true;
- }
-
- if(this.DOMEventListeners.keys().member("disable_" + eventType)) {
- var value = this.DOMEventListeners.remove("disable_" + eventType);
- this.DOMEventListeners[eventType] = value;
- }
- },
- /**
- * Methods for the PluginFacade
- */
- registerOnEvent: function(eventType, callback) {
- if(!(this.DOMEventListeners.keys().member(eventType))) {
- this.DOMEventListeners[eventType] = [];
- }
- this.DOMEventListeners[eventType].push(callback);
- },
- unregisterOnEvent: function(eventType, callback) {
- if(this.DOMEventListeners.keys().member(eventType)) {
- this.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback);
- } else {
- // Event is not supported
- // TODO: Error Handling
- }
- },
- getSelection: function() {
- return this.selection || [];
- },
- getStencilSets: function() {
- return ORYX.Core.StencilSet.stencilSets(this.id);
- },
-
- getRules: function() {
- return ORYX.Core.StencilSet.rules(this.id);
- },
-
- loadStencilSet: function(source) {
- try {
- ORYX.Core.StencilSet.loadStencilSet(source, this.id);
- this.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED});
- } catch (e) {
- ORYX.Log.warn("Requesting stencil set file failed. (" + e + ")");
- }
- },
- offer: function(pluginData) {
- if(!this.pluginsData.member(pluginData)){
- this.pluginsData.push(pluginData);
- }
- },
-
- /**
- * It creates an new event or adds the callback, if already existing,
- * for the key combination that the plugin passes in keyCodes attribute
- * of the offer method.
- *
- * The new key down event fits the schema:
- * key.event[.metactrl][.alt][.shift].'thekeyCode'
- */
- registerPluginsOnKeyEvents: function() {
- this.pluginsData.each(function(pluginData) {
-
- if(pluginData.keyCodes) {
-
- pluginData.keyCodes.each(function(keyComb) {
- var eventName = "key.event";
-
- /* Include key action */
- eventName += '.' + keyComb.keyAction;
-
- if(keyComb.metaKeys) {
- /* Register on ctrl or apple meta key as meta key */
- if(keyComb.metaKeys.
- indexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) {
- eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL;
- }
-
- /* Register on alt key as meta key */
- if(keyComb.metaKeys.
- indexOf(ORYX.CONFIG.META_KEY_ALT) > -1) {
- eventName += '.' + ORYX.CONFIG.META_KEY_ALT;
- }
-
- /* Register on shift key as meta key */
- if(keyComb.metaKeys.
- indexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) {
- eventName += '.' + ORYX.CONFIG.META_KEY_SHIFT;
- }
- }
-
- /* Register on the actual key */
- if(keyComb.keyCode) {
- eventName += '.' + keyComb.keyCode;
- }
-
- /* Register the event */
- ORYX.Log.debug("Register Plugin on Key Event: %0", eventName);
- if (pluginData.toggle === true && pluginData.buttonInstance) {
- this.registerOnEvent(eventName, function(){
- pluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle
- pluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function
- });
- } else {
- this.registerOnEvent(eventName, pluginData.functionality)
- }
-
- }.bind(this));
- }
- }.bind(this));
- },
-
- isEqual: function(a,b){
- return a === b || (a.length === b.length && a.all(function(r){ return b.include(r) }))
- },
-
- isDirty: function(a){
- return a.any(function(shape){ return shape.isPropertyChanged() })
- },
- setSelection: function(elements, subSelectionElement, force) {
-
- if (!elements) { elements = []; }
- if (!(elements instanceof Array)) { elements = [elements]; }
-
- elements = elements.findAll(function(n){ return n && n instanceof ORYX.Core.Shape });
-
- if (elements[0] instanceof ORYX.Core.Canvas) {
- elements = [];
- }
-
- if (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)){
- return;
- }
-
- this.selection = elements;
- this._subSelection = subSelectionElement;
-
- this.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED, elements:elements, subSelection: subSelectionElement, force: !!force})
- },
-
- updateSelection: function() {
- this.setSelection(this.selection, this._subSelection, true);
- /*var s = this.selection;
- this.setSelection();
- this.setSelection(s);*/
- },
- getCanvas: function() {
- return this._canvas;
- },
-
- /**
- * option = {
- * type: string,
- * position: {x:int, y:int},
- * connectingType: uiObj-Class
- * connectedShape: uiObj
- * draggin: bool
- * namespace: url
- * parent: ORYX.Core.AbstractShape
- * template: a template shape that the newly created inherits properties from.
- * }
- */
- createShape: function(option) {
- if(option && option.serialize && option.serialize instanceof Array){
-
- var type = option.serialize.find(function(obj){return (obj.prefix+"-"+obj.name) == "oryx-type"});
- var stencil = ORYX.Core.StencilSet.stencil(type.value);
-
- if(stencil.type() == 'node'){
- var newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil);
- } else {
- var newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil);
- }
-
- this.getCanvas().add(newShapeObject);
- newShapeObject.deserialize(option.serialize);
-
- return newShapeObject;
- }
- // If there is no argument, throw an exception
- if(!option || !option.type || !option.namespace) { throw "To create a new shape you have to give an argument with type and namespace";}
-
- var canvas = this.getCanvas();
- var newShapeObject;
- // Get the shape type
- var shapetype = option.type;
- // Get the stencil set
- var sset = ORYX.Core.StencilSet.stencilSet(option.namespace);
- // Create an New Shape, dependents on an Edge or a Node
- if(sset.stencil(shapetype).type() == "node") {
- newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype))
- } else {
- newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype))
- }
-
- // when there is a template, inherit the properties.
- if(option.template) {
- newShapeObject._jsonStencil.properties = option.template._jsonStencil.properties;
- newShapeObject.postProcessProperties();
- }
- // Add to the canvas
- if(option.parent && newShapeObject instanceof ORYX.Core.Node) {
- option.parent.add(newShapeObject);
- } else {
- canvas.add(newShapeObject);
- }
-
-
- // Set the position
- var point = option.position ? option.position : {x:100, y:200};
-
-
- var con;
- // If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge
- if(option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) {
- // there will be create a new Edge
- con = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(option.connectingType));
-
- // And both endings dockers will be referenced to the both shapes
- con.dockers.first().setDockedShape(option.connectedShape);
-
- var magnet = option.connectedShape.getDefaultMagnet()
- var cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint();
- con.dockers.first().setReferencePoint( cPoint );
- con.dockers.last().setDockedShape(newShapeObject);
- con.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center());
-
- // The Edge will be added to the canvas and be updated
- canvas.add(con);
- //con.update();
-
- }
-
- // Move the new Shape to the position
- if(newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) {
- newShapeObject.dockers.first().setDockedShape(option.connectedShape);
-
- if( option.connectedShape instanceof ORYX.Core.Node ){
- newShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center());
- newShapeObject.dockers.last().bounds.centerMoveTo(point);
- } else {
- newShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint());
- }
- } else {
-
- var b = newShapeObject.bounds
- if( newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1){
- b = newShapeObject.dockers.first().bounds
- }
-
- b.centerMoveTo(point);
-
- var upL = b.upperLeft();
- b.moveBy( -Math.min(upL.x, 0) , -Math.min(upL.y, 0) )
-
- var lwR = b.lowerRight();
- b.moveBy( -Math.max(lwR.x-canvas.bounds.width(), 0) , -Math.max(lwR.y-canvas.bounds.height(), 0) )
-
- }
-
- // Update the shape
- if (newShapeObject instanceof ORYX.Core.Edge) {
- newShapeObject._update(false);
- }
-
- // And refresh the selection
- if(!(newShapeObject instanceof ORYX.Core.Edge)&&!(option.dontUpdateSelection)) {
- this.setSelection([newShapeObject]);
- }
-
- if(con && con.alignDockers) {
- con.alignDockers();
- }
- if(newShapeObject.alignDockers) {
- newShapeObject.alignDockers();
- }
- return newShapeObject;
- },
-
- deleteShape: function(shape) {
-
- if (!shape || !shape.parent){ return }
-
- //remove shape from parent
- // this also removes it from DOM
- shape.parent.remove(shape);
-
- //delete references to outgoing edges
- shape.getOutgoingShapes().each(function(os) {
- var docker = os.getDockers().first();
- if(docker && docker.getDockedShape() == shape) {
- docker.setDockedShape(undefined);
- }
- });
-
- //delete references to incoming edges
- shape.getIncomingShapes().each(function(is) {
- var docker = is.getDockers().last();
- if(docker && docker.getDockedShape() == shape) {
- docker.setDockedShape(undefined);
- }
- });
-
- //delete references of the shape's dockers
- shape.getDockers().each(function(docker) {
- docker.setDockedShape(undefined);
- });
- },
-
- /**
- * Returns an object with meta data about the model.
- * Like name, description, ...
- *
- * Empty object with the current backend.
- *
- * @return {Object} Meta data about the model
- */
- getModelMetaData: function() {
- return this.modelMetaData;
- },
- /* Event-Handler Methods */
-
- /**
- * Helper method to execute an event immediately. The event is not
- * scheduled in the _eventsQueue. Needed to handle Layout-Callbacks.
- */
- _executeEventImmediately: function(eventObj) {
- if(this.DOMEventListeners.keys().member(eventObj.event.type)) {
- this.DOMEventListeners[eventObj.event.type].each((function(value) {
- value(eventObj.event, eventObj.arg);
- }).bind(this));
- }
- },
- _executeEvents: function() {
- this._queueRunning = true;
- while(this._eventsQueue.length > 0) {
- var val = this._eventsQueue.shift();
- this._executeEventImmediately(val);
- }
- this._queueRunning = false;
- },
-
- /**
- * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter
- * @param {Object} event Event , welches gefeuert wurde
- * @param {Object} uiObj Target-UiObj
- */
- handleEvents: function(event, uiObj) {
-
- ORYX.Log.trace("Dispatching event type %0 on %1", event.type, uiObj);
- switch(event.type) {
- case ORYX.CONFIG.EVENT_MOUSEDOWN:
- this._handleMouseDown(event, uiObj);
- break;
- case ORYX.CONFIG.EVENT_MOUSEMOVE:
- this._handleMouseMove(event, uiObj);
- break;
- case ORYX.CONFIG.EVENT_MOUSEUP:
- this._handleMouseUp(event, uiObj);
- break;
- case ORYX.CONFIG.EVENT_MOUSEOVER:
- this._handleMouseHover(event, uiObj);
- break;
- case ORYX.CONFIG.EVENT_MOUSEOUT:
- this._handleMouseOut(event, uiObj);
- break;
- }
- /* Force execution if necessary. Used while handle Layout-Callbacks. */
- if(event.forceExecution) {
- this._executeEventImmediately({event: event, arg: uiObj});
- } else {
- this._eventsQueue.push({event: event, arg: uiObj});
- }
-
- if(!this._queueRunning) {
- this._executeEvents();
- }
-
- // TODO: Make this return whether no listener returned false.
- // So that, when one considers bubbling undesireable, it won't happen.
- return false;
- },
- isValidEvent: function(e){
- try {
- var isInput = ["INPUT", "TEXTAREA"].include(e.target.tagName.toUpperCase());
- var gridHasFocus = e.target.className.include("x-grid3-focus") && !e.target.className.include("x-grid3-focus-canvas");
- return !isInput && !gridHasFocus;
- } catch(e){
- return false;
- }
- },
- catchKeyUpEvents: function(event) {
- if(!this._keyupEnabled) {
- return;
- }
- /* assure we have the current event. */
- if (!event)
- event = window.event;
-
- // Checks if the event comes from some input field
- if (!this.isValidEvent(event)){
- return;
- }
-
- /* Create key up event type */
- var keyUpEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_UP);
-
- ORYX.Log.debug("Key Event to handle: %0", keyUpEvent);
- /* forward to dispatching. */
- this.handleEvents({type: keyUpEvent, event:event});
- },
-
- /**
- * Catches all key down events and forward the appropriated event to
- * dispatching concerning to the pressed keys.
- *
- * @param {Event}
- * The key down event to handle
- */
- catchKeyDownEvents: function(event) {
- if(!this._keydownEnabled) {
- return;
- }
- /* Assure we have the current event. */
- if (!event)
- event = window.event;
-
- /* Fixed in FF3 */
- // This is a mac-specific fix. The mozilla event object has no knowledge
- // of meta key modifier on osx, however, it is needed for certain
- // shortcuts. This fix adds the metaKey field to the event object, so
- // that all listeners that registered per Oryx plugin facade profit from
- // this. The original bug is filed in
- // https://bugzilla.mozilla.org/show_bug.cgi?id=418334
- //if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) {
- // event.appleMetaKey = true;
- //}
- //this.__currentKey = pressedKey;
-
- // Checks if the event comes from some input field
- if (!this.isValidEvent(event)){
- return;
- }
-
- /* Create key up event type */
- var keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN);
-
- ORYX.Log.debug("Key Event to handle: %0", keyDownEvent);
-
- /* Forward to dispatching. */
- this.handleEvents({type: keyDownEvent,event: event});
- },
-
- /**
- * Creates the event type name concerning to the pressed keys.
- *
- * @param {Event} keyDownEvent
- * The source keyDownEvent to build up the event name
- */
- createKeyCombEvent: function(keyEvent, keyAction) {
- /* Get the currently pressed key code. */
- var pressedKey = keyEvent.which || keyEvent.keyCode;
- //this.__currentKey = pressedKey;
-
- /* Event name */
- var eventName = "key.event";
-
- /* Key action */
- if(keyAction) {
- eventName += "." + keyAction;
- }
-
- /* Ctrl or apple meta key is pressed */
- if(keyEvent.ctrlKey || keyEvent.metaKey) {
- eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL;
- }
-
- /* Alt key is pressed */
- if(keyEvent.altKey) {
- eventName += "." + ORYX.CONFIG.META_KEY_ALT;
- }
-
- /* Alt key is pressed */
- if(keyEvent.shiftKey) {
- eventName += "." + ORYX.CONFIG.META_KEY_SHIFT;
- }
-
- /* Return the composed event name */
- return eventName + "." + pressedKey;
- },
- _handleMouseDown: function(event, uiObj) {
-
- // get canvas.
- var canvas = this.getCanvas();
- // Try to get the focus
- canvas.focus()
-
- // find the shape that is responsible for this element's id.
- var element = event.currentTarget;
- var elementController = uiObj;
- // gather information on selection.
- var currentIsSelectable = (elementController !== null) &&
- (elementController !== undefined) && (elementController.isSelectable);
- var currentIsMovable = (elementController !== null) &&
- (elementController !== undefined) && (elementController.isMovable);
- var modifierKeyPressed = event.shiftKey || event.ctrlKey;
- var noObjectsSelected = this.selection.length === 0;
- var currentIsSelected = this.selection.member(elementController);
- // Rule #1: When there is nothing selected, select the clicked object.
- if(currentIsSelectable && noObjectsSelected) {
- this.setSelection([elementController]);
- ORYX.Log.trace("Rule #1 applied for mouse down on %0", element.id);
- // Rule #3: When at least one element is selected, and there is no
- // control key pressed, and the clicked object is not selected, select
- // the clicked object.
- } else if(currentIsSelectable && !noObjectsSelected &&
- !modifierKeyPressed && !currentIsSelected) {
- this.setSelection([elementController]);
- //var objectType = elementController.readAttributes();
- //alert(objectType[0] + ": " + objectType[1]);
- ORYX.Log.trace("Rule #3 applied for mouse down on %0", element.id);
- // Rule #4: When the control key is pressed, and the current object is
- // not selected, add it to the selection.
- } else if(currentIsSelectable && modifierKeyPressed
- && !currentIsSelected) {
-
- var newSelection = this.selection.clone();
- newSelection.push(elementController)
- this.setSelection(newSelection)
- ORYX.Log.trace("Rule #4 applied for mouse down on %0", element.id);
- // Rule #6
- } else if(currentIsSelectable && currentIsSelected &&
- modifierKeyPressed) {
- var newSelection = this.selection.clone();
- this.setSelection(newSelection.without(elementController))
- ORYX.Log.trace("Rule #6 applied for mouse down on %0", elementController.id);
- // Rule #5: When there is at least one object selected and no control
- // key pressed, we're dragging.
- /*} else if(currentIsSelectable && !noObjectsSelected
- && !modifierKeyPressed) {
- if(this.log.isTraceEnabled())
- this.log.trace("Rule #5 applied for mouse down on "+element.id);
- */
- // Rule #2: When clicked on something that is neither
- // selectable nor movable, clear the selection, and return.
- } else if (!currentIsSelectable && !currentIsMovable) {
-
- this.setSelection([]);
-
- ORYX.Log.trace("Rule #2 applied for mouse down on %0", element.id);
- return;
- // Rule #7: When the current object is not selectable but movable,
- // it is probably a control. Leave the selection unchanged but set
- // the movedObject to the current one and enable Drag. Dockers will
- // be processed in the dragDocker plugin.
- } else if(!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) {
-
- // TODO: If there is any moveable elements, do this in a plugin
- //ORYX.Core.UIEnableDrag(event, elementController);
- ORYX.Log.trace("Rule #7 applied for mouse down on %0", element.id);
-
- // Rule #8: When the element is selectable and is currently selected and no
- // modifier key is pressed
- } else if(currentIsSelectable && currentIsSelected &&
- !modifierKeyPressed) {
-
- this._subSelection = this._subSelection != elementController ? elementController : undefined;
-
- this.setSelection(this.selection, this._subSelection);
-
- ORYX.Log.trace("Rule #8 applied for mouse down on %0", element.id);
- }
-
-
- // prevent event from bubbling, return.
- //Event.stop(event);
- return;
- },
- _handleMouseMove: function(event, uiObj) {
- return;
- },
- _handleMouseUp: function(event, uiObj) {
- // get canvas.
- var canvas = this.getCanvas();
- // find the shape that is responsible for this elemement's id.
- var elementController = uiObj;
- //get event position
- var evPos = this.eventCoordinates(event);
- //Event.stop(event);
- },
- _handleMouseHover: function(event, uiObj) {
- return;
- },
- _handleMouseOut: function(event, uiObj) {
- return;
- },
- /**
- * Calculates the event coordinates to SVG document coordinates.
- * @param {Event} event
- * @return {SVGPoint} The event coordinates in the SVG document
- */
- eventCoordinates: function(event) {
- var canvas = this.getCanvas();
- var svgPoint = canvas.node.ownerSVGElement.createSVGPoint();
- svgPoint.x = event.clientX;
- svgPoint.y = event.clientY;
- var matrix = canvas.node.getScreenCTM();
- return svgPoint.matrixTransform(matrix.inverse());
- }
- };
- ORYX.Editor = Clazz.extend(ORYX.Editor);
- /**
- * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur
- * @param {String} modelUrl The JSON URL of a model.
- * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl
- */
- ORYX.Editor.createByUrl = function(modelUrl, config){
- if(!config) config = {};
-
- new Ajax.Request(modelUrl, {
- method: 'GET',
- onSuccess: function(transport) {
- var editorConfig = Ext.decode(transport.responseText);
- editorConfig = Ext.applyIf(editorConfig, config);
- new ORYX.Editor(editorConfig);
- }.bind(this)
- });
- }
- // TODO Implement namespace awareness on attribute level.
- /**
- * graft() function
- * Originally by Sean M. Burke from interglacial.com, altered for usage with
- * SVG and namespace (xmlns) support. Be sure you understand xmlns before
- * using this funtion, as it creates all grafted elements in the xmlns
- * provided by you and all element's attribures in default xmlns. If you
- * need to graft elements in a certain xmlns and wish to assign attributes
- * in both that and another xmlns, you will need to do stepwise grafting,
- * adding non-default attributes yourself or you'll have to enhance this
- * function. Latter, I would appreciate: martin�apfelfabrik.de
- * @param {Object} namespace The namespace in which
- * elements should be grafted.
- * @param {Object} parent The element that should contain the grafted
- * structure after the function returned.
- * @param {Object} t the crafting structure.
- * @param {Object} doc the document in which grafting is performed.
- */
- ORYX.Editor.graft = function(namespace, parent, t, doc) {
- doc = (doc || (parent && parent.ownerDocument) || document);
- var e;
- if(t === undefined) {
- throw "Can't graft an undefined value";
- } else if(t.constructor == String) {
- e = doc.createTextNode( t );
- } else {
- for(var i = 0; i < t.length; i++) {
- if( i === 0 && t[i].constructor == String ) {
- var snared;
- snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i );
- if( snared ) {
- e = doc.createElementNS(namespace, snared[1] );
- e.setAttributeNS(null, 'class', snared[2] );
- continue;
- }
- snared = t[i].match( /^([a-z][a-z0-9]*)$/i );
- if( snared ) {
- e = doc.createElementNS(namespace, snared[1] ); // but no class
- continue;
- }
- // Otherwise:
- e = doc.createElementNS(namespace, "span" );
- e.setAttribute(null, "class", "namelessFromLOL" );
- }
- if( t[i] === undefined ) {
- throw "Can't graft an undefined value in a list!";
- } else if( t[i].constructor == String || t[i].constructor == Array ) {
- this.graft(namespace, e, t[i], doc );
- } else if( t[i].constructor == Number ) {
- this.graft(namespace, e, t[i].toString(), doc );
- } else if( t[i].constructor == Object ) {
- // hash's properties => element's attributes
- for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); }
- } else {
- }
- }
- }
- if(parent) {
- parent.appendChild( e );
- } else {
- }
- return e; // return the topmost created node
- };
- ORYX.Editor.provideId = function() {
- var res = [], hex = '0123456789ABCDEF';
- for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);
- res[14] = 4;
- res[19] = (res[19] & 0x3) | 0x8;
- for (var i = 0; i < 36; i++) res[i] = hex[res[i]];
- res[8] = res[13] = res[18] = res[23] = '-';
- return "oryx_" + res.join('');
- };
- /**
- * When working with Ext, conditionally the window needs to be resized. To do
- * so, use this class method. Resize is deferred until 100ms, and all subsequent
- * resizeBugFix calls are ignored until the initially requested resize is
- * performed.
- */
- ORYX.Editor.resizeFix = function() {
- if (!ORYX.Editor._resizeFixTimeout) {
- ORYX.Editor._resizeFixTimeout = window.setTimeout(function() {
- window.resizeBy(1,1);
- window.resizeBy(-1,-1);
- ORYX.Editor._resizefixTimeout = null;
- }, 100);
- }
- };
- ORYX.Editor.Cookie = {
-
- callbacks:[],
-
- onChange: function( callback, interval ){
-
- this.callbacks.push(callback);
- this.start( interval )
-
- },
-
- start: function( interval ){
-
- if( this.pe ){
- return;
- }
-
- var currentString = document.cookie;
-
- this.pe = new PeriodicalExecuter( function(){
-
- if( currentString != document.cookie ){
- currentString = document.cookie;
- this.callbacks.each(function(callback){ callback(this.getParams()) }.bind(this));
- }
-
- }.bind(this), ( interval || 10000 ) / 1000);
- },
-
- stop: function(){
- if( this.pe ){
- this.pe.stop();
- this.pe = null;
- }
- },
-
- getParams: function(){
- var res = {};
-
- var p = document.cookie;
- p.split("; ").each(function(param){ res[param.split("=")[0]] = param.split("=")[1];});
-
- return res;
- },
-
- toString: function(){
- return document.cookie;
- }
- };
- /**
- * Workaround for SAFARI/Webkit, because
- * when trying to check SVGSVGElement of instanceof there is
- * raising an error
- *
- */
- ORYX.Editor.SVGClassElementsAreAvailable = true;
- ORYX.Editor.setMissingClasses = function() {
-
- try {
- SVGElement;
- } catch(e) {
- ORYX.Editor.SVGClassElementsAreAvailable = false;
- SVGSVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg').toString();
- SVGGElement = document.createElementNS('http://www.w3.org/2000/svg', 'g').toString();
- SVGPathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path').toString();
- SVGTextElement = document.createElementNS('http://www.w3.org/2000/svg', 'text').toString();
- //SVGMarkerElement = document.createElementNS('http://www.w3.org/2000/svg', 'marker').toString();
- SVGRectElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect').toString();
- SVGImageElement = document.createElementNS('http://www.w3.org/2000/svg', 'image').toString();
- SVGCircleElement = document.createElementNS('http://www.w3.org/2000/svg', 'circle').toString();
- SVGEllipseElement = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse').toString();
- SVGLineElement = document.createElementNS('http://www.w3.org/2000/svg', 'line').toString();
- SVGPolylineElement = document.createElementNS('http://www.w3.org/2000/svg', 'polyline').toString();
- SVGPolygonElement = document.createElementNS('http://www.w3.org/2000/svg', 'polygon').toString();
-
- }
-
- }
- ORYX.Editor.checkClassType = function( classInst, classType ) {
-
- if( ORYX.Editor.SVGClassElementsAreAvailable ){
- return classInst instanceof classType
- } else {
- return classInst == classType
- }
- };
- ORYX.Editor.makeExtModalWindowKeysave = function(facade) {
- Ext.override(Ext.Window,{
- beforeShow : function(){
- delete this.el.lastXY;
- delete this.el.lastLT;
- if(this.x === undefined || this.y === undefined){
- var xy = this.el.getAlignToXY(this.container, 'c-c');
- var pos = this.el.translatePoints(xy[0], xy[1]);
- this.x = this.x === undefined? pos.left : this.x;
- this.y = this.y === undefined? pos.top : this.y;
- }
- this.el.setLeftTop(this.x, this.y);
-
- if(this.expandOnShow){
- this.expand(false);
- }
-
- if(this.modal){
- facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- Ext.getBody().addClass("x-body-masked");
- this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
- this.mask.show();
- }
- },
- afterHide : function(){
- this.proxy.hide();
- if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
- Ext.EventManager.removeResizeListener(this.onWindowResize, this);
- }
- if(this.modal){
- this.mask.hide();
- facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- Ext.getBody().removeClass("x-body-masked");
- }
- if(this.keyMap){
- this.keyMap.disable();
- }
- this.fireEvent("hide", this);
- },
- beforeDestroy : function(){
- if(this.modal)
- facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- Ext.destroy(
- this.resizer,
- this.dd,
- this.proxy,
- this.mask
- );
- Ext.Window.superclass.beforeDestroy.call(this);
- }
- });
- }
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- new function(){
-
- ORYX.Core.UIEnableDrag = function(event, uiObj, option) {
-
- this.uiObj = uiObj;
- var upL = uiObj.bounds.upperLeft();
-
- var a = uiObj.node.getScreenCTM();
- this.faktorXY= {x: a.a, y: a.d};
-
- this.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode;
-
- this.offSetPosition = {
- x: Event.pointerX(event) - (upL.x * this.faktorXY.x),
- y: Event.pointerY(event) - (upL.y * this.faktorXY.y)};
-
- this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
-
- this.dragCallback = ORYX.Core.UIDragCallback.bind(this);
- this.disableCallback = ORYX.Core.UIDisableDrag.bind(this);
-
- this.movedCallback = option ? option.movedCallback : undefined;
- this.upCallback = option ? option.upCallback : undefined;
-
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback , false);
-
- };
-
- ORYX.Core.UIDragCallback = function(event) {
-
- var position = {
- x: Event.pointerX(event) - this.offSetPosition.x,
- y: Event.pointerY(event) - this.offSetPosition.y}
-
- position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
- position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
-
- position.x /= this.faktorXY.x;
- position.y /= this.faktorXY.y;
-
- this.uiObj.bounds.moveTo(position);
- //this.uiObj.update();
-
- if(this.movedCallback)
- this.movedCallback(event);
-
- Event.stop(event);
-
- };
-
- ORYX.Core.UIDisableDrag = function(event) {
- document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.dragCallback, false);
- document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.disableCallback, true);
-
- if(this.upCallback)
- this.upCallback(event);
-
- this.upCallback = undefined;
- this.movedCallback = undefined;
-
- Event.stop(event);
- };
-
- /**
- * Implements a command to move docker by an offset.
- *
- * @class ORYX.Core.MoveDockersCommand
- * @param {Object} object An object with the docker id as key and docker and offset as object value
- *
- */
- ORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({
- construct: function(dockers){
- this.dockers = $H(dockers);
- this.edges = $H({});
- },
- execute: function(){
- if (this.changes) {
- this.executeAgain();
- return;
- } else {
- this.changes = $H({});
- }
-
- this.dockers.values().each(function(docker){
- var edge = docker.docker.parent;
- if (!edge){ return }
-
- if (!this.changes[edge.getId()]) {
- this.changes[edge.getId()] = {
- edge : edge,
- oldDockerPositions : edge.dockers.map(function(r){ return r.bounds.center() })
- }
- }
- docker.docker.bounds.moveBy(docker.offset);
- this.edges[edge.getId()] = edge;
- docker.docker.update();
- }.bind(this));
- this.edges.each(function(edge){
- this.updateEdge(edge.value);
- if (this.changes[edge.value.getId()])
- this.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function(r){ return r.bounds.center() })
- }.bind(this));
- },
- updateEdge: function(edge){
- edge._update(true);
- [edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke("_update", [true])
- },
- executeAgain: function(){
- this.changes.values().each(function(change){
- // Reset the dockers
- this.removeAllDocker(change.edge);
- change.dockerPositions.each(function(pos, i){
- if (i==0||i==change.dockerPositions.length-1){ return }
- var docker = change.edge.createDocker(undefined, pos);
- docker.bounds.centerMoveTo(pos);
- docker.update();
- }.bind(this));
- this.updateEdge(change.edge);
- }.bind(this));
- },
- rollback: function(){
- this.changes.values().each(function(change){
- // Reset the dockers
- this.removeAllDocker(change.edge);
- change.oldDockerPositions.each(function(pos, i){
- if (i==0||i==change.oldDockerPositions.length-1){ return }
- var docker = change.edge.createDocker(undefined, pos);
- docker.bounds.centerMoveTo(pos);
- docker.update();
- }.bind(this));
- this.updateEdge(change.edge);
- }.bind(this));
- },
- removeAllDocker: function(edge){
- edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){
- edge.removeDocker(docker);
- })
- }
- });
-
- }();
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- /**
- * @classDescription Base class for Shapes.
- * @extends ORYX.Core.AbstractShape
- */
- ORYX.Core.Shape = {
- /**
- * Constructor
- */
- construct: function(options, stencil) {
- // call base class constructor
- arguments.callee.$.construct.apply(this, arguments);
-
- this.dockers = [];
- this.magnets = [];
-
- this._defaultMagnet;
-
- this.incoming = [];
- this.outgoing = [];
-
- this.nodes = [];
-
- this._dockerChangedCallback = this._dockerChanged.bind(this);
-
- //Hash map for all labels. Labels are not treated as children of shapes.
- this._labels = new Hash();
-
- // create SVG node
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
- null,
- ['g', {id:"svg-" + this.resourceId},
- ['g', {"class": "stencils"},
- ['g', {"class": "me"}],
- ['g', {"class": "children", style:"overflow:hidden"}],
- ['g', {"class": "edge"}]
- ],
- ['g', {"class": "controls"},
- ['g', {"class": "dockers"}],
- ['g', {"class": "magnets"}]
- ]
- ]);
- },
- /**
- * If changed flag is set, refresh method is called.
- */
- update: function() {
- //if(this.isChanged) {
- //this.layout();
- //}
- },
-
- /**
- * !!!Not called from any sub class!!!
- */
- _update: function() {
- },
-
- /**
- * Calls the super class refresh method
- * and updates the svg elements that are referenced by a property.
- */
- refresh: function() {
- //call base class refresh method
- arguments.callee.$.refresh.apply(this, arguments);
-
- if(this.node.ownerDocument) {
- //adjust SVG to properties' values
- var me = this;
- this.propertiesChanged.each((function(propChanged) {
- if(propChanged.value) {
- var prop = this.properties[propChanged.key];
- var property = this.getStencil().property(propChanged.key);
- if (property != undefined) {
- this.propertiesChanged[propChanged.key] = false;
-
- //handle choice properties
- if(property.type() == ORYX.CONFIG.TYPE_CHOICE) {
- //iterate all references to SVG elements
- property.refToView().each((function(ref) {
- //if property is referencing a label, update the label
- if(ref !== "") {
- var label = this._labels[this.id + ref];
- if (label && property.item(prop)) {
- label.text(property.item(prop).title());
- }
- }
- }).bind(this));
-
- //if the choice's items are referencing SVG elements
- // show the selected and hide all other referenced SVG
- // elements
- var refreshedSvgElements = new Hash();
- property.items().each((function(item) {
- item.refToView().each((function(itemRef) {
- if(itemRef == "") { return; }
-
- var svgElem = this.node.ownerDocument.getElementById(this.id + itemRef);
-
- if(!svgElem) { return; }
-
-
- /* Do not refresh the same svg element multiple times */
- if(!refreshedSvgElements[svgElem.id] || prop == item.value()) {
- svgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none'));
- refreshedSvgElements[svgElem.id] = svgElem;
- }
-
- // Reload the href if there is an image-tag
- if(ORYX.Editor.checkClassType(svgElem, SVGImageElement)) {
- svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href'));
- }
- }).bind(this));
- }).bind(this));
-
- } else { //handle properties that are not of type choice
- //iterate all references to SVG elements
- property.refToView().each((function(ref) {
- //if the property does not reference an SVG element,
- // do nothing
-
- if(ref === "") { return; }
-
- var refId = this.id + ref;
-
- //get the SVG element
- var svgElem = this.node.ownerDocument.getElementById(refId);
-
- //if the SVG element can not be found
- if(!svgElem || !(svgElem.ownerSVGElement)) {
- //if the referenced SVG element is a SVGAElement, it cannot
- // be found with getElementById (Firefox bug).
- // this is a work around
- if(property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) {
- var svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a');
-
- svgElem = $A(svgElems).find(function(elem) {
- return elem.getAttributeNS(null, 'id') === refId;
- });
-
- if(!svgElem) { return; }
- } else {
- //this.propertiesChanged[propChanged.key] = true;
- return;
- }
- }
-
- if (property.complexAttributeToView()) {
- var label = this._labels[refId];
- if (label) {
- try {
- propJson = prop.evalJSON();
- var value = propJson[property.complexAttributeToView()]
- label.text(value ? value : prop);
- } catch (e) {
- label.text(prop);
- }
- }
-
- } else {
-
- switch (property.type()) {
- case ORYX.CONFIG.TYPE_BOOLEAN:
-
- if (typeof prop == "string")
- prop = prop === "true"
-
- svgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none');
-
- break;
- case ORYX.CONFIG.TYPE_COLOR:
- if(property.fill()) {
- if (svgElem.tagName.toLowerCase() === "stop"){
- if (prop){
-
- if (property.lightness() && property.lightness() !== 1){
- prop = ORYX.Utils.adjustLightness(prop, property.lightness());
- }
-
- svgElem.setAttributeNS(null, "stop-color", prop);
-
- // Adjust stop color of the others
- if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){
- ORYX.Utils.adjustGradient(svgElem.parentNode, svgElem);
- }
- }
-
- // If there is no value, set opaque
- if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){
- $A(svgElem.parentNode.getElementsByTagName('stop')).each(function(stop){
- stop.setAttributeNS(null, "stop-opacity", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0);
- }.bind(this))
- }
- } else {
- svgElem.setAttributeNS(null, 'fill', prop);
- }
- }
- if(property.stroke()) {
- svgElem.setAttributeNS(null, 'stroke', prop);
- }
- break;
- case ORYX.CONFIG.TYPE_STRING:
- var label = this._labels[refId];
- if (label) {
- label.text(prop);
- }
- break;
- case ORYX.CONFIG.TYPE_INTEGER:
- var label = this._labels[refId];
- if (label) {
- label.text(prop);
- }
- break;
- case ORYX.CONFIG.TYPE_FLOAT:
- if(property.fillOpacity()) {
- svgElem.setAttributeNS(null, 'fill-opacity', prop);
- }
- if(property.strokeOpacity()) {
- svgElem.setAttributeNS(null, 'stroke-opacity', prop);
- }
- if(!property.fillOpacity() && !property.strokeOpacity()) {
- var label = this._labels[refId];
- if (label) {
- label.text(prop);
- }
- }
- break;
- case ORYX.CONFIG.TYPE_URL:
- case ORYX.CONFIG.TYPE_DIAGRAM_LINK:
- //TODO what is the dafault path?
- var hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href');
- if(hrefAttr) {
- hrefAttr.textContent = prop;
- } else {
- svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop);
- }
- break;
- }
- }
- }).bind(this));
-
-
- }
- }
-
- }
- }).bind(this));
-
- //update labels
- this._labels.values().each(function(label) {
- label.update();
- });
- }
- },
-
- layout: function() {
- //this.getStencil().layout(this)
- var layoutEvents = this.getStencil().layout()
- if (layoutEvents) {
- layoutEvents.each(function(event) {
-
- // setup additional attributes
- event.shape = this;
- event.forceExecution = true;
-
- // do layouting
- this._delegateEvent(event);
- }.bind(this))
-
- }
- },
-
- /**
- * Returns an array of Label objects.
- */
- getLabels: function() {
- return this._labels.values();
- },
-
- /**
- * Returns the label for a given ref
- * @return {ORYX.Core.Label} Returns null if there is no label
- */
- getLabel: function(ref){
- if (!ref){
- return null;
- }
- return (this._labels.find(function(o){
- return o.key.endsWith(ref);
- })||{}).value || null;
- },
-
- /**
- * Hides all related labels
- *
- */
- hideLabels: function(){
- this.getLabels().invoke("hide");
- },
- /**
- * Shows all related labels
- *
- */
- showLabels: function(){
- var labels = this.getLabels();
- labels.invoke("show");
- labels.each(function(label) {
- label.update();
- });
- },
-
- setOpacity: function(value, animate){
-
- // 0.0 <= value <= 1.0
- value = Math.max(Math.min((typeof value == "number" ? value : 1.0), 1.0), 0.0);
-
- //if (animate !== true){
- if (value !== 1.0){
- value = String(value);
- this.node.setAttributeNS(null, "fill-opacity", value)
- this.node.setAttributeNS(null, "stroke-opacity", value)
- } else {
- this.node.removeAttributeNS(null, "fill-opacity");
- this.node.removeAttributeNS(null, "stroke-opacity");
- }
- /*} else {
- var args = {opacity:{to:value}};
- if (!this.isVisible){
- this.show();
- }
- if (this.currentAnim){
- this.currentAnim.stop();
- }
-
- this.currentAnim = Ext.lib.Anim.run(this.node, args, 0.4, "easeOut", function(){
- if (args.opacity.to === 0.0){
- this.hide();
- } else if (args.opacity.to === 1.0){
- this.node.removeAttributeNS(null, "style");
- }
- delete this.currentAnim;
- }, this)
- }*/
-
- },
-
- /**
- * Returns an array of dockers of this object.
- */
- getDockers: function() {
- return this.dockers;
- },
-
- getMagnets: function() {
- return this.magnets;
- },
-
- getDefaultMagnet: function() {
- if(this._defaultMagnet) {
- return this._defaultMagnet;
- } else if (this.magnets.length > 0) {
- return this.magnets[0];
- } else {
- return undefined;
- }
- },
- getParentShape: function() {
- return this.parent;
- },
-
- getIncomingShapes: function(iterator) {
- if(iterator) {
- this.incoming.each(iterator);
- }
- return this.incoming;
- },
-
- getIncomingNodes: function(iterator) {
- return this.incoming.select(function(incoming){
- var isNode = (incoming instanceof ORYX.Core.Node);
- if(isNode && iterator) iterator(incoming);
- return isNode;
- });
- },
-
-
- getOutgoingShapes: function(iterator) {
- if(iterator) {
- this.outgoing.each(iterator);
- }
- return this.outgoing;
- },
-
- getOutgoingNodes: function(iterator) {
- return this.outgoing.select(function(out){
- var isNode = (out instanceof ORYX.Core.Node);
- if(isNode && iterator) iterator(out);
- return isNode;
- });
- },
-
- getAllDockedShapes: function(iterator) {
- var result = this.incoming.concat(this.outgoing);
- if(iterator) {
- result.each(iterator);
- }
- return result
- },
- getCanvas: function() {
- if(this.parent instanceof ORYX.Core.Canvas) {
- return this.parent;
- } else if(this.parent instanceof ORYX.Core.Shape) {
- return this.parent.getCanvas();
- } else {
- return undefined;
- }
- },
-
- /**
- *
- * @param {Object} deep
- * @param {Object} iterator
- */
- getChildNodes: function(deep, iterator) {
- if(!deep && !iterator) {
- return this.nodes.clone();
- } else {
- var result = [];
- this.nodes.each(function(uiObject) {
- if(!uiObject.isVisible){return}
- if(iterator) {
- iterator(uiObject);
- }
- result.push(uiObject);
-
- if(deep && uiObject instanceof ORYX.Core.Shape) {
- result = result.concat(uiObject.getChildNodes(deep, iterator));
- }
- });
-
- return result;
- }
- },
-
- /**
- * Overrides the UIObject.add method. Adds uiObject to the correct sub node.
- * @param {UIObject} uiObject
- * @param {Number} index
- */
- add: function(uiObject, index, silent) {
- //parameter has to be an UIObject, but
- // must not be an Edge.
- if(uiObject instanceof ORYX.Core.UIObject
- && !(uiObject instanceof ORYX.Core.Edge)) {
-
- if (!(this.children.member(uiObject))) {
- //if uiObject is child of another parent, remove it from that parent.
- if(uiObject.parent) {
- uiObject.parent.remove(uiObject, true);
- }
- //add uiObject to this Shape
- if(index != undefined)
- this.children.splice(index, 0, uiObject);
- else
- this.children.push(uiObject);
- //set parent reference
- uiObject.parent = this;
- //add uiObject.node to this.node depending on the type of uiObject
- var parent;
- if(uiObject instanceof ORYX.Core.Node) {
- parent = this.node.childNodes[0].childNodes[1];
- this.nodes.push(uiObject);
- } else if(uiObject instanceof ORYX.Core.Controls.Control) {
- var ctrls = this.node.childNodes[1];
- if(uiObject instanceof ORYX.Core.Controls.Docker) {
- parent = ctrls.childNodes[0];
- if (this.dockers.length >= 2){
- this.dockers.splice(index!==undefined?Math.min(index, this.dockers.length-1):this.dockers.length-1, 0, uiObject);
- } else {
- this.dockers.push(uiObject);
- }
- } else if(uiObject instanceof ORYX.Core.Controls.Magnet) {
- parent = ctrls.childNodes[1];
- this.magnets.push(uiObject);
- } else {
- parent = ctrls;
- }
- } else { //UIObject
- parent = this.node;
- }
- if(index != undefined && index < parent.childNodes.length)
- uiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]);
- else
- uiObject.node = parent.appendChild(uiObject.node);
-
- this._changed();
- //uiObject.bounds.registerCallback(this._changedCallback);
-
-
- if(this.eventHandlerCallback && silent !== true)
- this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject})
-
- } else {
- ORYX.Log.warn("add: ORYX.Core.UIObject is already a child of this object.");
- }
- } else {
- ORYX.Log.warn("add: Parameter is not of type ORYX.Core.UIObject.");
- }
- },
- /**
- * Overrides the UIObject.remove method. Removes uiObject.
- * @param {UIObject} uiObject
- */
- remove: function(uiObject, silent) {
- //if uiObject is a child of this object, remove it.
- if (this.children.member(uiObject)) {
- //remove uiObject from children
- var parent = uiObject.parent;
- this.children = this.children.without(uiObject);
- //delete parent reference of uiObject
- uiObject.parent = undefined;
- //delete uiObject.node from this.node
- if(uiObject instanceof ORYX.Core.Shape) {
- if(uiObject instanceof ORYX.Core.Edge) {
- uiObject.removeMarkers();
- uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node);
- } else {
- uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node);
- this.nodes = this.nodes.without(uiObject);
- }
- } else if(uiObject instanceof ORYX.Core.Controls.Control) {
- if (uiObject instanceof ORYX.Core.Controls.Docker) {
- uiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node);
- this.dockers = this.dockers.without(uiObject);
- } else if (uiObject instanceof ORYX.Core.Controls.Magnet) {
- uiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node);
- this.magnets = this.magnets.without(uiObject);
- } else {
- uiObject.node = this.node.childNodes[1].removeChild(uiObject.node);
- }
- }
- if(this.eventHandlerCallback && silent !== true)
- this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent});
-
- this._changed();
- //uiObject.bounds.unregisterCallback(this._changedCallback);
- } else {
- ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object.");
- }
- },
-
- /**
- * Calculate the Border Intersection Point between two points
- * @param {PointA}
- * @param {PointB}
- */
- getIntersectionPoint: function() {
-
- var pointAX, pointAY, pointBX, pointBY;
-
- // Get the the two Points
- switch(arguments.length) {
- case 2:
- pointAX = arguments[0].x;
- pointAY = arguments[0].y;
- pointBX = arguments[1].x;
- pointBY = arguments[1].y;
- break;
- case 4:
- pointAX = arguments[0];
- pointAY = arguments[1];
- pointBX = arguments[2];
- pointBY = arguments[3];
- break;
- default:
- throw "getIntersectionPoints needs two or four arguments";
- }
-
-
-
- // Defined an include and exclude point
- var includePointX, includePointY, excludePointX, excludePointY;
- var bounds = this.absoluteBounds();
-
- if(this.isPointIncluded(pointAX, pointAY, bounds)){
- includePointX = pointAX;
- includePointY = pointAY;
- } else {
- excludePointX = pointAX;
- excludePointY = pointAY;
- }
- if(this.isPointIncluded(pointBX, pointBY, bounds)){
- includePointX = pointBX;
- includePointY = pointBY;
- } else {
- excludePointX = pointBX;
- excludePointY = pointBY;
- }
-
- // If there is no inclue or exclude Shape, than return
- if(!includePointX || !includePointY || !excludePointX || !excludePointY) {
- return undefined;
- }
- var midPointX = 0;
- var midPointY = 0;
-
- var refPointX, refPointY;
-
- var minDifferent = 1;
- // Get the UpperLeft and LowerRight
- //var ul = bounds.upperLeft();
- //var lr = bounds.lowerRight();
-
- var i = 0;
-
- while(true) {
- // Calculate the midpoint of the current to points
- var midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0);
- var midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0);
-
-
- // Set the new midpoint by the means of the include of the bounds
- if(this.isPointIncluded(midPointX, midPointY, bounds)){
- includePointX = midPointX;
- includePointY = midPointY;
- } else {
- excludePointX = midPointX;
- excludePointY = midPointY;
- }
-
- // Calc the length of the line
- var length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2))
- // Calc a point one step from the include point
- refPointX = includePointX + ((excludePointX - includePointX) / length),
- refPointY = includePointY + ((excludePointY - includePointY) / length)
-
-
- // If the reference point not in the bounds, break
- if(!this.isPointIncluded(refPointX, refPointY, bounds)) {
- break
- }
-
-
- }
- // Return the last includepoint
- return {x:refPointX , y:refPointY};
- },
-
-
- /**
- * Calculate if the point is inside the Shape
- * @param {PointX}
- * @param {PointY}
- */
- isPointIncluded: function(){
- return false
- },
- /**
- * Returns TRUE if the given node
- * is a child node of the shapes node
- * @param {Element} node
- * @return {Boolean}
- *
- */
- containsNode: function(node){
- var me = this.node.firstChild.firstChild;
- while(node){
- if (node == me){
- return true;
- }
- node = node.parentNode;
- }
- return false
- },
-
- /**
- * Calculate if the point is over an special offset area
- * @param {Point}
- */
- isPointOverOffset: function(){
- return this.isPointIncluded.apply( this , arguments )
- },
-
- _dockerChanged: function() {
- },
-
- /**
- * Create a Docker for this Edge
- *
- */
- createDocker: function(index, position) {
- var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});
- docker.bounds.registerCallback(this._dockerChangedCallback);
- if(position) {
- docker.bounds.centerMoveTo(position);
- }
- this.add(docker, index);
-
- return docker
- },
- /**
- * Get the serialized object
- * return Array with hash-entrees (prefix, name, value)
- * Following values will given:
- * Bounds
- * Outgoing Shapes
- * Parent
- */
- serialize: function() {
- var serializedObject = arguments.callee.$.serialize.apply(this);
- // Add the bounds
- serializedObject.push({name: 'bounds', prefix:'oryx', value: this.bounds.serializeForERDF(), type: 'literal'});
- // Add the outgoing shapes
- this.getOutgoingShapes().each((function(followingShape){
- serializedObject.push({name: 'outgoing', prefix:'raziel', value: '#'+ERDF.__stripHashes(followingShape.resourceId), type: 'resource'});
- }).bind(this));
- // Add the parent shape, if the parent not the canvas
- //if(this.parent instanceof ORYX.Core.Shape){
- serializedObject.push({name: 'parent', prefix:'raziel', value: '#'+ERDF.__stripHashes(this.parent.resourceId), type: 'resource'});
- //}
-
- return serializedObject;
- },
-
-
- deserialize: function(serialize, json){
- arguments.callee.$.deserialize.apply(this, arguments);
-
- // Set the Bounds
- var bounds = serialize.find(function(ser){ return 'oryx-bounds' === (ser.prefix+"-"+ser.name) });
- if (bounds) {
- var b = bounds.value.replace(/,/g, " ").split(" ").without("");
- if (this instanceof ORYX.Core.Edge) {
- if (!this.dockers.first().isChanged)
- this.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1]));
- if (!this.dockers.last().isChanged)
- this.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3]));
- } else {
- this.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3]));
- }
- }
-
- if (json && json.labels instanceof Array){
- json.labels.each(function(slabel){
- var label = this.getLabel(slabel.ref);
- if (label){
- label.deserialize(slabel, this);
- }
- }.bind(this))
- }
- },
-
- toJSON: function(){
- var json = arguments.callee.$.toJSON.apply(this, arguments);
-
- var labels = [], id = this.id;
- this._labels.each(function(obj){
- var slabel = obj.value.serialize();
- if (slabel){
- slabel.ref = obj.key.replace(id, '');
- labels.push(slabel);
- }
- });
-
- if (labels.length > 0){
- json.labels = labels;
- }
- return json;
- },
-
- /**
- * Private methods.
- */
- /**
- * Child classes have to overwrite this method for initializing a loaded
- * SVG representation.
- * @param {SVGDocument} svgDocument
- */
- _init: function(svgDocument) {
- //adjust ids
- this._adjustIds(svgDocument, 0);
- },
- _adjustIds: function(element, idIndex) {
- if(element instanceof Element) {
- var eid = element.getAttributeNS(null, 'id');
- if(eid && eid !== "") {
- element.setAttributeNS(null, 'id', this.id + eid);
- } else {
- element.setAttributeNS(null, 'id', this.id + "_" + this.id + "_" + idIndex);
- idIndex++;
- }
-
- // Replace URL in fill attribute
- var fill = element.getAttributeNS(null, 'fill');
- if (fill&&fill.include("url(#")){
- fill = fill.replace(/url\(#/g, 'url(#'+this.id);
- element.setAttributeNS(null, 'fill', fill);
- }
-
- if(element.hasChildNodes()) {
- for(var i = 0; i < element.childNodes.length; i++) {
- idIndex = this._adjustIds(element.childNodes[i], idIndex);
- }
- }
- }
- return idIndex;
- },
- toString: function() { return "ORYX.Core.Shape " + this.getId() }
- };
- ORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
- /**
- * @classDescription Abstract base class for all Controls.
- */
- ORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({
-
- toString: function() { return "Control " + this.id; }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
- /**
- * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used
- * for positioning shape objects.
- * @extends {Control}
- *
- * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!!
- */
- ORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({
- /**
- * Constructor
- */
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
-
- this.isMovable = true; // Enables movability
- this.bounds.set(0, 0, 16, 16); // Set the bounds
- this.referencePoint = undefined; // Refrenzpoint
- this._dockedShapeBounds = undefined;
- this._dockedShape = undefined;
- this._oldRefPoint1 = undefined;
- this._oldRefPoint2 = undefined;
-
- //this.anchors = [];
- this.anchorLeft;
- this.anchorRight;
- this.anchorTop;
- this.anchorBottom;
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
- null,
- ['g']);
- // The DockerNode reprasentation
- this._dockerNode = ORYX.Editor.graft("http://www.w3.org/2000/svg",
- this.node,
- ['g', {"pointer-events":"all"},
- ['circle', {cx:"8", cy:"8", r:"8", stroke:"none", fill:"none"}],
- ['circle', {cx:"8", cy:"8", r:"3", stroke:"black", fill:"red", "stroke-width":"1"}]
- ]);
-
- // The ReferenzNode reprasentation
- this._referencePointNode = ORYX.Editor.graft("http://www.w3.org/2000/svg",
- this.node,
- ['g', {"pointer-events":"none"},
- ['circle', {cx: this.bounds.upperLeft().x, cy: this.bounds.upperLeft().y, r: 3, fill:"red", "fill-opacity":0.4}]]);
- // Hide the Docker
- this.hide();
-
- //Add to the EventHandler
- this.addEventHandlers(this._dockerNode);
- // Buffer the Update Callback for un-/register on Event-Handler
- this._updateCallback = this._changed.bind(this);
- },
-
- update: function() {
- // If there have an DockedShape
- if(this._dockedShape) {
- if(this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) {
- // Calc the delta of width and height of the lastBounds and the current Bounds
- var dswidth = this._dockedShapeBounds.width();
- var dsheight = this._dockedShapeBounds.height();
- if(!dswidth)
- dswidth = 1;
- if(!dsheight)
- dsheight = 1;
- var widthDelta = this._dockedShape.bounds.width() / dswidth;
- var heightDelta = this._dockedShape.bounds.height() / dsheight;
-
- // If there is an different
- if(widthDelta !== 1.0 || heightDelta !== 1.0) {
- // Set the delta
- this.referencePoint.x *= widthDelta;
- this.referencePoint.y *= heightDelta;
- }
-
- // Clone these bounds
- this._dockedShapeBounds = this._dockedShape.bounds.clone();
- }
-
- // Get the first and the last Docker of the parent Shape
- var dockerIndex = this.parent.dockers.indexOf(this)
- var dock1 = this;
- var dock2 = this.parent.dockers.length > 1 ?
- (dockerIndex === 0? // If there is the first element
- this.parent.dockers[dockerIndex + 1]: // then take the next docker
- this.parent.dockers[dockerIndex - 1]): // if not, then take the docker before
- undefined;
-
- // Calculate the first absolute Refenzpoint
- var absoluteReferenzPoint1 = dock1.getDockedShape() ?
- dock1.getAbsoluteReferencePoint() :
- dock1.bounds.center();
- // Calculate the last absolute Refenzpoint
- var absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ?
- dock2.getAbsoluteReferencePoint() :
- dock2 ?
- dock2.bounds.center() :
- undefined;
- // If there is no last absolute Referenzpoint
- if(!absoluteReferenzPoint2) {
- // Calculate from the middle of the DockedShape
- var center = this._dockedShape.absoluteCenterXY();
- var minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height();
- absoluteReferenzPoint2 = {
- x: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension,
- y: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension
- }
- }
-
- var newPoint = undefined;
-
- /*if (!this._oldRefPoint1 || !this._oldRefPoint2 ||
- absoluteReferenzPoint1.x !== this._oldRefPoint1.x ||
- absoluteReferenzPoint1.y !== this._oldRefPoint1.y ||
- absoluteReferenzPoint2.x !== this._oldRefPoint2.x ||
- absoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/
-
- // Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points
- newPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2);
-
- // If there is new point, take the referencepoint as the new point
- if(!newPoint) {
- newPoint = this.getAbsoluteReferencePoint();
- }
-
- if(this.parent && this.parent.parent) {
- var grandParentPos = this.parent.parent.absoluteXY();
- newPoint.x -= grandParentPos.x;
- newPoint.y -= grandParentPos.y;
- }
-
- // Set the bounds to the new point
- this.bounds.centerMoveTo(newPoint)
-
- this._oldRefPoint1 = absoluteReferenzPoint1;
- this._oldRefPoint2 = absoluteReferenzPoint2;
- }
- /*else {
- newPoint = this.bounds.center();
- }*/
-
-
- // }
-
- // Call the super class
- arguments.callee.$.update.apply(this, arguments);
- },
- /**
- * Calls the super class refresh method and updates the view of the docker.
- */
- refresh: function() {
- arguments.callee.$.refresh.apply(this, arguments);
-
- // Refresh the dockers node
- var p = this.bounds.upperLeft();
- this._dockerNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
-
- // Refresh the referencepoints node
- p = Object.clone(this.referencePoint);
-
- if(p && this._dockedShape){
- var upL
- if(this.parent instanceof ORYX.Core.Edge) {
- upL = this._dockedShape.absoluteXY();
- } else {
- upL = this._dockedShape.bounds.upperLeft();
- }
- p.x += upL.x;
- p.y += upL.y;
- } else {
- p = this.bounds.center();
- }
- this._referencePointNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
- },
- /**
- * Set the reference point
- * @param {Object} point
- */
- setReferencePoint: function(point) {
- // Set the referencepoint
- if(this.referencePoint !== point &&
- (!this.referencePoint ||
- !point ||
- this.referencePoint.x !== point.x ||
- this.referencePoint.y !== point.y)) {
-
- this.referencePoint = point;
- this._changed();
- }
-
- // Update directly, because the referencepoint has no influence of the bounds
- //this.refresh();
- },
-
- /**
- * Get the absolute referencepoint
- */
- getAbsoluteReferencePoint: function() {
- if(!this.referencePoint || !this._dockedShape) {
- return undefined;
- } else {
- var absUL = this._dockedShape.absoluteXY();
- return {
- x: this.referencePoint.x + absUL.x,
- y: this.referencePoint.y + absUL.y
- }
- }
- },
-
- /**
- * Set the docked Shape from the docker
- * @param {Object} shape
- */
- setDockedShape: function(shape) {
- // If there is an old docked Shape
- if(this._dockedShape) {
- this._dockedShape.bounds.unregisterCallback(this._updateCallback)
-
- // Delete the Shapes from the incoming and outgoing array
- // If this Docker the incoming of the Shape
- if(this === this.parent.dockers.first()) {
-
- this.parent.incoming = this.parent.incoming.without(this._dockedShape);
- this._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent);
-
- // If this Docker the outgoing of the Shape
- } else if (this === this.parent.dockers.last()){
-
- this.parent.outgoing = this.parent.outgoing.without(this._dockedShape);
- this._dockedShape.incoming = this._dockedShape.incoming.without(this.parent);
-
- }
-
- }
-
- // Set the new Shape
- this._dockedShape = shape;
- this._dockedShapeBounds = undefined;
- var referencePoint = undefined;
-
- // If there is an Shape, register the updateCallback if there are changes in the shape bounds
- if(this._dockedShape) {
-
- // Add the Shapes to the incoming and outgoing array
- // If this Docker the incoming of the Shape
- if(this === this.parent.dockers.first()) {
-
- this.parent.incoming.push(shape);
- shape.outgoing.push(this.parent);
-
- // If this Docker the outgoing of the Shape
- } else if (this === this.parent.dockers.last()){
-
- this.parent.outgoing.push(shape);
- shape.incoming.push(this.parent);
-
- }
-
- // Get the bounds and set the new referencepoint
- var bounds = this.bounds;
- var absUL = shape.absoluteXY();
-
- /*if(shape.parent){
- var b = shape.parent.bounds.upperLeft();
- absUL.x -= b.x;
- absUL.y -= b.y;
- }*/
-
- referencePoint = {
- x: bounds.center().x - absUL.x,
- y: bounds.center().y - absUL.y
- }
-
- this._dockedShapeBounds = this._dockedShape.bounds.clone();
-
- this._dockedShape.bounds.registerCallback(this._updateCallback);
-
- // Set the color of the docker as docked
- this.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR);
- } else {
- // Set the color of the docker as undocked
- this.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR);
- }
- // Set the referencepoint
- this.setReferencePoint(referencePoint);
- this._changed();
- //this.update();
- },
-
- /**
- * Get the docked Shape
- */
- getDockedShape: function() {
- return this._dockedShape;
- },
- /**
- * Returns TRUE if the docker has a docked shape
- */
- isDocked: function() {
- return !!this._dockedShape;
- },
-
- /**
- * Set the Color of the Docker
- * @param {Object} color
- */
- setDockerColor: function(color) {
- this._dockerNode.lastChild.setAttributeNS(null, "fill", color);
- },
-
- preventHiding: function(prevent){
- this._preventHiding = Math.max(0, (this._preventHiding||0) + (prevent ? 1 : -1));
- },
-
- /**
- * Hides this UIObject and all its children.
- */
- hide: function() {
- if (this._preventHiding){
- return false;
- }
-
- // Hide docker and reference point
- this.node.setAttributeNS(null, 'visibility', 'hidden');
- this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');
-
- this.children.each(function(uiObj) {
- uiObj.hide();
- });
- },
-
- /**
- * Enables visibility of this UIObject and all its children.
- */
- show: function() {
- // Show docker
- this.node.setAttributeNS(null, 'visibility', 'visible');
-
- // Hide reference point if the connected shape is an edge
- if (this.getDockedShape() instanceof ORYX.Core.Edge){
- this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden');
- } else {
- this._referencePointNode.setAttributeNS(null, 'visibility', 'visible');
- }
-
- this.children.each(function(uiObj) {
- uiObj.show();
- });
- },
-
- toString: function() { return "Docker " + this.id }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if(!ORYX) {var ORYX = {};}
- if(!ORYX.Core) {ORYX.Core = {};}
- if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};}
- /**
- * @classDescription Represents a magnet that is part of another shape and can
- * be attached to dockers. Magnets are used for linking edge objects
- * to other Shape objects.
- * @extends {Control}
- */
- ORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({
-
- /**
- * Constructor
- */
- construct: function() {
- arguments.callee.$.construct.apply(this, arguments);
-
- //this.anchors = [];
- this.anchorLeft;
- this.anchorRight;
- this.anchorTop;
- this.anchorBottom;
-
- this.bounds.set(0, 0, 16, 16);
-
- //graft magnet's root node into owner's control group.
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg",
- null,
- ['g', {"pointer-events":"all"},
- ['circle', {cx:"8", cy:"8", r:"4", stroke:"none", fill:"red", "fill-opacity":"0.3"}],
- ]);
-
- this.hide();
- },
-
- update: function() {
- arguments.callee.$.update.apply(this, arguments);
-
- //this.isChanged = true;
- },
-
- _update: function() {
- arguments.callee.$.update.apply(this, arguments);
-
- //this.isChanged = true;
- },
-
- refresh: function() {
- arguments.callee.$.refresh.apply(this, arguments);
- var p = this.bounds.upperLeft();
- /*if(this.parent) {
- var parentPos = this.parent.bounds.upperLeft();
- p.x += parentPos.x;
- p.y += parentPos.y;
- }*/
-
- this.node.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')');
- },
-
- show: function() {
- //this.refresh();
- arguments.callee.$.show.apply(this, arguments);
- },
-
- toString: function() {
- return "Magnet " + this.id;
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * Init namespaces
- */
- if (!ORYX) {
- var ORYX = {};
- }
- if (!ORYX.Core) {
- ORYX.Core = {};
- }
- /**
- * @classDescription Abstract base class for all Nodes.
- * @extends ORYX.Core.Shape
- */
- ORYX.Core.Node = {
- /**
- * Constructor
- * @param options {Object} A container for arguments.
- * @param stencil {Stencil}
- */
- construct: function(options, stencil){
- arguments.callee.$.construct.apply(this, arguments);
-
- this.isSelectable = true;
- this.isMovable = true;
- this._dockerUpdated = false;
-
- this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values
- this._svgShapes = []; //array of all SVGShape objects of
- // SVG representation
-
- //TODO vielleicht in shape verschieben?
- this.minimumSize = undefined; // {width:..., height:...}
- this.maximumSize = undefined;
-
- //TODO vielleicht in shape oder uiobject verschieben?
- // vielleicht sogar isResizable ersetzen?
- this.isHorizontallyResizable = false;
- this.isVerticallyResizable = false;
-
- this.dataId = undefined;
-
- this._init(this._stencil.view());
- },
-
- /**
- * This method checks whether the shape is resized correctly and calls the
- * super class update method.
- */
- _update: function(){
-
- this.dockers.invoke("update");
- if (this.isChanged) {
- var bounds = this.bounds;
- var oldBounds = this._oldBounds;
-
- if (this.isResized) {
-
- var widthDelta = bounds.width() / oldBounds.width();
- var heightDelta = bounds.height() / oldBounds.height();
-
- //iterate over all relevant svg elements and resize them
- this._svgShapes.each(function(svgShape){
- //adjust width
- if (svgShape.isHorizontallyResizable) {
- svgShape.width = svgShape.oldWidth * widthDelta;
- }
- //adjust height
- if (svgShape.isVerticallyResizable) {
- svgShape.height = svgShape.oldHeight * heightDelta;
- }
-
- //check, if anchors are set
- var anchorOffset;
- var leftIncluded = svgShape.anchorLeft;
- var rightIncluded = svgShape.anchorRight;
-
- if (rightIncluded) {
- anchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth);
- if (leftIncluded) {
- svgShape.width = bounds.width() - svgShape.x - anchorOffset;
- }
- else {
- svgShape.x = bounds.width() - (anchorOffset + svgShape.width);
- }
- }
- else
- if (!leftIncluded) {
- svgShape.x = widthDelta * svgShape.oldX;
- if (!svgShape.isHorizontallyResizable) {
- svgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2;
- }
- }
-
- var topIncluded = svgShape.anchorTop;
- var bottomIncluded = svgShape.anchorBottom;
-
- if (bottomIncluded) {
- anchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight);
- if (topIncluded) {
- svgShape.height = bounds.height() - svgShape.y - anchorOffset;
- }
- else {
- // Hack for choreography task layouting
- if (!svgShape._isYLocked) {
- svgShape.y = bounds.height() - (anchorOffset + svgShape.height);
- }
- }
- }
- else
- if (!topIncluded) {
- svgShape.y = heightDelta * svgShape.oldY;
- if (!svgShape.isVerticallyResizable) {
- svgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2;
- }
- }
- });
-
- //check, if the current bounds is unallowed horizontally or vertically resized
- var p = {
- x: 0,
- y: 0
- };
- if (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) {
- p.x = oldBounds.width() - bounds.width();
- }
- if (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) {
- p.y = oldBounds.height() - bounds.height();
- }
- if (p.x !== 0 || p.y !== 0) {
- bounds.extend(p);
- }
-
- //check, if the current bounds are between maximum and minimum bounds
- p = {
- x: 0,
- y: 0
- };
- var widthDifference, heightDifference;
- if (this.minimumSize) {
-
- ORYX.Log.debug("Shape (%0)'s min size: (%1x%2)", this, this.minimumSize.width, this.minimumSize.height);
- widthDifference = this.minimumSize.width - bounds.width();
- if (widthDifference > 0) {
- p.x += widthDifference;
- }
- heightDifference = this.minimumSize.height - bounds.height();
- if (heightDifference > 0) {
- p.y += heightDifference;
- }
- }
- if (this.maximumSize) {
-
- ORYX.Log.debug("Shape (%0)'s max size: (%1x%2)", this, this.maximumSize.width, this.maximumSize.height);
- widthDifference = bounds.width() - this.maximumSize.width;
- if (widthDifference > 0) {
- p.x -= widthDifference;
- }
- heightDifference = bounds.height() - this.maximumSize.height;
- if (heightDifference > 0) {
- p.y -= heightDifference;
- }
- }
- if (p.x !== 0 || p.y !== 0) {
- bounds.extend(p);
- }
-
- //update magnets
-
- var widthDelta = bounds.width() / oldBounds.width();
- var heightDelta = bounds.height() / oldBounds.height();
-
- var leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY;
-
- this.magnets.each(function(magnet){
- leftIncluded = magnet.anchorLeft;
- rightIncluded = magnet.anchorRight;
- topIncluded = magnet.anchorTop;
- bottomIncluded = magnet.anchorBottom;
-
- center = magnet.bounds.center();
-
- if (leftIncluded) {
- newX = center.x;
- }
- else
- if (rightIncluded) {
- newX = bounds.width() - (oldBounds.width() - center.x)
- }
- else {
- newX = center.x * widthDelta;
- }
-
- if (topIncluded) {
- newY = center.y;
- }
- else
- if (bottomIncluded) {
- newY = bounds.height() - (oldBounds.height() - center.y);
- }
- else {
- newY = center.y * heightDelta;
- }
-
- if (center.x !== newX || center.y !== newY) {
- magnet.bounds.centerMoveTo(newX, newY);
- }
- });
-
- //set new position of labels
- this.getLabels().each(function(label){
- // Set the position dependings on it anchor
- if (!label.isAnchorLeft()) {
- if (label.isAnchorRight()) {
- label.setX(bounds.width() - (oldBounds.width() - label.oldX))
- } else {
- label.setX((label.position?label.position.x:label.x) * widthDelta);
- }
- }
- if (!label.isAnchorTop()) {
- if (label.isAnchorBottom()) {
- label.setY(bounds.height() - (oldBounds.height() - label.oldY));
- } else {
- label.setY((label.position?label.position.y:label.y) * heightDelta);
- }
- }
-
- // If there is an position,
- // set the origin position as well
- if (label.position){
- if (!label.isOriginAnchorLeft()) {
- if (label.isOriginAnchorRight()) {
- label.setOriginX(bounds.width() - (oldBounds.width() - label.oldX))
- } else {
- label.setOriginX(label.x * widthDelta);
- }
- }
- if (!label.isOriginAnchorTop()) {
- if (label.isOriginAnchorBottom()) {
- label.setOriginY(bounds.height() - (oldBounds.height() - label.oldY));
- } else {
- label.setOriginY(label.y * heightDelta);
- }
- }
- }
- });
-
- //update docker
- var docker = this.dockers[0];
- if (docker) {
- docker.bounds.unregisterCallback(this._dockerChangedCallback);
- if (!this._dockerUpdated) {
- docker.bounds.centerMoveTo(this.bounds.center());
- this._dockerUpdated = false;
- }
-
- docker.update();
- docker.bounds.registerCallback(this._dockerChangedCallback);
- }
- this.isResized = false;
- }
-
- this.refresh();
-
- this.isChanged = false;
-
- this._oldBounds = this.bounds.clone();
- }
-
- this.children.each(function(value) {
- if(!(value instanceof ORYX.Core.Controls.Docker)) {
- value._update();
- }
- });
-
- if (this.dockers.length > 0&&!this.dockers.first().getDockedShape()) {
- this.dockers.each(function(docker){
- docker.bounds.centerMoveTo(this.bounds.center())
- }.bind(this))
- }
-
- /*this.incoming.each((function(edge) {
- if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))
- edge._update(true);
- }).bind(this));
-
- this.outgoing.each((function(edge) {
- if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node))
- edge._update(true);
- }).bind(this)); */
- },
-
- /**
- * This method repositions and resizes the SVG representation
- * of the shape.
- */
- refresh: function(){
- arguments.callee.$.refresh.apply(this, arguments);
-
- /** Movement */
- var x = this.bounds.upperLeft().x;
- var y = this.bounds.upperLeft().y;
-
- //set translation in transform attribute
- /*var attributeTransform = document.createAttributeNS(ORYX.CONFIG.NAMESPACE_SVG, "transform");
- attributeTransform.nodeValue = "translate(" + x + ", " + y + ")";
- this.node.firstChild.setAttributeNode(attributeTransform);*/
- // Move owner element
- this.node.firstChild.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
- // Move magnets
- this.node.childNodes[1].childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
-
- /** Resize */
-
- //iterate over all relevant svg elements and update them
- this._svgShapes.each(function(svgShape){
- svgShape.update();
- });
- },
-
- _dockerChanged: function(){
- var docker = this.dockers[0];
-
- //set the bounds of the the association
- this.bounds.centerMoveTo(docker.bounds.center());
-
- this._dockerUpdated = true;
- //this._update(true);
- },
-
- /**
- * This method traverses a tree of SVGElements and returns
- * all SVGShape objects. For each basic shape or path element
- * a SVGShape object is initialized.
- *
- * @param svgNode {SVGElement}
- * @return {Array} Array of SVGShape objects
- */
- _initSVGShapes: function(svgNode){
- var svgShapes = [];
- try {
- var svgShape = new ORYX.Core.SVG.SVGShape(svgNode);
- svgShapes.push(svgShape);
- }
- catch (e) {
- //do nothing
- }
-
- if (svgNode.hasChildNodes()) {
- for (var i = 0; i < svgNode.childNodes.length; i++) {
- svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i]));
- }
- }
-
- return svgShapes;
- },
-
- /**
- * Calculate if the point is inside the Shape
- * @param {PointX}
- * @param {PointY}
- * @param {absoluteBounds} optional: for performance
- */
- isPointIncluded: function(pointX, pointY, absoluteBounds){
- // If there is an arguments with the absoluteBounds
- var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds();
-
- if (!absBounds.isIncluded(pointX, pointY)) {
- return false;
- } else {
-
- }
-
-
- //point = Object.clone(point);
- var ul = absBounds.upperLeft();
- var x = pointX - ul.x;
- var y = pointY - ul.y;
-
- var i=0;
- do {
- var isPointIncluded = this._svgShapes[i++].isPointIncluded( x, y );
- } while( !isPointIncluded && i < this._svgShapes.length)
-
- return isPointIncluded;
- /*return this._svgShapes.any(function(svgShape){
- return svgShape.isPointIncluded(point);
- });*/
- },
-
-
- /**
- * Calculate if the point is over an special offset area
- * @param {Point}
- */
- isPointOverOffset: function( pointX, pointY ){
- var isOverEl = arguments.callee.$.isPointOverOffset.apply( this , arguments );
-
- if (isOverEl) {
-
- // If there is an arguments with the absoluteBounds
- var absBounds = this.absoluteBounds();
- absBounds.widen( - ORYX.CONFIG.BORDER_OFFSET );
-
- if ( !absBounds.isIncluded( pointX, pointY )) {
- return true;
- }
- }
-
- return false;
-
- },
-
- serialize: function(){
- var result = arguments.callee.$.serialize.apply(this);
-
- // Add the docker's bounds
- // nodes only have at most one docker!
- this.dockers.each((function(docker){
- if (docker.getDockedShape()) {
- var center = docker.referencePoint;
- center = center ? center : docker.bounds.center();
- result.push({
- name: 'docker',
- prefix: 'oryx',
- value: $H(center).values().join(','),
- type: 'literal'
- });
- }
- }).bind(this));
-
- // Get the spezific serialized object from the stencil
- try {
- //result = this.getStencil().serialize(this, result);
- var serializeEvent = this.getStencil().serialize();
-
- /*
- * call serialize callback by reference, result should be found
- * in serializeEvent.result
- */
- if(serializeEvent.type) {
- serializeEvent.shape = this;
- serializeEvent.data = result;
- serializeEvent.result = undefined;
- serializeEvent.forceExecution = true;
-
- this._delegateEvent(serializeEvent);
-
- if(serializeEvent.result) {
- result = serializeEvent.result;
- }
- }
- }
- catch (e) {
- }
- return result;
- },
-
- deserialize: function(data){
- arguments.callee.$.deserialize.apply(this, arguments);
-
- try {
- //data = this.getStencil().deserialize(this, data);
- var deserializeEvent = this.getStencil().deserialize();
-
- /*
- * call serialize callback by reference, result should be found
- * in serializeEventInfo.result
- */
- if(deserializeEvent.type) {
- deserializeEvent.shape = this;
- deserializeEvent.data = data;
- deserializeEvent.result = undefined;
- deserializeEvent.forceExecution = true;
-
- this._delegateEvent(deserializeEvent);
- if(deserializeEvent.result) {
- data = deserializeEvent.result;
- }
- }
- }
- catch (e) {
- }
-
- // Set the outgoing shapes
- var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'});
- outgoing.each((function(obj){
- // TODO: Look at Canvas
- if(!this.parent) {return};
-
- // Set outgoing Shape
- var next = this.getCanvas().getChildShapeByResourceId(obj.value);
-
- if(next){
- if(next instanceof ORYX.Core.Edge) {
- //Set the first docker of the next shape
- next.dockers.first().setDockedShape(this);
- next.dockers.first().setReferencePoint(next.dockers.first().bounds.center());
- } else if(next.dockers.length > 0) { //next is a node and next has a docker
- next.dockers.first().setDockedShape(this);
- //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
- }
- }
-
- }).bind(this));
-
- if (this.dockers.length === 1) {
- var dockerPos;
- dockerPos = data.find(function(entry){
- return (entry.prefix + "-" + entry.name === "oryx-dockers");
- });
-
- if (dockerPos) {
- var points = dockerPos.value.replace(/,/g, " ").split(" ").without("").without("#");
- if (points.length === 2 && this.dockers[0].getDockedShape()) {
- this.dockers[0].setReferencePoint({
- x: parseFloat(points[0]),
- y: parseFloat(points[1])
- });
- }
- else {
- this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1]));
- }
- }
- }
- },
-
- /**
- * This method excepts the SVGDoucment that is the SVG representation
- * of this shape.
- * The bounds of the shape are calculated, the SVG representation's upper left point
- * is moved to 0,0 and it the method sets if this shape is resizable.
- *
- * @param {SVGDocument} svgDocument
- */
- _init: function(svgDocument){
- arguments.callee.$._init.apply(this, arguments);
-
- var svgNode = svgDocument.getElementsByTagName("g")[0]; //outer most g node
- // set all required attributes
- var attributeTitle = svgDocument.ownerDocument.createAttributeNS(null, "title");
- attributeTitle.nodeValue = this.getStencil().title();
- svgNode.setAttributeNode(attributeTitle);
-
- var attributeId = svgDocument.ownerDocument.createAttributeNS(null, "id");
- attributeId.nodeValue = this.id;
- svgNode.setAttributeNode(attributeId);
-
- //
- var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //<g class=me>"
- svgNode = stencilTargetNode.appendChild(svgNode);
-
- // Add to the EventHandler
- this.addEventHandlers(svgNode.parentNode);
-
- /**set minimum and maximum size*/
- var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "minimumSize");
- if (minSizeAttr) {
- minSizeAttr = minSizeAttr.replace("/,/g", " ");
- var minSizeValues = minSizeAttr.split(" ");
- minSizeValues = minSizeValues.without("");
-
- if (minSizeValues.length > 1) {
- this.minimumSize = {
- width: parseFloat(minSizeValues[0]),
- height: parseFloat(minSizeValues[1])
- };
- }
- else {
- //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0)
- this.minimumSize = {
- width: 1,
- height: 1
- };
- }
- }
-
- var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "maximumSize");
- if (maxSizeAttr) {
- maxSizeAttr = maxSizeAttr.replace("/,/g", " ");
- var maxSizeValues = maxSizeAttr.split(" ");
- maxSizeValues = maxSizeValues.without("");
-
- if (maxSizeValues.length > 1) {
- this.maximumSize = {
- width: parseFloat(maxSizeValues[0]),
- height: parseFloat(maxSizeValues[1])
- };
- }
- }
-
- if (this.minimumSize && this.maximumSize &&
- (this.minimumSize.width > this.maximumSize.width ||
- this.minimumSize.height > this.maximumSize.height)) {
-
- //TODO wird verschluckt!!!
- throw this + ": Minimum Size must be greater than maxiumSize.";
- }
-
- /**get current bounds and adjust it to upperLeft == (0,0)*/
- //initialize all SVGShape objects
- this._svgShapes = this._initSVGShapes(svgNode);
-
- //get upperLeft and lowerRight of stencil
- var upperLeft = {
- x: undefined,
- y: undefined
- };
- var lowerRight = {
- x: undefined,
- y: undefined
- };
- var me = this;
- this._svgShapes.each(function(svgShape){
- upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x;
- upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y;
- lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width;
- lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height;
-
- /** set if resizing is enabled */
- //TODO isResizable durch die beiden anderen booleans ersetzen?
- if (svgShape.isHorizontallyResizable) {
- me.isHorizontallyResizable = true;
- me.isResizable = true;
- }
- if (svgShape.isVerticallyResizable) {
- me.isVerticallyResizable = true;
- me.isResizable = true;
- }
- if (svgShape.anchorTop && svgShape.anchorBottom) {
- me.isVerticallyResizable = true;
- me.isResizable = true;
- }
- if (svgShape.anchorLeft && svgShape.anchorRight) {
- me.isHorizontallyResizable = true;
- me.isResizable = true;
- }
- });
-
- //move all SVGShapes by -upperLeft
- this._svgShapes.each(function(svgShape){
- svgShape.x -= upperLeft.x;
- svgShape.y -= upperLeft.y;
- svgShape.update();
- });
-
- //set bounds of shape
- //the offsets are also needed for positioning the magnets and the docker
- var offsetX = upperLeft.x;
- var offsetY = upperLeft.y;
-
- lowerRight.x -= offsetX;
- lowerRight.y -= offsetY;
- upperLeft.x = 0;
- upperLeft.y = 0;
-
- //prevent that width or height of initial bounds is 0
- if (lowerRight.x === 0) {
- lowerRight.x = 1;
- }
- if (lowerRight.y === 0) {
- lowerRight.y = 1;
- }
-
- this._oldBounds.set(upperLeft, lowerRight);
- this.bounds.set(upperLeft, lowerRight);
-
- /**initialize magnets */
-
- var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnets");
-
- if (magnets && magnets.length > 0) {
-
- magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnet"));
-
- var me = this;
- magnets.each(function(magnetElem){
- var magnet = new ORYX.Core.Controls.Magnet({
- eventHandlerCallback: me.eventHandlerCallback
- });
- var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx"));
- var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy"));
- magnet.bounds.centerMoveTo({
- x: cx - offsetX,
- y: cy - offsetY
- });
-
- //get anchors
- var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
- if (anchors) {
- anchors = anchors.replace("/,/g", " ");
- anchors = anchors.split(" ").without("");
- for(var i = 0; i < anchors.length; i++) {
- switch(anchors[i].toLowerCase()) {
- case "left":
- magnet.anchorLeft = true;
- break;
- case "right":
- magnet.anchorRight = true;
- break;
- case "top":
- magnet.anchorTop = true;
- break;
- case "bottom":
- magnet.anchorBottom = true;
- break;
- }
- }
- }
-
- me.add(magnet);
-
- //check, if magnet is default magnet
- if (!this._defaultMagnet) {
- var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "default");
- if (defaultAttr && defaultAttr.toLowerCase() === "yes") {
- me._defaultMagnet = magnet;
- }
- }
- });
- }
- else {
- // Add a Magnet in the Center of Shape
- var magnet = new ORYX.Core.Controls.Magnet();
- magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2);
- this.add(magnet);
- }
-
- /**initialize docker */
- var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "docker");
-
- if (dockerElem && dockerElem.length > 0) {
- dockerElem = dockerElem[0];
- var docker = this.createDocker();
- var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx"));
- var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy"));
- docker.bounds.centerMoveTo({
- x: cx - offsetX,
- y: cy - offsetY
- });
-
- //get anchors
- var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors");
- if (anchors) {
- anchors = anchors.replace("/,/g", " ");
- anchors = anchors.split(" ").without("");
-
- for(var i = 0; i < anchors.length; i++) {
- switch(anchors[i].toLowerCase()) {
- case "left":
- docker.anchorLeft = true;
- break;
- case "right":
- docker.anchorRight = true;
- break;
- case "top":
- docker.anchorTop = true;
- break;
- case "bottom":
- docker.anchorBottom = true;
- break;
- }
- }
- }
- }
-
- /**initialize labels*/
- var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');
- $A(textElems).each((function(textElem){
- var label = new ORYX.Core.SVG.Label({
- textElement: textElem,
- shapeId: this.id
- });
- label.x -= offsetX;
- label.y -= offsetY;
- this._labels[label.id] = label;
-
- label.registerOnChange(this.layout.bind(this));
-
- }).bind(this));
- },
-
- /**
- * Override the Method, that a docker is not shown
- *
- */
- createDocker: function() {
- var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback});
- docker.bounds.registerCallback(this._dockerChangedCallback);
-
- this.dockers.push( docker );
- docker.parent = this;
- docker.bounds.registerCallback(this._changedCallback);
-
- return docker
- },
-
- toString: function(){
- return this._stencil.title() + " " + this.id
- }
- };
- ORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node);
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- NAMESPACE_SVG = "http://www.w3.org/2000/svg";
- NAMESPACE_ORYX = "http://www.b3mn.org/oryx";
- /**
- * Init namespaces
- */
- if (!ORYX) {
- var ORYX = {};
- }
- if (!ORYX.Core) {
- ORYX.Core = {};
- }
- /**
- * @classDescription Abstract base class for all connections.
- * @extends {ORYX.Core.Shape}
- * @param options {Object}
- *
- * TODO da die verschiebung der Edge nicht ueber eine
- * translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt,
- * muessen die kinder hier beim verschieben speziell betrachtet werden.
- * Das sollte ueberarbeitet werden.
- *
- */
- ORYX.Core.Edge = {
- /**
- * Constructor
- * @param {Object} options
- * @param {Stencil} stencil
- */
- construct: function(options, stencil){
- arguments.callee.$.construct.apply(this, arguments);
-
- this.isMovable = true;
- this.isSelectable = true;
-
- this._dockerUpdated = false;
-
- this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids
- this._paths = [];
- this._interactionPaths = [];
- this._dockersByPath = new Hash();
- this._markersByPath = new Hash();
-
- /* Data structures to store positioning information of attached child nodes */
- this.attachedNodePositionData = new Hash();
-
- //TODO was muss hier initial erzeugt werden?
- var stencilNode = this.node.childNodes[0].childNodes[0];
- stencilNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", stencilNode, ['g', {
- "pointer-events": "painted"
- }]);
-
- //Add to the EventHandler
- this.addEventHandlers(stencilNode.parentNode);
-
-
- this._oldBounds = this.bounds.clone();
-
- //load stencil
- this._init(this._stencil.view());
-
- if (stencil instanceof Array) {
- this.deserialize(stencil);
- }
-
- },
-
- _update: function(force){
- if(this._dockerUpdated || this.isChanged || force) {
-
- this.dockers.invoke("update");
-
- if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) {
- var width = this.bounds.width();
- var height = this.bounds.height();
- this.bounds.extend({
- x: width === 0 ? 2 : 0,
- y: height === 0 ? 2 : 0
- });
- this.bounds.moveBy({
- x: width === 0 ? -1 : 0,
- y: height === 0 ? -1 : 0
- });
-
- }
-
- // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden
- var upL = this.bounds.upperLeft();
- var oldUpL = this._oldBounds.upperLeft();
- var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width();
- var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height();
- var diffX = upL.x - oldUpL.x;
- var diffY = upL.y - oldUpL.y;
- var diffWidth = (this.bounds.width() / oldWidth) || 1;
- var diffHeight = (this.bounds.height() / oldHeight) || 1;
-
- this.dockers.each((function(docker){
- // Unregister on BoundsChangedCallback
- docker.bounds.unregisterCallback(this._dockerChangedCallback);
-
- // If there is any changes at the edge and is there is not an DockersUpdate
- // set the new bounds to the docker
- if (!this._dockerUpdated) {
- docker.bounds.moveBy(diffX, diffY);
-
- if (diffWidth !== 1 || diffHeight !== 1) {
- var relX = docker.bounds.upperLeft().x - upL.x;
- var relY = docker.bounds.upperLeft().y - upL.y;
-
- docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight);
- }
- }
- // Do Docker update and register on DockersBoundChange
- docker.update();
- docker.bounds.registerCallback(this._dockerChangedCallback);
-
- }).bind(this));
-
- if (this._dockerUpdated) {
- var a = this.dockers.first().bounds.center();
- var b = this.dockers.first().bounds.center();
-
- this.dockers.each((function(docker){
- var center = docker.bounds.center();
- a.x = Math.min(a.x, center.x);
- a.y = Math.min(a.y, center.y);
- b.x = Math.max(b.x, center.x);
- b.y = Math.max(b.y, center.y);
- }).bind(this));
-
- //set the bounds of the the association
- this.bounds.set(Object.clone(a), Object.clone(b));
- }
-
- upL = this.bounds.upperLeft(); oldUpL = this._oldBounds.upperLeft();
- diffWidth = (this.bounds.width() / (oldWidth||this.bounds.width())); diffHeight = (this.bounds.height() / (oldHeight||this.bounds.height()));
- diffX = upL.x - oldUpL.x; diffY = upL.y - oldUpL.y;
-
- //reposition labels
- this.getLabels().each(function(label) {
-
- if (label.getReferencePoint()){
- var ref = label.getReferencePoint();
- var from = ref.segment.from, to = ref.segment.to;
- if (!from || !from.parent || !to || !to.parent) {
- return;
- }
-
- var fromPosition = from.bounds.center(), toPosition = to.bounds.center();
- if (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y &&
- toPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty){
- return;
- }
-
- if (!this.parent.initializingShapes) {
- var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);
- var newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance);
-
- /**
- * Set position
- */
- // Get the orthogonal identity vector of the current segment
- var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);
- var isHor = Math.abs(oiv.y)===1, isVer = Math.abs(oiv.x)===1;
- oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance
- oiv.x += newIntersection.x; oiv.y += newIntersection.y; // vector + the intersection point
- var mx = isHor && ref.orientation && (ref.iorientation||ref.orientation).endsWith("r") ? -label.getWidth() : 0;
- var my = isVer && ref.orientation && (ref.iorientation||ref.orientation).startsWith("l") ? -label.getHeight()+2 : 0;
- label.setX(oiv.x+mx); label.setY(oiv.y+my);
-
- // Update the reference point
- this.updateReferencePointOfLabel(label, newIntersection, from, to);
- } else {
- var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition);
- oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance
- oiv.x += ref.intersection.x; oiv.y += ref.intersection.y; // vector + the intersection point
- label.setX(oiv.x); label.setY(oiv.y);
- ref.segment.fromPosition = fromPosition; ref.segment.toPosition = toPosition;
- }
-
- return;
- }
-
- // Update label position if no reference point is set
- if (label.position && !this.parent.initializingShapes){
- var x = label.position.x + (diffX * (diffWidth||1));
- if (x > this.bounds.lowerRight().x){
- x += this.bounds.width()-(this.bounds.width()/(diffWidth||1));
- }
-
- var y = label.position.y + (diffY * (diffHeight||1));
- if (y > this.bounds.lowerRight().y){
- y += this.bounds.height()-(this.bounds.height()/(diffHeight||1));
- }
- label.setX(x);label.setY(y);
- return;
- }
-
- switch (label.getEdgePosition()) {
- case "starttop":
- var angle = this._getAngle(this.dockers[0], this.dockers[1]);
- var pos = this.dockers.first().bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- label.x = pos.x + label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- label.x = pos.x - label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(180 - angle, pos);
- }
-
- break;
- case "startmiddle":
- var angle = this._getAngle(this.dockers[0], this.dockers[1]);
- var pos = this.dockers.first().bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- label.x = pos.x + 2;
- label.y = pos.y + 4;
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- label.x = pos.x + 1;
- label.y = pos.y + 4;
- label.rotate(180 - angle, pos);
- }
-
- break;
-
- case "startbottom":
- var angle = this._getAngle(this.dockers[0], this.dockers[1]);
- var pos = this.dockers.first().bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("left");
- label.verticalAlign("top");
- label.x = pos.x + label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("right");
- label.verticalAlign("top");
- label.x = pos.x - label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(180 - angle, pos);
- }
-
- break;
- case "midtop":
- var numOfDockers = this.dockers.length;
- if(numOfDockers%2 == 0) {
- var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])
- var pos1 = this.dockers[numOfDockers/2-1].bounds.center();
- var pos2 = this.dockers[numOfDockers/2].bounds.center();
- var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};
-
- label.horizontalAlign("center");
- label.verticalAlign("bottom");
- label.x = pos.x;
- label.y = pos.y - label.getOffsetTop();
-
- if (angle <= 90 || angle > 270) {
- label.rotate(360 - angle, pos);
- } else {
- label.rotate(180 - angle, pos);
- }
- } else {
- var index = parseInt(numOfDockers/2);
- var angle = this._getAngle(this.dockers[index], this.dockers[index+1])
- var pos = this.dockers[index].bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- label.x = pos.x + label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- label.x = pos.x - label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(180 - angle, pos);
- }
- }
-
- break;
- case "midbottom":
- var numOfDockers = this.dockers.length;
- if(numOfDockers%2 == 0) {
- var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2])
- var pos1 = this.dockers[numOfDockers/2-1].bounds.center();
- var pos2 = this.dockers[numOfDockers/2].bounds.center();
- var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0};
-
- label.horizontalAlign("center");
- label.verticalAlign("top");
- label.x = pos.x;
- label.y = pos.y + label.getOffsetTop();
-
- if (angle <= 90 || angle > 270) {
- label.rotate(360 - angle, pos);
- } else {
- label.rotate(180 - angle, pos);
- }
- } else {
- var index = parseInt(numOfDockers/2);
- var angle = this._getAngle(this.dockers[index], this.dockers[index+1])
- var pos = this.dockers[index].bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("left");
- label.verticalAlign("top");
- label.x = pos.x + label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("right");
- label.verticalAlign("top");
- label.x = pos.x - label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(180 - angle, pos);
- }
- }
-
- break;
- case "endtop":
- var length = this.dockers.length;
- var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);
- var pos = this.dockers.last().bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- label.x = pos.x - label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- label.x = pos.x + label.getOffsetTop();
- label.y = pos.y - label.getOffsetTop();
- label.rotate(180 - angle, pos);
- }
-
- break;
- case "endbottom":
- var length = this.dockers.length;
- var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]);
- var pos = this.dockers.last().bounds.center();
-
- if (angle <= 90 || angle > 270) {
- label.horizontalAlign("right");
- label.verticalAlign("top");
- label.x = pos.x - label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(360 - angle, pos);
- } else {
- label.horizontalAlign("left");
- label.verticalAlign("top");
- label.x = pos.x + label.getOffsetBottom();
- label.y = pos.y + label.getOffsetBottom();
- label.rotate(180 - angle, pos);
- }
-
- break;
- }
- }.bind(this));
-
- this.children.each(function(value) {
- if(value instanceof ORYX.Core.Node) {
- this.calculatePositionOfAttachedChildNode.call(this, value);
- }
- }.bind(this));
-
- this.refreshAttachedNodes();
- this.refresh();
-
- this.isChanged = false;
- this._dockerUpdated = false;
-
- this._oldBounds = this.bounds.clone();
- }
-
- },
-
- /**
- * Moves a point to the upperLeft of a node's bounds.
- *
- * @param {point} point
- * The point to move
- * @param {ORYX.Core.Bounds} bounds
- * The Bounds of the related noe
- */
- movePointToUpperLeftOfNode: function(point, bounds) {
- point.x -= bounds.width()/2;
- point.y -= bounds.height()/2;
- },
-
- /**
- * Refreshes the visual representation of edge's attached nodes.
- */
- refreshAttachedNodes: function() {
- this.attachedNodePositionData.values().each(function(nodeData) {
- var startPoint = nodeData.segment.docker1.bounds.center();
- var endPoint = nodeData.segment.docker2.bounds.center();
- this.relativizePoint(startPoint);
- this.relativizePoint(endPoint);
-
- var newNodePosition = new Object();
-
- /* Calculate new x-coordinate */
- newNodePosition.x = startPoint.x
- + nodeData.relativDistanceFromDocker1
- * (endPoint.x - startPoint.x);
-
- /* Calculate new y-coordinate */
- newNodePosition.y = startPoint.y
- + nodeData.relativDistanceFromDocker1
- * (endPoint.y - startPoint.y);
-
- /* Convert new position to the upper left of the node */
- this.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds);
-
- /* Move node to its new position */
- nodeData.node.bounds.moveTo(newNodePosition);
- nodeData.node._update();
-
- }.bind(this));
- },
-
- /**
- * Calculates the position of an edge's child node. The node is placed on
- * the path of the edge.
- *
- * @param {node}
- * The node to calculate the new position
- * @return {Point}
- * The calculated upper left point of the node's shape.
- */
- calculatePositionOfAttachedChildNode: function(node) {
- /* Initialize position */
- var position = new Object();
- position.x = 0;
- position.y = 0;
-
- /* Case: Node was just added */
- if(!this.attachedNodePositionData[node.getId()]) {
- this.attachedNodePositionData[node.getId()] = new Object();
- this.attachedNodePositionData[node.getId()]
- .relativDistanceFromDocker1 = 0;
- this.attachedNodePositionData[node.getId()].node = node;
- this.attachedNodePositionData[node.getId()].segment = new Object();
- this.findEdgeSegmentForNode(node);
- }else if(node.isChanged) {
- this.findEdgeSegmentForNode(node);
- }
-
-
-
- },
-
- /**
- * Finds the appropriate edge segement for a node.
- * The segment is choosen, which has the smallest distance to the node.
- *
- * @param {ORYX.Core.Node} node
- * The concerning node
- */
- findEdgeSegmentForNode: function(node) {
- var length = this.dockers.length;
- var smallestDistance = undefined;
-
- for(i=1;i<length;i++) {
- var lineP1 = this.dockers[i-1].bounds.center();
- var lineP2 = this.dockers[i].bounds.center();
- this.relativizePoint(lineP1);
- this.relativizePoint(lineP2);
-
- var nodeCenterPoint = node.bounds.center();
- var distance = ORYX.Core.Math.distancePointLinie(
- lineP1,
- lineP2,
- nodeCenterPoint,
- true);
-
- if((distance || distance == 0) && ((!smallestDistance && smallestDistance != 0)
- || distance < smallestDistance)) {
-
- smallestDistance = distance;
-
- this.attachedNodePositionData[node.getId()].segment.docker1 =
- this.dockers[i-1];
- this.attachedNodePositionData[node.getId()].segment.docker2 =
- this.dockers[i];
-
- }
-
- /* Either the distance does not match the segment or the distance
- * between docker1 and docker2 is 0
- *
- * In this case choose the nearest docker as attaching point.
- *
- */
- if(!distance && !smallestDistance && smallestDistance != 0) {
- (ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1)
- < ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2)) ?
- this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 0 :
- this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 1;
- this.attachedNodePositionData[node.getId()].segment.docker1 =
- this.dockers[i-1];
- this.attachedNodePositionData[node.getId()].segment.docker2 =
- this.dockers[i];
- }
- }
-
- /* Calculate position on edge segment for the node */
- if(smallestDistance || smallestDistance == 0) {
- this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 =
- this.getLineParameterForPosition(
- this.attachedNodePositionData[node.getId()].segment.docker1,
- this.attachedNodePositionData[node.getId()].segment.docker2,
- node);
- }
- },
-
-
- /**
- *
- * @param {ORYX.Core.Node|Object} node or position
- * @return {Object} An object with the following attribute: {ORYX.Core.Docker} fromDocker, {ORYX.Core.Docker} toDocker, {X/Y} position, {int} distance
- */
- findSegment: function(node){
-
- var length = this.dockers.length;
- var result;
-
- var nodeCenterPoint = node instanceof ORYX.Core.UIObject ? node.bounds.center() : node;
-
- for (i = 1; i < length; i++) {
- var lineP1 = this.dockers[i - 1].bounds.center();
- var lineP2 = this.dockers[i].bounds.center();
-
- var distance = ORYX.Core.Math.distancePointLinie(lineP1, lineP2, nodeCenterPoint, true);
-
- if (typeof distance == "number" && (result === undefined || distance < result.distance)) {
- result = {
- distance: distance,
- fromDocker: this.dockers[i - 1],
- toDocker: this.dockers[i]
- }
-
- }
- }
- return result;
- },
-
- /**
- * Returns the value of the scalar to determine the position of the node on
- * line defined by docker1 and docker2.
- *
- * @param {point} docker1
- * The docker that defines the start of the line segment
- * @param {point} docker2
- * The docker that defines the end of the line segment
- * @param {ORYX.Core.Node} node
- * The concerning node
- *
- * @return {float} positionParameter
- * The scalar value to determine the position on the line
- */
- getLineParameterForPosition: function(docker1, docker2, node) {
- var dockerPoint1 = docker1.bounds.center();
- var dockerPoint2 = docker2.bounds.center();
- this.relativizePoint(dockerPoint1);
- this.relativizePoint(dockerPoint2);
-
- var intersectionPoint = ORYX.Core.Math.getPointOfIntersectionPointLine(
- dockerPoint1,
- dockerPoint2,
- node.bounds.center(), true);
- if(!intersectionPoint) {
- return 0;
- }
-
- var relativeDistance =
- ORYX.Core.Math.getDistancePointToPoint(intersectionPoint, dockerPoint1) /
- ORYX.Core.Math.getDistancePointToPoint(dockerPoint1, dockerPoint2);
-
- return relativeDistance;
- },
- /**
- * Makes point relative to the upper left of the edge's bound.
- *
- * @param {point} point
- * The point to relativize
- */
- relativizePoint: function(point) {
- point.x -= this.bounds.upperLeft().x;
- point.y -= this.bounds.upperLeft().y;
- },
-
- /**
- * Move the first and last docker and calls the refresh method.
- * Attention: This does not calculates intersection point between the
- * edge and the bounded nodes. This only works if only the nodes are
- * moves.
- *
- */
- optimizedUpdate: function(){
-
- var updateDocker = function(docker){
- if (!docker._dockedShape || !docker._dockedShapeBounds)
- return;
- var off = {
- x: docker._dockedShape.bounds.a.x - docker._dockedShapeBounds.a.x,
- y: docker._dockedShape.bounds.a.y - docker._dockedShapeBounds.a.y
- };
- docker.bounds.moveBy(off);
- docker._dockedShapeBounds.moveBy(off);
- }
-
- updateDocker(this.dockers.first());
- updateDocker(this.dockers.last());
-
- this.refresh();
- },
-
- refresh: function(){
- //call base class refresh method
- arguments.callee.$.refresh.apply(this, arguments);
-
- //TODO consider points for marker mids
- var lastPoint;
- this._paths.each((function(path, index){
- var dockers = this._dockersByPath[path.id];
- var c = undefined;
- var d = undefined;
- if (lastPoint) {
- d = "M" + lastPoint.x + " " + lastPoint.y;
- }
- else {
- c = dockers[0].bounds.center();
- lastPoint = c;
-
- d = "M" + c.x + " " + c.y;
- }
-
- for (var i = 1; i < dockers.length; i++) {
- // for each docker, draw a line to the center
- c = dockers[i].bounds.center();
- d = d + "L" + c.x + " " + c.y + " ";
- lastPoint = c;
- }
-
- path.setAttributeNS(null, "d", d);
- this._interactionPaths[index].setAttributeNS(null, "d", d);
-
- }).bind(this));
-
-
- /* move child shapes of an edge */
- if(this.getChildNodes().length > 0) {
- var x = this.bounds.upperLeft().x;
- var y = this.bounds.upperLeft().y;
-
- this.node.firstChild.childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")");
- }
-
- },
-
- /**
- * Calculate the Border Intersection Point between two points
- * @param {PointA}
- * @param {PointB}
- */
- getIntersectionPoint: function(){
-
- var length = Math.floor(this.dockers.length / 2)
-
- return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center())
- },
-
- /**
- * Returns TRUE if the bounds is over the edge
- * @param {Bounds}
- *
- */
- isBoundsIncluded: function(bounds){
- var dockers = this.dockers, size = dockers.length;
- return dockers.any(function(docker, i){
- if (i == size-1){ return false; }
- var a = docker.bounds.center();
- var b = dockers[i+1].bounds.center();
-
- 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);
- });
- },
-
- /**
- * Calculate if the point is inside the Shape
- * @param {PointX}
- * @param {PointY}
- */
- isPointIncluded: function(pointX, pointY){
-
- var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY,
- ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
-
- var isPointIncluded = undefined;
-
- if (isbetweenAB && this.dockers.length > 0) {
-
- var i = 0;
- var point1, point2;
-
-
- do {
-
- point1 = this.dockers[i].bounds.center();
- point2 = this.dockers[++i].bounds.center();
-
- isPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY,
- point1.x, point1.y,
- point2.x, point2.y,
- ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
-
- } while (!isPointIncluded && i < this.dockers.length - 1)
-
- }
-
- return isPointIncluded;
- },
-
-
- /**
- * Calculate if the point is over an special offset area
- * @param {Point}
- */
- isPointOverOffset: function(){
- return false
- },
-
- /**
- * Returns TRUE if the given node
- * is a child node of the shapes node
- * @param {Element} node
- * @return {Boolean}
- *
- */
- containsNode: function(node){
- if (this._paths.include(node) ||
- this._interactionPaths.include(node)){
- return true;
- }
- return false;
- },
-
- /**
- * Returns the angle of the line between two dockers
- * (0 - 359.99999999)
- */
- _getAngle: function(docker1, docker2) {
- var p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1;
- var p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2;
-
- return ORYX.Core.Math.getAngle(p1, p2);
- },
-
- alignDockers: function(){
- this._update(true);
-
- var firstPoint = this.dockers.first().bounds.center();
- var lastPoint = this.dockers.last().bounds.center();
-
- var deltaX = lastPoint.x - firstPoint.x;
- var deltaY = lastPoint.y - firstPoint.y;
-
- var numOfDockers = this.dockers.length - 1;
-
- this.dockers.each((function(docker, index){
- var part = index / numOfDockers;
- docker.bounds.unregisterCallback(this._dockerChangedCallback);
- docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY);
- docker.bounds.registerCallback(this._dockerChangedCallback);
- }).bind(this));
-
- this._dockerChanged();
- },
-
- add: function(shape){
- arguments.callee.$.add.apply(this, arguments);
-
- // If the new shape is a Docker which is not contained
- if (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)){
- // Add it to the dockers list ordered by paths
- var pathArray = this._dockersByPath.values()[0];
- if (pathArray) {
- pathArray.splice(this.dockers.indexOf(shape), 0, shape);
- }
-
- /* Perform nessary adjustments on the edge's child shapes */
- this.handleChildShapesAfterAddDocker(shape);
- }
- },
-
- /**
- * Performs nessary adjustments on the edge's child shapes.
- *
- * @param {ORYX.Core.Controls.Docker} docker
- * The added docker
- */
- handleChildShapesAfterAddDocker: function(docker) {
- /* Ensure type of Docker */
- if(!docker instanceof ORYX.Core.Controls.Docker) {return undefined;}
-
- var index = this.dockers.indexOf(docker);
- if(!(0 < index && index < this.dockers.length - 1)) {
- /* Exception: Expect added docker between first and last node of the edge */
- return undefined;
- }
-
- /* Get child nodes concerning the segment of the new docker */
- var startDocker = this.dockers[index-1];
- var endDocker = this.dockers[index+1];
-
- /* Adjust the position of edge's child nodes */
- var segmentElements =
- this.getAttachedNodePositionDataForSegment(startDocker, endDocker);
-
- var lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint(
- startDocker.bounds.center(),
- docker.bounds.center());
- var lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint(
- endDocker.bounds.center(),
- docker.bounds.center());
-
- if(!(lengthSegmentPart1 + lengthSegmentPart2)) {return;}
-
- var relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2);
-
- segmentElements.each(function(nodePositionData) {
- /* Assign child node to the new segment */
- if(nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) {
- /* Case: before added Docker */
- nodePositionData.value.segment.docker2 = docker;
- nodePositionData.value.relativDistanceFromDocker1 =
- nodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition;
- } else {
- /* Case: after added Docker */
- nodePositionData.value.segment.docker1 = docker;
- var newFullDistance = 1 - relativDockerPosition;
- var relativPartOfSegment =
- nodePositionData.value.relativDistanceFromDocker1
- - relativDockerPosition;
-
- nodePositionData.value.relativDistanceFromDocker1 =
- relativPartOfSegment / newFullDistance;
-
- }
- })
-
-
- // Update all labels reference points
- this.getLabels().each(function(label){
- var ref = label.getReferencePoint();
- if (!ref) {
- return;
- }
- var index = this.dockers.indexOf(docker);
- if (index >= ref.segment.fromIndex && index <= ref.segment.toIndex){
-
- var segment = this.findSegment(ref.intersection);
- if (!segment){
- // Choose whether the first of the last segment
- segment.fromDocker = ref.segment.fromIndex >= (this.dockers.length/2) ? this.dockers[0] : this.dockers[this.dockers.length-2];
- segment.toDocker = this.dockers[this.dockers.indexOf(from)+1]; // The next one if the to docker
- }
-
- var fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center();
-
- var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(
- fromPosition, // P1 - Center of the first docker
- toPosition, // P2 - Center of the second docker
- ref.intersection, // P3 - Center of the label
- true);
- //var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection);
- //intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew);
-
- // Update the reference point
- this.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true);
- }
- }.bind(this));
-
- /* Update attached nodes visual representation */
- this.refreshAttachedNodes();
- },
-
- /**
- * Returns elements from {@link attachedNodePositiondata} that match the
- * segement defined by startDocker and endDocker.
- *
- * @param {ORYX.Core.Controls.Docker} startDocker
- * The docker defining the begin of the segment.
- * @param {ORYX.Core.Controls.Docker} endDocker
- * The docker defining the begin of the segment.
- *
- * @return {Hash} attachedNodePositionData
- * Child elements matching the segment
- */
- getAttachedNodePositionDataForSegment: function(startDocker, endDocker) {
- /* Ensure that the segment is defined correctly */
- if(!((startDocker instanceof ORYX.Core.Controls.Docker)
- && (endDocker instanceof ORYX.Core.Controls.Docker))) {
- return [];
- }
-
- /* Get elements of the segment */
- var elementsOfSegment =
- this.attachedNodePositionData.findAll(function(nodePositionData) {
- return nodePositionData.value.segment.docker1 === startDocker &&
- nodePositionData.value.segment.docker2 === endDocker;
- });
-
- /* Return a Hash in each case */
- if(!elementsOfSegment) {return [];}
-
- return elementsOfSegment;
- },
-
- /**
- * Removes an edge's child shape
- */
- remove: function(shape) {
- arguments.callee.$.remove.apply(this, arguments);
-
- if(this.attachedNodePositionData[shape.getId()]) {
- delete this.attachedNodePositionData[shape.getId()];
- }
-
- /* Adjust child shapes if neccessary */
- if(shape instanceof ORYX.Core.Controls.Docker) {
- this.handleChildShapesAfterRemoveDocker(shape);
- }
- },
-
- updateReferencePointOfLabel: function(label, intersection, from, to, dirty){
- if (!label.getReferencePoint() || !label.isVisible) {
- return;
- }
-
- var ref = label.getReferencePoint();
-
- //
- if (ref.orientation && ref.orientation !== "ce"){
- var angle = this._getAngle(from, to);
- if (ref.distance >= 0){
- if(angle == 0){
- label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left");
- label.verticalAlign("bottom");
- } else if (angle > 0 && angle < 90){
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- } else if (angle == 90){
- label.horizontalAlign("right");
- label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top");
- } else if (angle > 90 && angle < 180){
- label.horizontalAlign("right");
- label.verticalAlign("top");
- } else if (angle == 180){
- label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left");
- label.verticalAlign("top");
- } else if (angle > 180 && angle < 270){
- label.horizontalAlign("left");
- label.verticalAlign("top");
- } else if (angle == 270){
- label.horizontalAlign("left");
- label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top");
- } else if (angle > 270 && angle <= 360){
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- }
- } else {
- if(angle == 0){
- label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left");
- label.verticalAlign("top");
- } else if (angle > 0 && angle < 90){
- label.horizontalAlign("left");
- label.verticalAlign("top");
- } else if (angle == 90){
- label.horizontalAlign("left");
- label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top");
- } else if (angle > 90 && angle < 180){
- label.horizontalAlign("left");
- label.verticalAlign("bottom");
- } else if (angle == 180){
- label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left");
- label.verticalAlign("bottom");
- } else if (angle > 180 && angle < 270){
- label.horizontalAlign("right");
- label.verticalAlign("bottom");
- } else if (angle == 270){
- label.horizontalAlign("right");
- label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top");
- } else if (angle > 270 && angle <= 360){
- label.horizontalAlign("right");
- label.verticalAlign("top");
- }
- }
- ref.iorientation = ref.iorientation || ref.orientation;
- ref.orientation = (label.verticalAlign()=="top"?"u":"l") + (label.horizontalAlign()=="left"?"l":"r");
- }
-
- label.setReferencePoint(Ext.apply({},{
- intersection: intersection,
- segment: {
- from: from,
- fromIndex: this.dockers.indexOf(from),
- fromPosition: from.bounds.center(),
- to: to,
- toIndex: this.dockers.indexOf(to),
- toPosition: to.bounds.center()
- },
- dirty: dirty || false
- },ref))
- },
- /**
- * Adjusts the child shapes of an edges after a docker was removed.
- *
- * @param{ORYX.Core.Controls.Docker} docker
- * The removed docker.
- */
- handleChildShapesAfterRemoveDocker: function(docker) {
- /* Ensure docker type */
- if(!(docker instanceof ORYX.Core.Controls.Docker)) {return;}
-
- this.attachedNodePositionData.each(function(nodePositionData) {
- if(nodePositionData.value.segment.docker1 === docker) {
- /* The new start of the segment is the predecessor of docker2. */
- var index = this.dockers.indexOf(nodePositionData.value.segment.docker2);
- if(index == -1) {return;}
- nodePositionData.value.segment.docker1 = this.dockers[index - 1];
- }
- else if(nodePositionData.value.segment.docker2 === docker) {
- /* The new end of the segment is the successor of docker1. */
- var index = this.dockers.indexOf(nodePositionData.value.segment.docker1);
- if(index == -1) {return;}
- nodePositionData.value.segment.docker2 = this.dockers[index + 1];
- }
- }.bind(this));
-
- // Update all labels reference points
- this.getLabels().each(function(label){
- var ref = label.getReferencePoint();
- if (!ref) {
- return;
- }
- var from = ref.segment.from;
- var to = ref.segment.to;
-
- if (from !== docker && to !== docker){
- return;
- }
-
- var segment = this.findSegment(ref.intersection);
- if (!segment){
- from = segment.fromDocker;
- to = segment.toDocker;
- } else {
- from = from === docker ? this.dockers[this.dockers.indexOf(to)-1] : from;
- to = this.dockers[this.dockers.indexOf(from)+1];
- }
- var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true);
- // Update the reference point
- this.updateReferencePointOfLabel(label, intersection, from, to, true);
- }.bind(this));
-
- /* Update attached nodes visual representation */
- this.refreshAttachedNodes();
- },
-
- /**
- *@deprecated Use the .createDocker() Method and set the point via the bounds
- */
- addDocker: function(position, exDocker){
- var lastDocker;
- var result;
- this._dockersByPath.any((function(pair){
- return pair.value.any((function(docker, index){
- if (!lastDocker) {
- lastDocker = docker;
- return false;
- }
- else {
- var point1 = lastDocker.bounds.center();
- var point2 = docker.bounds.center();
-
- if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) {
- var path = this._paths.find(function(path){
- return path.id === pair.key;
- });
- if (path) {
- var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers');
- if (allowAttr && allowAttr.toLowerCase() === "no") {
- return true;
- }
- }
- var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position);
- newDocker.bounds.centerMoveTo(position);
- if(exDocker)
- this.add(newDocker, this.dockers.indexOf(lastDocker) + 1);
- // Remove new Docker from 'to add' dockers
- //pair.value = pair.value.without(newDocker);
- //pair.value.splice(this.dockers.indexOf(lastDocker) + 1, 0, newDocker);
- // Remove the Docker from the Docker list and add the Docker to the new position
- //this.dockers = this.dockers.without(newDocker);
- //this.dockers.splice(this.dockers.indexOf(lastDocker) + 1, 0, newDocker);
- //this._update(true);
- result = newDocker;
- return true;
- }
- else {
- lastDocker = docker;
- return false;
- }
- }
- }).bind(this));
- }).bind(this));
- return result;
- },
-
- removeDocker: function(docker){
- if (this.dockers.length > 2 && !(this.dockers.first() === docker)) {
- this._dockersByPath.any((function(pair){
- if (pair.value.member(docker)) {
- if (docker === pair.value.last()) {
- return true;
- }
- else {
- this.remove(docker);
- this._dockersByPath[pair.key] = pair.value.without(docker);
- this.isChanged = true;
- this._dockerChanged();
- return true;
- }
- }
- return false;
- }).bind(this));
- }
- },
-
- /**
- * Removes all dockers from the edge which are on
- * the line between two dockers
- * @return {Object} Removed dockers in an indicied array
- * (key is the removed position of the docker, value is docker themselve)
- */
- removeUnusedDockers:function(){
- var marked = $H({});
-
- this.dockers.each(function(docker, i){
- if (i==0||i==this.dockers.length-1){ return }
- var previous = this.dockers[i-1];
-
- /* Do not consider already removed dockers */
- if(marked.values().indexOf(previous) != -1 && this.dockers[i-2]) {
- previous = this.dockers[i-2];
- }
- var next = this.dockers[i+1];
-
- var cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center();
- var cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center();
- var cd = docker.bounds.center();
-
- if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)){
- marked[i] = docker;
- }
- }.bind(this))
-
- marked.each(function(docker){
- this.removeDocker(docker.value);
- }.bind(this))
-
- if (marked.values().length > 0){
- this._update(true);
- }
-
- return marked;
- },
-
- /**
- * Initializes the Edge after loading the SVG representation of the edge.
- * @param {SVGDocument} svgDocument
- */
- _init: function(svgDocument){
- arguments.callee.$._init.apply(this, arguments);
-
- var minPointX, minPointY, maxPointX, maxPointY;
-
- //init markers
- var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "defs");
- if (defs.length > 0) {
- defs = defs[0];
- var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, "marker"));
- var marker;
- var me = this;
- markerElements.each(function(markerElement){
- try {
- marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true));
- me._markers[marker.id] = marker;
- var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, "text"));
- var label;
- textElements.each(function(textElement){
- label = new ORYX.Core.SVG.Label({
- textElement: textElement,
- shapeId: this.id
- });
- me._labels[label.id] = label;
- });
- }
- catch (e) {
- }
- });
- }
-
-
- var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "g");
- if (gs.length <= 0) {
- throw "Edge: No g element found.";
- }
- var g = gs[0];
-
-
- g.setAttributeNS(null, "id", null);
-
- var isFirst = true;
-
- $A(g.childNodes).each((function(path, index){
- if (ORYX.Editor.checkClassType(path, SVGPathElement)) {
- path = path.cloneNode(false);
-
- var pathId = this.id + "_" + index;
- path.setAttributeNS(null, "id", pathId);
- this._paths.push(path);
-
- //check, if markers are set and update the id
- var markersByThisPath = [];
- var markerUrl = path.getAttributeNS(null, "marker-start");
-
- if (markerUrl && markerUrl !== "") {
- markerUrl = markerUrl.strip();
- markerUrl = markerUrl.replace(/^url\(#/, '');
- var markerStartId = this.id.concat(markerUrl.replace(/\)$/, ''));
- path.setAttributeNS(null, "marker-start", "url(#" + markerStartId + ")");
-
- markersByThisPath.push(this._markers[markerStartId]);
- }
-
- markerUrl = path.getAttributeNS(null, "marker-mid");
-
- if (markerUrl && markerUrl !== "") {
- markerUrl = markerUrl.strip();
- markerUrl = markerUrl.replace(/^url\(#/, '');
- var markerMidId = this.id.concat(markerUrl.replace(/\)$/, ''));
- path.setAttributeNS(null, "marker-mid", "url(#" + markerMidId + ")");
-
- markersByThisPath.push(this._markers[markerMidId]);
- }
-
- markerUrl = path.getAttributeNS(null, "marker-end");
-
- if (markerUrl && markerUrl !== "") {
- markerUrl = markerUrl.strip();
- markerUrl = markerUrl.replace(/^url\(#/, '');
- var markerEndId = this.id.concat(markerUrl.replace(/\)$/, ''));
- path.setAttributeNS(null, "marker-end", "url(#" + markerEndId + ")");
-
- markersByThisPath.push(this._markers[markerEndId]);
- }
-
- this._markersByPath[pathId] = markersByThisPath;
-
- //init dockers
- var parser = new PathParser();
- var handler = new ORYX.Core.SVG.PointsPathHandler();
- parser.setHandler(handler);
- parser.parsePath(path);
-
- if (handler.points.length < 4) {
- throw "Edge: Path has to have two or more points specified.";
- }
-
- this._dockersByPath[pathId] = [];
-
- for (var i = 0; i < handler.points.length; i += 2) {
- //handler.points.each((function(point, pIndex){
- var x = handler.points[i];
- var y = handler.points[i+1];
- if (isFirst || i > 0) {
- var docker = new ORYX.Core.Controls.Docker({
- eventHandlerCallback: this.eventHandlerCallback
- });
- docker.bounds.centerMoveTo(x,y);
- docker.bounds.registerCallback(this._dockerChangedCallback);
- this.add(docker, this.dockers.length);
-
- //this._dockersByPath[pathId].push(docker);
-
- //calculate minPoint and maxPoint
- if (minPointX) {
- minPointX = Math.min(x, minPointX);
- minPointY = Math.min(y, minPointY);
- }
- else {
- minPointX = x;
- minPointY = y;
- }
-
- if (maxPointX) {
- maxPointX = Math.max(x, maxPointX);
- maxPointY = Math.max(y, maxPointY);
- }
- else {
- maxPointX = x;
- maxPointY = y;
- }
- }
- //}).bind(this));
- }
- isFirst = false;
- }
- }).bind(this));
-
- this.bounds.set(minPointX, minPointY, maxPointX, maxPointY);
-
- if (false&&(this.bounds.width() === 0 || this.bounds.height() === 0)) {
- var width = this.bounds.width();
- var height = this.bounds.height();
-
- this.bounds.extend({
- x: width === 0 ? 2 : 0,
- y: height === 0 ? 2 : 0
- });
-
- this.bounds.moveBy({
- x: width === 0 ? -1 : 0,
- y: height === 0 ? -1 : 0
- });
-
- }
-
- this._oldBounds = this.bounds.clone();
-
- //add paths to this.node
- this._paths.reverse();
- var paths = [];
- this._paths.each((function(path){
- paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path));
- }).bind(this));
-
- this._paths = paths;
-
- //init interaction path
- this._paths.each((function(path){
- var iPath = path.cloneNode(false);
- iPath.setAttributeNS(null, "id", undefined);
- iPath.setAttributeNS(null, "stroke-width", 10);
- iPath.setAttributeNS(null, "visibility", "hidden");
- iPath.setAttributeNS(null, "stroke-dasharray", null);
- iPath.setAttributeNS(null, "stroke", "black");
- iPath.setAttributeNS(null, "fill", "none");
- iPath.setAttributeNS(null, "title", this.getStencil().title());
- this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath));
- }).bind(this));
-
- this._paths.reverse();
- this._interactionPaths.reverse();
-
- /**initialize labels*/
- var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text');
-
- $A(textElems).each((function(textElem){
- var label = new ORYX.Core.SVG.Label({
- textElement: textElem,
- shapeId: this.id
- });
- this.node.childNodes[0].childNodes[0].appendChild(label.node);
- this._labels[label.id] = label;
-
- label.registerOnChange(this.layout.bind(this));
- }).bind(this));
-
-
- this.propertiesChanged.each(function(pair){
- pair.value = true;
- });
-
- //this._update(true);
- },
-
- /**
- * Adds all necessary markers of this Edge to the SVG document.
- * Has to be called, while this.node is part of DOM.
- */
- addMarkers: function(defs){
- this._markers.each(function(marker){
- if (!defs.ownerDocument.getElementById(marker.value.id)) {
- marker.value.element = defs.appendChild(marker.value.element);
- }
- });
- },
-
- /**
- * Removes all necessary markers of this Edge from the SVG document.
- * Has to be called, while this.node is part of DOM.
- */
- removeMarkers: function(){
- var svgElement = this.node.ownerSVGElement;
- if (svgElement) {
- var defs = svgElement.getElementsByTagNameNS(NAMESPACE_SVG, "defs");
- if (defs.length > 0) {
- defs = defs[0];
- this._markers.each(function(marker){
- var foundMarker = defs.ownerDocument.getElementById(marker.value.id);
- if (foundMarker) {
- marker.value.element = defs.removeChild(marker.value.element);
- }
- });
- }
- }
- },
-
- /**
- * Calls when a docker has changed
- */
- _dockerChanged: function(){
-
- //this._update(true);
- this._dockerUpdated = true;
-
- },
-
- serialize: function(){
- var result = arguments.callee.$.serialize.apply(this);
-
- //add dockers triple
- var value = "";
- this._dockersByPath.each((function(pair){
- pair.value.each(function(docker){
- var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
- value = value.concat(position.x + " " + position.y + " ");
- });
-
- value += " # ";
- }).bind(this));
- result.push({
- name: 'dockers',
- prefix: 'oryx',
- value: value,
- type: 'literal'
- });
-
- //add parent triple dependant on the dockedShapes
- //TODO change this when canvas becomes a resource
- /* var source = this.dockers.first().getDockedShape();
- var target = this.dockers.last().getDockedShape();
- var sharedParent;
- if (source && target) {
- //get shared parent
- while (source.parent) {
- source = source.parent;
- if (source instanceof ORYX.Core.Canvas) {
- sharedParent = source;
- break;
- }
- else {
- var targetParent = target.parent;
- var found;
- while (targetParent) {
- if (source === targetParent) {
- sharedParent = source;
- found = true;
- break;
- }
- else {
- targetParent = targetParent.parent;
- }
- }
- if (found) {
- break;
- }
- }
- }
- }
- else
- if (source) {
- sharedParent = source.parent;
- }
- else
- if (target) {
- sharedParent = target.parent;
- }
- */
- //if (sharedParent) {
- /* result.push({
- name: 'parent',
- prefix: 'raziel',
- //value: '#' + ERDF.__stripHashes(sharedParent.resourceId),
- value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId),
- type: 'resource'
- });*/
- //}
-
- //serialize target and source
- var lastDocker = this.dockers.last();
-
- var target = lastDocker.getDockedShape();
-
- if(target) {
- result.push({
- name: 'target',
- prefix: 'raziel',
- value: '#' + ERDF.__stripHashes(target.resourceId),
- type: 'resource'
- });
- }
-
- try {
- //result = this.getStencil().serialize(this, result);
- var serializeEvent = this.getStencil().serialize();
-
- /*
- * call serialize callback by reference, result should be found
- * in serializeEvent.result
- */
- if(serializeEvent.type) {
- serializeEvent.shape = this;
- serializeEvent.data = result;
- serializeEvent.result = undefined;
- serializeEvent.forceExecution = true;
-
- this._delegateEvent(serializeEvent);
-
- if(serializeEvent.result) {
- result = serializeEvent.result;
- }
- }
- }
- catch (e) {
- }
- return result;
- },
-
- deserialize: function(data){
- try {
- //data = this.getStencil().deserialize(this, data);
-
- var deserializeEvent = this.getStencil().deserialize();
-
- /*
- * call serialize callback by reference, result should be found
- * in serializeEventInfo.result
- */
- if(deserializeEvent.type) {
- deserializeEvent.shape = this;
- deserializeEvent.data = data;
- deserializeEvent.result = undefined;
- deserializeEvent.forceExecution = true;
-
- this._delegateEvent(deserializeEvent);
- if(deserializeEvent.result) {
- data = deserializeEvent.result;
- }
- }
- }
- catch (e) {
- }
-
- // Set the outgoing shapes
- var target = data.find(function(ser) {return (ser.prefix+"-"+ser.name) == 'raziel-target'});
- var targetShape;
- if(target) {
- targetShape = this.getCanvas().getChildShapeByResourceId(target.value);
- }
-
- var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'});
- outgoing.each((function(obj){
- // TODO: Look at Canvas
- if(!this.parent) {return};
-
- // Set outgoing Shape
- var next = this.getCanvas().getChildShapeByResourceId(obj.value);
-
- if(next){
- if(next == targetShape) {
- // If this is an edge, set the last docker to the next shape
- this.dockers.last().setDockedShape(next);
- this.dockers.last().setReferencePoint({x: next.bounds.width() / 2.0, y: next.bounds.height() / 2.0});
- } else if(next instanceof ORYX.Core.Edge) {
- //Set the first docker of the next shape
- next.dockers.first().setDockedShape(this);
- //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
- } /*else if(next.dockers.length > 0) { //next is a node and next has a docker
- next.dockers.first().setDockedShape(this);
- next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0});
- }*/
- }
-
- }).bind(this));
-
-
- var oryxDockers = data.find(function(obj){
- return (obj.prefix === "oryx" &&
- obj.name === "dockers");
- });
-
- if (oryxDockers) {
- var dataByPath = oryxDockers.value.split("#").without("").without(" ");
-
- dataByPath.each((function(data, index){
- var values = data.replace(/,/g, " ").split(" ").without("");
-
- //for each docker two values must be defined
- if (values.length % 2 === 0) {
- var path = this._paths[index];
-
- if (path) {
- if (index === 0) {
- while (this._dockersByPath[path.id].length > 2) {
- this.removeDocker(this._dockersByPath[path.id][1]);
- }
- }
- else {
- while (this._dockersByPath[path.id].length > 1) {
- this.removeDocker(this._dockersByPath[path.id][0]);
- }
- }
-
- var dockersByPath = this._dockersByPath[path.id];
-
- if (index === 0) {
- //set position of first docker
- var x = parseFloat(values.shift());
- var y = parseFloat(values.shift());
-
- if (dockersByPath.first().getDockedShape()) {
- dockersByPath.first().setReferencePoint({
- x: x,
- y: y
- });
- }
- else {
- dockersByPath.first().bounds.centerMoveTo(x, y);
- }
- }
-
- //set position of last docker
- y = parseFloat(values.pop());
- x = parseFloat(values.pop());
-
- if (dockersByPath.last().getDockedShape()) {
- dockersByPath.last().setReferencePoint({
- x: x,
- y: y
- });
- } else {
- dockersByPath.last().bounds.centerMoveTo(x, y);
- }
-
- //add additional dockers
- for (var i = 0; i < values.length; i++) {
- x = parseFloat(values[i]);
- y = parseFloat(values[++i]);
-
- var newDocker = this.createDocker();
- newDocker.bounds.centerMoveTo(x, y);
-
- //this.dockers = this.dockers.without(newDocker);
- //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);
- //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker);
- }
- }
- }
- }).bind(this));
- } else {
- this.alignDockers();
- }
-
- arguments.callee.$.deserialize.apply(this, arguments);
-
- this._changed();
- },
-
- toString: function(){
- return this.getStencil().title() + " " + this.id;
- },
-
- /**
- * @return {ORYX.Core.Shape} Returns last docked shape or null.
- */
- getTarget: function(){
- return this.dockers.last() ? this.dockers.last().getDockedShape() : null;
- },
-
- /**
- * @return {ORYX.Core.Shape} Returns the first docked shape or null
- */
- getSource: function() {
- return this.dockers.first() ? this.dockers.first().getDockedShape() : null;
- },
-
- /**
- * Checks whether the edge is at least docked to one shape.
- *
- * @return {boolean} True if edge is docked
- */
- isDocked: function() {
- var isDocked = false;
- this.dockers.each(function(docker) {
- if(docker.isDocked()) {
- isDocked = true;
- throw $break;
- }
- });
- return isDocked;
- },
-
- /**
- * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information.
- */
- toJSON: function() {
- var json = arguments.callee.$.toJSON.apply(this, arguments);
-
- if(this.getTarget()) {
- json.target = {
- resourceId: this.getTarget().resourceId
- };
- }
-
- return json;
- }
- };
- ORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge);
- /**
- * Copyright (c) 2009
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX){ var ORYX = {} }
- if(!ORYX.Plugins){ ORYX.Plugins = {} }
- /**
- This abstract plugin class can be used to build plugins on.
- It provides some more basic functionality like registering events (on*-handlers)...
- @example
- ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({
- construct: function() {
- // Call super class constructor
- arguments.callee.$.construct.apply(this, arguments);
-
- [...]
- },
- [...]
- });
-
- @class ORYX.Plugins.AbstractPlugin
- @constructor Creates a new instance
- @author Willi Tscheschner
- */
- ORYX.Plugins.AbstractPlugin = Clazz.extend({
- /**
- * The facade which offer editor-specific functionality
- * @type Facade
- * @memberOf ORYX.Plugins.AbstractPlugin.prototype
- */
- facade: null,
-
- construct: function( facade ){
- this.facade = facade;
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this));
- },
-
- /**
- Overwrite to handle load event. TODO: Document params!!!
- @methodOf ORYX.Plugins.AbstractPlugin.prototype
- */
- onLoaded: function(){},
-
- /**
- Overwrite to handle selection changed event. TODO: Document params!!!
- @methodOf ORYX.Plugins.AbstractPlugin.prototype
- */
- onSelectionChanged: function(){},
-
- /**
- Show overlay on given shape.
- @methodOf ORYX.Plugins.AbstractPlugin.prototype
- @example
- showOverlay(
- myShape,
- { stroke: "green" },
- ORYX.Editor.graft("http://www.w3.org/2000/svg", null, ['path', {
- "title": "Click the element to execute it!",
- "stroke-width": 2.0,
- "stroke": "black",
- "d": "M0,-5 L5,0 L0,5 Z",
- "line-captions": "round"
- }])
- )
- @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on
- @param {Oryx.XXX.Attributes} attributes some attributes...
- @param {Oryx.svg.node} svgNode The svg node which should be used as overlay
- @param {String} [svgNode="NW"] The svg node position where the overlay should be placed
- */
- showOverlay: function(shapes, attributes, svgNode, svgNodePosition ){
-
- if( !(shapes instanceof Array) ){
- shapes = [shapes]
- }
-
- // Define Shapes
- shapes = shapes.map(function(shape){
- var el = shape;
- if( typeof shape == "string" ){
- el = this.facade.getCanvas().getChildShapeByResourceId( shape );
- el = el || this.facade.getCanvas().getChildById( shape, true );
- }
- return el;
- }.bind(this)).compact();
-
- // Define unified id
- if( !this.overlayID ){
- this.overlayID = this.type + ORYX.Editor.provideId();
- }
-
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_OVERLAY_SHOW,
- id : this.overlayID,
- shapes : shapes,
- attributes : attributes,
- node : svgNode,
- nodePosition: svgNodePosition || "NW"
- });
-
- },
-
- /**
- Hide current overlay.
- @methodOf ORYX.Plugins.AbstractPlugin.prototype
- */
- hideOverlay: function(){
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_OVERLAY_HIDE,
- id : this.overlayID
- });
- },
-
- /**
- Does a transformation with the given xslt stylesheet.
- @methodOf ORYX.Plugins.AbstractPlugin.prototype
- @param {String} data The data (e.g. eRDF) which should be transformed
- @param {String} stylesheet URL of a stylesheet which should be used for transforming data.
- */
- doTransform: function( data, stylesheet ) {
-
- if( !stylesheet || !data ){
- return ""
- }
- var parser = new DOMParser();
- var parsedData = parser.parseFromString(data, "text/xml");
- source=stylesheet;
- new Ajax.Request(source, {
- asynchronous: false,
- method: 'get',
- onSuccess: function(transport){
- xsl = transport.responseText
- }.bind(this),
- onFailure: (function(transport){
- ORYX.Log.error("XSL load failed" + transport);
- }).bind(this)
- });
- var xsltProcessor = new XSLTProcessor();
- var domParser = new DOMParser();
- var xslObject = domParser.parseFromString(xsl, "text/xml");
- xsltProcessor.importStylesheet(xslObject);
-
- try {
-
- var newData = xsltProcessor.transformToFragment(parsedData, document);
- var serializedData = (new XMLSerializer()).serializeToString(newData);
-
- /* Firefox 2 to 3 problem?! */
- serializedData = !serializedData.startsWith("<?xml") ? "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serializedData : serializedData;
-
- return serializedData;
-
- }catch (error) {
- return -1;
- }
-
- },
-
- /**
- * Opens a new window that shows the given XML content.
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- * @param {Object} content The XML content to be shown.
- * @example
- * openDownloadWindow( "my.xml", "<exampleXML />" );
- */
- openXMLWindow: function(content) {
- var win = window.open(
- 'data:application/xml,' + encodeURIComponent(
- content
- ),
- '_blank', "resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes"
- );
- },
-
- /**
- * Opens a download window for downloading the given content.
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- * @param {String} filename The content's file name
- * @param {String} content The content to download
- */
- openDownloadWindow: function(filename, content) {
- var win = window.open("");
- if (win != null) {
- win.document.open();
- win.document.write("<html><body>");
- var submitForm = win.document.createElement("form");
- win.document.body.appendChild(submitForm);
-
- var createHiddenElement = function(name, value) {
- var newElement = document.createElement("input");
- newElement.name=name;
- newElement.type="hidden";
- newElement.value = value;
- return newElement
- }
-
- submitForm.appendChild( createHiddenElement("download", content) );
- submitForm.appendChild( createHiddenElement("file", filename) );
-
-
- submitForm.method = "POST";
- win.document.write("</body></html>");
- win.document.close();
- submitForm.action= ORYX.PATH + "/download";
- submitForm.submit();
- }
- },
-
- /**
- * Serializes DOM.
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- * @type {String} Serialized DOM
- */
- getSerializedDOM: function(){
- // Force to set all resource IDs
- var serializedDOM = DataManager.serializeDOM( this.facade );
- //add namespaces
- serializedDOM = '<?xml version="1.0" encoding="utf-8"?>' +
- '<html xmlns="http://www.w3.org/1999/xhtml" ' +
- 'xmlns:b3mn="http://b3mn.org/2007/b3mn" ' +
- 'xmlns:ext="http://b3mn.org/2007/ext" ' +
- 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ' +
- 'xmlns:atom="http://b3mn.org/2007/atom+xhtml">' +
- '<head profile="http://purl.org/NET/erdf/profile">' +
- '<link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" />' +
- '<link rel="schema.dcTerms" href="http://purl.org/dc/terms/ " />' +
- '<link rel="schema.b3mn" href="http://b3mn.org" />' +
- '<link rel="schema.oryx" href="http://oryx-editor.org/" />' +
- '<link rel="schema.raziel" href="http://raziel.org/" />' +
- '<base href="' +
- location.href.split("?")[0] +
- '" />' +
- '</head><body>' +
- serializedDOM +
- '</body></html>';
-
- return serializedDOM;
- },
-
- /**
- * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore,
- * shapes cannot be selected anymore.
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- */
- enableReadOnlyMode: function(){
- //Edges cannot be moved anymore
- this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);
-
- // Stop the user from editing the diagram while the plugin is active
- this._stopSelectionChange = function(){
- if(this.facade.getSelection().length > 0) {
- this.facade.setSelection([]);
- }
- };
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));
- },
- /**
- * Disables read only mode, see @see
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode
- */
- disableReadOnlyMode: function(){
- // Edges can be moved now again
- this.facade.enableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN);
-
- if (this._stopSelectionChange) {
- this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this));
- this._stopSelectionChange = undefined;
- }
- },
-
- /**
- * Extracts RDF from DOM.
- * @methodOf ORYX.Plugins.AbstractPlugin.prototype
- * @type {String} Extracted RFD. Null if there are transformation errors.
- */
- getRDFFromDOM: function(){
- //convert to RDF
- try {
- var xsl = "";
- source=ORYX.PATH + "lib/extract-rdf.xsl";
- new Ajax.Request(source, {
- asynchronous: false,
- method: 'get',
- onSuccess: function(transport){
- xsl = transport.responseText
- }.bind(this),
- onFailure: (function(transport){
- ORYX.Log.error("XSL load failed" + transport);
- }).bind(this)
- });
- /*
- var parser = new DOMParser();
- var parsedDOM = parser.parseFromString(this.getSerializedDOM(), "text/xml");
- var xsltPath = ORYX.PATH + "lib/extract-rdf.xsl";
- var xsltProcessor = new XSLTProcessor();
- var xslRef = document.implementation.createDocument("", "", null);
- xslRef.async = false;
- xslRef.load(xsltPath);
- xsltProcessor.importStylesheet(xslRef);
- try {
- var rdf = xsltProcessor.transformToDocument(parsedDOM);
- return (new XMLSerializer()).serializeToString(rdf);
- } catch (error) {
- Ext.Msg.alert("Oryx", error);
- return null;
- }*/
- var domParser = new DOMParser();
- var xmlObject = domParser.parseFromString(this.getSerializedDOM(), "text/xml");
- var xslObject = domParser.parseFromString(xsl, "text/xml");
- var xsltProcessor = new XSLTProcessor();
- xsltProcessor.importStylesheet(xslObject);
- var result = xsltProcessor.transformToFragment(xmlObject, document);
-
- var serializer = new XMLSerializer();
-
- return serializer.serializeToString(result);
- }catch(e){
- Ext.Msg.alert("Oryx", error);
- return "";
- }
-
- },
-
- /**
- * Checks if a certain stencil set is loaded right now.
- *
- */
- isStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) {
- return this.facade.getStencilSets().values().any(
- function(ss){
- return ss.extensions().keys().any(
- function(extensionKey) {
- return extensionKey == stencilSetExtensionNamespace;
- }.bind(this)
- );
- }.bind(this)
- );
- },
-
- /**
- * Raises an event so that registered layouters does
- * have the posiblility to layout the given shapes
- * For further reading, have a look into the AbstractLayouter
- * class
- * @param {Object} shapes
- */
- doLayout: function(shapes){
- // Raises a do layout event
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_LAYOUT,
- shapes : shapes
- });
- },
-
-
- /**
- * Does a primitive layouting with the incoming/outgoing
- * edges (set the dockers to the right position) and if
- * necessary, it will be called the real layouting
- * @param {ORYX.Core.Node} node
- * @param {Array} edges
- */
- layoutEdges : function(node, allEdges, offset){
- if (!this.facade.isExecutingCommands()){ return }
- var Command = ORYX.Core.Command.extend({
- construct: function(edges, node, offset, plugin){
- this.edges = edges;
- this.node = node;
- this.plugin = plugin;
- this.offset = offset;
-
- // Get the new absolute center
- var center = node.absoluteXY();
- this.ulo = {x: center.x - offset.x, y:center.y - offset.y};
-
-
- },
- execute: function(){
-
- if (this.changes){
- this.executeAgain();
- return;
- } else {
- this.changes = [];
- this.edges.each(function(edge){
- this.changes.push({
- edge: edge,
- oldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() })
- })
- }.bind(this));
- }
-
- // Find all edges, which are related to the node and
- // have more than two dockers
- this.edges
- // Find all edges with more than two dockers
- .findAll(function(r){ return r.dockers.length > 2 }.bind(this))
- // For every edge, check second and one before last docker
- // if there are horizontal/vertical on the same level
- // and if so, align the the bounds
- .each(function(edge){
- if (edge.dockers.first().getDockedShape() === this.node){
- var second = edge.dockers[1];
- if (this.align(second.bounds, edge.dockers.first())){ second.update(); }
- } else if (edge.dockers.last().getDockedShape() === this.node) {
- var beforeLast = edge.dockers[edge.dockers.length-2];
- if (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); }
- }
- edge._update(true);
- edge.removeUnusedDockers();
- if (this.isBendPointIncluded(edge)){
- this.plugin.doLayout(edge);
- return;
- }
- }.bind(this));
-
-
- // Find all edges, which have only to dockers
- // and is located horizontal/vertical.
- // Do layout with those edges
- this.edges
- // Find all edges with exactly two dockers
- .each(function(edge){
- if (edge.dockers.length == 2){
- var p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();
- var p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center();
- // Find all horizontal/vertical edges
- 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){
- this.plugin.doLayout(edge);
- }
- }
- }.bind(this));
-
- this.edges.each(function(edge, i){
- this.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() });
- }.bind(this));
-
- },
- /**
- * Align the bounds if the center is
- * the same than the old center
- * @params {Object} bounds
- * @params {Object} bounds2
- */
- align: function(bounds, refDocker){
-
- var abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center();
-
- var xdif = bounds.center().x-abRef.x;
- var ydif = bounds.center().y-abRef.y;
- if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){
- bounds.moveBy({x:-xdif, y:0})
- }
- if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){
- bounds.moveBy({y:-ydif, x:0})
- }
-
- if (this.offset.xs !== undefined || this.offset.ys !== undefined){
- var absPXY = refDocker.getDockedShape().absoluteXY();
- xdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs));
- ydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys));
-
- if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){
- bounds.moveBy({x:-(bounds.center().x-abRef.x), y:0})
- }
-
- if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){
- bounds.moveBy({y:-(bounds.center().y-abRef.y), x:0})
- }
- }
- },
-
- /**
- * Returns a TRUE if there are bend point which overlay the shape
- */
- isBendPointIncluded: function(edge){
- // Get absolute bounds
- var ab = edge.dockers.first().getDockedShape();
- var bb = edge.dockers.last().getDockedShape();
-
- if (ab) {
- ab = ab.absoluteBounds();
- ab.widen(5);
- }
-
- if (bb) {
- bb = bb.absoluteBounds();
- bb.widen(20); // Wide with 20 because of the arrow from the edge
- }
-
- return edge.dockers
- .any(function(docker, i){
- var c = docker.bounds.center();
- // Dont count first and last
- return i != 0 && i != edge.dockers.length-1 &&
- // Check if the point is included to the absolute bounds
- ((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c)))
- })
- },
-
- removeAllDocker: function(edge){
- edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){
- edge.removeDocker(docker);
- })
- },
- executeAgain: function(){
- this.changes.each(function(change){
- // Reset the dockers
- this.removeAllDocker(change.edge);
- change.dockerPositions.each(function(pos, i){
- if (i==0||i==change.dockerPositions.length-1){ return }
- var docker = change.edge.createDocker(undefined, pos);
- docker.bounds.centerMoveTo(pos);
- docker.update();
- }.bind(this));
- change.edge._update(true);
- }.bind(this));
- },
- rollback: function(){
- this.changes.each(function(change){
- // Reset the dockers
- this.removeAllDocker(change.edge);
- change.oldDockerPositions.each(function(pos, i){
- if (i==0||i==change.oldDockerPositions.length-1){ return }
- var docker = change.edge.createDocker(undefined, pos);
- docker.bounds.centerMoveTo(pos);
- docker.update();
- }.bind(this));
- change.edge._update(true);
- }.bind(this));
- }
- });
-
- this.facade.executeCommands([new Command(allEdges, node, offset, this)]);
- }
- });/**
- * Copyright (c) 2009
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX){ var ORYX = {} }
- if(!ORYX.Plugins){ ORYX.Plugins = {} }
- /**
- This abstract plugin implements the core behaviour of layout
-
- @class ORYX.Plugins.AbstractLayouter
- @constructor Creates a new instance
- @author Willi Tscheschner
- */
- ORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({
-
- /**
- * 'layouted' defined all types of shapes which will be layouted.
- * It can be one value or an array of values. The value
- * can be a Stencil ID (as String) or an class type of either
- * a ORYX.Core.Node or ORYX.Core.Edge
- * @type Array|String|Object
- * @memberOf ORYX.Plugins.AbstractLayouter.prototype
- */
- layouted : [],
-
- /**
- * Constructor
- * @param {Object} facade
- * @memberOf ORYX.Plugins.AbstractLayouter.prototype
- */
- construct: function( facade ){
- arguments.callee.$.construct.apply(this, arguments);
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this));
- },
-
- /**
- * Proofs if this shape should be layouted or not
- * @param {Object} shape
- * @memberOf ORYX.Plugins.AbstractLayouter.prototype
- */
- isIncludedInLayout: function(shape){
- if (!(this.layouted instanceof Array)){
- this.layouted = [this.layouted].compact();
- }
-
- // If there are no elements
- if (this.layouted.length <= 0) {
- // Return TRUE
- return true;
- }
-
- // Return TRUE if there is any correlation between
- // the 'layouted' attribute and the shape themselve.
- return this.layouted.any(function(s){
- if (typeof s == "string") {
- return shape.getStencil().id().include(s);
- } else {
- return shape instanceof s;
- }
- })
- },
-
- /**
- * Callback to start the layouting
- * @param {Object} event Layout event
- * @param {Object} shapes Given shapes
- * @memberOf ORYX.Plugins.AbstractLayouter.prototype
- */
- _initLayout: function(event){
-
- // Get the shapes
- var shapes = [event.shapes].flatten().compact();
-
- // Find all shapes which should be layouted
- var toLayout = shapes.findAll(function(shape){
- return this.isIncludedInLayout(shape)
- }.bind(this))
-
- // If there are shapes left
- if (toLayout.length > 0){
- // Do layout
- this.layout(toLayout);
- }
- },
-
- /**
- * Implementation of layouting a set on shapes
- * @param {Object} shapes Given shapes
- * @memberOf ORYX.Plugins.AbstractLayouter.prototype
- */
- layout: function(shapes){
- throw new Error("Layouter has to implement the layout function.")
- }
- });ImageViewer = Ext.extend(Ext.Window, {
- initComponent: function() {
- this.bodyCfg = {
- tag: 'img',
- src: this.src,
- autoscroll: true,
- fixedcenter : true
- };
- ImageViewer.superclass.initComponent.apply(this, arguments);
- },
- onRender: function() {
- ImageViewer.superclass.onRender.apply(this, arguments);
- this.body.on('load', this.onImageLoad, this, {single: true});
- },
- onImageLoad: function() {
- // var h = this.getFrameHeight(),
- // w = this.getFrameWidth();
- // this.setSize(this.body.dom.offsetWidth + w, this.body.dom.offsetHeight + h);
- },
- setSrc: function(src) {
- this.body.on('load', this.onImageLoad, this, {single: true});
- //this.body.dom.style.width = this.body.dom.style.width = 'auto';
- this.body.dom.src = src;
- },
- initEvents: function() {
- ImageViewer.superclass.initEvents.apply(this, arguments);
- if (this.resizer) {
- this.resizer.preserveRatio = true;
- }
- }
- });if(!Signavio){ var Signavio = {} };
- if (!Signavio.Core) { Signavio.Core = {} };
- Signavio.Core.Version = "1.0";
- /**
- * Copyright (c) 2009
- *
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!Signavio) {
- var Signavio = new Object();
- }
- if (!Signavio.Plugins) {
- Signavio.Plugins = new Object();
- }
- if (!Signavio.Plugins.Utils) {
- Signavio.Plugins.Utils = new Object();
- }
- if (!Signavio.Helper) {
- Signavio.Helper = new Object();
- }
- new function(){
-
- var mask;
-
-
- Signavio.Plugins.Utils.getFFVersion = function(){
- try {
- return Number(window.navigator.userAgent.match("Firefox.([0-9]+[\.][0-9]+)")[1]) || 0 ;
- } catch(e){
- return 0;
- }
- }
-
-
- /**
- * Shows an overlay of signavio
- */
- Signavio.Helper.ShowMask = function(force, parent){
-
- if (!force && ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY === true){
- return;
- }
-
- if (mask){
- return;
- }
-
- var s = "background:white;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100000;"
- var ss = "left:50%;margin-left:-200px;margin-top:-90px;position:absolute;top:50%;display:none;width:391px;"
- var sversion = "color:#ad0f5b;padding-right:10px;font-family:tahoma,arial,san-serif;font-size:12px;";
- var stext = "display:block;position:relative;text-align:right;top:0;width:100%;";
- var stitle = "color:#ad0f5b;font-weight:bold;padding-right:10px;font-family:tahoma,arial,san-serif;font-size:12px;"
- var sloading = "height:16px;width:16px;margin-bottom:-4px;background: transparent url(../libs/ext-2.0.2/resources/images/default/tree/loading.gif) no-repeat center;"
- var simg = "padding-bottom:10px;border-bottom:1px solid #ad0f5b;";
- // Define the parent
- parent = (parent ? Ext.get(parent) : null) || Ext.getBody();
-
- if (parent !== Ext.getBody()){
- parent.setStyle("position", "relative")
- }
- mask = Ext.get(document.createElement("div"));
- parent.appendChild(mask);
- mask.dom.setAttribute("style", s);
- mask.dom.innerHTML = "<div class='mask-logo' style='"+ss+"'>"+
- "<div>"+
- "<img style='"+simg+"' src='"+ORYX.CONFIG.EXPLORER_PATH+"/src/img/signavio/smoky/logo.png' />"+
- "</div>"+
- "<span class='mask-text' style='"+stext+"'>"+
- "<span class='mask-title' style='"+stitle+"'>Editor</span>"+
- "<span class='mask-version' style='"+sversion+"'>Version "+Signavio.Core.Version+"</span>"+
- "<img style='"+sloading+"' src='"+(ORYX.CONFIG.BLANK_IMAGE||Ext.BLANK_IMAGE_URL)+"'/>"+
- "</span>" +
- "</div>";
- mask.first().show({duration:0.3});
- }
-
- // When body is loaded, show overlay
- Ext.onReady(Signavio.Helper.ShowMask);
-
- /**
- * Hides the overlay
- */
- Signavio.Helper.HideMask = function(){
- window.setTimeout(function(){
- if (mask){
- mask.first().hide({duration:0.4, remove:true, block:true});
- mask.hide({duration:0.3, remove:true, block :true});
- delete mask;
- }
- }.bind(this), 2000)
- }
-
- Signavio.Plugins.Loading = {
-
- facade: undefined,
- construct: function(facade) {
- this.facade = facade;
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, Signavio.Helper.HideMask);
-
- /**
- * Overwrite the toJSON method in the Canvas
- * to set the correct stencilset namespace.
- *
- */
- /*(var me = this;
- new function(){
- // Copy prototype method
- var toJSON = ORYX.Core.Canvas.prototype.toJSON;
- ORYX.Core.Canvas.prototype.toJSON = function(){
- // Call super
- var json = toJSON.call(this);
- // Check for replace stencil set namespace
- json.stencilset.namespace = me.facade.getModelMetaData().model.stencilset.namespace;
-
- return json;
- }
- }()*/
- }
- }
-
- Signavio.Plugins.Loading = Clazz.extend(Signavio.Plugins.Loading);
- /**
- * Provides an uniq id
- * @overwrite
- * @return {String}
- *
- */
- ORYX.Editor.provideId = function() {
- var res = [], hex = '0123456789ABCDEF';
-
- for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10);
-
- res[14] = 4;
- res[19] = (res[19] & 0x3) | 0x8;
-
- for (var i = 0; i < 36; i++) res[i] = hex[res[i]];
-
- res[8] = res[13] = res[18] = res[23] = '-';
-
- return "sid-" + res.join('');
- };
- }();
- /**
- * Ext specific extension
- *
- *
- *
- */
- new function(){
-
- /**
- * Implementation of an Ext-LinkButton
- *
- *
- */
- Ext.LinkButton = Ext.extend(Ext.BoxComponent, {
- // On Click Handler
- click: null,
-
- // Image url
- image: null,
-
- // Image style (only if an image url is setted)
- imageStyle: null,
- toggle:false,
-
- toggleStyle:null,
- selected:false,
-
- href:false,
- el: null,
-
- // private
- onRender : function(ct, position){
-
- if( this.el == null ){
- this.el = document.createElement('a');
- if (this.tabIndex)
- this.el.setAttribute("tabindex", this.tabIndex)
-
- this.el.id = this.getId();
- this.el.className = this.cls||"x-link-button";
-
- if( !this.disabled )
- this.el.href = this.href ? this.href : "#" + this.text;
- if( !this.disabled ){
- Element.observe( this.el, 'click', this.onClick.bind(this));
- }
-
- if( this.image ){
- this.el.innerHTML = '<img src="' + this.image + '" title="' + this.text + '"' + ( this.imageStyle ? ' style="' + this.imageStyle + '"/>': '/>')
- } else {
- this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
- }
- if(this.forId){
- this.el.setAttribute('htmlFor', this.forId);
- }
- }
- Ext.LinkButton.superclass.onRender.call(this, ct, position);
- },
-
- onClick: function(e){
-
- if( this.disabled ){ Event.stop(e); return; }
-
- // Toggle the button
- if( this.toggle ){
- this.selected = !this.selected;
- if( this.toggleStyle ){
- this._setStyle( this.el.dom, '')
- this.el.dom.setAttribute('style','')
- if( this.selected ){
- this.el.applyStyles( this.toggleStyle )
- } else {
- this.el.applyStyles( this.initialConfig.style )
- }
- }
- }
-
- if( this.click instanceof Function )
- this.click.apply(this.click, [this, e]);
-
- Event.stop(e)
- },
-
- setText: function(t, encode){
- this.text = t;
- if(this.rendered){
- this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
- }
- return this;
- },
-
- _setStyle: function(node, style){
- if( Ext.isIE ){
- node.style.setAttribute('cssText', style );
- } else {
- node.setAttribute('style', style );
- }
- }
- });
- Ext.reg('linkbutton', Ext.LinkButton);
-
- }();
- /**
- * Helper Methods
- *
- */
- new function(){
-
-
- Signavio.Helper.RecordReader = function(meta){
- meta = meta || {};
- this.rels = meta.rels || this.rels;
- Signavio.Helper.RecordReader.superclass.constructor.call(this, meta, ['rep','href','rel']);
- };
- Ext.extend(Signavio.Helper.RecordReader, Ext.data.JsonReader, {
- rels: ["gitem"],
-
- read : function(response){
- var json = response.responseText;
- var o = eval("("+json+")");
- if(!o) {
- throw {message: "JsonReader.read: Json object not found"};
- }
- var Record = this.recordType;
- var records = [], total = 0;
- o.each(function(rec){
- if (this.rels.include(rec.rel)) {
- records.push(new Record(rec));
- }
- if (rec.rel == "info" && rec.rep.size){
- total = rec.rep.size;
- }
- }.bind(this))
- return {
- success : true,
- records : records,
- totalRecords : total || records.length
- }
- }
- })
-
-
-
- /**
- * Creates a new record, including 'rel', 'href', and 'rep' attributes
- * @param {String} rel
- * @param {String} href
- * @param {Object} rep
- */
- Signavio.Helper.createRecord = function(rel, href, rep){
-
- var Rec = Ext.data.Record.create(["rel", "href", "rep"]);
- var record = new Rec({
- rel : rel,
- href: href,
- rep : rep
- });
-
- return record;
- }
- }()
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- ORYX.Plugins.Toolbar = Clazz.extend({
- facade: undefined,
- plugs: [],
- construct: function(facade, ownPluginData) {
- this.facade = facade;
-
- this.groupIndex = new Hash();
- ownPluginData.properties.each((function(value){
- if(value.group && value.index != undefined) {
- this.groupIndex[value.group] = value.index
- }
- }).bind(this));
-
- Ext.QuickTips.init();
- this.buttons = [];
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_BUTTON_UPDATE, this.onButtonUpdate.bind(this));
- },
-
- /**
- * Can be used to manipulate the state of a button.
- * @example
- * this.facade.raiseEvent({
- * type: ORYX.CONFIG.EVENT_BUTTON_UPDATE,
- * id: this.buttonId, // have to be generated before and set in the offer method
- * pressed: true
- * });
- * @param {Object} event
- */
- onButtonUpdate: function(event){
- var button = this.buttons.find(function(button){
- return button.id === event.id;
- });
-
- if(event.pressed !== undefined){
- button.buttonInstance.toggle(event.pressed);
- }
- },
- registryChanged: function(pluginsData) {
- // Sort plugins by group and index
- var newPlugs = pluginsData.sortBy((function(value) {
- return ((this.groupIndex[value.group] != undefined ? this.groupIndex[value.group] : "" ) + value.group + "" + value.index).toLowerCase();
- }).bind(this));
- var plugs = $A(newPlugs).findAll(function(value){
- return !this.plugs.include(value) && (!value.target || value.target === ORYX.Plugins.Toolbar)
- }.bind(this));
- if(plugs.length<1)
- return;
- this.buttons = [];
- ORYX.Log.trace("Creating a toolbar.")
- if(!this.toolbar){
- this.toolbar = new Ext.ux.SlicedToolbar({
- height: 24
- });
- var region = this.facade.addToRegion("north", this.toolbar, "Toolbar");
- }
-
-
- var currentGroupsName = this.plugs.last()?this.plugs.last().group:plugs[0].group;
-
- // Map used to store all drop down buttons of current group
- var currentGroupsDropDownButton = {};
-
- plugs.each((function(value) {
- if(!value.name) {return}
- this.plugs.push(value);
- // Add seperator if new group begins
- if(currentGroupsName != value.group) {
- this.toolbar.add('-');
- currentGroupsName = value.group;
- currentGroupsDropDownButton = {};
- }
- // If an drop down group icon is provided, a split button should be used
- if(value.dropDownGroupIcon){
- var splitButton = currentGroupsDropDownButton[value.dropDownGroupIcon];
-
- // Create a new split button if this is the first plugin using it
- if(splitButton === undefined){
- splitButton = currentGroupsDropDownButton[value.dropDownGroupIcon] = new Ext.Toolbar.SplitButton({
- cls: "x-btn-icon", //show icon only
- icon: value.dropDownGroupIcon,
- menu: new Ext.menu.Menu({
- items: [] // items are added later on
- }),
- listeners: {
- click: function(button, event){
- // The "normal" button should behave like the arrow button
- if(!button.menu.isVisible() && !button.ignoreNextClick){
- button.showMenu();
- } else {
- button.hideMenu();
- }
- }
- }
- });
-
- this.toolbar.add(splitButton);
- }
-
- // General config button which will be used either to create a normal button
- // or a check button (if toggling is enabled)
- var buttonCfg = {
- icon: value.icon,
- text: value.name,
- itemId: value.id,
- handler: value.toggle ? undefined : value.functionality,
- checkHandler: value.toggle ? value.functionality : undefined,
- listeners: {
- render: function(item){
- // After rendering, a tool tip should be added to component
- if (value.description) {
- new Ext.ToolTip({
- target: item.getEl(),
- title: value.description
- })
- }
- }
- }
- }
-
- // Create buttons depending on toggle
- if(value.toggle) {
- var button = new Ext.menu.CheckItem(buttonCfg);
- } else {
- var button = new Ext.menu.Item(buttonCfg);
- }
-
- splitButton.menu.add(button);
-
- } else if(value.addFill) {
- this.toolbar.addFill();
- } else { // create normal, simple button
- var button = new Ext.Toolbar.Button({
- icon: value.icon, // icons can also be specified inline
- cls: 'x-btn-icon', // Class who shows only the icon
- itemId: value.id,
- tooltip: value.description, // Set the tooltip
- tooltipType: 'title', // Tooltip will be shown as in the html-title attribute
- handler: value.toggle ? null : value.functionality, // Handler for mouse click
- enableToggle: value.toggle, // Option for enabling toggling
- toggleHandler: value.toggle ? value.functionality : null // Handler for toggle (Parameters: button, active)
- });
-
- this.toolbar.add(button);
- button.getEl().onclick = function() {this.blur()}
- }
-
- value['buttonInstance'] = button;
- this.buttons.push(value);
-
- }).bind(this));
- this.enableButtons([]);
-
- //TODO this should be done when resizing and adding elements!!!!
- this.toolbar.calcSlices();
- window.addEventListener("resize", function(event){this.toolbar.calcSlices()}.bind(this), false);
- window.addEventListener("onresize", function(event){this.toolbar.calcSlices()}.bind(this), false);
- },
-
- onSelectionChanged: function(event) {
- this.enableButtons(event.elements);
- },
- enableButtons: function(elements) {
- // Show the Buttons
- this.buttons.each((function(value){
- value.buttonInstance.enable();
-
- // If there is less elements than minShapes
- if(value.minShape && value.minShape > elements.length)
- value.buttonInstance.disable();
- // If there is more elements than minShapes
- if(value.maxShape && value.maxShape < elements.length)
- value.buttonInstance.disable();
- // If the plugin is not enabled
- if(value.isEnabled && !value.isEnabled(value.buttonInstance))
- value.buttonInstance.disable();
-
- }).bind(this));
- }
- });
- Ext.ns("Ext.ux");
- Ext.ux.SlicedToolbar = Ext.extend(Ext.Toolbar, {
- currentSlice: 0,
- iconStandardWidth: 22, //22 px
- seperatorStandardWidth: 2, //2px, minwidth for Ext.Toolbar.Fill
- toolbarStandardPadding: 2,
-
- initComponent: function(){
- Ext.apply(this, {
- });
- Ext.ux.SlicedToolbar.superclass.initComponent.apply(this, arguments);
- },
-
- onRender: function(){
- Ext.ux.SlicedToolbar.superclass.onRender.apply(this, arguments);
- },
-
- onResize: function(){
- Ext.ux.SlicedToolbar.superclass.onResize.apply(this, arguments);
- },
-
- calcSlices: function(){
- var slice = 0;
- this.sliceMap = {};
- var sliceWidth = 0;
- var toolbarWidth = this.getEl().getWidth();
- this.items.getRange().each(function(item, index){
- //Remove all next and prev buttons
- if (item.helperItem) {
- item.destroy();
- return;
- }
-
- var itemWidth = item.getEl().getWidth();
-
- if(sliceWidth + itemWidth + 5 * this.iconStandardWidth > toolbarWidth){
- var itemIndex = this.items.indexOf(item);
-
- this.insertSlicingButton("next", slice, itemIndex);
-
- if (slice !== 0) {
- this.insertSlicingButton("prev", slice, itemIndex);
- }
-
- this.insertSlicingSeperator(slice, itemIndex);
- slice += 1;
- sliceWidth = 0;
- }
-
- this.sliceMap[item.id] = slice;
- sliceWidth += itemWidth;
- }.bind(this));
-
- // Add prev button at the end
- if(slice > 0){
- this.insertSlicingSeperator(slice, this.items.getCount()+1);
- this.insertSlicingButton("prev", slice, this.items.getCount()+1);
- var spacer = new Ext.Toolbar.Spacer();
- this.insertSlicedHelperButton(spacer, slice, this.items.getCount()+1);
- Ext.get(spacer.id).setWidth(this.iconStandardWidth);
- }
-
- this.maxSlice = slice;
-
- // Update view
- this.setCurrentSlice(this.currentSlice);
- },
-
- insertSlicedButton: function(button, slice, index){
- this.insertButton(index, button);
- this.sliceMap[button.id] = slice;
- },
-
- insertSlicedHelperButton: function(button, slice, index){
- button.helperItem = true;
- this.insertSlicedButton(button, slice, index);
- },
-
- insertSlicingSeperator: function(slice, index){
- // Align right
- this.insertSlicedHelperButton(new Ext.Toolbar.Fill(), slice, index);
- },
-
- // type => next or prev
- insertSlicingButton: function(type, slice, index){
- var nextHandler = function(){this.setCurrentSlice(this.currentSlice+1)}.bind(this);
- var prevHandler = function(){this.setCurrentSlice(this.currentSlice-1)}.bind(this);
-
- var button = new Ext.Toolbar.Button({
- cls: "x-btn-icon",
- icon: ORYX.CONFIG.ROOT_PATH + "images/toolbar_"+type+".png",
- handler: (type === "next") ? nextHandler : prevHandler
- });
-
- this.insertSlicedHelperButton(button, slice, index);
- },
-
- setCurrentSlice: function(slice){
- if(slice > this.maxSlice || slice < 0) return;
-
- this.currentSlice = slice;
- this.items.getRange().each(function(item){
- item.setVisible(slice === this.sliceMap[item.id]);
- }.bind(this));
- }
- });/**
- * Copyright (c) 2009
- * Jan-Felix Schwarz, Willi Tscheschner, Nicolas Peters, Martin Czuchra, Daniel Polak
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- ORYX.Plugins.ShapeMenuPlugin = {
- construct: function(facade) {
- this.facade = facade;
-
- this.alignGroups = new Hash();
- var containerNode = this.facade.getCanvas().getHTMLContainer();
- this.shapeMenu = new ORYX.Plugins.ShapeMenu(containerNode);
- this.currentShapes = [];
- // Register on dragging and resizing events for show/hide of ShapeMenu
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hideShapeMenu.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END, this.showShapeMenu.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_RESIZE_START, (function(){
- this.hideShapeMenu();
- this.hideMorphMenu();
- }).bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_RESIZE_END, this.showShapeMenu.bind(this));
-
- // Enable DragZone
- var DragZone = new Ext.dd.DragZone(containerNode.parentNode, {shadow: !Ext.isMac});
- DragZone.afterDragDrop = this.afterDragging.bind(this, DragZone);
- DragZone.beforeDragOver = this.beforeDragOver.bind(this, DragZone);
-
- // Memory of created Buttons
- this.createdButtons = {};
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_STENCIL_SET_LOADED, (function(){ this.registryChanged() }).bind(this));
- this.timer = null;
-
- this.resetElements = true;
- },
- hideShapeMenu: function(event) {
- window.clearTimeout(this.timer);
- this.timer = null;
- this.shapeMenu.hide();
- },
- showShapeMenu: function( dontGenerateNew ) {
-
- if( !dontGenerateNew || this.resetElements ){
-
- window.clearTimeout(this.timer);
- this.timer = window.setTimeout(function(){
-
- // Close all Buttons
- this.shapeMenu.closeAllButtons();
-
- // Show the Morph Button
- this.showMorphButton(this.currentShapes);
-
- // Show the Stencil Buttons
- this.showStencilButtons(this.currentShapes);
-
- // Show the ShapeMenu
- this.shapeMenu.show(this.currentShapes);
-
- this.resetElements = false;
- }.bind(this), 300)
-
- } else {
-
- window.clearTimeout(this.timer);
- this.timer = null;
-
- // Show the ShapeMenu
- this.shapeMenu.show(this.currentShapes);
-
- }
- },
- registryChanged: function(pluginsData) {
-
- if(pluginsData) {
- pluginsData = pluginsData.each(function(value) {value.group = value.group ? value.group : 'unknown'});
- this.pluginsData = pluginsData.sortBy( function(value) {
- return (value.group + "" + value.index);
- });
- }
-
- this.shapeMenu.removeAllButtons();
- this.shapeMenu.setNumberOfButtonsPerLevel(ORYX.CONFIG.SHAPEMENU_RIGHT, 2);
- this.createdButtons = {};
-
- this.createMorphMenu();
-
- if( !this.pluginsData ){
- this.pluginsData = [];
- }
- this.baseMorphStencils = this.facade.getRules().baseMorphs();
-
- // Checks if the stencil set has morphing attributes
- var isMorphing = this.facade.getRules().containsMorphingRules();
-
- // Create Buttons for all Stencils of all loaded stencilsets
- var stencilsets = this.facade.getStencilSets();
- stencilsets.values().each((function(stencilSet){
-
- var nodes = stencilSet.nodes();
- nodes.each((function(stencil) {
-
- // Create a button for each node
- var option = {type: stencil.id(), namespace: stencil.namespace(), connectingType: true};
- var button = new ORYX.Plugins.ShapeMenuButton({
- callback: this.newShape.bind(this, option),
- icon: stencil.icon(),
- align: ORYX.CONFIG.SHAPEMENU_RIGHT,
- group: 0,
- //dragcallback: this.hideShapeMenu.bind(this),
- msg: stencil.title() + " - " + ORYX.I18N.ShapeMenuPlugin.clickDrag
- });
-
- // Add button to shape menu
- this.shapeMenu.addButton(button);
-
- // Add to the created Button Array
- this.createdButtons[stencil.namespace() + stencil.type() + stencil.id()] = button;
-
- // Drag'n'Drop will enable
- Ext.dd.Registry.register(button.node.lastChild, option);
- }).bind(this));
-
- var edges = stencilSet.edges();
- edges.each((function(stencil) {
- // Create a button for each edge
- var option = {type: stencil.id(), namespace: stencil.namespace()};
- var button = new ORYX.Plugins.ShapeMenuButton({
- callback: this.newShape.bind(this, option),
- // icon: isMorphing ? ORYX.PATH + "images/edges.png" : stencil.icon(),
- icon: stencil.icon(),
- align: ORYX.CONFIG.SHAPEMENU_RIGHT,
- group: 1,
- //dragcallback: this.hideShapeMenu.bind(this),
- msg: (isMorphing ? ORYX.I18N.Edge : stencil.title()) + " - " + ORYX.I18N.ShapeMenuPlugin.drag
- });
-
- // Add button to shape menu
- this.shapeMenu.addButton(button);
-
- // Add to the created Button Array
- this.createdButtons[stencil.namespace() + stencil.type() + stencil.id()] = button;
-
- // Drag'n'Drop will enable
- Ext.dd.Registry.register(button.node.lastChild, option);
-
- }).bind(this));
-
- }).bind(this));
-
- },
-
- createMorphMenu: function() {
-
- this.morphMenu = new Ext.menu.Menu({
- id: 'Oryx_morph_menu',
- items: []
- });
-
- this.morphMenu.on("mouseover", function() {
- this.morphMenuHovered = true;
- }, this);
- this.morphMenu.on("mouseout", function() {
- this.morphMenuHovered = false;
- }, this);
-
-
- // Create the button to show the morph menu
- var button = new ORYX.Plugins.ShapeMenuButton({
- hovercallback: (ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER ? this.showMorphMenu.bind(this) : undefined),
- resetcallback: (ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER ? this.hideMorphMenu.bind(this) : undefined),
- callback: (ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER ? undefined : this.toggleMorphMenu.bind(this)),
- icon: ORYX.PATH + 'images/wrench_orange.png',
- align: ORYX.CONFIG.SHAPEMENU_BOTTOM,
- group: 0,
- msg: ORYX.I18N.ShapeMenuPlugin.morphMsg
- });
-
- this.shapeMenu.setNumberOfButtonsPerLevel(ORYX.CONFIG.SHAPEMENU_BOTTOM, 1)
- this.shapeMenu.addButton(button);
- this.morphMenu.getEl().appendTo(button.node);
- this.morphButton = button;
- },
-
- showMorphMenu: function() {
- this.morphMenu.show(this.morphButton.node);
- this._morphMenuShown = true;
- },
-
- hideMorphMenu: function() {
- this.morphMenu.hide();
- this._morphMenuShown = false;
- },
-
- toggleMorphMenu: function() {
- if(this._morphMenuShown)
- this.hideMorphMenu();
- else
- this.showMorphMenu();
- },
-
- onSelectionChanged: function(event) {
- var elements = event.elements;
- this.hideShapeMenu();
- this.hideMorphMenu();
-
- if( this.currentShapes.inspect() !== elements.inspect() ){
- this.currentShapes = elements;
- this.resetElements = true;
-
- this.showShapeMenu();
- } else {
- this.showShapeMenu(true)
- }
-
- },
-
- /**
- * Show button for morphing the selected shape into another stencil
- */
- showMorphButton: function(elements) {
-
- if(elements.length != 1) return;
-
- var possibleMorphs = this.facade.getRules().morphStencils({ stencil: elements[0].getStencil() });
- possibleMorphs = possibleMorphs.select(function(morph) {
- if(elements[0].getStencil().type() === "node") {
- //check containment rules
- return this.facade.getRules().canContain({containingShape:elements[0].parent, containedStencil:morph});
- } else {
- //check connect rules
- return this.facade.getRules().canConnect({
- sourceShape: elements[0].dockers.first().getDockedShape(),
- edgeStencil: morph,
- targetShape: elements[0].dockers.last().getDockedShape()
- });
- }
- }.bind(this));
- if(possibleMorphs.size()<=1) return; // if morphing to other stencils is not possible, don't show button
-
- this.morphMenu.removeAll();
-
- // populate morph menu with the possible morph stencils ordered by their position
- possibleMorphs = possibleMorphs.sortBy(function(stencil) { return stencil.position(); });
- possibleMorphs.each((function(morph) {
- var menuItem = new Ext.menu.Item({
- text: morph.title(),
- icon: morph.icon(),
- disabled: morph.id()==elements[0].getStencil().id(),
- disabledClass: ORYX.CONFIG.MORPHITEM_DISABLED,
- handler: (function() { this.morphShape(elements[0], morph); }).bind(this)
- });
- this.morphMenu.add(menuItem);
- }).bind(this));
-
- this.morphButton.prepareToShow();
-
- },
- /**
- * Show buttons for creating following shapes
- */
- showStencilButtons: function(elements) {
- if(elements.length != 1) return;
- //TODO temporaere nutzung des stencilsets
- var sset = this.facade.getStencilSets()[elements[0].getStencil().namespace()];
- // Get all available edges
- var edges = this.facade.getRules().outgoingEdgeStencils({canvas:this.facade.getCanvas(), sourceShape:elements[0]});
-
- // And find all targets for each Edge
- var targets = new Array();
- var addedEdges = new Array();
-
- var isMorphing = this.facade.getRules().containsMorphingRules();
-
- edges.each((function(edge) {
-
- if (isMorphing){
- if(this.baseMorphStencils.include(edge)) {
- var shallAppear = true;
- } else {
-
- // if edge is member of a morph groups where none of the base morphs is in the outgoing edges
- // we want to display the button (but only for the first one)
-
- var possibleMorphs = this.facade.getRules().morphStencils({ stencil: edge });
-
- var shallAppear = !possibleMorphs.any((function(morphStencil) {
- if(this.baseMorphStencils.include(morphStencil) && edges.include(morphStencil)) return true;
- return addedEdges.include(morphStencil);
- }).bind(this));
-
- }
- }
- if(shallAppear || !isMorphing) {
- if(this.createdButtons[edge.namespace() + edge.type() + edge.id()])
- this.createdButtons[edge.namespace() + edge.type() + edge.id()].prepareToShow();
- addedEdges.push(edge);
- }
-
- // get all targets for this edge
- targets = targets.concat(this.facade.getRules().targetStencils(
- {canvas:this.facade.getCanvas(), sourceShape:elements[0], edgeStencil:edge}));
- }).bind(this));
-
- targets.uniq();
-
- var addedTargets = new Array();
- // Iterate all possible target
- targets.each((function(target) {
-
- if (isMorphing){
-
- // continue with next target stencil
- if (target.type()==="edge") return;
-
- // continue when stencil should not shown in the shape menu
- if (!this.facade.getRules().showInShapeMenu(target)) return
-
- // if target is not a base morph
- if(!this.baseMorphStencils.include(target)) {
-
- // if target is member of a morph groups where none of the base morphs is in the targets
- // we want to display the button (but only for the first one)
-
- var possibleMorphs = this.facade.getRules().morphStencils({ stencil: target });
- if(possibleMorphs.size()==0) return; // continue with next target
-
- var baseMorphInTargets = possibleMorphs.any((function(morphStencil) {
- if(this.baseMorphStencils.include(morphStencil) && targets.include(morphStencil)) return true;
- return addedTargets.include(morphStencil);
- }).bind(this));
-
- if(baseMorphInTargets) return; // continue with next target
- }
- }
-
- // if this is reached the button shall appear in the shape menu:
- if(this.createdButtons[target.namespace() + target.type() + target.id()])
- this.createdButtons[target.namespace() + target.type() + target.id()].prepareToShow();
- addedTargets.push(target);
-
- }).bind(this));
-
- },
-
- beforeDragOver: function(dragZone, target, event){
- if (this.shapeMenu.isVisible){
- this.hideShapeMenu();
- }
- var coord = this.facade.eventCoordinates(event.browserEvent);
- var aShapes = this.facade.getCanvas().getAbstractShapesAtPosition(coord);
- if(aShapes.length <= 0) {return false;}
-
- var el = aShapes.last();
-
- if(this._lastOverElement == el) {
-
- return false;
-
- } else {
- // check containment rules
- var option = Ext.dd.Registry.getHandle(target.DDM.currentTarget);
-
- // revert to original options if these were modified
- if(option.backupOptions) {
- for(key in option.backupOptions) {
- option[key] = option.backupOptions[key];
- }
- delete option.backupOptions;
- }
- var stencilSet = this.facade.getStencilSets()[option.namespace];
- var stencil = stencilSet.stencil(option.type);
- var candidate = aShapes.last();
- if(stencil.type() === "node") {
- //check containment rules
- var canContain = this.facade.getRules().canContain({containingShape:candidate, containedStencil:stencil});
-
- // if not canContain, try to find a morph which can be contained
- if(!canContain) {
- var possibleMorphs = this.facade.getRules().morphStencils({stencil: stencil});
- for(var i=0; i<possibleMorphs.size(); i++) {
- canContain = this.facade.getRules().canContain({
- containingShape:candidate,
- containedStencil:possibleMorphs[i]
- });
- if(canContain) {
- option.backupOptions = Object.clone(option);
- option.type = possibleMorphs[i].id();
- option.namespace = possibleMorphs[i].namespace();
- break;
- }
- }
- }
-
- this._currentReference = canContain ? candidate : undefined;
-
-
- } else { //Edge
-
- var curCan = candidate, orgCan = candidate;
- var canConnect = false;
- while(!canConnect && curCan && !(curCan instanceof ORYX.Core.Canvas)){
- candidate = curCan;
- //check connection rules
- canConnect = this.facade.getRules().canConnect({
- sourceShape: this.currentShapes.first(),
- edgeStencil: stencil,
- targetShape: curCan
- });
- curCan = curCan.parent;
- }
- // if not canConnect, try to find a morph which can be connected
- if(!canConnect) {
-
- candidate = orgCan;
- var possibleMorphs = this.facade.getRules().morphStencils({stencil: stencil});
- for(var i=0; i<possibleMorphs.size(); i++) {
- var curCan = candidate;
- var canConnect = false;
- while(!canConnect && curCan && !(curCan instanceof ORYX.Core.Canvas)){
- candidate = curCan;
- //check connection rules
- canConnect = this.facade.getRules().canConnect({
- sourceShape: this.currentShapes.first(),
- edgeStencil: possibleMorphs[i],
- targetShape: curCan
- });
- curCan = curCan.parent;
- }
- if(canConnect) {
- option.backupOptions = Object.clone(option);
- option.type = possibleMorphs[i].id();
- option.namespace = possibleMorphs[i].namespace();
- break;
- } else {
- candidate = orgCan;
- }
- }
- }
-
- this._currentReference = canConnect ? candidate : undefined;
-
- }
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'shapeMenu',
- elements: [candidate],
- color: this._currentReference ? ORYX.CONFIG.SELECTION_VALID_COLOR : ORYX.CONFIG.SELECTION_INVALID_COLOR
- });
-
- var pr = dragZone.getProxy();
- pr.setStatus(this._currentReference ? pr.dropAllowed : pr.dropNotAllowed );
- pr.sync();
-
- }
-
- this._lastOverElement = el;
-
- return false;
- },
- afterDragging: function(dragZone, target, event) {
-
- if (!(this.currentShapes instanceof Array)||this.currentShapes.length<=0) {
- return;
- }
- var sourceShape = this.currentShapes;
-
- this._lastOverElement = undefined;
-
- // Hide the highlighting
- this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'shapeMenu'});
-
- // Check if drop is allowed
- var proxy = dragZone.getProxy()
- if(proxy.dropStatus == proxy.dropNotAllowed) { return this.facade.updateSelection();}
-
- // Check if there is a current Parent
- if(!this._currentReference) { return }
-
- var option = Ext.dd.Registry.getHandle(target.DDM.currentTarget);
- option['parent'] = this._currentReference;
- var xy = event.getXY();
- var pos = {x: xy[0], y: xy[1]};
- var a = this.facade.getCanvas().node.getScreenCTM();
- // Correcting the UpperLeft-Offset
- pos.x -= a.e; pos.y -= a.f;
- // Correcting the Zoom-Faktor
- pos.x /= a.a; pos.y /= a.d;
- // Correcting the ScrollOffset
- pos.x -= document.documentElement.scrollLeft;
- pos.y -= document.documentElement.scrollTop;
- var parentAbs = this._currentReference.absoluteXY();
- pos.x -= parentAbs.x;
- pos.y -= parentAbs.y;
-
- // If the ctrl key is not pressed,
- // snapp the new shape to the center
- // if it is near to the center of the other shape
- if (!event.ctrlKey){
- // Get the center of the shape
- var cShape = this.currentShapes[0].bounds.center();
- // Snapp +-20 Pixel horizontal to the center
- if (20 > Math.abs(cShape.x - pos.x)){
- pos.x = cShape.x;
- }
- // Snapp +-20 Pixel vertical to the center
- if (20 > Math.abs(cShape.y - pos.y)){
- pos.y = cShape.y;
- }
- }
-
- option['position'] = pos;
- option['connectedShape'] = this.currentShapes[0];
- if(option['connectingType']) {
- var stencilset = this.facade.getStencilSets()[option.namespace];
- var containedStencil = stencilset.stencil(option.type);
- var args = { sourceShape: this.currentShapes[0], targetStencil: containedStencil };
- option['connectingType'] = this.facade.getRules().connectMorph(args).id();
- }
-
- if (ORYX.CONFIG.SHAPEMENU_DISABLE_CONNECTED_EDGE===true) {
- delete option['connectingType'];
- }
-
- var command = new ORYX.Plugins.ShapeMenuPlugin.CreateCommand(Object.clone(option), this._currentReference, pos, this);
-
- this.facade.executeCommands([command]);
-
- // Inform about completed Drag
- this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE, source:sourceShape, destination:this.currentShapes});
-
- // revert to original options if these were modified
- if(option.backupOptions) {
- for(key in option.backupOptions) {
- option[key] = option.backupOptions[key];
- }
- delete option.backupOptions;
- }
-
- this._currentReference = undefined;
- },
- newShape: function(option, event) {
- var stencilset = this.facade.getStencilSets()[option.namespace];
- var containedStencil = stencilset.stencil(option.type);
- if(this.facade.getRules().canContain({
- containingShape:this.currentShapes.first().parent,
- "containedStencil":containedStencil
- })) {
- option['connectedShape'] = this.currentShapes[0];
- option['parent'] = this.currentShapes.first().parent;
- option['containedStencil'] = containedStencil;
-
- var args = { sourceShape: this.currentShapes[0], targetStencil: containedStencil };
- var targetStencil = this.facade.getRules().connectMorph(args);
- if (!targetStencil){ return }// Check if there can be a target shape
- option['connectingType'] = targetStencil.id();
- if (ORYX.CONFIG.SHAPEMENU_DISABLE_CONNECTED_EDGE===true) {
- delete option['connectingType'];
- }
-
- var command = new ORYX.Plugins.ShapeMenuPlugin.CreateCommand(option, undefined, undefined, this);
-
- this.facade.executeCommands([command]);
- }
- },
-
- /**
- * Morph a shape to a new stencil
- * {Command implemented}
- * @param {Shape} shape
- * @param {Stencil} stencil
- */
- morphShape: function(shape, stencil) {
-
- var MorphTo = ORYX.Core.Command.extend({
- construct: function(shape, stencil, facade){
- this.shape = shape;
- this.stencil = stencil;
- this.facade = facade;
- },
- execute: function(){
-
- var shape = this.shape;
- var stencil = this.stencil;
- var resourceId = shape.resourceId;
-
- // Serialize all attributes
- var serialized = shape.serialize();
- stencil.properties().each((function(prop) {
- if(prop.readonly()) {
- serialized = serialized.reject(function(serProp) {
- return serProp.name==prop.id();
- });
- }
- }).bind(this));
-
- // Get shape if already created, otherwise create a new shape
- if (this.newShape){
- newShape = this.newShape;
- this.facade.getCanvas().add(newShape);
- } else {
- newShape = this.facade.createShape({
- type: stencil.id(),
- namespace: stencil.namespace(),
- resourceId: resourceId
- });
- }
-
- // calculate new bounds using old shape's upperLeft and new shape's width/height
- var boundsObj = serialized.find(function(serProp){
- return (serProp.prefix === "oryx" && serProp.name === "bounds");
- });
-
- var changedBounds = null;
-
- if(!this.facade.getRules().preserveBounds(shape.getStencil())) {
-
- var bounds = boundsObj.value.split(",");
- if (parseInt(bounds[0], 10) > parseInt(bounds[2], 10)) { // if lowerRight comes first, swap array items
- var tmp = bounds[0];
- bounds[0] = bounds[2];
- bounds[2] = tmp;
- tmp = bounds[1];
- bounds[1] = bounds[3];
- bounds[3] = tmp;
- }
- bounds[2] = parseInt(bounds[0], 10) + newShape.bounds.width();
- bounds[3] = parseInt(bounds[1], 10) + newShape.bounds.height();
- boundsObj.value = bounds.join(",");
-
- } else {
-
- var height = shape.bounds.height();
- var width = shape.bounds.width();
-
- // consider the minimum and maximum size of
- // the new shape
-
- if (newShape.minimumSize) {
- if (shape.bounds.height() < newShape.minimumSize.height) {
- height = newShape.minimumSize.height;
- }
-
-
- if (shape.bounds.width() < newShape.minimumSize.width) {
- width = newShape.minimumSize.width;
- }
- }
-
- if(newShape.maximumSize) {
- if(shape.bounds.height() > newShape.maximumSize.height) {
- height = newShape.maximumSize.height;
- }
-
- if(shape.bounds.width() > newShape.maximumSize.width) {
- width = newShape.maximumSize.width;
- }
- }
-
- changedBounds = {
- a : {
- x: shape.bounds.a.x,
- y: shape.bounds.a.y
- },
- b : {
- x: shape.bounds.a.x + width,
- y: shape.bounds.a.y + height
- }
- };
-
- }
-
- var oPos = shape.bounds.center();
- if(changedBounds !== null) {
- newShape.bounds.set(changedBounds);
- }
-
- // Set all related dockers
- this.setRelatedDockers(shape, newShape);
-
- // store DOM position of old shape
- var parentNode = shape.node.parentNode;
- var nextSibling = shape.node.nextSibling;
-
- // Delete the old shape
- this.facade.deleteShape(shape);
-
- // Deserialize the new shape - Set all attributes
- newShape.deserialize(serialized);
- /*
- * Change color to default if unchanged
- * 23.04.2010
- */
- if(shape.getStencil().property("oryx-bgcolor")
- && shape.properties["oryx-bgcolor"]
- && shape.getStencil().property("oryx-bgcolor").value().toUpperCase()== shape.properties["oryx-bgcolor"].toUpperCase()){
- if(newShape.getStencil().property("oryx-bgcolor")){
- newShape.setProperty("oryx-bgcolor", newShape.getStencil().property("oryx-bgcolor").value());
- }
- }
- if(changedBounds !== null) {
- newShape.bounds.set(changedBounds);
- }
-
- if(newShape.getStencil().type()==="edge" || (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
- newShape.bounds.centerMoveTo(oPos);
- }
-
- if(newShape.getStencil().type()==="node" && (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
- this.setRelatedDockers(newShape, newShape);
-
- }
-
- // place at the DOM position of the old shape
- if(nextSibling) parentNode.insertBefore(newShape.node, nextSibling);
- else parentNode.appendChild(newShape.node);
-
- // Set selection
- this.facade.setSelection([newShape]);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- this.newShape = newShape;
-
- },
- rollback: function(){
-
- if (!this.shape || !this.newShape || !this.newShape.parent) {return}
-
- // Append shape to the parent
- this.newShape.parent.add(this.shape);
- // Set dockers
- this.setRelatedDockers(this.newShape, this.shape);
- // Delete new shape
- this.facade.deleteShape(this.newShape);
- // Set selection
- this.facade.setSelection([this.shape]);
- // Update
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- },
-
- /**
- * Set all incoming and outgoing edges from the shape to the new shape
- * @param {Shape} shape
- * @param {Shape} newShape
- */
- setRelatedDockers: function(shape, newShape){
-
- if(shape.getStencil().type()==="node") {
-
- (shape.incoming||[]).concat(shape.outgoing||[])
- .each(function(i) {
- i.dockers.each(function(docker) {
- if (docker.getDockedShape() == shape) {
- var rPoint = Object.clone(docker.referencePoint);
- // Move reference point per percent
- var rPointNew = {
- x: rPoint.x*newShape.bounds.width()/shape.bounds.width(),
- y: rPoint.y*newShape.bounds.height()/shape.bounds.height()
- };
- docker.setDockedShape(newShape);
- // Set reference point and center to new position
- docker.setReferencePoint(rPointNew);
- if(i instanceof ORYX.Core.Edge) {
- docker.bounds.centerMoveTo(rPointNew);
- } else {
- var absXY = shape.absoluteXY();
- docker.bounds.centerMoveTo({x:rPointNew.x+absXY.x, y:rPointNew.y+absXY.y});
- //docker.bounds.moveBy({x:rPointNew.x-rPoint.x, y:rPointNew.y-rPoint.y});
- }
- }
- });
- });
-
- // for attached events
- if(shape.dockers.length>0&&shape.dockers.first().getDockedShape()) {
- newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
- newShape.dockers.first().setReferencePoint(Object.clone(shape.dockers.first().referencePoint));
- }
-
- } else { // is edge
- newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
- newShape.dockers.first().setReferencePoint(shape.dockers.first().referencePoint);
- newShape.dockers.last().setDockedShape(shape.dockers.last().getDockedShape());
- newShape.dockers.last().setReferencePoint(shape.dockers.last().referencePoint);
- }
- }
- });
-
- // Create and execute command (for undo/redo)
- var command = new MorphTo(shape, stencil, this.facade);
- this.facade.executeCommands([command]);
- }
- }
- ORYX.Plugins.ShapeMenuPlugin = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.ShapeMenuPlugin);
- ORYX.Plugins.ShapeMenu = {
- /***
- * Constructor.
- */
- construct: function(parentNode) {
- this.bounds = undefined;
- this.shapes = undefined;
- this.buttons = [];
- this.isVisible = false;
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $(parentNode),
- ['div', {id: ORYX.Editor.provideId(), 'class':'Oryx_ShapeMenu'}]);
-
- this.alignContainers = new Hash();
- this.numberOfButtonsPerLevel = new Hash();
- },
- addButton: function(button) {
- this.buttons.push(button);
- // lazy grafting of the align containers
- if(!this.alignContainers[button.align]) {
- this.alignContainers[button.align] = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.node,
- ['div', {'class':button.align}]);
- this.node.appendChild(this.alignContainers[button.align]);
-
- // add event listeners for hover effect
- var onBubble = false;
- this.alignContainers[button.align].addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this.hoverAlignContainer.bind(this, button.align), onBubble);
- this.alignContainers[button.align].addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this.resetAlignContainer.bind(this, button.align), onBubble);
- this.alignContainers[button.align].addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.hoverAlignContainer.bind(this, button.align), onBubble);
- }
- this.alignContainers[button.align].appendChild(button.node);
- },
- deleteButton: function(button) {
- this.buttons = this.buttons.without(button);
- this.node.removeChild(button.node);
- },
- removeAllButtons: function() {
- var me = this;
- this.buttons.each(function(value){
- if (value.node&&value.node.parentNode)
- value.node.parentNode.removeChild(value.node);
- });
- this.buttons = [];
- },
- closeAllButtons: function() {
- this.buttons.each(function(value){ value.prepareToHide() });
- this.isVisible = false;
- },
-
- /**
- * Show the shape menu
- */
- show: function(shapes) {
- //shapes = (shapes||[]).findAll(function(r){ return r && r.node && r.node.parent });
- if(shapes.length <= 0 )
- return
- this.shapes = shapes;
- var newBounds = undefined;
- var tmpBounds = undefined;
- this.shapes.each(function(value) {
- var a = value.node.getScreenCTM();
- var upL = value.absoluteXY();
- a.e = a.a*upL.x;
- a.f = a.d*upL.y;
- tmpBounds = new ORYX.Core.Bounds(a.e, a.f, a.e+a.a*value.bounds.width(), a.f+a.d*value.bounds.height());
- /*if(value instanceof ORYX.Core.Edge) {
- tmpBounds.moveBy(value.bounds.upperLeft())
- }*/
- if(!newBounds)
- newBounds = tmpBounds
- else
- newBounds.include(tmpBounds);
- });
- this.bounds = newBounds;
- //this.bounds.moveBy({x:document.documentElement.scrollLeft, y:document.documentElement.scrollTop});
- var bounds = this.bounds;
- var a = this.bounds.upperLeft();
- var left = 0,
- leftButtonGroup = 0;
- var top = 0,
- topButtonGroup = 0;
- var bottom = 0,
- bottomButtonGroup;
- var right = 0
- rightButtonGroup = 0;
- var size = 22;
-
- this.getWillShowButtons().sortBy(function(button) {
- return button.group;
- });
-
- this.getWillShowButtons().each(function(button){
-
- var numOfButtonsPerLevel = this.getNumberOfButtonsPerLevel(button.align);
- if (button.align == ORYX.CONFIG.SHAPEMENU_LEFT) {
- // vertical levels
- if(button.group!=leftButtonGroup) {
- left = 0;
- leftButtonGroup = button.group;
- }
- var x = Math.floor(left / numOfButtonsPerLevel)
- var y = left % numOfButtonsPerLevel;
-
- button.setLevel(x);
-
- button.setPosition(a.x-5 - (x+1)*size,
- a.y+numOfButtonsPerLevel*button.group*size + button.group*0.3*size + y*size);
-
- //button.setPosition(a.x-22, a.y+left*size);
- left++;
- } else if (button.align == ORYX.CONFIG.SHAPEMENU_TOP) {
- // horizontal levels
- if(button.group!=topButtonGroup) {
- top = 0;
- topButtonGroup = button.group;
- }
- var x = top % numOfButtonsPerLevel;
- var y = Math.floor(top / numOfButtonsPerLevel);
-
- button.setLevel(y);
-
- button.setPosition(a.x+numOfButtonsPerLevel*button.group*size + button.group*0.3*size + x*size,
- a.y-5 - (y+1)*size);
- top++;
- } else if (button.align == ORYX.CONFIG.SHAPEMENU_BOTTOM) {
- // horizontal levels
- if(button.group!=bottomButtonGroup) {
- bottom = 0;
- bottomButtonGroup = button.group;
- }
- var x = bottom % numOfButtonsPerLevel;
- var y = Math.floor(bottom / numOfButtonsPerLevel);
-
- button.setLevel(y);
-
- button.setPosition(a.x+numOfButtonsPerLevel*button.group*size + button.group*0.3*size + x*size,
- a.y+bounds.height() + 5 + y*size);
- bottom++;
- } else {
- // vertical levels
- if(button.group!=rightButtonGroup) {
- right = 0;
- rightButtonGroup = button.group;
- }
- var x = Math.floor(right / numOfButtonsPerLevel)
- var y = right % numOfButtonsPerLevel;
-
- button.setLevel(x);
-
- button.setPosition(a.x+bounds.width() + 5 + x*size,
- a.y+numOfButtonsPerLevel*button.group*size + button.group*0.3*size + y*size - 5);
- right++;
- }
- button.show();
- }.bind(this));
- this.isVisible = true;
- },
- /**
- * Hide the shape menu
- */
- hide: function() {
- this.buttons.each(function(button){
- button.hide();
- });
- this.isVisible = false;
- //this.bounds = undefined;
- //this.shape = undefined;
- },
- hoverAlignContainer: function(align, evt) {
- this.buttons.each(function(button){
- if(button.align == align) button.showOpaque();
- });
- },
-
- resetAlignContainer: function(align, evt) {
- this.buttons.each(function(button){
- if(button.align == align) button.showTransparent();
- });
- },
-
- isHover: function() {
- return this.buttons.any(function(value){
- return value.isHover();
- });
- },
-
- getWillShowButtons: function() {
- return this.buttons.findAll(function(value){return value.willShow});
- },
-
- /**
- * Returns a set on buttons for that align value
- * @params {String} align
- * @params {String} group
- */
- getButtons: function(align, group){
- return this.getWillShowButtons().findAll(function(b){ return b.align == align && (group === undefined || b.group == group)})
- },
-
- /**
- * Set the number of buttons to display on each level of the shape menu in the specified align group.
- * Example: setNumberOfButtonsPerLevel(ORYX.CONFIG.SHAPEMENU_RIGHT, 2) causes that the buttons of the right align group
- * will be rendered in 2 rows.
- */
- setNumberOfButtonsPerLevel: function(align, number) {
- this.numberOfButtonsPerLevel[align] = number;
- },
-
- /**
- * Returns the number of buttons to display on each level of the shape menu in the specified align group.
- * Default value is 1
- */
- getNumberOfButtonsPerLevel: function(align) {
- if(this.numberOfButtonsPerLevel[align])
- return Math.min(this.getButtons(align,0).length, this.numberOfButtonsPerLevel[align]);
- else
- return 1;
- }
- }
- ORYX.Plugins.ShapeMenu = Clazz.extend(ORYX.Plugins.ShapeMenu);
- ORYX.Plugins.ShapeMenuButton = {
-
- /**
- * Constructor
- * @param option A key map specifying the configuration options:
- * id: (String) The id of the parent DOM element for the new button
- * icon: (String) The url to the icon of the button
- * msg: (String) A tooltip message
- * caption:(String) The caption of the button (attention: button width > 22, only set for single column button layouts)
- * align: (String) The direction in which the button is aligned
- * group: (Integer) The button group in the specified alignment
- * (buttons in the same group will be aligned side by side)
- * callback: (Function) A callback that is executed when the button is clicked
- * dragcallback: (Function) A callback that is executed when the button is dragged
- * hovercallback: (Function) A callback that is executed when the button is hovered
- * resetcallback: (Function) A callback that is executed when the button is reset
- * arguments: (Array) An argument array to pass to the callback functions
- */
- construct: function(option) {
- if(option) {
- this.option = option;
- if(!this.option.arguments)
- this.option.arguments = [];
- } else {
- //TODO error
- }
- this.parentId = this.option.id ? this.option.id : null;
- // graft the button.
- var buttonClassName = this.option.caption ? "Oryx_button_with_caption" : "Oryx_button";
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $(this.parentId),
- ['div', {'class':buttonClassName}]);
- var imgOptions = {src:this.option.icon};
- if(this.option.msg){
- imgOptions.title = this.option.msg;
- }
-
- // graft and update icon (not in grafting for ns reasons).
- //TODO Enrich graft()-function to do this in one of the above steps.
- if(this.option.icon)
- ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.node,
- ['img', imgOptions]);
-
- if(this.option.caption) {
- var captionNode = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.node, ['span']);
- ORYX.Editor.graft("http://www.w3.org/1999/xhtml", captionNode, this.option.caption);
- }
- var onBubble = false;
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this.hover.bind(this), onBubble);
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this.reset.bind(this), onBubble);
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.activate.bind(this), onBubble);
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.hover.bind(this), onBubble);
- this.node.addEventListener('click', this.trigger.bind(this), onBubble);
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.move.bind(this), onBubble);
- this.align = this.option.align ? this.option.align : ORYX.CONFIG.SHAPEMENU_RIGHT;
- this.group = this.option.group ? this.option.group : 0;
- this.hide();
- this.dragStart = false;
- this.isVisible = false;
- this.willShow = false;
- this.resetTimer;
- },
-
- hide: function() {
- this.node.style.display = "none";
- this.isVisible = false;
- },
- show: function() {
- this.node.style.display = "";
- this.node.style.opacity = this.opacity;
- this.isVisible = true;
- },
-
- showOpaque: function() {
- this.node.style.opacity = 1.0;
- },
-
- showTransparent: function() {
- this.node.style.opacity = this.opacity;
- },
-
- prepareToShow: function() {
- this.willShow = true;
- },
- prepareToHide: function() {
- this.willShow = false;
- this.hide();
- },
- setPosition: function(x, y) {
- this.node.style.left = x + "px";
- this.node.style.top = y + "px";
- },
-
- setLevel: function(level) {
- if(level==0) this.opacity = 0.5;
- else if(level==1) this.opacity = 0.2;
- //else if(level==2) this.opacity = 0.1;
- else this.opacity = 0.0;
- },
-
- setChildWidth: function(width) {
- this.childNode.style.width = width + "px";
- },
- reset: function(evt) {
- // Delete the timeout for hiding
- window.clearTimeout( this.resetTimer )
- this.resetTimer = window.setTimeout( this.doReset.bind(this), 100)
-
- if(this.option.resetcallback) {
- this.option.arguments.push(evt);
- var state = this.option.resetcallback.apply(this, this.option.arguments);
- this.option.arguments.remove(evt);
- }
- },
-
- doReset: function() {
-
- if(this.node.hasClassName('Oryx_down'))
- this.node.removeClassName('Oryx_down');
- if(this.node.hasClassName('Oryx_hover'))
- this.node.removeClassName('Oryx_hover');
- },
- activate: function(evt) {
- this.node.addClassName('Oryx_down');
- //Event.stop(evt);
- this.dragStart = true;
- },
- isHover: function() {
- return this.node.hasClassName('Oryx_hover') ? true: false;
- },
- hover: function(evt) {
- // Delete the timeout for hiding
- window.clearTimeout( this.resetTimer )
- this.resetTimer = null;
-
- this.node.addClassName('Oryx_hover');
- this.dragStart = false;
-
- if(this.option.hovercallback) {
- this.option.arguments.push(evt);
- var state = this.option.hovercallback.apply(this, this.option.arguments);
- this.option.arguments.remove(evt);
- }
- },
- move: function(evt) {
- if(this.dragStart && this.option.dragcallback) {
- this.option.arguments.push(evt);
- var state = this.option.dragcallback.apply(this, this.option.arguments);
- this.option.arguments.remove(evt);
- }
- },
- trigger: function(evt) {
- if(this.option.callback) {
- //Event.stop(evt);
- this.option.arguments.push(evt);
- var state = this.option.callback.apply(this, this.option.arguments);
- this.option.arguments.remove(evt);
- }
- this.dragStart = false;
- },
- toString: function() {
- return "HTML-Button " + this.id;
- }
- }
- ORYX.Plugins.ShapeMenuButton = Clazz.extend(ORYX.Plugins.ShapeMenuButton);
- //create command for undo/redo
- ORYX.Plugins.ShapeMenuPlugin.CreateCommand = ORYX.Core.Command.extend({
- construct: function(option, currentReference, position, plugin){
- this.option = option;
- this.currentReference = currentReference;
- this.position = position;
- this.plugin = plugin;
- this.shape;
- this.edge;
- this.targetRefPos;
- this.sourceRefPos;
- /*
- * clone options parameters
- */
- this.connectedShape = option.connectedShape;
- this.connectingType = option.connectingType;
- this.namespace = option.namespace;
- this.type = option.type;
- this.containedStencil = option.containedStencil;
- this.parent = option.parent;
- this.currentReference = currentReference;
- this.shapeOptions = option.shapeOptions;
- },
- execute: function(){
-
- var resume = false;
-
- if (this.shape) {
- if (this.shape instanceof ORYX.Core.Node) {
- this.parent.add(this.shape);
- if (this.edge) {
- this.plugin.facade.getCanvas().add(this.edge);
- this.edge.dockers.first().setDockedShape(this.connectedShape);
- this.edge.dockers.first().setReferencePoint(this.sourceRefPos);
- this.edge.dockers.last().setDockedShape(this.shape);
- this.edge.dockers.last().setReferencePoint(this.targetRefPos);
- }
-
- this.plugin.facade.setSelection([this.shape]);
-
- } else if (this.shape instanceof ORYX.Core.Edge) {
- this.plugin.facade.getCanvas().add(this.shape);
- this.shape.dockers.first().setDockedShape(this.connectedShape);
- this.shape.dockers.first().setReferencePoint(this.sourceRefPos);
- }
- resume = true;
- }
- else {
- this.shape = this.plugin.facade.createShape(this.option);
- this.edge = (!(this.shape instanceof ORYX.Core.Edge)) ? this.shape.getIncomingShapes().first() : undefined;
- }
-
- if (this.currentReference && this.position) {
-
- if (this.shape instanceof ORYX.Core.Edge) {
-
- if (!(this.currentReference instanceof ORYX.Core.Canvas)) {
- this.shape.dockers.last().setDockedShape(this.currentReference);
-
- // @deprecated It now uses simply the midpoint
- var upL = this.currentReference.absoluteXY();
- var refPos = {
- x: this.position.x - upL.x,
- y: this.position.y - upL.y
- };
-
- this.shape.dockers.last().setReferencePoint(this.currentReference.bounds.midPoint());
- }
- else {
- this.shape.dockers.last().bounds.centerMoveTo(this.position);
- //this.shape.dockers.last().update();
- }
- this.sourceRefPos = this.shape.dockers.first().referencePoint;
- this.targetRefPos = this.shape.dockers.last().referencePoint;
-
- } else if (this.edge){
- this.sourceRefPos = this.edge.dockers.first().referencePoint;
- this.targetRefPos = this.edge.dockers.last().referencePoint;
- }
- } else {
- var containedStencil = this.containedStencil;
- var connectedShape = this.connectedShape;
- var bc = connectedShape.bounds;
- var bs = this.shape.bounds;
-
- var pos = bc.center();
- if(containedStencil.defaultAlign()==="north") {
- pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);
- } else if(containedStencil.defaultAlign()==="northeast") {
- pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);
- pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);
- } else if(containedStencil.defaultAlign()==="southeast") {
- pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);
- pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);
- } else if(containedStencil.defaultAlign()==="south") {
- pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.height()/2);
- } else if(containedStencil.defaultAlign()==="southwest") {
- pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);
- pos.y += (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);
- } else if(containedStencil.defaultAlign()==="west") {
- pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);
- } else if(containedStencil.defaultAlign()==="northwest") {
- pos.x -= (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.width()/2);
- pos.y -= (bc.height() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER + (bs.height()/2);
- } else {
- pos.x += (bc.width() / 2) + ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET + (bs.width()/2);
- }
-
- // Move shape to the new position
- this.shape.bounds.centerMoveTo(pos);
-
- // Move all dockers of a node to the position
- if (this.shape instanceof ORYX.Core.Node){
- (this.shape.dockers||[]).each(function(docker){
- docker.bounds.centerMoveTo(pos);
- })
- }
-
- //this.shape.update();
- this.position = pos;
-
- if (this.edge){
- this.sourceRefPos = this.edge.dockers.first().referencePoint;
- this.targetRefPos = this.edge.dockers.last().referencePoint;
- }
- }
-
- this.plugin.facade.getCanvas().update();
- this.plugin.facade.updateSelection();
-
- if (!resume) {
- // If there is a connected shape
- if (this.edge){
- // Try to layout it
- this.plugin.doLayout(this.edge);
- } else if (this.shape instanceof ORYX.Core.Edge){
- // Try to layout it
- this.plugin.doLayout(this.shape);
- }
- }
- },
- rollback: function(){
- this.plugin.facade.deleteShape(this.shape);
- if(this.edge) {
- this.plugin.facade.deleteShape(this.edge);
- }
- //this.currentParent.update();
- this.plugin.facade.setSelection(this.plugin.facade.getSelection().without(this.shape, this.edge));
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- ORYX.Plugins.ShapeRepository = {
- facade: undefined,
- construct: function(facade) {
- this.facade = facade;
- this._currentParent;
- this._canContain = undefined;
- this._canAttach = undefined;
- this.shapeList = new Ext.tree.TreeNode({
-
- });
- var panel = new Ext.tree.TreePanel({
- cls:'shaperepository',
- loader: new Ext.tree.TreeLoader(),
- root: this.shapeList,
- autoScroll:true,
- rootVisible: false,
- lines: false,
- anchors: '0, -30'
- });
- var region = this.facade.addToRegion("west", panel, ORYX.I18N.ShapeRepository.title);
-
-
- // Create a Drag-Zone for Drag'n'Drop
- var DragZone = new Ext.dd.DragZone(this.shapeList.getUI().getEl(), {shadow: !Ext.isMac});
- DragZone.afterDragDrop = this.drop.bind(this, DragZone);
- DragZone.beforeDragOver = this.beforeDragOver.bind(this, DragZone);
- DragZone.beforeDragEnter = function(){this._lastOverElement = false; return true}.bind(this);
-
- // Load all Stencilssets
- this.setStencilSets();
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_STENCIL_SET_LOADED, this.setStencilSets.bind(this));
- },
-
-
- /**
- * Load all stencilsets in the shaperepository
- */
- setStencilSets: function() {
- // Remove all childs
- var child = this.shapeList.firstChild;
- while(child) {
- this.shapeList.removeChild(child);
- child = this.shapeList.firstChild;
- }
- ORYX.Log.info("stencilsets " + this.facade.getStencilSets());
-
- // Go thru all Stencilsets and stencils
- this.facade.getStencilSets().values().each((function(sset) {
-
- // For each Stencilset create and add a new Tree-Node
- var stencilSetNode;
-
- var typeTitle = sset.title();
-
- this.shapeList.appendChild(stencilSetNode = new Ext.tree.TreeNode({
- text:typeTitle, // Stencilset Name
- allowDrag:false,
- allowDrop:false,
- iconCls:'headerShapeRepImg',
- cls:'headerShapeRep',
- singleClickExpand:true}));
-
- ORYX.Log.info("stencilSetNode " + stencilSetNode.text);
-
- this.shapeList.appendChild(stencilSetNode);
-
- stencilSetNode.render();
- stencilSetNode.expand();
- // Get Stencils from Stencilset
- var stencils = sset.stencils(this.facade.getCanvas().getStencil(),
- this.facade.getRules());
- var treeGroups = new Hash();
-
- // Sort the stencils according to their position and add them to the repository
- stencils = stencils.sortBy(function(value) { return value.position(); } );
- stencils.each((function(value) {
-
- // Show stencils in no group if there is less than 10 shapes
- //if(stencils.length <= ORYX.CONFIG.MAX_NUM_SHAPES_NO_GROUP) {
- // this.createStencilTreeNode(stencilSetNode, value);
- // return;
- //}
-
- // Get the groups name
- var groups = value.groups();
-
- // For each Group-Entree
- groups.each((function(group) {
-
- // If there is a new group
- if(!treeGroups[group]) {
- // Create a new group
- treeGroups[group] = new Ext.tree.TreeNode({
- text:group, // Group-Name
- allowDrag:false,
- allowDrop:false,
- iconCls:'headerShapeRepImg', // Css-Class for Icon
- cls:'headerShapeRepChild', // CSS-Class for Stencil-Group
- singleClickExpand:true});
-
- // Add the Group to the ShapeRepository
- stencilSetNode.appendChild(treeGroups[group]);
- treeGroups[group].render();
- }
-
- // Create the Stencil-Tree-Node
- this.createStencilTreeNode(treeGroups[group], value);
-
- }).bind(this));
-
-
- // If there is no group
- if(groups.length == 0) {
- // Create the Stencil-Tree-Node
- this.createStencilTreeNode(stencilSetNode, value);
- }
-
- }).bind(this));
- }).bind(this));
- },
- createStencilTreeNode: function(parentTreeNode, stencil) {
- // Create and add the Stencil to the Group
- var newElement = new Ext.tree.TreeNode({
- text: stencil.title(), // Text of the stencil
- icon: stencil.icon(), // Icon of the stencil
- allowDrag: false, // Don't use the Drag and Drop of Ext-Tree
- allowDrop: false,
- iconCls: 'ShapeRepEntreeImg', // CSS-Class for Icon
- cls: 'ShapeRepEntree' // CSS-Class for the Tree-Entree
- });
- parentTreeNode.appendChild(newElement);
- newElement.render();
-
- var ui = newElement.getUI();
-
- // Set the tooltip
- ui.elNode.setAttributeNS(null, "title", stencil.description());
-
- // Register the Stencil on Drag and Drop
- Ext.dd.Registry.register(ui.elNode, {
- node: ui.node,
- handles: [ui.elNode, ui.textNode].concat($A(ui.elNode.childNodes)), // Set the Handles
- isHandle: false,
- type: stencil.id(), // Set Type of stencil
- namespace: stencil.namespace() // Set Namespace of stencil
- });
-
- },
-
- drop: function(dragZone, target, event) {
-
- this._lastOverElement = undefined;
-
- // Hide the highlighting
- this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'shapeRepo.added'});
- this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'shapeRepo.attached'});
-
- // Check if drop is allowed
- var proxy = dragZone.getProxy()
- if(proxy.dropStatus == proxy.dropNotAllowed) { return }
-
- // Check if there is a current Parent
- if(!this._currentParent) { return }
-
- var option = Ext.dd.Registry.getHandle(target.DDM.currentTarget);
-
- var xy = event.getXY();
- var pos = {x: xy[0], y: xy[1]};
- var a = this.facade.getCanvas().node.getScreenCTM();
- // Correcting the UpperLeft-Offset
- pos.x -= a.e; pos.y -= a.f;
- // Correcting the Zoom-Faktor
- pos.x /= a.a; pos.y /= a.d;
- // Correting the ScrollOffset
- pos.x -= document.documentElement.scrollLeft;
- pos.y -= document.documentElement.scrollTop;
- // Correct position of parent
- var parentAbs = this._currentParent.absoluteXY();
- pos.x -= parentAbs.x;
- pos.y -= parentAbs.y;
- // Set position
- option['position'] = pos
-
- // Set parent
- if( this._canAttach && this._currentParent instanceof ORYX.Core.Node ){
- option['parent'] = undefined;
- } else {
- option['parent'] = this._currentParent;
- }
-
-
- var commandClass = ORYX.Core.Command.extend({
- construct: function(option, currentParent, canAttach, position, facade){
- this.option = option;
- this.currentParent = currentParent;
- this.canAttach = canAttach;
- this.position = position;
- this.facade = facade;
- this.selection = this.facade.getSelection();
- this.shape;
- this.parent;
- },
- execute: function(){
- if (!this.shape) {
- this.shape = this.facade.createShape(option);
- this.parent = this.shape.parent;
- } else {
- this.parent.add(this.shape);
- }
-
-
-
- if( this.canAttach && this.currentParent instanceof ORYX.Core.Node && this.shape.dockers.length > 0){
-
- var docker = this.shape.dockers[0];
-
- if( this.currentParent.parent instanceof ORYX.Core.Node ) {
- this.currentParent.parent.add( docker.parent );
- }
-
- docker.bounds.centerMoveTo( this.position );
- docker.setDockedShape( this.currentParent );
- //docker.update();
- }
-
- //this.currentParent.update();
- //this.shape.update();
- this.facade.setSelection([this.shape]);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
- },
- rollback: function(){
- this.facade.deleteShape(this.shape);
-
- //this.currentParent.update();
- this.facade.setSelection(this.selection.without(this.shape));
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
- }
- });
-
- var position = this.facade.eventCoordinates( event.browserEvent );
-
- var command = new commandClass(option, this._currentParent, this._canAttach, position, this.facade);
-
- this.facade.executeCommands([command]);
-
- this._currentParent = undefined;
- },
- beforeDragOver: function(dragZone, target, event){
- var coord = this.facade.eventCoordinates(event.browserEvent);
- var aShapes = this.facade.getCanvas().getAbstractShapesAtPosition( coord );
- if(aShapes.length <= 0) {
-
- var pr = dragZone.getProxy();
- pr.setStatus(pr.dropNotAllowed);
- pr.sync();
-
- return false;
- }
-
- var el = aShapes.last();
-
-
- if(aShapes.lenght == 1 && aShapes[0] instanceof ORYX.Core.Canvas) {
-
- return false;
-
- } else {
- // check containment rules
- var option = Ext.dd.Registry.getHandle(target.DDM.currentTarget);
- var stencilSet = this.facade.getStencilSets()[option.namespace];
- var stencil = stencilSet.stencil(option.type);
- if(stencil.type() === "node") {
-
- var parentCandidate = aShapes.reverse().find(function(candidate) {
- return (candidate instanceof ORYX.Core.Canvas
- || candidate instanceof ORYX.Core.Node
- || candidate instanceof ORYX.Core.Edge);
- });
-
- if( parentCandidate !== this._lastOverElement){
-
- this._canAttach = undefined;
- this._canContain = undefined;
-
- }
-
- if( parentCandidate ) {
- //check containment rule
-
- if (!(parentCandidate instanceof ORYX.Core.Canvas) && parentCandidate.isPointOverOffset(coord.x, coord.y) && this._canAttach == undefined) {
-
- this._canAttach = this.facade.getRules().canConnect({
- sourceShape: parentCandidate,
- edgeStencil: stencil,
- targetStencil: stencil
- });
-
- if( this._canAttach ){
- // Show Highlight
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId: "shapeRepo.attached",
- elements: [parentCandidate],
- style: ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,
- color: ORYX.CONFIG.SELECTION_VALID_COLOR
- });
-
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId: "shapeRepo.added"
- });
-
- this._canContain = undefined;
- }
-
- }
-
- if(!(parentCandidate instanceof ORYX.Core.Canvas) && !parentCandidate.isPointOverOffset(coord.x, coord.y)){
- this._canAttach = this._canAttach == false ? this._canAttach : undefined;
- }
-
- if( this._canContain == undefined && !this._canAttach) {
-
- this._canContain = this.facade.getRules().canContain({
- containingShape:parentCandidate,
- containedStencil:stencil
- });
-
- // Show Highlight
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'shapeRepo.added',
- elements: [parentCandidate],
- color: this._canContain ? ORYX.CONFIG.SELECTION_VALID_COLOR : ORYX.CONFIG.SELECTION_INVALID_COLOR
- });
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId:"shapeRepo.attached"
- });
- }
-
-
-
- this._currentParent = this._canContain || this._canAttach ? parentCandidate : undefined;
- this._lastOverElement = parentCandidate;
- var pr = dragZone.getProxy();
- pr.setStatus(this._currentParent ? pr.dropAllowed : pr.dropNotAllowed );
- pr.sync();
-
- }
- } else { //Edge
- this._currentParent = this.facade.getCanvas();
- var pr = dragZone.getProxy();
- pr.setStatus(pr.dropAllowed);
- pr.sync();
- }
- }
-
-
- return false
- }
- }
- ORYX.Plugins.ShapeRepository = Clazz.extend(ORYX.Plugins.ShapeRepository);
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- ORYX.Plugins.PropertyWindow = {
- facade: undefined,
- construct: function(facade) {
- // Reference to the Editor-Interface
- this.facade = facade;
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW, this.init.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.selectDiagram.bind(this));
- this.init();
- },
-
- init: function(){
- // The parent div-node of the grid
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml",
- null,
- ['div']);
- // If the current property in focus is of type 'Date', the date format
- // is stored here.
- this.currentDateFormat;
- // the properties array
- this.popularProperties = [];
- this.properties = [];
-
- /* The currently selected shapes whos properties will shown */
- this.shapeSelection = new Hash();
- this.shapeSelection.shapes = new Array();
- this.shapeSelection.commonProperties = new Array();
- this.shapeSelection.commonPropertiesValues = new Hash();
-
- this.updaterFlag = false;
- // creating the column model of the grid.
- this.columnModel = new Ext.grid.ColumnModel([
- {
- //id: 'name',
- header: ORYX.I18N.PropertyWindow.name,
- dataIndex: 'name',
- width: 90,
- sortable: true,
- renderer: this.tooltipRenderer.bind(this)
- }, {
- //id: 'value',
- header: ORYX.I18N.PropertyWindow.value,
- dataIndex: 'value',
- id: 'propertywindow_column_value',
- width: 110,
- editor: new Ext.form.TextField({
- allowBlank: false
- }),
- renderer: this.renderer.bind(this)
- },
- {
- header: "Pop",
- dataIndex: 'popular',
- hidden: true,
- sortable: true
- }
- ]);
- // creating the store for the model.
- this.dataSource = new Ext.data.GroupingStore({
- proxy: new Ext.data.MemoryProxy(this.properties),
- reader: new Ext.data.ArrayReader({}, [
- {name: 'popular'},
- {name: 'name'},
- {name: 'value'},
- {name: 'icons'},
- {name: 'gridProperties'}
- ]),
- sortInfo: {field: 'popular', direction: "ASC"},
- sortData : function(f, direction){
- direction = direction || 'ASC';
- var st = this.fields.get(f).sortType;
- var fn = function(r1, r2){
- var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
- var p1 = r1.data['popular'], p2 = r2.data['popular'];
- return p1 && !p2 ? -1 : (!p1 && p2 ? 1 : (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)));
- };
- this.data.sort(direction, fn);
- if(this.snapshot && this.snapshot != this.data){
- this.snapshot.sort(direction, fn);
- }
- },
- groupField: 'popular'
- });
- this.dataSource.load();
-
- this.grid = new Ext.grid.EditorGridPanel({
- clicksToEdit: 1,
- stripeRows: true,
- autoExpandColumn: "propertywindow_column_value",
- width:'auto',
- // the column model
- colModel: this.columnModel,
- enableHdMenu: false,
- view: new Ext.grid.GroupingView({
- forceFit: true,
- groupTextTpl: '{[values.rs.first().data.popular ? ORYX.I18N.PropertyWindow.oftenUsed : ORYX.I18N.PropertyWindow.moreProps]}'
- }),
-
- // the data store
- store: this.dataSource
-
- });
- region = this.facade.addToRegion('east', new Ext.Panel({
- width: 220,
- layout: "fit",
- border: false,
- title: 'Properties',
- items: [
- this.grid
- ]
- }), ORYX.I18N.PropertyWindow.title)
- // Register on Events
- this.grid.on('beforeedit', this.beforeEdit, this, true);
- this.grid.on('afteredit', this.afterEdit, this, true);
- this.grid.view.on('refresh', this.hideMoreAttrs, this, true);
-
- //this.grid.on(ORYX.CONFIG.EVENT_KEYDOWN, this.keyDown, this, true);
-
- // Renderer the Grid
- this.grid.enableColumnMove = false;
- //this.grid.render();
- // Sort as Default the first column
- //this.dataSource.sort('name');
- },
-
- // Select the Canvas when the editor is ready
- selectDiagram: function() {
- this.shapeSelection.shapes = [this.facade.getCanvas()];
-
- this.setPropertyWindowTitle();
- this.identifyCommonProperties();
- this.createProperties();
- },
- specialKeyDown: function(field, event) {
- // If there is a TextArea and the Key is an Enter
- if(field instanceof Ext.form.TextArea && event.button == ORYX.CONFIG.KEY_Code_enter) {
- // Abort the Event
- return false
- }
- },
- tooltipRenderer: function(value, p, record) {
- /* Prepare tooltip */
- p.cellAttr = 'title="' + record.data.gridProperties.tooltip + '"';
- return value;
- },
-
- renderer: function(value, p, record) {
-
- this.tooltipRenderer(value, p, record);
-
- if(value instanceof Date) {
- // TODO: Date-Schema is not generic
- value = value.dateFormat(ORYX.I18N.PropertyWindow.dateFormat);
- } else if(String(value).search("<a href='") < 0) {
- // Shows the Value in the Grid in each Line
- value = String(value).gsub("<", "<");
- value = String(value).gsub(">", ">");
- value = String(value).gsub("%", "%");
- value = String(value).gsub("&", "&");
- if(record.data.gridProperties.type == ORYX.CONFIG.TYPE_COLOR) {
- value = "<div class='prop-background-color' style='background-color:" + value + "' />";
- }
- record.data.icons.each(function(each) {
- if(each.name == value) {
- if(each.icon) {
- value = "<img src='" + each.icon + "' /> " + value;
- }
- }
- });
- }
- return value;
- },
- beforeEdit: function(option) {
- var editorGrid = this.dataSource.getAt(option.row).data.gridProperties.editor;
- var editorRenderer = this.dataSource.getAt(option.row).data.gridProperties.renderer;
- if(editorGrid) {
- // Disable KeyDown
- this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- option.grid.getColumnModel().setEditor(1, editorGrid);
-
- editorGrid.field.row = option.row;
- // Render the editor to the grid, therefore the editor is also available
- // for the first and last row
- editorGrid.render(this.grid);
-
- //option.grid.getColumnModel().setRenderer(1, editorRenderer);
- editorGrid.setSize(option.grid.getColumnModel().getColumnWidth(1), editorGrid.height);
- } else {
- return false;
- }
-
- var key = this.dataSource.getAt(option.row).data.gridProperties.propId;
-
- this.oldValues = new Hash();
- this.shapeSelection.shapes.each(function(shape){
- this.oldValues[shape.getId()] = shape.properties[key];
- }.bind(this));
- },
- afterEdit: function(option) {
- //Ext1.0: option.grid.getDataSource().commitChanges();
- option.grid.getStore().commitChanges();
- var key = option.record.data.gridProperties.propId;
- var selectedElements = this.shapeSelection.shapes;
-
- var oldValues = this.oldValues;
-
- var newValue = option.value;
- var facade = this.facade;
-
- // Implement the specific command for property change
- var commandClass = ORYX.Core.Command.extend({
- construct: function(){
- this.key = key;
- this.selectedElements = selectedElements;
- this.oldValues = oldValues;
- this.newValue = newValue;
- this.facade = facade;
- },
- execute: function(){
- this.selectedElements.each(function(shape){
- if(!shape.getStencil().property(this.key).readonly()) {
- shape.setProperty(this.key, this.newValue);
- }
- }.bind(this));
- this.facade.setSelection(this.selectedElements);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- },
- rollback: function(){
- this.selectedElements.each(function(shape){
- shape.setProperty(this.key, this.oldValues[shape.getId()]);
- }.bind(this));
- this.facade.setSelection(this.selectedElements);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- }
- })
- // Instanciated the class
- var command = new commandClass();
-
- // Execute the command
- this.facade.executeCommands([command]);
- // extended by Kerstin (start)
- //
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,
- elements : selectedElements,
- key : key,
- value : option.value
- });
- // extended by Kerstin (end)
- },
-
- // Changes made in the property window will be shown directly
- editDirectly:function(key, value){
-
- this.shapeSelection.shapes.each(function(shape){
- if(!shape.getStencil().property(key).readonly()) {
- shape.setProperty(key, value);
- //shape.update();
- }
- }.bind(this));
-
- /* Propagate changed properties */
- var selectedElements = this.shapeSelection.shapes;
-
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,
- elements : selectedElements,
- key : key,
- value : value
- });
- this.facade.getCanvas().update();
-
- },
-
- // if a field becomes invalid after editing the shape must be restored to the old value
- updateAfterInvalid : function(key) {
- this.shapeSelection.shapes.each(function(shape) {
- if(!shape.getStencil().property(key).readonly()) {
- shape.setProperty(key, this.oldValues[shape.getId()]);
- shape.update();
- }
- }.bind(this));
-
- this.facade.getCanvas().update();
- },
- // extended by Kerstin (start)
- dialogClosed: function(data) {
- var row = this.field ? this.field.row : this.row
- this.scope.afterEdit({
- grid:this.scope.grid,
- record:this.scope.grid.getStore().getAt(row),
- //value:this.scope.grid.getStore().getAt(this.row).get("value")
- value: data
- })
- // reopen the text field of the complex list field again
- this.scope.grid.startEditing(row, this.col);
- },
- // extended by Kerstin (end)
-
- /**
- * Changes the title of the property window panel according to the selected shapes.
- */
- setPropertyWindowTitle: function() {
- if(this.shapeSelection.shapes.length == 1) {
- // add the name of the stencil of the selected shape to the title
- region.setTitle(ORYX.I18N.PropertyWindow.title +' ('+this.shapeSelection.shapes.first().getStencil().title()+')' );
- } else {
- region.setTitle(ORYX.I18N.PropertyWindow.title +' ('
- + this.shapeSelection.shapes.length
- + ' '
- + ORYX.I18N.PropertyWindow.selected
- +')');
- }
- },
- /**
- * Sets this.shapeSelection.commonPropertiesValues.
- * If the value for a common property is not equal for each shape the value
- * is left empty in the property window.
- */
- setCommonPropertiesValues: function() {
- this.shapeSelection.commonPropertiesValues = new Hash();
- this.shapeSelection.commonProperties.each(function(property){
- var key = property.prefix() + "-" + property.id();
- var emptyValue = false;
- var firstShape = this.shapeSelection.shapes.first();
-
- this.shapeSelection.shapes.each(function(shape){
- if(firstShape.properties[key] != shape.properties[key]) {
- emptyValue = true;
- }
- }.bind(this));
-
- /* Set property value */
- if(!emptyValue) {
- this.shapeSelection.commonPropertiesValues[key]
- = firstShape.properties[key];
- }
- }.bind(this));
- },
-
- /**
- * Returns the set of stencils used by the passed shapes.
- */
- getStencilSetOfSelection: function() {
- var stencils = new Hash();
-
- this.shapeSelection.shapes.each(function(shape) {
- stencils[shape.getStencil().id()] = shape.getStencil();
- })
- return stencils;
- },
-
- /**
- * Identifies the common Properties of the selected shapes.
- */
- identifyCommonProperties: function() {
- this.shapeSelection.commonProperties.clear();
-
- /*
- * A common property is a property, that is part of
- * the stencil definition of the first and all other stencils.
- */
- var stencils = this.getStencilSetOfSelection();
- var firstStencil = stencils.values().first();
- var comparingStencils = stencils.values().without(firstStencil);
-
-
- if(comparingStencils.length == 0) {
- this.shapeSelection.commonProperties = firstStencil.properties();
- } else {
- var properties = new Hash();
-
- /* put all properties of on stencil in a Hash */
- firstStencil.properties().each(function(property){
- properties[property.namespace() + '-' + property.id()
- + '-' + property.type()] = property;
- });
-
- /* Calculate intersection of properties. */
-
- comparingStencils.each(function(stencil){
- var intersection = new Hash();
- stencil.properties().each(function(property){
- if(properties[property.namespace() + '-' + property.id()
- + '-' + property.type()]){
- intersection[property.namespace() + '-' + property.id()
- + '-' + property.type()] = property;
- }
- });
- properties = intersection;
- });
-
- this.shapeSelection.commonProperties = properties.values();
- }
- },
-
- onSelectionChanged: function(event) {
- /* Event to call afterEdit method */
- this.grid.stopEditing();
-
- /* Selected shapes */
- this.shapeSelection.shapes = event.elements;
-
- /* Case: nothing selected */
- if(event.elements.length == 0) {
- this.shapeSelection.shapes = [this.facade.getCanvas()];
- }
-
- /* subselection available */
- if(event.subSelection){
- this.shapeSelection.shapes = [event.subSelection];
- }
-
- this.setPropertyWindowTitle();
- this.identifyCommonProperties();
- this.setCommonPropertiesValues();
-
- // Create the Properties
-
- this.createProperties();
- },
-
- /**
- * Creates the properties for the ExtJS-Grid from the properties of the
- * selected shapes.
- */
- createProperties: function() {
- this.properties = [];
- this.popularProperties = [];
- if(this.shapeSelection.commonProperties) {
-
- // add new property lines
- this.shapeSelection.commonProperties.each((function(pair, index) {
- var key = pair.prefix() + "-" + pair.id();
-
- // Get the property pair
- var name = pair.title();
- var icons = [];
- var attribute = this.shapeSelection.commonPropertiesValues[key];
-
- var editorGrid = undefined;
- var editorRenderer = null;
- if(!pair.readonly()){
- switch(pair.type()) {
- case ORYX.CONFIG.TYPE_STRING:
- // If the Text is MultiLine
- if(pair.wrapLines()) {
- // Set the Editor as TextArea
- var editorTextArea = new Ext.form.TextArea({alignment: "tl-tl", allowBlank: pair.optional(), msgTarget:'title', maxLength:pair.length()});
- editorTextArea.on('keyup', function(textArea, event) {
- this.editDirectly(key, textArea.getValue());
- }.bind(this));
-
- editorGrid = new Ext.Editor(editorTextArea);
- } else {
- // If not, set the Editor as InputField
- var editorInput = new Ext.form.TextField({allowBlank: pair.optional(), msgTarget:'title', maxLength:pair.length()});
- editorInput.on('keyup', function(input, event) {
- this.editDirectly(key, input.getValue());
- }.bind(this));
-
- // reverts the shape if the editor field is invalid
- editorInput.on('blur', function(input) {
- if(!input.isValid(false))
- this.updateAfterInvalid(key);
- }.bind(this));
-
- editorInput.on("specialkey", function(input, e) {
- if(!input.isValid(false))
- this.updateAfterInvalid(key);
- }.bind(this));
-
- editorGrid = new Ext.Editor(editorInput);
- }
- break;
- case ORYX.CONFIG.TYPE_BOOLEAN:
- // Set the Editor as a CheckBox
- var editorCheckbox = new Ext.form.Checkbox();
- editorCheckbox.on('check', function(c,checked) {
- this.editDirectly(key, checked);
- }.bind(this));
-
- editorGrid = new Ext.Editor(editorCheckbox);
- break;
- case ORYX.CONFIG.TYPE_INTEGER:
- // Set as an Editor for Integers
- var numberField = new Ext.form.NumberField({allowBlank: pair.optional(), allowDecimals:false, msgTarget:'title', minValue: pair.min(), maxValue: pair.max()});
- numberField.on('keyup', function(input, event) {
- this.editDirectly(key, input.getValue());
- }.bind(this));
-
- editorGrid = new Ext.Editor(numberField);
- break;
- case ORYX.CONFIG.TYPE_FLOAT:
- // Set as an Editor for Float
- var numberField = new Ext.form.NumberField({ allowBlank: pair.optional(), allowDecimals:true, msgTarget:'title', minValue: pair.min(), maxValue: pair.max()});
- numberField.on('keyup', function(input, event) {
- this.editDirectly(key, input.getValue());
- }.bind(this));
-
- editorGrid = new Ext.Editor(numberField);
- break;
- case ORYX.CONFIG.TYPE_COLOR:
- // Set as a ColorPicker
- // Ext1.0 editorGrid = new gEdit(new form.ColorField({ allowBlank: pair.optional(), msgTarget:'title' }));
- var editorPicker = new Ext.ux.ColorField({ allowBlank: pair.optional(), msgTarget:'title', facade: this.facade });
-
- /*this.facade.registerOnEvent(ORYX.CONFIG.EVENT_COLOR_CHANGE, function(option) {
- this.editDirectly(key, option.value);
- }.bind(this));*/
-
- editorGrid = new Ext.Editor(editorPicker);
- break;
- case ORYX.CONFIG.TYPE_CHOICE:
- var items = pair.items();
-
- var options = [];
- items.each(function(value) {
- if(value.value() == attribute)
- attribute = value.title();
-
- options.push([value.icon(), value.title(), value.value()]);
-
- icons.push({
- name: value.title(),
- icon: value.icon()
- });
- });
-
- var store = new Ext.data.SimpleStore({
- fields: [{name: 'icon'},
- {name: 'title'},
- {name: 'value'} ],
- data : options // from states.js
- });
-
- // Set the grid Editor
- var editorCombo = new Ext.form.ComboBox({
- tpl: '<tpl for="."><div class="x-combo-list-item">{[(values.icon) ? "<img src=\'" + values.icon + "\' />" : ""]} {title}</div></tpl>',
- store: store,
- displayField:'title',
- valueField: 'value',
- typeAhead: true,
- mode: 'local',
- triggerAction: 'all',
- selectOnFocus:true
- });
-
- editorCombo.on('select', function(combo, record, index) {
- this.editDirectly(key, combo.getValue());
- }.bind(this))
-
- editorGrid = new Ext.Editor(editorCombo);
- break;
- case ORYX.CONFIG.TYPE_DATE:
- var currFormat = ORYX.I18N.PropertyWindow.dateFormat
- if(!(attribute instanceof Date))
- attribute = Date.parseDate(attribute, currFormat)
- editorGrid = new Ext.Editor(new Ext.form.DateField({ allowBlank: pair.optional(), format:currFormat, msgTarget:'title'}));
- break;
- case ORYX.CONFIG.TYPE_TEXT:
-
- var cf = new Ext.form.ComplexTextField({
- allowBlank: pair.optional(),
- dataSource:this.dataSource,
- grid:this.grid,
- row:index,
- facade:this.facade
- });
- cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf});
- editorGrid = new Ext.Editor(cf);
- break;
-
- case ORYX.CONFIG.TYPE_MODEL_LINK:
- var cf = new Ext.form.ComplexModelLinkField({
- allowBlank: pair.optional(),
- dataSource:this.dataSource,
- grid:this.grid,
- row:index,
- facade:this.facade
- });
- cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf});
- editorGrid = new Ext.Editor(cf);
- break;
-
- case ORYX.CONFIG.TYPE_LISTENER:
- var cf = new Ext.form.ListenerDefinitionField({
- allowBlank: pair.optional(),
- dataSource:this.dataSource,
- grid:this.grid,
- row:index,
- facade:this.facade
- });
- cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf});
- editorGrid = new Ext.Editor(cf);
- break;
-
- // extended by Kerstin (start)
- case ORYX.CONFIG.TYPE_COMPLEX:
-
- var cf = new Ext.form.ComplexListField({ allowBlank: pair.optional()}, pair.complexItems(), key, this.facade);
- cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf});
- editorGrid = new Ext.Editor(cf);
- break;
- // extended by Kerstin (end)
-
- case ORYX.CONFIG.TYPE_MULTIPLECOMPLEX:
-
- var cf = new Ext.form.MultipleComplexListField({ allowBlank: pair.optional()}, pair.complexItems(), key, this.facade);
- cf.on('dialogClosed', this.dialogClosed, {scope:this, row:index, col:1,field:cf});
- editorGrid = new Ext.Editor(cf);
- break;
-
- // extended by Gerardo (Start)
- case "CPNString":
- var editorInput = new Ext.form.TextField(
- {
- allowBlank: pair.optional(),
- msgTarget:'title',
- maxLength:pair.length(),
- enableKeyEvents: true
- });
-
- editorInput.on('keyup', function(input, event) {
- this.editDirectly(key, input.getValue());
- console.log(input.getValue());
- alert("huhu");
- }.bind(this));
-
- editorGrid = new Ext.Editor(editorInput);
- break;
- // extended by Gerardo (End)
-
- default:
- var editorInput = new Ext.form.TextField({ allowBlank: pair.optional(), msgTarget:'title', maxLength:pair.length(), enableKeyEvents: true});
- editorInput.on('keyup', function(input, event) {
- this.editDirectly(key, input.getValue());
- }.bind(this));
-
- editorGrid = new Ext.Editor(editorInput);
- }
- // Register Event to enable KeyDown
- editorGrid.on('beforehide', this.facade.enableEvent.bind(this, ORYX.CONFIG.EVENT_KEYDOWN));
- editorGrid.on('specialkey', this.specialKeyDown.bind(this));
- } else if(pair.type() === ORYX.CONFIG.TYPE_URL || pair.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK){
- attribute = String(attribute).search("http") !== 0 ? ("http://" + attribute) : attribute;
- attribute = "<a href='" + attribute + "' target='_blank'>" + attribute.split("://")[1] + "</a>"
- }
-
- // Push to the properties-array
- if(pair.visible()) {
- // Popular Properties are those which are set to be popular
- if (pair.popular()) {
- pair.setPopular();
- }
-
- if(pair.popular()) {
- this.popularProperties.push([pair.popular(), name, attribute, icons, {
- editor: editorGrid,
- propId: key,
- type: pair.type(),
- tooltip: pair.description(),
- renderer: editorRenderer
- }]);
- }
- else {
- this.properties.push([pair.popular(), name, attribute, icons, {
- editor: editorGrid,
- propId: key,
- type: pair.type(),
- tooltip: pair.description(),
- renderer: editorRenderer
- }]);
- }
- }
- }).bind(this));
- }
- this.setProperties();
- },
-
- hideMoreAttrs: function(panel) {
- // TODO: Implement the case that the canvas has no attributes
- if (this.properties.length <= 0){ return }
-
- // collapse the "more attr" group
- this.grid.view.toggleGroup(this.grid.view.getGroupId(this.properties[0][0]), false);
-
- // prevent the more attributes pane from closing after a attribute has been edited
- this.grid.view.un("refresh", this.hideMoreAttrs, this);
- },
- setProperties: function() {
- var props = this.popularProperties.concat(this.properties);
-
- this.dataSource.loadData(props);
- }
- }
- ORYX.Plugins.PropertyWindow = Clazz.extend(ORYX.Plugins.PropertyWindow);
- /**
- * Editor for complex type
- *
- * When starting to edit the editor, it creates a new dialog where new attributes
- * can be specified which generates json out of this and put this
- * back to the input field.
- *
- * This is implemented from Kerstin Pfitzner
- *
- * @param {Object} config
- * @param {Object} items
- * @param {Object} key
- * @param {Object} facade
- */
- Ext.form.ComplexListField = function(config, items, key, facade){
- Ext.form.ComplexListField.superclass.constructor.call(this, config);
- this.items = items;
- this.key = key;
- this.facade = facade;
- };
- /**
- * This is a special trigger field used for complex properties.
- * The trigger field opens a dialog that shows a list of properties.
- * The entered values will be stored as trigger field value in the JSON format.
- */
- Ext.extend(Ext.form.ComplexListField, Ext.form.TriggerField, {
- /**
- * @cfg {String} triggerClass
- * An additional CSS class used to style the trigger button. The trigger will always get the
- * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified.
- */
- triggerClass: 'x-form-complex-trigger',
- readOnly: true,
- emptyText: ORYX.I18N.PropertyWindow.clickIcon,
-
- /**
- * Builds the JSON value from the data source of the grid in the dialog.
- */
- buildValue: function() {
- var ds = this.grid.getStore();
- ds.commitChanges();
-
- if (ds.getCount() == 0) {
- return "";
- }
-
- var jsonString = "[";
- for (var i = 0; i < ds.getCount(); i++) {
- var data = ds.getAt(i);
- jsonString += "{";
- for (var j = 0; j < this.items.length; j++) {
- var key = this.items[j].id();
- jsonString += key + ':' + ("" + data.get(key)).toJSON();
- if (j < (this.items.length - 1)) {
- jsonString += ", ";
- }
- }
- jsonString += "}";
- if (i < (ds.getCount() - 1)) {
- jsonString += ", ";
- }
- }
- jsonString += "]";
-
- jsonString = "{'totalCount':" + ds.getCount().toJSON() +
- ", 'items':" + jsonString + "}";
- return Object.toJSON(jsonString.evalJSON());
- },
-
- /**
- * Returns the field key.
- */
- getFieldKey: function() {
- return this.key;
- },
-
- /**
- * Returns the actual value of the trigger field.
- * If the table does not contain any values the empty
- * string will be returned.
- */
- getValue : function(){
- // return actual value if grid is active
- if (this.grid) {
- return this.buildValue();
- } else if (this.data == undefined) {
- return "";
- } else {
- return this.data;
- }
- },
-
- /**
- * Sets the value of the trigger field.
- * In this case this sets the data that will be shown in
- * the grid of the dialog.
- *
- * @param {Object} value The value to be set (JSON format or empty string)
- */
- setValue: function(value) {
- if (value.length > 0 && value.indexOf('<') == -1) {
- // set only if this.data not set yet
- // only to initialize the grid
- if (this.data == undefined) {
- this.data = value;
- }
- }
- },
-
- /**
- * Returns false. In this way key events will not be propagated
- * to other elements.
- *
- * @param {Object} event The keydown event.
- */
- keydownHandler: function(event) {
- return false;
- },
-
- /**
- * The listeners of the dialog.
- *
- * If the dialog is hidded, a dialogClosed event will be fired.
- * This has to be used by the parent element of the trigger field
- * to reenable the trigger field (focus gets lost when entering values
- * in the dialog).
- */
- dialogListeners : {
- show : function(){ // retain focus styling
- this.onFocus();
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keydownHandler.bind(this));
- this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- return;
- },
- hide : function(){
- var dl = this.dialogListeners;
- this.dialog.un("show", dl.show, this);
- this.dialog.un("hide", dl.hide, this);
-
- this.dialog.destroy(true);
- this.grid.destroy(true);
- delete this.grid;
- delete this.dialog;
-
- this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keydownHandler.bind(this));
- this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
-
- // store data and notify parent about the closed dialog
- // parent has to handel this event and start editing the text field again
- this.fireEvent('dialogClosed', this.data);
-
- Ext.form.ComplexListField.superclass.setValue.call(this, this.data);
- }
- },
-
- /**
- * Builds up the initial values of the grid.
- *
- * @param {Object} recordType The record type of the grid.
- * @param {Object} items The initial items of the grid (columns)
- */
- buildInitial: function(recordType, items) {
- var initial = new Hash();
-
- for (var i = 0; i < items.length; i++) {
- var id = items[i].id();
- initial[id] = items[i].value();
- }
-
- var RecordTemplate = Ext.data.Record.create(recordType);
- return new RecordTemplate(initial);
- },
-
- /**
- * Builds up the column model of the grid. The parent element of the
- * grid.
- *
- * Sets up the editors for the grid columns depending on the
- * type of the items.
- *
- * @param {Object} parent The
- */
- buildColumnModel: function(parent) {
- var cols = [];
- for (var i = 0; i < this.items.length; i++) {
- var id = this.items[i].id();
- var header = this.items[i].name();
- var width = this.items[i].width();
- var type = this.items[i].type();
- var editor;
-
- if (type == ORYX.CONFIG.TYPE_STRING) {
- editor = new Ext.form.TextField({ allowBlank : this.items[i].optional(), width : width});
- } else if (type == ORYX.CONFIG.TYPE_CHOICE) {
- var items = this.items[i].items();
- var select = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parent, ['select', {style:'display:none'}]);
- var optionTmpl = new Ext.Template('<option value="{value}">{value}</option>');
- items.each(function(value){
- optionTmpl.append(select, {value:value.value()});
- });
-
- editor = new Ext.form.ComboBox(
- { typeAhead: true, triggerAction: 'all', transform:select, lazyRender:true, msgTarget:'title', width : width});
- } else if (type == ORYX.CONFIG.TYPE_BOOLEAN) {
- editor = new Ext.form.Checkbox( { width : width } );
- } else if (type == ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- cols.push({
- id: id,
- header: header,
- dataIndex: id,
- resizable: true,
- editor: editor,
- width: width
- });
-
- }
- return new Ext.grid.ColumnModel(cols);
- },
-
- /**
- * After a cell was edited the changes will be commited.
- *
- * @param {Object} option The option that was edited.
- */
- afterEdit: function(option) {
- option.grid.getStore().commitChanges();
- },
-
- /**
- * Before a cell is edited it has to be checked if this
- * cell is disabled by another cell value. If so, the cell editor will
- * be disabled.
- *
- * @param {Object} option The option to be edited.
- */
- beforeEdit: function(option) {
- var state = this.grid.getView().getScrollState();
-
- var col = option.column;
- var row = option.row;
-
- var editId = this.grid.getColumnModel().config[col].id;
- // check if there is an item in the row, that disables this cell
- for (var i = 0; i < this.items.length; i++) {
- // check each item that defines a "disable" property
- var item = this.items[i];
- var disables = item.disable();
- if (disables != undefined) {
-
- // check if the value of the column of this item in this row is equal to a disabling value
- var value = this.grid.getStore().getAt(row).get(item.id());
- for (var j = 0; j < disables.length; j++) {
- var disable = disables[j];
- if (disable.value == value) {
-
- for (var k = 0; k < disable.items.length; k++) {
- // check if this value disables the cell to select
- // (id is equals to the id of the column to edit)
- var disItem = disable.items[k];
- if (disItem == editId) {
- this.grid.getColumnModel().getCellEditor(col, row).disable();
- return;
- }
- }
- }
- }
- }
- }
- this.grid.getColumnModel().getCellEditor(col, row).enable();
- //this.grid.getView().restoreScroll(state);
- },
-
- onCellClick: function() {
- alert()
- },
-
- /**
- * If the trigger was clicked a dialog has to be opened
- * to enter the values for the complex property.
- */
- onTriggerClick : function(){
- if(this.disabled){
- return;
- }
-
- //if(!this.dialog) {
-
- var dialogWidth = 0;
- var recordType = [];
-
- for (var i = 0; i < this.items.length; i++) {
- var id = this.items[i].id();
- var width = this.items[i].width();
- var type = this.items[i].type();
-
- if (type == ORYX.CONFIG.TYPE_CHOICE || type == ORYX.CONFIG.TYPE_COMPLEX) {
- type = ORYX.CONFIG.TYPE_STRING;
- }
-
- dialogWidth += width;
- recordType[i] = {name:id, type:type};
- }
-
- if (dialogWidth > 800) {
- dialogWidth = 800;
- }
- dialogWidth += 22;
-
- var data = this.data;
-
- if (data == "") {
- // empty string can not be parsed
- data = "{}";
- }
-
- var ds = new Ext.data.Store({
- proxy: new Ext.data.MemoryProxy(eval("(" + data + ")")),
- reader: new Ext.data.JsonReader({
- root: 'items',
- totalProperty: 'totalCount'
- }, recordType)
- });
- ds.load();
-
-
- var cm = this.buildColumnModel();
-
-
- //var gridHead = this.grid.getView().getHeaderPanel(true);
- var toolbar = new Ext.Toolbar(
- [{
- text: ORYX.I18N.PropertyWindow.add,
- icon: '../editor/images/add.png',
- iconCls: "x-dummy",
- handler: function(){
- var ds = this.grid.getStore();
- var index = ds.getCount();
- this.grid.stopEditing();
- var p = this.buildInitial(recordType, this.items);
- ds.insert(index, p);
- ds.commitChanges();
- this.grid.startEditing(index, 0);
- }.bind(this)
- },{
- text: ORYX.I18N.PropertyWindow.rem,
- icon: '../editor/images/delete.png',
- iconCls: "x-dummy",
- handler : function(){
- var ds = this.grid.getStore();
- var selection = this.grid.getSelectionModel().getSelectedCell();
- if (selection == undefined) {
- return;
- }
- this.grid.getSelectionModel().clearSelections();
- this.grid.stopEditing();
- var record = ds.getAt(selection[0]);
- ds.remove(record);
- ds.commitChanges();
- }.bind(this)
- }]);
-
- this.grid = new Ext.grid.EditorGridPanel({
- store: ds,
- cm: cm,
- stripeRows: true,
- clicksToEdit: 1,
- autoScroll: true,
- stateId: "x-editor-complex-grid",
- anchor: "100% 100%",
- enableHdMenu: false, // Disable header menu
- selModel: new Ext.grid.CellSelectionModel(),
- tbar:toolbar
-
- });
-
- // Basic Dialog
- this.dialog = new Ext.Window({
- autoCreate: true,
- layout: "anchor",
- title: ORYX.I18N.PropertyWindow.complex,
- height: 350,
- width: dialogWidth,
- modal:true,
- collapsible:false,
- fixedcenter: true,
- shadow:true,
- proxyDrag: true,
- keys:[{
- key: 27,
- fn: function(){
- this.dialog.hide
- }.bind(this)
- }],
- items:[this.grid],
- bodyStyle:"background-color:#FFFFFF",
- buttons: [{
- text: ORYX.I18N.PropertyWindow.ok,
- handler: function(){
- this.grid.stopEditing();
- // store dialog input
- this.data = this.buildValue();
- this.dialog.hide()
- }.bind(this)
- }, {
- text: ORYX.I18N.PropertyWindow.cancel,
- handler: function(){
- this.dialog.hide()
- }.bind(this)
- }]
- });
-
- this.dialog.on(Ext.apply({}, this.dialogListeners, {
- scope:this
- }));
-
- this.dialog.show();
-
-
- this.grid.on('beforeedit', this.beforeEdit, this, true);
- this.grid.on('afteredit', this.afterEdit, this, true);
-
- this.grid.render();
-
- /*} else {
- this.dialog.show();
- }*/
-
- }
- });
- Ext.form.MultipleComplexListField = function(config, items, key, facade){
- Ext.form.MultipleComplexListField.superclass.constructor.call(this, config);
- this.items = items;
- this.key = key;
- this.facade = facade;
- };
- Ext.extend(Ext.form.MultipleComplexListField, Ext.form.TriggerField, {
- /**
- * @cfg {String} triggerClass
- * An additional CSS class used to style the trigger button. The trigger will always get the
- * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified.
- */
- triggerClass: 'x-form-complex-trigger',
- readOnly: true,
- emptyText: ORYX.I18N.PropertyWindow.clickIcon,
-
- /**
- * Builds the JSON value from the data source of the grid in the dialog.
- */
- buildValue: function() {
- var ds = this.grid.getStore();
- ds.commitChanges();
-
- if (ds.getCount() == 0) {
- return "";
- }
-
- var jsonString = "[";
- for (var i = 0; i < ds.getCount(); i++) {
- var data = ds.getAt(i);
- jsonString += "{";
- for (var j = 0; j < this.items.length; j++) {
- var key = this.items[j].id();
- jsonString += key + ':' + ("" + data.get(key)).toJSON();
- if (j < (this.items.length - 1)) {
- jsonString += ", ";
- }
- }
- jsonString += "}";
- if (i < (ds.getCount() - 1)) {
- jsonString += ", ";
- }
- }
- jsonString += "]";
-
- jsonString = "{'totalCount':" + ds.getCount().toJSON() +
- ", 'items':" + jsonString + "}";
- return Object.toJSON(jsonString.evalJSON());
- },
-
- /**
- * Returns the field key.
- */
- getFieldKey: function() {
- return this.key;
- },
-
- /**
- * Returns the actual value of the trigger field.
- * If the table does not contain any values the empty
- * string will be returned.
- */
- getValue : function(){
- // return actual value if grid is active
- if (this.grid) {
- return this.buildValue();
- } else if (this.data == undefined) {
- return "";
- } else {
- return this.data;
- }
- },
-
- /**
- * Sets the value of the trigger field.
- * In this case this sets the data that will be shown in
- * the grid of the dialog.
- *
- * @param {Object} value The value to be set (JSON format or empty string)
- */
- setValue: function(value) {
- if (value.length > 0 && value.indexOf('<') == -1) {
- // set only if this.data not set yet
- // only to initialize the grid
- if (this.data == undefined) {
- this.data = value;
- }
- }
- },
-
- /**
- * Returns false. In this way key events will not be propagated
- * to other elements.
- *
- * @param {Object} event The keydown event.
- */
- keydownHandler: function(event) {
- return false;
- },
-
- /**
- * The listeners of the dialog.
- *
- * If the dialog is hidded, a dialogClosed event will be fired.
- * This has to be used by the parent element of the trigger field
- * to reenable the trigger field (focus gets lost when entering values
- * in the dialog).
- */
- dialogListeners : {
- show : function(){ // retain focus styling
- this.onFocus();
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keydownHandler.bind(this));
- this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- return;
- },
- hide : function(){
- var dl = this.dialogListeners;
- this.dialog.un("show", dl.show, this);
- this.dialog.un("hide", dl.hide, this);
-
- this.dialog.destroy(true);
- this.grid.destroy(true);
- delete this.grid;
- delete this.dialog;
-
- this.facade.unregisterOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keydownHandler.bind(this));
- this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
-
- // store data and notify parent about the closed dialog
- // parent has to handel this event and start editing the text field again
- this.fireEvent('dialogClosed', this.data);
-
- Ext.form.ComplexListField.superclass.setValue.call(this, this.data);
- }
- },
-
- /**
- * Builds up the initial values of the grid.
- *
- * @param {Object} recordType The record type of the grid.
- * @param {Object} items The initial items of the grid (columns)
- */
- buildInitial: function(recordType, items) {
- var initial = new Hash();
-
- for (var i = 0; i < items.length; i++) {
- var id = items[i].id();
- initial[id] = items[i].value();
- }
-
- var RecordTemplate = Ext.data.Record.create(recordType);
- return new RecordTemplate(initial);
- },
-
- /**
- * Builds up the column model of the grid. The parent element of the
- * grid.
- *
- * Sets up the editors for the grid columns depending on the
- * type of the items.
- *
- * @param {Object} parent The
- */
- buildColumnModel: function(parent) {
- var cols = [];
- for (var i = 0; i < this.items.length; i++) {
- var id = this.items[i].id();
- var header = this.items[i].name();
- var width = this.items[i].width();
- var type = this.items[i].type();
- var editor;
-
- if (type == ORYX.CONFIG.TYPE_STRING) {
- editor = new Ext.form.TextField({ allowBlank : this.items[i].optional(), width : width});
- } else if (type == ORYX.CONFIG.TYPE_CHOICE) {
- var items = this.items[i].items();
- var select = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parent, ['select', {style:'display:none'}]);
- var optionTmpl = new Ext.Template('<option value="{value}">{value}</option>');
- items.each(function(value){
- optionTmpl.append(select, {value:value.value()});
- });
-
- editor = new Ext.form.ComboBox(
- { typeAhead: true, triggerAction: 'all', transform:select, lazyRender:true, msgTarget:'title', width : width});
- } else if (type == ORYX.CONFIG.TYPE_BOOLEAN) {
- editor = new Ext.form.Checkbox( { width : width } );
- } else if (type == ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- cols.push({
- id: id,
- header: header,
- dataIndex: id,
- resizable: true,
- editor: editor,
- width: width
- });
-
- }
- return new Ext.grid.ColumnModel(cols);
- },
-
- buildSecondColumnModel: function(parent) {
- var cols = [];
- for (var i = 0; i < this.items.length; i++) {
-
- var parentType = this.items[i].type();
-
- if (parentType != ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- var complexItems = this.items[i].complexItems();
-
- for (var j = 0; j < complexItems.length; j++) {
- var id = complexItems[j].id();
- var header = complexItems[j].name();
- var type = complexItems[j].type();
- var width = complexItems[j].width();
- var editor;
-
- if (type == ORYX.CONFIG.TYPE_STRING) {
- editor = new Ext.form.TextField({ allowBlank : complexItems[j].optional(), width : width});
- } else if (type == ORYX.CONFIG.TYPE_CHOICE) {
- var items = complexItems[j].items();
- var select = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parent, ['select', {style:'display:none'}]);
- var optionTmpl = new Ext.Template('<option value="{value}">{value}</option>');
- items.each(function(value){
- optionTmpl.append(select, {value:value.value()});
- });
-
- editor = new Ext.form.ComboBox(
- { typeAhead: true, triggerAction: 'all', transform:select, lazyRender:true, msgTarget:'title', width : width});
- } else if (type == ORYX.CONFIG.TYPE_BOOLEAN) {
- editor = new Ext.form.Checkbox( { width : width } );
- } else if (type == ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- cols.push({
- id: id,
- header: header,
- dataIndex: id,
- resizable: true,
- editor: editor,
- width: width
- });
- }
- }
- return new Ext.grid.ColumnModel(cols);
- },
-
- /**
- * After a cell was edited the changes will be commited.
- *
- * @param {Object} option The option that was edited.
- */
- afterEdit: function(option) {
- option.grid.getStore().commitChanges();
- },
-
- afterEditSecondGrid: function(option) {
- this.secondGrid.getStore().commitChanges();
- var selectedCell = this.grid.getSelectionModel().getSelectedCell();
- if (selectedCell.length == 2) {
- var row = selectedCell[0];
-
- var jsonString = "[";
- for (var i = 0; i < this.secondGrid.getStore().getCount(); i++) {
- var data = this.secondGrid.getStore().getAt(i);
- jsonString += "{";
- for (var j = 0; j < this.items.length; j++) {
-
- var parentType = this.items[j].type();
-
- if (parentType != ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- var complexItems = this.items[j].complexItems();
-
- for (var k = 0; k < complexItems.length; k++) {
-
- var key = complexItems[k].id();
-
- jsonString += key + ':' + ("" + data.get(key)).toJSON();
- if (k < (complexItems.length - 1)) {
- jsonString += ", ";
- }
- }
- }
- jsonString += "}";
- if (i < (this.secondGrid.getStore().getCount() - 1)) {
- jsonString += ", ";
- }
- }
- jsonString += "]";
-
- jsonString = "{'totalCount':" + this.secondGrid.getStore().getCount().toJSON() +
- ", 'items':" + jsonString + "}";
-
- var activeRecord = this.grid.getStore().getAt(row);
- activeRecord.set(this.complexFieldId, Object.toJSON(jsonString.evalJSON()));
- }
- },
-
- /**
- * Before a cell is edited it has to be checked if this
- * cell is disabled by another cell value. If so, the cell editor will
- * be disabled.
- *
- * @param {Object} option The option to be edited.
- */
- beforeEdit: function(option) {
- var state = this.grid.getView().getScrollState();
-
- var col = option.column;
- var row = option.row;
-
- var editId = this.grid.getColumnModel().config[col].id;
- // check if there is an item in the row, that disables this cell
- for (var i = 0; i < this.items.length; i++) {
-
- if (this.items[i].type() == ORYX.CONFIG.TYPE_COMPLEX) {
- continue;
- }
-
- // check each item that defines a "disable" property
- var item = this.items[i];
- var disables = item.disable();
- if (disables != undefined) {
-
- // check if the value of the column of this item in this row is equal to a disabling value
- var value = this.grid.getStore().getAt(row).get(item.id());
- for (var j = 0; j < disables.length; j++) {
- var disable = disables[j];
- if (disable.value == value) {
-
- for (var k = 0; k < disable.items.length; k++) {
- // check if this value disables the cell to select
- // (id is equals to the id of the column to edit)
- var disItem = disable.items[k];
- if (disItem == editId) {
- this.grid.getColumnModel().getCellEditor(col, row).disable();
- return;
- }
- }
- }
- }
- }
- }
- this.grid.getColumnModel().getCellEditor(col, row).enable();
- //this.grid.getView().restoreScroll(state);
- },
-
- /**
- * If the trigger was clicked a dialog has to be opened
- * to enter the values for the complex property.
- */
- onTriggerClick : function(){
- if(this.disabled){
- return;
- }
-
- //if(!this.dialog) {
-
- var dialogWidth = 0;
- var recordType = [];
- var secondRecordType = [];
-
- this.complexFieldId;
- var complexItems;
-
- for (var i = 0; i < this.items.length; i++) {
-
- var id = this.items[i].id();
- var width = this.items[i].width();
- var type = this.items[i].type();
-
- if (type == ORYX.CONFIG.TYPE_CHOICE) {
- type = ORYX.CONFIG.TYPE_STRING;
- }
-
- if (type == ORYX.CONFIG.TYPE_COMPLEX) {
- this.complexFieldId = id;
- type = ORYX.CONFIG.TYPE_STRING;
-
- complexItems = this.items[i].complexItems();
-
- for (var j = 0; j < complexItems.length; j++) {
- var secondId = complexItems[j].id();
- var secondWidth = complexItems[j].width();
- var secondType = complexItems[j].type();
-
- if (secondType == ORYX.CONFIG.TYPE_CHOICE) {
- secondType = ORYX.CONFIG.TYPE_STRING;
- }
-
- secondRecordType[j] = {name:secondId, type:secondType};
- }
-
- } else {
- dialogWidth += width;
- }
- recordType[i] = {name:id, type:type};
- }
-
- if (dialogWidth > 800) {
- dialogWidth = 800;
- }
- dialogWidth += 22;
-
- var data = this.data;
- if (data == "") {
- // empty string can not be parsed
- data = "{}";
- }
-
- var ds = new Ext.data.Store({
- proxy: new Ext.data.MemoryProxy(eval("(" + data + ")")),
- reader: new Ext.data.JsonReader({
- root: 'items',
- totalProperty: 'totalCount'
- }, recordType)
- });
- ds.load();
-
- var secondDs = new Ext.data.Store();
-
- var cm = this.buildColumnModel();
-
- var secondCm = this.buildSecondColumnModel();
-
- //var gridHead = this.grid.getView().getHeaderPanel(true);
- var toolbar = new Ext.Toolbar(
- [{
- text: ORYX.I18N.PropertyWindow.add,
- icon: '../editor/images/add.png',
- iconCls: "x-dummy",
- handler: function(){
- var ds = this.grid.getStore();
- var index = ds.getCount();
- this.grid.stopEditing();
- var p = this.buildInitial(recordType, this.items);
- ds.insert(index, p);
- ds.commitChanges();
- this.grid.startEditing(index, 0);
- }.bind(this)
- },{
- text: ORYX.I18N.PropertyWindow.rem,
- icon: '../editor/images/delete.png',
- iconCls: "x-dummy",
- handler : function(){
- var ds = this.grid.getStore();
- var selection = this.grid.getSelectionModel().getSelectedCell();
- if (selection == undefined) {
- return;
- }
- this.grid.getSelectionModel().clearSelections();
- this.grid.stopEditing();
- var record = ds.getAt(selection[0]);
- ds.remove(record);
- ds.commitChanges();
- }.bind(this)
- }]);
-
- this.grid = new Ext.grid.EditorGridPanel({
- store: ds,
- cm: cm,
- stripeRows: true,
- clicksToEdit: 1,
- autoScroll: true,
- stateId: "x-editor-complex-grid",
- height: 280,
- anchor: '100%',
- enableHdMenu: false, // Disable header menu
- selModel: new Ext.grid.CellSelectionModel({
- listeners: {
- scope: this,
- cellselect: function(sm,row,col) {
- secondDs.removeAll(true);
- var masterRecord = ds.getAt(row);
- if (masterRecord.get('' + this.complexFieldId) != undefined && masterRecord.get('' + this.complexFieldId) != 'undefined') {
-
- var newDs = new Ext.data.Store({
- proxy: new Ext.data.MemoryProxy(eval("(" + masterRecord.get('' + this.complexFieldId) + ")")),
- reader: new Ext.data.JsonReader({
- root: 'items',
- totalProperty: 'totalCount'
- }, secondRecordType)
- });
- newDs.load();
-
- secondDs.removeAll(true);
- for (var i = 0; i < newDs.getCount(); i++) {
- secondDs.add(newDs.getAt(i));
- }
- }
- secondDs.commitChanges();
- }
- }
- }),
- tbar:toolbar
-
- });
-
- var secondToolbar = new Ext.Toolbar(
- [{
- text: ORYX.I18N.PropertyWindow.add,
- icon: '../editor/images/add.png',
- iconCls: "x-dummy",
- handler: function(){
- var ds = this.secondGrid.getStore();
- var index = ds.getCount();
- this.secondGrid.stopEditing();
- var p = this.buildInitial(secondRecordType, complexItems);
- ds.insert(index, p);
- ds.commitChanges();
- this.secondGrid.startEditing(index, 0);
- }.bind(this)
- },{
- text: ORYX.I18N.PropertyWindow.rem,
- icon: '../editor/images/delete.png',
- iconCls: "x-dummy",
- handler : function(){
- var ds = this.secondGrid.getStore();
- var selection = this.secondGrid.getSelectionModel().getSelectedCell();
- if (selection == undefined) {
- return;
- }
- this.secondGrid.getSelectionModel().clearSelections();
- this.secondGrid.stopEditing();
- var record = ds.getAt(selection[0]);
- ds.remove(record);
- ds.commitChanges();
- this.afterEditSecondGrid();
- }.bind(this)
- }]);
-
- this.secondGrid = new Ext.grid.EditorGridPanel({
- store: secondDs,
- cm: secondCm,
- stripeRows: true,
- clicksToEdit: 1,
- autoScroll: true,
- stateId: "x-editor-complex-grid",
- height: 280,
- anchor: '100%',
- enableHdMenu: false, // Disable header menu
- selModel: new Ext.grid.CellSelectionModel(),
- tbar:secondToolbar
-
- });
-
- // Basic Dialog
- this.dialog = new Ext.Window({
- autoCreate: true,
- layout: "anchor",
- title: ORYX.I18N.PropertyWindow.complex,
- height: 600,
- width: dialogWidth,
- modal:true,
- collapsible:false,
- fixedcenter: true,
- shadow:true,
- proxyDrag: true,
- keys:[{
- key: 27,
- fn: function(){
- this.dialog.hide
- }.bind(this)
- }],
- items:[this.grid, this.secondGrid],
- bodyStyle:"background-color:#FFFFFF",
- buttons: [{
- text: ORYX.I18N.PropertyWindow.ok,
- handler: function(){
- this.grid.stopEditing();
- // store dialog input
- this.data = this.buildValue();
- this.dialog.hide()
- }.bind(this)
- }]
- });
-
- this.dialog.on(Ext.apply({}, this.dialogListeners, {
- scope:this
- }));
-
- this.dialog.show();
-
-
- this.grid.on('beforeedit', this.beforeEdit, this, true);
- this.grid.on('afteredit', this.afterEdit, this, true);
-
- this.secondGrid.on('beforeedit', this.beforeEdit, this, true);
- this.secondGrid.on('afteredit', this.afterEditSecondGrid, this, true);
-
- this.grid.render();
- this.secondGrid.render();
-
- if (ds.getCount() > 0) {
- this.grid.getSelectionModel().select(0,0);
- }
-
- /*} else {
- this.dialog.show();
- }*/
-
- }
- });
- Ext.form.ComplexTextField = Ext.extend(Ext.form.TriggerField, {
- defaultAutoCreate : {tag: "textarea", rows:1, style:"height:16px;overflow:hidden;" },
- /**
- * If the trigger was clicked a dialog has to be opened
- * to enter the values for the complex property.
- */
- onTriggerClick : function(){
-
- if(this.disabled){
- return;
- }
-
- var grid = new Ext.form.TextArea({
- anchor : '100% 100%',
- value : this.value,
- listeners : {
- focus: function(){
- this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- }.bind(this)
- }
- })
-
-
- // Basic Dialog
- var dialog = new Ext.Window({
- layout : 'anchor',
- autoCreate : true,
- title : ORYX.I18N.PropertyWindow.text,
- height : 500,
- width : 500,
- modal : true,
- collapsible : false,
- fixedcenter : true,
- shadow : true,
- proxyDrag : true,
- keys:[{
- key : 27,
- fn : function(){
- dialog.hide()
- }.bind(this)
- }],
- items :[grid],
- listeners :{
- hide: function(){
- this.fireEvent('dialogClosed', this.value);
- //this.focus.defer(10, this);
- dialog.destroy();
- }.bind(this)
- },
- buttons : [{
- text: ORYX.I18N.PropertyWindow.ok,
- handler: function(){
- // store dialog input
- var value = grid.getValue();
- this.setValue(value);
-
- this.dataSource.getAt(this.row).set('value', value)
- this.dataSource.commitChanges()
- dialog.hide()
- }.bind(this)
- }, {
- text: ORYX.I18N.PropertyWindow.cancel,
- handler: function(){
- this.setValue(this.value);
- dialog.hide()
- }.bind(this)
- }]
- });
-
- dialog.show();
- grid.render();
- this.grid.stopEditing();
- grid.focus( false, 100 );
-
- }
- });
- Ext.form.ComplexModelLinkField = Ext.extend(Ext.form.TriggerField, {
- onTriggerClick : function() {
- if(this.disabled){
- return;
- }
-
- var CallElementDef = Ext.data.Record.create([{
- name: 'name'
- }, {
- name: 'revision'
- }, {
- name: 'imgsrc'
- }]);
-
- var calldefsProxy = new Ext.data.MemoryProxy({
- root: []
- });
-
- var calldefs = new Ext.data.Store({
- autoDestroy: true,
- reader: new Ext.data.JsonReader({
- root: "root"
- }, CallElementDef),
- proxy: calldefsProxy,
- sorters: [{
- property: 'name',
- direction:'ASC'
- }]
- });
- calldefs.load();
-
- var loadProcessesMask = new Ext.LoadMask(Ext.getBody(), {msg:'Loading Process Information'});
- loadProcessesMask.show();
- Ext.Ajax.request({
- url: ORYX.CONFIG.MODEL_LIST_URL,
- method: 'GET',
- success: function(response) {
- try {
- loadProcessesMask.hide();
- if(response.responseText.length > 0 && response.responseText != "false") {
- var responseJson = Ext.decode(response.responseText);
- var modelsArray = responseJson["models"];
- for(var i = 0; i < modelsArray.length; i++) {
- var modelObj = modelsArray[i];
- calldefs.add(new CallElementDef({
- name: modelObj["name"],
- revision: modelObj["revision"],
- imgsrc: ORYX.CONFIG.SERVER_MODEL_HANDLER + "/" + modelObj["modelId"] + "/svg"
- }));
- }
- calldefs.commitChanges();
-
- var gridId = Ext.id();
- var grid = new Ext.grid.EditorGridPanel({
- store: calldefs,
- id: gridId,
- stripeRows: true,
- cm: new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), {
- id: 'pid',
- header: 'Process Id',
- width: 200,
- dataIndex: 'name',
- editor: new Ext.form.TextField({ allowBlank: false, disabled: true })
- }, {
- id: 'revi',
- header: 'Revision',
- width: 200,
- dataIndex: 'revision',
- editor: new Ext.form.TextField({ allowBlank: false, disabled: true })
- },{
- id: 'pim',
- header: 'Process Image',
- width: 250,
- dataIndex: 'imgsrc',
- renderer: function(val) {
- if(val && val.length > 0) {
- return '<center><img src="'+ORYX.CONFIG.ROOT_PATH+'images/processimagepreview.png" onclick="new ImageViewer({title: \'Process Image\', width: \'1100\', height: \'900\', autoScroll: true, fixedcenter: true, src: \''+val+'\',hideAction: \'close\'}).show();" alt="Click to view Process Image"/></center>';
- } else {
- return "<center>Process image not available.</center>";
- }
- }
- }]),
- autoHeight: true
- });
-
- grid.on('afterrender', function(e) {
- if(this.value.length > 0) {
- var index = 0;
- var val = this.value;
- var mygrid = grid;
- calldefs.data.each(function() {
- if(this.data['name'] == val) {
- mygrid.getSelectionModel().select(index, 1);
- }
- index++;
- });
- }
- }.bind(this));
-
- var calledElementsPanel = new Ext.Panel({
- id: 'calledElementsPanel',
- title: '<center>Select Process Id and click "Save" to select.</center>',
- layout:'column',
- items:[
- grid
- ],
- layoutConfig: {
- columns: 1
- },
- defaults: {
- columnWidth: 1.0
- }
- });
-
- var dialog = new Ext.Window({
- layout : 'anchor',
- autoCreate : true,
- title : 'Editor for Called Elements',
- height : 350,
- width : 680,
- modal : true,
- collapsible : false,
- fixedcenter : true,
- shadow : true,
- resizable : true,
- proxyDrag : true,
- autoScroll : true,
- keys:[{
- key : 27,
- fn : function(){
- dialog.hide()
- }.bind(this)
- }],
- items :[calledElementsPanel],
- listeners :{
- hide: function(){
- this.fireEvent('dialogClosed', this.value);
- dialog.destroy();
- }.bind(this)
- },
- buttons : [{
- text: 'Save',
- handler: function(){
- if(grid.getSelectionModel().getSelectedCell() != null) {
- var selectedIndex = grid.getSelectionModel().getSelectedCell()[0];
- var outValue = calldefs.getAt(selectedIndex).data['name'];
- grid.stopEditing();
- grid.getView().refresh();
- this.setValue(outValue);
- this.dataSource.getAt(this.row).set('value', outValue)
- this.dataSource.commitChanges()
- dialog.hide()
- } else {
- Ext.Msg.alert('Please select a process id.');
- }
- }.bind(this)
- }, {
- text: ORYX.I18N.PropertyWindow.cancel,
- handler: function(){
- this.setValue(this.value);
- dialog.hide()
- }.bind(this)
- }]
- });
-
- dialog.show();
- grid.render();
- grid.fireEvent('afterrender');
- this.grid.stopEditing();
- grid.focus( false, 100 );
- } else {
- Ext.Msg.alert('Unable to find other processes in pacakge.');
- }
- } catch(e) {
- Ext.Msg.alert('Error resolving other process info :\n' + e);
- }
- }.bind(this),
- failure: function(){
- loadProcessesMask.hide();
- Ext.Msg.alert('Error resolving other process info.');
- }
- });
- }
- });
- Ext.form.ListenerDefinitionField = Ext.extend(Ext.form.TriggerField, {
- onTriggerClick : function() {
- if(this.disabled){
- return;
- }
-
- var ListenerDef = Ext.data.Record.create([{
- name: 'class'
- }, {
- name: 'expression'
- }, {
- name: 'event'
- }]);
-
- var calldefsProxy = new Ext.data.MemoryProxy({
- root: []
- });
-
- var calldefs = new Ext.data.Store({
- autoDestroy: true,
- reader: new Ext.data.JsonReader({
- root: "root"
- }, ListenerDef),
- proxy: calldefsProxy,
- sorters: [{
- property: 'event',
- direction:'ASC'
- }]
- });
- calldefs.load();
- var gridId = Ext.id();
- var grid = new Ext.grid.EditorGridPanel({
- store: calldefs,
- id: gridId,
- stripeRows: true,
- cm: new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), {
- id: 'pid',
- header: 'Process Id',
- width: 200,
- dataIndex: 'class',
- editor: new Ext.form.TextField({ allowBlank: false, disabled: true })
- }, {
- id: 'revi',
- header: 'Revision',
- width: 200,
- dataIndex: 'expression',
- editor: new Ext.form.TextField({ allowBlank: false, disabled: true })
- },{
- id: 'pim',
- header: 'Process Image',
- width: 250,
- dataIndex: 'event',
- renderer: function(val) {
- if(val && val.length > 0) {
- return '<center><img src="'+ORYX.CONFIG.ROOT_PATH+'images/processimagepreview.png" onclick="new ImageViewer({title: \'Process Image\', width: \'1100\', height: \'900\', autoScroll: true, fixedcenter: true, src: \''+val+'\',hideAction: \'close\'}).show();" alt="Click to view Process Image"/></center>';
- } else {
- return "<center>Process image not available.</center>";
- }
- }
- }]),
- autoHeight: true
- });
- var calledElementsPanel = new Ext.Panel({
- id: 'calledElementsPanel',
- title: '<center>Select Process Id and click "Save" to select.</center>',
- layout:'column',
- items:[
- grid
- ],
- layoutConfig: {
- columns: 1
- },
- defaults: {
- columnWidth: 1.0
- }
- });
- var dialog = new Ext.Window({
- layout : 'anchor',
- autoCreate : true,
- title : 'Editor for Called Elements',
- height : 350,
- width : 680,
- modal : true,
- collapsible : false,
- fixedcenter : true,
- shadow : true,
- resizable : true,
- proxyDrag : true,
- autoScroll : true,
- keys:[{
- key : 27,
- fn : function(){
- dialog.hide()
- }.bind(this)
- }],
- items :[calledElementsPanel],
- listeners :{
- hide: function(){
- this.fireEvent('dialogClosed', this.value);
- dialog.destroy();
- }.bind(this)
- },
- buttons : [{
- text: 'Save',
- handler: function(){
- if(grid.getSelectionModel().getSelectedCell() != null) {
- var selectedIndex = grid.getSelectionModel().getSelectedCell()[0];
- var outValue = calldefs.getAt(selectedIndex).data['name'];
- grid.stopEditing();
- grid.getView().refresh();
- this.setValue(outValue);
- this.dataSource.getAt(this.row).set('value', outValue)
- this.dataSource.commitChanges()
- dialog.hide()
- } else {
- Ext.Msg.alert('Please select a process id.');
- }
- }.bind(this)
- }, {
- text: ORYX.I18N.PropertyWindow.cancel,
- handler: function(){
- this.setValue(this.value);
- dialog.hide()
- }.bind(this)
- }]
- });
- dialog.show();
- grid.render();
- grid.fireEvent('afterrender');
- this.grid.stopEditing();
- grid.focus( false, 100 );
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- /**
- * This plugin is responsible for displaying loading indicators and to prevent
- * the user from accidently unloading the page by, e.g., pressing the backspace
- * button and returning to the previous site in history.
- * @param {Object} facade The editor plugin facade to register enhancements with.
- */
- ORYX.Plugins.Loading = {
- construct: function(facade){
-
- this.facade = facade;
-
- // The parent Node
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.facade.getCanvas().getHTMLContainer().parentNode, ['div', {
- 'class': 'LoadingIndicator'
- }, '']);
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_ENABLE, this.enableLoading.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_DISABLE, this.disableLoading.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADING_STATUS, this.showStatus.bind(this));
-
- this.disableLoading();
- },
-
- enableLoading: function(options){
- if(options.text)
- this.node.innerHTML = options.text + "...";
- else
- this.node.innerHTML = ORYX.I18N.Loading.waiting;
- this.node.removeClassName('StatusIndicator');
- this.node.addClassName('LoadingIndicator');
- this.node.style.display = "block";
-
- var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;
- this.node.style.top = pos.offsetTop + 'px';
- this.node.style.left = pos.offsetLeft +'px';
-
- },
-
- disableLoading: function(){
- this.node.style.display = "none";
- },
-
- showStatus: function(options) {
- if(options.text) {
- this.node.innerHTML = options.text;
- this.node.addClassName('StatusIndicator');
- this.node.removeClassName('LoadingIndicator');
- this.node.style.display = 'block';
- var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode;
- this.node.style.top = pos.offsetTop + 'px';
- this.node.style.left = pos.offsetLeft +'px';
-
- var tout = options.timeout ? options.timeout : 2000;
-
- window.setTimeout((function(){
-
- this.disableLoading();
-
- }).bind(this), tout);
- }
-
- }
- }
- ORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading);
- /**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins) {
- ORYX.Plugins = new Object();
- }
- /**
- * This plugin is responsible for resizing the canvas.
- * @param {Object} facade The editor plugin facade to register enhancements with.
- */
- ORYX.Plugins.CanvasResize = Clazz.extend({
- construct: function(facade){
-
- this.facade = facade;
-
- new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "N", this.resize.bind(this));
- new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "W", this.resize.bind(this));
- new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "E", this.resize.bind(this));
- new ORYX.Plugins.CanvasResizeButton( this.facade.getCanvas(), "S", this.resize.bind(this));
- },
-
- resize: function( position, shrink ){
-
- resizeCanvas = function(position, extentionSize, facade) {
- var canvas = facade.getCanvas();
- var b = canvas.bounds;
- var scrollNode = facade.getCanvas().getHTMLContainer().parentNode.parentNode;
-
- if( position == "E" || position == "W"){
- canvas.setSize({width: (b.width() + extentionSize)*canvas.zoomLevel, height: (b.height())*canvas.zoomLevel})
- } else if( position == "S" || position == "N"){
- canvas.setSize({width: (b.width())*canvas.zoomLevel, height: (b.height() + extentionSize)*canvas.zoomLevel})
- }
- if( position == "N" || position == "W"){
-
- var move = position == "N" ? {x: 0, y: extentionSize}: {x: extentionSize, y: 0 };
- // Move all children
- canvas.getChildNodes(false, function(shape){ shape.bounds.moveBy(move) })
- // Move all dockers, when the edge has at least one docked shape
- var edges = canvas.getChildEdges().findAll(function(edge){ return edge.getAllDockedShapes().length > 0})
- var dockers = edges.collect(function(edge){ return edge.dockers.findAll(function(docker){ return !docker.getDockedShape() })}).flatten();
- dockers.each(function(docker){ docker.bounds.moveBy(move)})
- } else if( position == "S" ){
- scrollNode.scrollTop += extentionSize;
- } else if( position == "E" ){
- scrollNode.scrollLeft += extentionSize;
- }
-
- canvas.update();
- facade.updateSelection();
- }
-
- var commandClass = ORYX.Core.Command.extend({
- construct: function(position, extentionSize, facade){
- this.position = position;
- this.extentionSize = extentionSize;
- this.facade = facade;
- },
- execute: function(){
- resizeCanvas(this.position, this.extentionSize, this.facade);
- },
- rollback: function(){
- resizeCanvas(this.position, -this.extentionSize, this.facade);
- },
- update:function(){
- }
- });
-
- var extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL;
- if(shrink) extentionSize = -extentionSize;
- var command = new commandClass(position, extentionSize, this.facade);
-
- this.facade.executeCommands([command]);
-
- }
-
- });
- ORYX.Plugins.CanvasResizeButton = Clazz.extend({
-
- construct: function(canvas, position, callback){
- this.canvas = canvas;
- var parentNode = canvas.getHTMLContainer().parentNode.parentNode.parentNode;
-
- window.myParent=parentNode
- var scrollNode = parentNode.firstChild;
- var svgRootNode = scrollNode.firstChild.firstChild;
- // The buttons
- var buttonGrow = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parentNode, ['div', { 'class': 'canvas_resize_indicator canvas_resize_indicator_grow' + ' ' + position ,'title':ORYX.I18N.RESIZE.tipGrow+ORYX.I18N.RESIZE[position]}]);
- var buttonShrink = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", parentNode, ['div', { 'class': 'canvas_resize_indicator canvas_resize_indicator_shrink' + ' ' + position ,'title':ORYX.I18N.RESIZE.tipShrink+ORYX.I18N.RESIZE[position]}]);
-
- // Defines a callback which gives back
- // a boolean if the current mouse event
- // is over the particular button area
- var offSetWidth = 60;
- var isOverOffset = function(event){
- if(event.target!=parentNode && event.target!=scrollNode&& event.target!=scrollNode.firstChild&& event.target!=svgRootNode&& event.target!=scrollNode){ return false }
- //if(inCanvas){offSetWidth=30}else{offSetWidth=30*2}
- //Safari work around
- var X=event.layerX !== undefined ? event.layerX : event.offsetX;
- var Y=event.layerY !== undefined ? event.layerY : event.offsetY;
-
- if((X - scrollNode.scrollLeft)<0 ||Ext.isSafari){ X+=scrollNode.scrollLeft;}
- if((Y - scrollNode.scrollTop )<0 ||Ext.isSafari){ Y+=scrollNode.scrollTop ;}
-
- //
- if(position == "N"){
- return Y < offSetWidth+scrollNode.firstChild.offsetTop;
- } else if(position == "W"){
- return X < offSetWidth + scrollNode.firstChild.offsetLeft;
- } else if(position == "E"){
- //other offset
- var offsetRight=(scrollNode.offsetWidth-(scrollNode.firstChild.offsetLeft + scrollNode.firstChild.offsetWidth));
- if(offsetRight<0)offsetRight=0;
- return X > scrollNode.scrollWidth-offsetRight-offSetWidth;
- } else if(position == "S"){
- //other offset
- var offsetDown=(scrollNode.offsetHeight-(scrollNode.firstChild.offsetTop + scrollNode.firstChild.offsetHeight));
- if(offsetDown<0)offsetDown=0;
- return Y > scrollNode.scrollHeight -offsetDown- offSetWidth;
- }
-
- return false;
- }
-
- var showButtons = (function() {
- buttonGrow.show();
-
- var x1, y1, x2, y2;
- try {
- var bb = this.canvas.getRootNode().childNodes[1].getBBox();
- x1 = bb.x;
- y1 = bb.y;
- x2 = bb.x + bb.width;
- y2 = bb.y + bb.height;
- } catch(e) {
- this.canvas.getChildShapes(true).each(function(shape) {
- var absBounds = shape.absoluteBounds();
- var ul = absBounds.upperLeft();
- var lr = absBounds.lowerRight();
- if(x1 == undefined) {
- x1 = ul.x;
- y1 = ul.y;
- x2 = lr.x;
- y2 = lr.y;
- } else {
- x1 = Math.min(x1, ul.x);
- y1 = Math.min(y1, ul.y);
- x2 = Math.max(x2, lr.x);
- y2 = Math.max(y2, lr.y);
- }
- });
- }
-
- var w = canvas.bounds.width();
- var h = canvas.bounds.height();
-
- var isEmpty = canvas.getChildNodes().size()==0;
-
- if(position=="N" && (y1>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL || (isEmpty && h>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL))) buttonShrink.show();
- else if(position=="E" && (w-x2)>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL) buttonShrink.show();
- else if(position=="S" && (h-y2)>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL) buttonShrink.show();
- else if(position=="W" && (x1>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL || (isEmpty && w>ORYX.CONFIG.CANVAS_RESIZE_INTERVAL))) buttonShrink.show();
- else buttonShrink.hide();
- }).bind(this);
-
- var hideButtons = function() {
- buttonGrow.hide();
- buttonShrink.hide();
- }
-
- // If the mouse move is over the button area, show the button
- scrollNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEMOVE, function(event){ if( isOverOffset(event) ){showButtons();} else {hideButtons()}} , false );
- // If the mouse is over the button, show them
- buttonGrow.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true );
- buttonShrink.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true );
- // If the mouse is out, hide the button
- //scrollNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){button.hide()}, true )
- parentNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){hideButtons()} , true );
- //svgRootNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){ inCanvas = false } , true );
-
- // Hide the button initialy
- hideButtons();
- // Add the callbacks
- buttonGrow.addEventListener('click', function(){callback( position ); showButtons();}, true);
- buttonShrink.addEventListener('click', function(){callback( position, true ); showButtons();}, true);
- }
-
- });
- /**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.RenameShapes = Clazz.extend({
- facade: undefined,
-
- construct: function(facade){
-
- this.facade = facade;
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK, this.actOnDBLClick.bind(this));
- this.facade.offer({
- keyCodes: [{
- keyCode: 113, // F2-Key
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.renamePerF2.bind(this)
- });
-
-
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true )
- },
-
- /**
- * This method handles the "F2" key down event. The selected shape are looked
- * up and the editing of title/name of it gets started.
- */
- renamePerF2 : function() {
- var selectedShapes = this.facade.getSelection();
- this.actOnDBLClick(undefined, selectedShapes.first());
- },
-
- actOnDBLClick: function(evt, shape){
- if( !(shape instanceof ORYX.Core.Shape) ){ return }
-
- // Destroys the old input, if there is one
- this.destroy();
-
- // Get all properties which where at least one ref to view is set
- var props = shape.getStencil().properties().findAll(function(item){
- return (item.refToView()
- && item.refToView().length > 0
- && item.directlyEditable());
- });
- // from these, get all properties where write access are and the type is String
- props = props.findAll(function(item){ return !item.readonly() && item.type() == ORYX.CONFIG.TYPE_STRING });
-
- // Get all ref ids
- var allRefToViews = props.collect(function(prop){ return prop.refToView() }).flatten().compact();
- // Get all labels from the shape with the ref ids
- var labels = shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView) }); })
-
- // If there are no referenced labels --> return
- if( labels.length == 0 ){ return }
-
- // Define the nearest label
- var nearestLabel = labels.length <= 1 ? labels[0] : null;
- if( !nearestLabel ){
-
- nearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode })
- if( !nearestLabel ){
-
- var evtCoord = this.facade.eventCoordinates(evt);
- var trans = this.facade.getCanvas().rootNode.lastChild.getScreenCTM();
- evtCoord.x *= trans.a;
- evtCoord.y *= trans.d;
- var diff = labels.collect(function(label){
- var center = this.getCenterPosition( label.node );
- var len = Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));
- return {diff: len, label: label}
- }.bind(this));
-
- diff.sort(function(a, b){ return a.diff > b.diff })
-
- nearestLabel = diff[0].label;
- }
- }
- // Get the particular property for the label
- var prop = props.find(function(item){ return item.refToView().any(function(toView){ return nearestLabel.id == shape.id + toView })});
- // Set all particular config values
- var htmlCont = this.facade.getCanvas().getHTMLContainer().id;
- // Get the center position from the nearest label
- var width = Math.min(Math.max(100, shape.bounds.width()), 200);
- var center = this.getCenterPosition( nearestLabel.node );
- center.x -= (width/2);
- var propId = prop.prefix() + "-" + prop.id();
- // Set the config values for the TextField/Area
- var config = {
- renderTo : htmlCont,
- value : shape.properties[propId],
- x : (center.x < 10) ? 10 : center.x,
- y : center.y,
- width : width,
- style : 'position:absolute',
- allowBlank : prop.optional(),
- maxLength : prop.length(),
- emptyText : prop.title(),
- cls : 'x_form_text_set_absolute'
- }
-
- // Depending on the property, generate
- // ether an TextArea or TextField
- if(prop.wrapLines()) {
-
- config.y -= (60/2);
- config['grow'] = true;
- this.shownTextField = new Ext.form.TextArea(config);
- } else {
-
- config.y -= (20/2);
-
- this.shownTextField = new Ext.form.TextField(config);
- }
-
- //focus
- this.shownTextField.focus();
-
- // Define event handler
- // Blur -> Destroy
- // Change -> Set new values
- this.shownTextField.on( 'blur', this.destroy.bind(this) )
- this.shownTextField.on( 'change', function(node, value){
- var currentEl = shape;
- var oldValue = currentEl.properties[propId];
- var newValue = value;
- var facade = this.facade;
-
- if (oldValue != newValue) {
- // Implement the specific command for property change
- var commandClass = ORYX.Core.Command.extend({
- construct: function(){
- this.el = currentEl;
- this.propId = propId;
- this.oldValue = oldValue;
- this.newValue = newValue;
- this.facade = facade;
- },
- execute: function(){
- this.el.setProperty(this.propId, this.newValue);
- //this.el.update();
- this.facade.setSelection([this.el]);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- },
- rollback: function(){
- this.el.setProperty(this.propId, this.oldValue);
- //this.el.update();
- this.facade.setSelection([this.el]);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- }
- })
- // Instanciated the class
- var command = new commandClass();
-
- // Execute the command
- this.facade.executeCommands([command]);
- }
- }.bind(this) )
- // Diable the keydown in the editor (that when hitting the delete button, the shapes not get deleted)
- this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
-
- },
-
- getCenterPosition: function(svgNode){
-
- if (!svgNode) { return {x:0, y:0} }
-
- var center = {x: 0, y:0 };
- var trans,scale,transLocal,bounds;
- var useParent = false;
- try {
-
- if (('hidden' === svgNode.getAttributeNS(null, 'visibility')&&svgNode.childNodes.length>0)
- ||svgNode.childNodes.length === 0) {
- useParent = true;
- }
-
- var el = useParent ? svgNode.parentNode : svgNode;
-
- trans = el.getTransformToElement(this.facade.getCanvas().rootNode.lastChild);
- scale = this.facade.getCanvas().rootNode.lastChild.getScreenCTM();
- transLocal = el.getTransformToElement(el.parentNode);
- } catch(e){
- return {x:0, y:0}
- }
-
- center.x = trans.e - transLocal.e;
- center.y = trans.f - transLocal.f;
-
-
- try {
- bounds = svgNode.getBBox();
-
- if (!useParent&&!(bounds.x<-1000)) {
- bounds.y -= 1;
- } else {
- bounds = {x:Number(svgNode.getAttribute('x')), y:Number(svgNode.getAttribute('y')), width:0, height:0};
- }
- } catch(e){
- bounds = {x:Number(svgNode.getAttribute('x')), y:Number(svgNode.getAttribute('y')), width:0, height:0};
- }
-
- center.x += bounds.x;
- center.y += bounds.y;
-
- center.x += bounds.width/2;
- center.y += bounds.height/2;
-
- center.x *= scale.a;
- center.y *= scale.d;
-
- return center;
- },
-
- hide: function(e){
- if (this.shownTextField && (!e || !this.shownTextField.el || e.target !== this.shownTextField.el.dom)) {
- this.shownTextField.onBlur();
- }
- },
-
- destroy: function(e){
- if( this.shownTextField ){
- this.shownTextField.destroy();
- delete this.shownTextField;
-
- this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
- }
- }
- });
- /**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * This plugin offer the functionality of undo/redo
- * Therewith the command pattern is used.
- *
- * A Plugin which want that the changes could get undo/redo has
- * to implement a command-class (which implements the method .execute(), .rollback()).
- * Those instance of class must be execute thru the facade.executeCommands(). If so,
- * those command get stored here in the undo/redo stack and can get reset/restore.
- *
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.Undo = Clazz.extend({
-
- // Defines the facade
- facade : undefined,
-
- // Defines the undo/redo Stack
- undoStack : [],
- redoStack : [],
-
- // Constructor
- construct: function(facade){
-
- this.facade = facade;
-
- // Offers the functionality of undo
- this.facade.offer({
- name : ORYX.I18N.Undo.undo,
- description : ORYX.I18N.Undo.undoDesc,
- icon : ORYX.PATH + "images/arrow_undo.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 90,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality : this.doUndo.bind(this),
- group : ORYX.I18N.Undo.group,
- isEnabled : function(){ return this.undoStack.length > 0 }.bind(this),
- index : 0
- });
- // Offers the functionality of redo
- this.facade.offer({
- name : ORYX.I18N.Undo.redo,
- description : ORYX.I18N.Undo.redoDesc,
- icon : ORYX.PATH + "images/arrow_redo.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 89,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality : this.doRedo.bind(this),
- group : ORYX.I18N.Undo.group,
- isEnabled : function(){ return this.redoStack.length > 0 }.bind(this),
- index : 1
- });
-
- // Register on event for executing commands --> store all commands in a stack
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, this.handleExecuteCommands.bind(this) );
-
- },
-
- /**
- * Stores all executed commands in a stack
- *
- * @param {Object} evt
- */
- handleExecuteCommands: function( evt ){
-
- // If the event has commands
- if( !evt.commands ){ return }
-
- // Add the commands to a undo stack ...
- this.undoStack.push( evt.commands );
- // ...and delete the redo stack
- this.redoStack = [];
-
- // Update
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
- },
-
- /**
- * Does the undo
- *
- */
- doUndo: function(){
-
- // Get the last commands
- var lastCommands = this.undoStack.pop();
-
- if( lastCommands ){
- // Add the commands to the redo stack
- this.redoStack.push( lastCommands );
-
- // Rollback every command
- for(var i=lastCommands.length-1; i>=0; --i){
- lastCommands[i].rollback();
- }
-
- // Update and refresh the canvas
- //this.facade.getCanvas().update();
- //this.facade.updateSelection();
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_UNDO_ROLLBACK,
- commands: lastCommands
- });
-
- // Update
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- }
- },
-
- /**
- * Does the redo
- *
- */
- doRedo: function(){
-
- // Get the last commands from the redo stack
- var lastCommands = this.redoStack.pop();
-
- if( lastCommands ){
- // Add this commands to the undo stack
- this.undoStack.push( lastCommands );
-
- // Execute those commands
- lastCommands.each(function(command){
- command.execute();
- });
-
- // Update and refresh the canvas
- //this.facade.getCanvas().update();
- //this.facade.updateSelection();
- this.facade.raiseEvent({
- type : ORYX.CONFIG.EVENT_UNDO_EXECUTE,
- commands: lastCommands
- });
-
- // Update
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- }
- }
-
- });
- /**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- /**
- * Supports EPCs by offering a syntax check and export and import ability..
- *
- *
- */
- ORYX.Plugins.ProcessLink = Clazz.extend({
- facade: undefined,
- /**
- * Offers the plugin functionality:
- *
- */
- construct: function(facade) {
- this.facade = facade;
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this) );
-
- },
- /**
- *
- * @param {Object} option
- */
- propertyChanged: function( option, node){
- if( option.name !== "oryx-refuri" || !node instanceof ORYX.Core.Node ){ return }
-
-
- if( option.value && option.value.length > 0 && option.value != "undefined"){
-
- this.show( node, option.value );
-
- } else {
- this.hide( node );
- }
- },
-
- /**
- * Shows the Link for a particular shape with a specific url
- *
- * @param {Object} shape
- * @param {Object} url
- */
- show: function( shape, url){
-
- // Generate the svg-representation of a link
- var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null ,
- [ 'a',
- {'target': '_blank'},
- ['path',
- { "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"}
- ]
- ]);
- var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null ,
- [ 'a',
- {'target': '_blank'},
- ['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"}],
- ['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"}],
- ['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"}],
- ]);
- /*
- *
- * [ 'a',
- {'target': '_blank'},
- ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M7,4 l0,2"}],
- ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M4,8 l-2,0 l0,6"}],
- ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M10,8 l2,0 l0,6"}],
- ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 0}],
- ['rect', { "style": "fill:#ffafff;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 6}],
- ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 0, "y": 12}],
- ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 8, "y": 12}],
- ['rect', { "style": "fill:none;stroke:none;pointer-events:all", "width": 14, "height": 16, "x": 0, "y": 0}]
- ]);
- */
-
- // Set the link with the special namespace
- link.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url);
-
-
- // Shows the link in the overlay
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_OVERLAY_SHOW,
- id: "arissupport.urlref_" + shape.id,
- shapes: [shape],
- node: link,
- nodePosition: "SE"
- });
-
- },
- /**
- * Hides the Link for a particular shape
- *
- * @param {Object} shape
- */
- hide: function( shape ){
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_OVERLAY_HIDE,
- id: "arissupport.urlref_" + shape.id
- });
-
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- Array.prototype.insertFrom = function(from, to){
- to = Math.max(0, to);
- from = Math.min( Math.max(0, from), this.length-1 );
-
- var el = this[from];
- var old = this.without(el);
- var newA = old.slice(0, to);
- newA.push(el);
- if(old.length > to ){
- newA = newA.concat(old.slice(to))
- };
- return newA;
- }
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({
- facade: undefined,
- construct: function(facade) {
- this.facade = facade;
- // Z-Ordering
- /** Hide for SIGNAVIO
-
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.btf,
- 'functionality': this.setZLevel.bind(this, this.setToTop),
- 'group': ORYX.I18N.Arrangement.groupZ,
- 'icon': ORYX.PATH + "images/shape_move_front.png",
- 'description': ORYX.I18N.Arrangement.btfDesc,
- 'index': 1,
- 'minShape': 1});
-
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.btb,
- 'functionality': this.setZLevel.bind(this, this.setToBack),
- 'group': ORYX.I18N.Arrangement.groupZ,
- 'icon': ORYX.PATH + "images/shape_move_back.png",
- 'description': ORYX.I18N.Arrangement.btbDesc,
- 'index': 2,
- 'minShape': 1});
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.bf,
- 'functionality': this.setZLevel.bind(this, this.setForward),
- 'group': ORYX.I18N.Arrangement.groupZ,
- 'icon': ORYX.PATH + "images/shape_move_forwards.png",
- 'description': ORYX.I18N.Arrangement.bfDesc,
- 'index': 3,
- 'minShape': 1});
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.bb,
- 'functionality': this.setZLevel.bind(this, this.setBackward),
- 'group': ORYX.I18N.Arrangement.groupZ,
- 'icon': ORYX.PATH + "images/shape_move_backwards.png",
- 'description': ORYX.I18N.Arrangement.bbDesc,
- 'index': 4,
- 'minShape': 1});
- // Aligment
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.ab,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_bottom.png",
- 'description': ORYX.I18N.Arrangement.abDesc,
- 'index': 1,
- 'minShape': 2});
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.at,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_top.png",
- 'description': ORYX.I18N.Arrangement.atDesc,
- 'index': 3,
- 'minShape': 2});
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.al,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_left.png",
- 'description': ORYX.I18N.Arrangement.alDesc,
- 'index': 4,
- 'minShape': 2});
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.ar,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_right.png",
- 'description': ORYX.I18N.Arrangement.arDesc,
- 'index': 6,
- 'minShape': 2});
- **/
-
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.am,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_middle.png",
- 'description': ORYX.I18N.Arrangement.amDesc,
- 'index': 1,
- 'minShape': 2});
-
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.ac,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_CENTER]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_center.png",
- 'description': ORYX.I18N.Arrangement.acDesc,
- 'index': 2,
- 'minShape': 2});
-
- this.facade.offer({
- 'name':ORYX.I18N.Arrangement.as,
- 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_SIZE]),
- 'group': ORYX.I18N.Arrangement.groupA,
- 'icon': ORYX.PATH + "images/shape_align_size.png",
- 'description': ORYX.I18N.Arrangement.asDesc,
- 'index': 3,
- 'minShape': 2});
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, this.setZLevel.bind(this, this.setToTop) );
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACK, this.setZLevel.bind(this, this.setToBack) );
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD, this.setZLevel.bind(this, this.setForward) );
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD, this.setZLevel.bind(this, this.setBackward) );
-
- },
-
- onSelectionChanged: function(elemnt){
- var selection = this.facade.getSelection();
- if (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) {
- this.setToTop(selection);
- }
- },
-
- setZLevel:function(callback, event){
-
- //Command-Pattern for dragging one docker
- var zLevelCommand = ORYX.Core.Command.extend({
- construct: function(callback, elements, facade){
- this.callback = callback;
- this.elements = elements;
- // For redo, the previous elements get stored
- this.elAndIndex = elements.map(function(el){ return {el:el, previous:el.parent.children[el.parent.children.indexOf(el)-1]} })
- this.facade = facade;
- },
- execute: function(){
-
- // Call the defined z-order callback with the elements
- this.callback( this.elements )
- this.facade.setSelection( this.elements )
- },
- rollback: function(){
-
- // Sort all elements on the index of there containment
- var sortedEl = this.elAndIndex.sortBy( function( el ) {
- var value = el.el;
- var t = $A(value.node.parentNode.childNodes);
- return t.indexOf(value.node);
- });
-
- // Every element get setted back bevor the old previous element
- for(var i=0; i<sortedEl.length; i++){
- var el = sortedEl[i].el;
- var p = el.parent;
- var oldIndex = p.children.indexOf(el);
- var newIndex = p.children.indexOf(sortedEl[i].previous);
- newIndex = newIndex || 0
- p.children = p.children.insertFrom(oldIndex, newIndex)
- el.node.parentNode.insertBefore(el.node, el.node.parentNode.childNodes[newIndex+1]);
- }
- // Reset the selection
- this.facade.setSelection( this.elements )
- }
- });
-
- // Instanziate the dockCommand
- var command = new zLevelCommand(callback, this.facade.getSelection(), this.facade);
- if( event.excludeCommand ){
- command.execute();
- } else {
- this.facade.executeCommands( [command] );
- }
-
- },
- setToTop: function(elements) {
- // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
- var tmpElem = elements.sortBy( function(value, index) {
- var t = $A(value.node.parentNode.childNodes);
- return t.indexOf(value.node);
- });
- // Sortiertes Array wird nach oben verschoben.
- tmpElem.each( function(value) {
- var p = value.parent;
- if (p.children.last() === value){
- return;
- }
- p.children = p.children.without( value )
- p.children.push(value);
- value.node.parentNode.appendChild(value.node);
- });
- },
- setToBack: function(elements) {
- // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
- var tmpElem = elements.sortBy( function(value, index) {
- var t = $A(value.node.parentNode.childNodes);
- return t.indexOf(value.node);
- });
- tmpElem = tmpElem.reverse();
- // Sortiertes Array wird nach unten verschoben.
- tmpElem.each( function(value) {
- var p = value.parent
- p.children = p.children.without( value )
- p.children.unshift( value );
- value.node.parentNode.insertBefore(value.node, value.node.parentNode.firstChild);
- });
-
-
- },
- setBackward: function(elements) {
- // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
- var tmpElem = elements.sortBy( function(value, index) {
- var t = $A(value.node.parentNode.childNodes);
- return t.indexOf(value.node);
- });
- // Reverse the elements
- tmpElem = tmpElem.reverse();
-
- // Delete all Nodes who are the next Node in the nodes-Array
- var compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.previousSibling})});
-
- // Sortiertes Array wird nach eine Ebene nach oben verschoben.
- compactElem.each( function(el) {
- if(el.node.previousSibling === null) { return; }
- var p = el.parent;
- var index = p.children.indexOf(el);
- p.children = p.children.insertFrom(index, index-1)
- el.node.parentNode.insertBefore(el.node, el.node.previousSibling);
- });
-
-
- },
- setForward: function(elements) {
- // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten.
- var tmpElem = elements.sortBy( function(value, index) {
- var t = $A(value.node.parentNode.childNodes);
- return t.indexOf(value.node);
- });
- // Delete all Nodes who are the next Node in the nodes-Array
- var compactElem = tmpElem.findAll(function(el) {return !tmpElem.some(function(checkedEl){ return checkedEl.node == el.node.nextSibling})});
-
-
- // Sortiertes Array wird eine Ebene nach unten verschoben.
- compactElem.each( function(el) {
- var nextNode = el.node.nextSibling
- if(nextNode === null) { return; }
- var index = el.parent.children.indexOf(el);
- var p = el.parent;
- p.children = p.children.insertFrom(index, index+1)
- el.node.parentNode.insertBefore(nextNode, el.node);
- });
- },
- alignShapes: function(way) {
- var elements = this.facade.getSelection();
- // Set the elements to all Top-Level elements
- elements = this.facade.getCanvas().getShapesWithSharedParent(elements);
- // Get only nodes
- elements = elements.findAll(function(value) {
- return (value instanceof ORYX.Core.Node)
- });
- // Delete all attached intermediate events from the array
- elements = elements.findAll(function(value) {
- var d = value.getIncomingShapes()
- return d.length == 0 || !elements.include(d[0])
- });
- if(elements.length < 2) { return; }
- // get bounds of all shapes.
- var bounds = elements[0].absoluteBounds().clone();
- elements.each(function(shape) {
- bounds.include(shape.absoluteBounds().clone());
- });
-
- // get biggest width and heigth
- var maxWidth = 0;
- var maxHeight = 0;
- elements.each(function(shape){
- maxWidth = Math.max(shape.bounds.width(), maxWidth);
- maxHeight = Math.max(shape.bounds.height(), maxHeight);
- });
- var commandClass = ORYX.Core.Command.extend({
- construct: function(elements, bounds, maxHeight, maxWidth, way, plugin){
- this.elements = elements;
- this.bounds = bounds;
- this.maxHeight = maxHeight;
- this.maxWidth = maxWidth;
- this.way = way;
- this.facade = plugin.facade;
- this.plugin = plugin;
- this.orgPos = [];
- },
- setBounds: function(shape, maxSize) {
- if(!maxSize)
- maxSize = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};
- if(!shape.bounds) { throw "Bounds not definined." }
-
- var newBounds = {
- a: {x: shape.bounds.upperLeft().x - (this.maxWidth - shape.bounds.width())/2,
- y: shape.bounds.upperLeft().y - (this.maxHeight - shape.bounds.height())/2},
- b: {x: shape.bounds.lowerRight().x + (this.maxWidth - shape.bounds.width())/2,
- y: shape.bounds.lowerRight().y + (this.maxHeight - shape.bounds.height())/2}
- }
-
- /* If the new width of shape exceeds the maximum width, set width value to maximum. */
- if(this.maxWidth > maxSize.width) {
- newBounds.a.x = shape.bounds.upperLeft().x -
- (maxSize.width - shape.bounds.width())/2;
-
- newBounds.b.x = shape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width())/2
- }
-
- /* If the new height of shape exceeds the maximum height, set height value to maximum. */
- if(this.maxHeight > maxSize.height) {
- newBounds.a.y = shape.bounds.upperLeft().y -
- (maxSize.height - shape.bounds.height())/2;
-
- newBounds.b.y = shape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height())/2
- }
-
- /* set bounds of shape */
- shape.bounds.set(newBounds);
-
- },
- execute: function(){
- // align each shape according to the way that was specified.
- this.elements.each(function(shape, index) {
- this.orgPos[index] = shape.bounds.upperLeft();
-
- var relBounds = this.bounds.clone();
- var newCoordinates;
- if (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas) ) {
- var upL = shape.parent.absoluteBounds().upperLeft();
- relBounds.moveBy(-upL.x, -upL.y);
- }
-
- switch (this.way) {
- // align the shapes in the requested way.
- case ORYX.CONFIG.EDITOR_ALIGN_BOTTOM:
- newCoordinates = {
- x: shape.bounds.upperLeft().x,
- y: relBounds.b.y - shape.bounds.height()
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE:
- newCoordinates = {
- x: shape.bounds.upperLeft().x,
- y: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_TOP:
- newCoordinates = {
- x: shape.bounds.upperLeft().x,
- y: relBounds.a.y
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_LEFT:
- newCoordinates = {
- x: relBounds.a.x,
- y: shape.bounds.upperLeft().y
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_CENTER:
- newCoordinates = {
- x: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2,
- y: shape.bounds.upperLeft().y
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_RIGHT:
- newCoordinates = {
- x: relBounds.b.x - shape.bounds.width(),
- y: shape.bounds.upperLeft().y
- }; break;
-
- case ORYX.CONFIG.EDITOR_ALIGN_SIZE:
- if(shape.isResizable) {
- this.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()};
- this.setBounds(shape, shape.maximumSize);
- }
- break;
- }
-
- if (newCoordinates){
- var offset = {
- x: shape.bounds.upperLeft().x - newCoordinates.x,
- y: shape.bounds.upperLeft().y - newCoordinates.y
- }
- // Set the new position
- shape.bounds.moveTo(newCoordinates);
- this.plugin.layoutEdges(shape, shape.getAllDockedShapes(),offset);
- //shape.update()
- }
- }.bind(this));
-
- //this.facade.getCanvas().update();
- //this.facade.updateSelection();
- },
- rollback: function(){
- this.elements.each(function(shape, index) {
- if (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) {
- if(shape.isResizable) {shape.bounds.set(this.orgPos[index]);}
- } else {shape.bounds.moveTo(this.orgPos[index]);}
- }.bind(this));
-
- //this.facade.getCanvas().update();
- //this.facade.updateSelection();
- }
- })
-
- var command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this);
-
- this.facade.executeCommands([command]);
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.Save = Clazz.extend({
-
- facade: undefined,
-
- processURI: undefined,
-
- changeSymbol : "*",
-
- construct: function(facade){
- this.facade = facade;
-
- this.facade.offer({
- 'name': ORYX.I18N.Save.save,
- 'functionality': this.save.bind(this,false),
- 'group': ORYX.I18N.Save.group,
- 'icon': ORYX.PATH + "images/disk.png",
- 'description': ORYX.I18N.Save.saveDesc,
- 'index': 1,
- 'minShape': 0,
- 'maxShape': 0,
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 83, // s-Keycode
- keyAction: ORYX.CONFIG.KEY_ACTION_UP
- }
- ]
- });
-
- document.addEventListener("keydown", function(e){
- if (e.ctrlKey&&e.keyCode === 83){
- Event.stop(e);
- }
- }, false)
-
-
- /*this.facade.offer({
- 'name': ORYX.I18N.Save.saveAs,
- 'functionality': this.save.bind(this,true),
- 'group': ORYX.I18N.Save.group,
- 'icon': ORYX.PATH + "images/disk_multi.png",
- 'description': ORYX.I18N.Save.saveAsDesc,
- 'index': 2,
- 'minShape': 0,
- 'maxShape': 0
- }); */
-
- window.onbeforeunload = this.onUnLoad.bind(this)
-
- this.changeDifference = 0;
-
- // Register on event for executing commands --> store all commands in a stack
- // --> Execute
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_EXECUTE, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, function(){ this.changeDifference++; this.updateTitle(); }.bind(this) );
- // --> Rollback
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function(){ this.changeDifference--; this.updateTitle(); }.bind(this) );
-
- //TODO very critical for load time performance!!!
- //this.serializedDOM = DataManager.__persistDOM(this.facade);
- },
-
- updateTitle: function(){
-
- var value = window.document.title || document.getElementsByTagName("title")[0].childNodes[0].nodeValue;
-
- if (this.changeDifference === 0 && value.startsWith(this.changeSymbol)){
- window.document.title = value.slice(1);
- } else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)){
- window.document.title = this.changeSymbol + "" + value;
- }
- },
-
- onUnLoad: function(){
- if(this.changeDifference !== 0 || (this.facade.getModelMetaData()['new'] && this.facade.getCanvas().getChildShapes().size() > 0)) {
- return ORYX.I18N.Save.unsavedData;
- }
-
- },
-
-
- saveSynchronously: function(forceNew, modelInfo){
-
- if (!modelInfo) {
- return;
- }
-
- var modelMeta = this.facade.getModelMetaData();
- var reqURI = modelMeta.modelHandler;
- // Get the stencilset
- var ss = this.facade.getStencilSets().values()[0]
-
- var typeTitle = ss.title();
-
- // Define Default values
- var name = (modelMeta["new"] && modelMeta.name === "") ? ORYX.I18N.Save.newProcess : modelInfo.name;
- var defaultData = {title:Signavio.Utils.escapeHTML(name||""), summary:Signavio.Utils.escapeHTML(modelInfo.description||""), type:typeTitle, url: reqURI, namespace: modelInfo.model.stencilset.namespace, comment: '' }
-
- // Create a Template
- var dialog = new Ext.XTemplate(
- // TODO find some nice words here -- copy from above ;)
- '<form class="oryx_repository_edit_model" action="#" id="edit_model" onsubmit="return false;">',
-
- '<fieldset>',
- '<p class="description">' + ORYX.I18N.Save.dialogDesciption + '</p>',
- '<input type="hidden" name="namespace" value="{namespace}" />',
- '<p><label for="edit_model_title">' + ORYX.I18N.Save.dialogLabelTitle + '</label><input type="text" class="text" name="title" value="{title}" id="edit_model_title" onfocus="this.className = \'text activated\'" onblur="this.className = \'text\'"/></p>',
- '<p><label for="edit_model_summary">' + ORYX.I18N.Save.dialogLabelDesc + '</label><textarea rows="5" name="summary" id="edit_model_summary" onfocus="this.className = \'activated\'" onblur="this.className = \'\'">{summary}</textarea></p>',
- (modelMeta.versioning) ? '<p><label for="edit_model_comment">' + ORYX.I18N.Save.dialogLabelComment + '</label><textarea rows="5" name="comment" id="edit_model_comment" onfocus="this.className = \'activated\'" onblur="this.className = \'\'">{comment}</textarea></p>' : '',
- '<p><label for="edit_model_type">' + ORYX.I18N.Save.dialogLabelType + '</label><input type="text" name="type" class="text disabled" value="{type}" disabled="disabled" id="edit_model_type" /></p>',
-
- '</fieldset>',
-
- '</form>')
-
- // Create the callback for the template
- callback = function(form){
- // raise loading enable event
- /*this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_ENABLE,
- text: ORYX.I18N.Save.saving
- });*/
- var title = form.elements["title"].value.strip();
- title = title.length == 0 ? defaultData.title : title;
-
- var summary = form.elements["summary"].value.strip();
- summary = summary.length == 0 ? defaultData.summary : summary;
-
- var namespace = form.elements["namespace"].value.strip();
- namespace = namespace.length == 0 ? defaultData.namespace : namespace;
-
- modelMeta.name = title;
- modelMeta.description = summary;
- modelMeta.parent = modelInfo.parent;
- modelMeta.namespace = namespace;
-
- //added changing title of page after first save, but with the changed flag
- if(!forceNew) window.document.title = this.changeSymbol + title + " | " + ORYX.CONFIG.APPNAME;
-
-
- // Get json
- var json = this.facade.getJSON();
-
- var glossary = [];
-
- //Support for glossary
- if (this.facade.hasGlossaryExtension) {
-
- Ext.apply(json, ORYX.Core.AbstractShape.JSONHelper);
- var allNodes = json.getChildShapes(true);
-
- var orders = {};
-
- this.facade.getGlossary().each(function(entry){
- if ("undefined" == typeof orders[entry.shape.resourceId+"-"+entry.property.prefix()+"-"+entry.property.id()]){
- orders[entry.shape.resourceId+"-"+entry.property.prefix()+"-"+entry.property.id()] = 0;
- }
- // Add entry
- glossary.push({
- itemId : entry.glossary,
- elementId : entry.shape.resourceId,
- propertyId : entry.property.prefix()+"-"+entry.property.id(),
- order : orders[entry.shape.resourceId+"-"+entry.property.prefix()+"-"+entry.property.id()]++
- });
-
- // Replace the property with the generated glossary url
- /*var rId = entry.shape.resourceId;
- var pKe = entry.property.id();
- for (var i=0, size=allNodes.length; i<size; ++i) {
- var sh = allNodes[i];
- if (sh.resourceId == rId) {
- for (var prop in sh.properties) {
- if (prop === pKe) {
- sh.properties[prop] = this.facade.generateGlossaryURL(entry.glossary, sh.properties[prop]);
- break;
- }
- }
- break;
- }
- }*/
-
-
- // Replace SVG
- if (entry.property.refToView() && entry.property.refToView().length > 0) {
- entry.property.refToView().each(function(ref){
- var node = $(entry.shape.id+""+ref);
- if (node)
- node.setAttribute("oryx:glossaryIds", entry.glossary + ";")
- })
- }
- }.bind(this))
-
- // Set the json as string
- json = json.serialize();
- } else {
- json = Ext.encode(json);
- }
-
- // Set the glossaries as string
- glossary = Ext.encode(glossary);
-
- var selection = this.facade.getSelection();
- this.facade.setSelection([]);
- // Get the serialized svg image source
- var svgClone = this.facade.getCanvas().getSVGRepresentation(true);
- this.facade.setSelection(selection);
- if (this.facade.getCanvas().properties["oryx-showstripableelements"] === false) {
- var stripOutArray = svgClone.getElementsByClassName("stripable-element");
- for (var i=stripOutArray.length-1; i>=0; i--) {
- stripOutArray[i].parentNode.removeChild(stripOutArray[i]);
- }
- }
-
- // Remove all forced stripable elements
- var stripOutArray = svgClone.getElementsByClassName("stripable-element-force");
- for (var i=stripOutArray.length-1; i>=0; i--) {
- stripOutArray[i].parentNode.removeChild(stripOutArray[i]);
- }
-
- // Parse dom to string
- var svgDOM = DataManager.serialize(svgClone);
-
- var params = {
- json_xml: json,
- svg_xml: svgDOM,
- name: title,
- type: defaultData.type,
- parent: modelMeta.parent,
- description: summary,
- glossary_xml: glossary,
- namespace: modelMeta.namespace,
- views: Ext.util.JSON.encode(modelMeta.views || [])
- };
-
- var success = false;
-
- var successFn = function(transport) {
- var loc = transport.getResponseHeader.location;
- if (!this.processURI && loc) {
- this.processURI = loc;
- }
-
- if( forceNew ){
- var resJSON = transport.responseText.evalJSON();
-
- var modelURL = location.href.substring(0, location.href.indexOf(location.search)) + '?id=' + resJSON.href.substring(7);
- var newURLWin = new Ext.Window({
- title: ORYX.I18N.Save.savedAs,
- bodyStyle: "background:white;padding:10px",
- width: 'auto',
- height: 'auto',
- html:"<div style='font-weight:bold;margin-bottom:10px'>"+ORYX.I18N.Save.savedDescription+":</div><span><a href='" + modelURL +"' target='_blank'>" + modelURL + "</a></span>",
- buttons:[{text:'Ok',handler:function(){newURLWin.destroy()}}]
- });
- newURLWin.show();
-
- window.open(modelURL);
- }
-
- //show saved status
- /*this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_LOADING_STATUS,
- text:ORYX.I18N.Save.saved
- });*/
-
- success = true;
-
- win.close();
-
- if (success) {
- // Reset changes
- this.changeDifference = 0;
- this.updateTitle();
-
- var resJSON = transport.responseText.evalJSON();
- if(resJSON.modelId) {
- modelMeta.modelId = resJSON.modelId;
- }
-
- if(modelMeta["new"]) {
- modelMeta["new"] = false;
- }
- }
-
-
- delete this.saving;
-
- }.bind(this);
-
- var failure = function(transport) {
- // raise loading disable event.
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_DISABLE
- });
-
- win.close();
-
- if(transport.status && transport.status === 401) {
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.notAuthorized).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).center().syncSize();
- } else if(transport.status && transport.status === 403) {
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.noRights).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).center().syncSize();
- } else if(transport.statusText === "transaction aborted") {
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.transAborted).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).center().syncSize();
- } else if(transport.statusText === "communication failure") {
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.comFailed).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).center().syncSize();
- } else {
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.failed).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).center().syncSize();
- }
-
- delete this.saving;
-
- }.bind(this);
-
- if(modelMeta["new"]) {
- // Send the request out
- params.id = modelMeta.modelId;
- this.sendSaveRequest('POST', reqURI, params, true, successFn, failure);
- } else if(forceNew) {
- this.sendSaveRequest('POST', reqURI, params, true, successFn, failure);
- } else {
- params.id = modelMeta.modelId;
- // Send the request out
- this.sendSaveRequest('PUT', reqURI, params, false, successFn, failure);
- }
- }.bind(this);
-
- // Create a new window
- win = new Ext.Window({
- id : 'Propertie_Window',
- width : 'auto',
- height : 'auto',
- title : forceNew ? ORYX.I18N.Save.saveAsTitle : ORYX.I18N.Save.save,
- modal : true,
- resize : false,
- bodyStyle: 'background:#FFFFFF',
- html : dialog.apply( defaultData ),
- defaultButton: 0,
- buttons:[{
- text: ORYX.I18N.Save.saveBtn,
- handler: function(){
-
- win.body.mask(ORYX.I18N.Save.pleaseWait, "x-waiting-box");
-
- window.setTimeout(function(){
-
- callback($('edit_model'));
-
- }.bind(this), 10);
- },
- listeners:{
- render:function(){
- this.focus();
- }
- }
- },{
- text: ORYX.I18N.Save.close,
- handler: function(){
- win.close();
- }.bind(this)
- }],
- listeners: {
- close: function(){
- win.destroy();
- delete this.saving;
- }.bind(this)
- }
- });
-
- win.show();
- },
-
- /**
- * Get the model data and call the success callback
- *
- * @param {Function} success Success callback
- */
- retrieveModelData: function(success){
-
- var onComplete = function(){
- Ext.getBody().unmask();
- }
-
- var modelMeta = this.facade.getModelMetaData();
-
- new Ajax.Request("../service/model/" + modelMeta.modelId + "/json", {
- method: 'get',
- asynchronous: true,
- requestHeaders: {
- "Accept":"application/json"
- },
- encoding: 'UTF-8',
- onSuccess: (function(transport) {
- modelInfo = (transport.responseText||"{}").evalJSON();
- onComplete();
- success(modelInfo);
- }).bind(this),
- onException: function(){
- // raise loading disable event.
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_DISABLE
- });
- delete this.saving;
- onComplete();
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.exception).setIcon(Ext.Msg.ERROR).getDialog().setWidth(260).syncSize();
- }.bind(this),
- onFailure: (function(transport) {
- // raise loading disable event.
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_DISABLE
- });
-
- delete this.saving;
- onComplete();
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.failed).setIcon(Ext.Msg.ERROR).getDialog().setWidth(260).syncSize();
- }).bind(this),
- on401: (function(transport) {
- // raise loading disable event.
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_DISABLE
- });
-
- delete this.saving;
- onComplete();
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.notAuthorized).setIcon(Ext.Msg.WARNING).getDialog().setWidth(260).syncSize();
- }).bind(this),
- on403: (function(transport) {
- // raise loading disable event.
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_LOADING_DISABLE
- });
-
- delete this.saving;
- onComplete();
- Ext.Msg.alert(ORYX.I18N.Oryx.title, ORYX.I18N.Save.noRights).setIcon(Ext.Msg.ERROR).getDialog().setWidth(260).syncSize();
- }).bind(this)
- });
- },
-
- sendSaveRequest: function(method, url, params, forceNew, success, failure){
-
- var saveUri;
- if(forceNew == false) {
- saveUri = "../service/model/" + params.id + "/save";
- } else {
- saveUri = "../service/model/new";
- }
-
- // Send the request to the server.
- Ext.Ajax.request({
- url : saveUri,
- method : method,
- timeout : 1800000,
- disableCaching : true,
- headers : {'Accept':"application/json", 'Content-Type':'charset=UTF-8'},
- params : params,
- success : success,
- failure : failure
- });
- },
-
- /**
- * Saves the current process to the server.
- */
- save: function(forceNew, event){
-
- // Check if currently is saving
- if (this.saving){
- return;
- }
-
- this.saving = true;
-
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_ABOUT_TO_SAVE
- });
-
- // ... save synchronously
- window.setTimeout((function(){
-
- var meta = this.facade.getModelMetaData();
- // Check if new...
- if (meta["new"]){
- this.saveSynchronously(forceNew, meta);
- } else {
- Ext.getBody().mask(ORYX.I18N.Save.retrieveData, "x-waiting-box");
- // ...otherwise, get the current model data first.
- this.retrieveModelData(this.saveSynchronously.bind(this, forceNew))
- }
- }).bind(this), 10);
-
- return true;
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- /**
- * @namespace Oryx name space for plugins
- * @name ORYX.Plugins
- */
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- /**
- * The view plugin offers all of zooming functionality accessible over the
- * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model.
- *
- * @class ORYX.Plugins.View
- * @extends Clazz
- * @param {Object} facade The editor facade for plugins.
- */
- ORYX.Plugins.View = {
- /** @lends ORYX.Plugins.View.prototype */
- facade: undefined,
- construct: function(facade, ownPluginData) {
- this.facade = facade;
- //Standard Values
- this.zoomLevel = 1.0;
- this.maxFitToScreenLevel=1.5;
- this.minZoomLevel = 0.1;
- this.maxZoomLevel = 2.5;
- this.diff=5; //difference between canvas and view port, s.th. like toolbar??
-
- //Read properties
- ownPluginData.properties.each( function(property) {
- if (property.zoomLevel) {this.zoomLevel = Number(1.0);}
- if (property.maxFitToScreenLevel) {this.maxFitToScreenLevel=Number(property.maxFitToScreenLevel);}
- if (property.minZoomLevel) {this.minZoomLevel = Number(property.minZoomLevel);}
- if (property.maxZoomLevel) {this.maxZoomLevel = Number(property.maxZoomLevel);}
- }.bind(this));
-
- /* Register zoom in */
- this.facade.offer({
- 'name':ORYX.I18N.View.zoomIn,
- 'functionality': this.zoom.bind(this, [1.0 + ORYX.CONFIG.ZOOM_OFFSET]),
- 'group': ORYX.I18N.View.group,
- 'icon': ORYX.PATH + "images/magnifier_zoom_in.png",
- 'description': ORYX.I18N.View.zoomInDesc,
- 'index': 1,
- 'minShape': 0,
- 'maxShape': 0,
- 'isEnabled': function(){return this.zoomLevel < this.maxZoomLevel }.bind(this)});
-
- /* Register zoom out */
- this.facade.offer({
- 'name':ORYX.I18N.View.zoomOut,
- 'functionality': this.zoom.bind(this, [1.0 - ORYX.CONFIG.ZOOM_OFFSET]),
- 'group': ORYX.I18N.View.group,
- 'icon': ORYX.PATH + "images/magnifier_zoom_out.png",
- 'description': ORYX.I18N.View.zoomOutDesc,
- 'index': 2,
- 'minShape': 0,
- 'maxShape': 0,
- 'isEnabled': function(){ return this._checkSize() }.bind(this)});
-
- /* Register zoom standard */
- this.facade.offer({
- 'name':ORYX.I18N.View.zoomStandard,
- 'functionality': this.setAFixZoomLevel.bind(this, 1),
- 'group': ORYX.I18N.View.group,
- 'icon': ORYX.PATH + "images/zoom_standard.png",
- 'cls' : 'icon-large',
- 'description': ORYX.I18N.View.zoomStandardDesc,
- 'index': 3,
- 'minShape': 0,
- 'maxShape': 0,
- 'isEnabled': function(){return this.zoomLevel != 1}.bind(this)
- });
-
- /* Register zoom fit to model */
- this.facade.offer({
- 'name':ORYX.I18N.View.zoomFitToModel,
- 'functionality': this.zoomFitToModel.bind(this),
- 'group': ORYX.I18N.View.group,
- 'icon': ORYX.PATH + "images/image.png",
- 'description': ORYX.I18N.View.zoomFitToModelDesc,
- 'index': 4,
- 'minShape': 0,
- 'maxShape': 0
- });
- },
-
- /**
- * It sets the zoom level to a fix value and call the zooming function.
- *
- * @param {Number} zoomLevel
- * the zoom level
- */
- setAFixZoomLevel : function(zoomLevel) {
- this.zoomLevel = zoomLevel;
- this._checkZoomLevelRange();
- this.zoom(1);
- },
-
- /**
- * It does the actual zooming. It changes the viewable size of the canvas
- * and all to its child elements.
- *
- * @param {Number} factor
- * the factor to adjust the zoom level
- */
- zoom: function(factor) {
- // TODO: Zoomen auf allen Objekten im SVG-DOM
-
- this.zoomLevel *= factor;
- var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;
- var canvas = this.facade.getCanvas();
- var newWidth = canvas.bounds.width() * this.zoomLevel;
- var newHeight = canvas.bounds.height() * this.zoomLevel;
-
- /* Set new top offset */
- var offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0;
- offsetTop = offsetTop > 20 ? offsetTop - 20 : 0;
- canvas.node.parentNode.parentNode.style.marginTop = offsetTop + "px";
- offsetTop += 5;
- canvas.getHTMLContainer().style.top = offsetTop + "px";
-
- /*readjust scrollbar*/
- var newScrollTop= scrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight()-newHeight) / 2)+this.diff;
- var newScrollLeft= scrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth()-newWidth) / 2)+this.diff;
-
- /* Set new Zoom-Level */
- canvas.setSize({width: newWidth, height: newHeight}, true);
-
- /* Set Scale-Factor */
- canvas.node.setAttributeNS(null, "transform", "scale(" +this.zoomLevel+ ")");
- /* Refresh the Selection */
- this.facade.updateSelection();
- scrollNode.scrollTop=newScrollTop;
- scrollNode.scrollLeft=newScrollLeft;
-
- /* Update the zoom-level*/
- canvas.zoomLevel = this.zoomLevel;
- },
-
-
- /**
- * It calculates the zoom level to fit whole model into the visible area
- * of the canvas. Than the model gets zoomed and the position of the
- * scroll bars are adjusted.
- *
- */
- zoomFitToModel: function() {
-
- /* Get the size of the visible area of the canvas */
- var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode;
- var visibleHeight = scrollNode.getHeight() - 30;
- var visibleWidth = scrollNode.getWidth() - 30;
-
- var nodes = this.facade.getCanvas().getChildShapes();
-
- if(!nodes || nodes.length < 1) {
- return false;
- }
-
- /* Calculate size of canvas to fit the model */
- var bounds = nodes[0].absoluteBounds().clone();
- nodes.each(function(node) {
- bounds.include(node.absoluteBounds().clone());
- });
-
-
- /* Set new Zoom Level */
- var scaleFactorWidth = visibleWidth / bounds.width();
- var scaleFactorHeight = visibleHeight / bounds.height();
-
- /* Choose the smaller zoom level to fit the whole model */
- var zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth;
-
- /*Test if maximum zoom is reached*/
- if(zoomFactor>this.maxFitToScreenLevel){zoomFactor=this.maxFitToScreenLevel}
- /* Do zooming */
- this.setAFixZoomLevel(zoomFactor);
-
- /* Set scroll bar position */
- scrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5;
- scrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5;
-
- },
-
- /**
- * It checks if the zoom level is less or equal to the level, which is required
- * to schow the whole canvas.
- *
- * @private
- */
- _checkSize:function(){
- var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;
- var minForCanvas= Math.min((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));
- return 1.05 > minForCanvas;
-
- },
- /**
- * It checks if the zoom level is included in the definined zoom
- * level range.
- *
- * @private
- */
- _checkZoomLevelRange: function() {
- /*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode;
- var maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight()));
- if(this.zoomLevel > maxForCanvas) {
- this.zoomLevel = maxForCanvas;
- }*/
- if(this.zoomLevel < this.minZoomLevel) {
- this.zoomLevel = this.minZoomLevel;
- }
-
- if(this.zoomLevel > this.maxZoomLevel) {
- this.zoomLevel = this.maxZoomLevel;
- }
- }
- };
- ORYX.Plugins.View = Clazz.extend(ORYX.Plugins.View);
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({
- /**
- * Constructor
- * @param {Object} Facade: The Facade of the Editor
- */
- construct: function(facade) {
- this.facade = facade;
- // Initialize variables
- this.currentShapes = []; // Current selected Shapes
- //this.pluginsData = []; // Available Plugins
- this.toMoveShapes = []; // Shapes there will be moved
- this.distPoints = []; // Distance Points for Snap on Grid
- this.isResizing = false; // Flag: If there was currently resized
- this.dragEnable = false; // Flag: If Dragging is enabled
- this.dragIntialized = false; // Flag: If the Dragging is initialized
- this.edgesMovable = true; // Flag: If an edge is docked it is not movable
- this.offSetPosition = {x: 0, y: 0}; // Offset of the Dragging
- this.faktorXY = {x: 1, y: 1}; // The Current Zoom-Faktor
- this.containmentParentNode; // the current future parent node for the dragged shapes
- this.isAddingAllowed = false; // flag, if adding current selected shapes to containmentParentNode is allowed
- this.isAttachingAllowed = false; // flag, if attaching to the current shape is allowed
-
- this.callbackMouseMove = this.handleMouseMove.bind(this);
- this.callbackMouseUp = this.handleMouseUp.bind(this);
-
- // Get the SVG-Containernode
- var containerNode = this.facade.getCanvas().getSvgContainer();
-
- // Create the Selected Rectangle in the SVG
- this.selectedRect = new ORYX.Plugins.SelectedRect(containerNode);
-
- // Show grid line if enabled
- if (ORYX.CONFIG.SHOW_GRIDLINE) {
- this.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL);
- this.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL);
- }
-
- // Get a HTML-ContainerNode
- containerNode = this.facade.getCanvas().getHTMLContainer();
-
- this.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;
-
- // Create the southeastern button for resizing
- this.resizerSE = new ORYX.Plugins.Resizer(containerNode, "southeast", this.facade);
- this.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback
- this.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback
- this.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback
-
- // Create the northwestern button for resizing
- this.resizerNW = new ORYX.Plugins.Resizer(containerNode, "northwest", this.facade);
- this.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback
- this.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback
- this.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback
-
- // For the Drag and Drop
- // Register on MouseDown-Event on a Shape
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
- },
- /**
- * On Mouse Down
- *
- */
- handleMouseDown: function(event, uiObj) {
- // If the selection Bounds not intialized and the uiObj is not member of current selectio
- // then return
- if(!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) {return};
-
- // Start Dragging
- this.dragEnable = true;
- this.dragIntialized = true;
- this.edgesMovable = true;
- // Calculate the current zoom factor
- var a = this.facade.getCanvas().node.getScreenCTM();
- this.faktorXY.x = a.a;
- this.faktorXY.y = a.d;
- // Set the offset position of dragging
- var upL = this.dragBounds.upperLeft();
- this.offSetPosition = {
- x: Event.pointerX(event) - (upL.x * this.faktorXY.x),
- y: Event.pointerY(event) - (upL.y * this.faktorXY.y)};
-
- this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
-
- // Register on Global Mouse-MOVE Event
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);
- // Register on Global Mouse-UP Event
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);
- return;
- },
- /**
- * On Key Mouse Up
- *
- */
- handleMouseUp: function(event) {
-
- //disable containment highlighting
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId:"dragdropresize.contain"
- });
-
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId:"dragdropresize.attached"
- });
- // If Dragging is finished
- if(this.dragEnable) {
-
- // and update the current selection
- if(!this.dragIntialized) {
-
- // Do Method after Dragging
- this.afterDrag();
-
- // Check if the Shape is allowed to dock to the other Shape
- if ( this.isAttachingAllowed &&
- this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node &&
- this.toMoveShapes[0].dockers.length > 0) {
-
- // Get the position and the docker
- var position = this.facade.eventCoordinates( event );
- var docker = this.toMoveShapes[0].dockers[0];
-
- //Command-Pattern for dragging several Shapes
- var dockCommand = ORYX.Core.Command.extend({
- construct: function(docker, position, newDockedShape, facade){
- this.docker = docker;
- this.newPosition = position;
- this.newDockedShape = newDockedShape;
- this.newParent = newDockedShape.parent || facade.getCanvas();
- this.oldPosition = docker.parent.bounds.center();
- this.oldDockedShape = docker.getDockedShape();
- this.oldParent = docker.parent.parent || facade.getCanvas();
- this.facade = facade;
-
- if( this.oldDockedShape ){
- this.oldPosition = docker.parent.absoluteBounds().center();
- }
-
- },
- execute: function(){
- this.dock( this.newDockedShape, this.newParent, this.newPosition );
-
- // Raise Event for having the docked shape on top of the other shape
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true})
- },
- rollback: function(){
- this.dock( this.oldDockedShape, this.oldParent, this.oldPosition );
- },
- dock:function( toDockShape, parent, pos ){
- // Add to the same parent Shape
- parent.add( this.docker.parent )
-
-
- // Set the Docker to the new Shape
- this.docker.setDockedShape( undefined );
- this.docker.bounds.centerMoveTo( pos )
- this.docker.setDockedShape( toDockShape );
- //this.docker.update();
-
- this.facade.setSelection( [this.docker.parent] );
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
-
- }
- });
-
- // Instanziate the dockCommand
- var commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)];
- this.facade.executeCommands(commands);
-
-
- // Check if adding is allowed to the other Shape
- } else if( this.isAddingAllowed ) {
-
-
- // Refresh all Shapes --> Set the new Bounds
- this.refreshSelectedShapes();
-
- }
-
- this.facade.updateSelection();
-
- //this.currentShapes.each(function(shape) {shape.update()})
- // Raise Event: Dragging is finished
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END});
- }
- if (this.vLine)
- this.vLine.hide();
- if (this.hLine)
- this.hLine.hide();
- }
- // Disable
- this.dragEnable = false;
-
- // UnRegister on Global Mouse-UP/-Move Event
- document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true);
- document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false);
-
- return;
- },
- /**
- * On Key Mouse Move
- *
- */
- handleMouseMove: function(event) {
- // If dragging is not enabled, go return
- if(!this.dragEnable) { return };
- // If Dragging is initialized
- if(this.dragIntialized) {
- // Raise Event: Drag will be started
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START});
- this.dragIntialized = false;
-
- // And hide the resizers and the highlighting
- this.resizerSE.hide();
- this.resizerNW.hide();
-
- // if only edges are selected, containmentParentNode must be the canvas
- this._onlyEdges = this.currentShapes.all(function(currentShape) {
- return (currentShape instanceof ORYX.Core.Edge);
- });
-
- // /* If only edges are selected, check if they are movable. An Edge is
- // * movable in case it is not docked
- // */
- // if(this._onlyEdges) {
- // this.currentShapes.each(function(edge) {
- // if(edge.isDocked()) {
- // this.edgesMovable = false;
- // throw $break;
- // }
- // }.bind(this));
- // }
-
- // Do method before Drag
- this.beforeDrag();
-
- this._currentUnderlyingNodes = [];
-
- }
-
- // Calculate the new position
- var position = {
- x: Event.pointerX(event) - this.offSetPosition.x,
- y: Event.pointerY(event) - this.offSetPosition.y}
- position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
- position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
-
- // If not the Control-Key are pressed
- var modifierKeyPressed = event.shiftKey || event.ctrlKey;
- if(ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) {
- // Snap the current position to the nearest Snap-Point
- position = this.snapToGrid(position);
- } else {
- if (this.vLine)
- this.vLine.hide();
- if (this.hLine)
- this.hLine.hide();
- }
- // Adjust the point by the zoom faktor
- position.x /= this.faktorXY.x;
- position.y /= this.faktorXY.y;
- // Set that the position is not lower than zero
- position.x = Math.max( 0 , position.x)
- position.y = Math.max( 0 , position.y)
- // Set that the position is not bigger than the canvas
- var c = this.facade.getCanvas();
- position.x = Math.min( c.bounds.width() - this.dragBounds.width(), position.x)
- position.y = Math.min( c.bounds.height() - this.dragBounds.height(), position.y)
-
- // Drag this bounds
- this.dragBounds.moveTo(position);
- // Update all selected shapes and the selection rectangle
- //this.refreshSelectedShapes();
- this.resizeRectangle(this.dragBounds);
- this.isAttachingAllowed = false;
- //check, if a node can be added to the underlying node
- var underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(this.facade.eventCoordinates(event)));
-
- var checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0
- checkIfAttachable = checkIfAttachable && underlyingNodes.length != 1
-
-
- if( !checkIfAttachable &&
- underlyingNodes.length === this._currentUnderlyingNodes.length &&
- underlyingNodes.all(function(node, index){return this._currentUnderlyingNodes[index] === node}.bind(this))) {
-
- return
-
- } else if(this._onlyEdges) {
-
- this.isAddingAllowed = true;
- this.containmentParentNode = this.facade.getCanvas();
-
- } else {
-
- /* Check the containment and connection rules */
- var options = {
- event : event,
- underlyingNodes : underlyingNodes,
- checkIfAttachable : checkIfAttachable
- };
- this.checkRules(options);
-
- }
-
- this._currentUnderlyingNodes = underlyingNodes.reverse();
-
- //visualize the containment result
- if( this.isAttachingAllowed ) {
-
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId: "dragdropresize.attached",
- elements: [this.containmentParentNode],
- style: ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE,
- color: ORYX.CONFIG.SELECTION_VALID_COLOR
- });
-
- } else {
-
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId:"dragdropresize.attached"
- });
- }
-
- if( !this.isAttachingAllowed ){
- if( this.isAddingAllowed ) {
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:"dragdropresize.contain",
- elements:[this.containmentParentNode],
- color: ORYX.CONFIG.SELECTION_VALID_COLOR
- });
- } else {
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:"dragdropresize.contain",
- elements:[this.containmentParentNode],
- color: ORYX.CONFIG.SELECTION_INVALID_COLOR
- });
- }
- } else {
- this.facade.raiseEvent({
- type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE,
- highlightId:"dragdropresize.contain"
- });
- }
- // Stop the Event
- //Event.stop(event);
- return;
- },
-
- // /**
- // * Rollbacks the docked shape of an edge, if the edge is not movable.
- // */
- // redockEdges: function() {
- // this._undockedEdgesCommand.dockers.each(function(el){
- // el.docker.setDockedShape(el.dockedShape);
- // el.docker.setReferencePoint(el.refPoint);
- // })
- // },
-
- /**
- * Checks the containment and connection rules for the selected shapes.
- */
- checkRules : function(options) {
- var event = options.event;
- var underlyingNodes = options.underlyingNodes;
- var checkIfAttachable = options.checkIfAttachable;
- var noEdges = options.noEdges;
-
- //get underlying node that is not the same than one of the currently selected shapes or
- // a child of one of the selected shapes with the highest z Order.
- // The result is a shape or the canvas
- this.containmentParentNode = underlyingNodes.reverse().find((function(node) {
- return (node instanceof ORYX.Core.Canvas) ||
- (((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges))
- && (!(this.currentShapes.member(node) ||
- this.currentShapes.any(function(shape) {
- return (shape.children.length > 0 && shape.getChildNodes(true).member(node));
- }))));
- }).bind(this));
-
- if( checkIfAttachable ){
-
- this.isAttachingAllowed = this.facade.getRules().canConnect({
- sourceShape: this.containmentParentNode,
- edgeShape: this.toMoveShapes[0],
- targetShape: this.toMoveShapes[0]
- });
-
- if ( this.isAttachingAllowed ) {
- var point = this.facade.eventCoordinates(event);
- this.isAttachingAllowed = this.containmentParentNode.isPointOverOffset( point.x, point.y );
- }
- }
-
- if( !this.isAttachingAllowed ){
- //check all selected shapes, if they can be added to containmentParentNode
- this.isAddingAllowed = this.toMoveShapes.all((function(currentShape) {
- if(currentShape instanceof ORYX.Core.Edge ||
- currentShape instanceof ORYX.Core.Controls.Docker ||
- this.containmentParentNode === currentShape.parent) {
- return true;
- } else if(this.containmentParentNode !== currentShape) {
-
- if(!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) {
-
- if(this.facade.getRules().canContain({containingShape:this.containmentParentNode,
- containedShape:currentShape})) {
- return true;
- }
- }
- }
- return false;
- }).bind(this));
- }
-
- if(!this.isAttachingAllowed && !this.isAddingAllowed &&
- (this.containmentParentNode instanceof ORYX.Core.Edge)) {
- options.noEdges = true;
- options.underlyingNodes.reverse();
- this.checkRules(options);
- }
- },
-
- /**
- * Redraw the selected Shapes.
- *
- */
- refreshSelectedShapes: function() {
- // If the selection bounds not initialized, return
- if(!this.dragBounds) {return}
- // Calculate the offset between the bounds and the old bounds
- var upL = this.dragBounds.upperLeft();
- var oldUpL = this.oldDragBounds.upperLeft();
- var offset = {
- x: upL.x - oldUpL.x,
- y: upL.y - oldUpL.y };
- // Instanciate the dragCommand
- var commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)];
- // If the undocked edges command is setted, add this command
- if( this._undockedEdgesCommand instanceof ORYX.Core.Command ){
- commands.unshift( this._undockedEdgesCommand );
- }
- // Execute the commands
- this.facade.executeCommands( commands );
- // copy the bounds to the old bounds
- if( this.dragBounds )
- this.oldDragBounds = this.dragBounds.clone();
- },
-
- /**
- * Callback for Resize
- *
- */
- onResize: function(bounds) {
- // If the selection bounds not initialized, return
- if(!this.dragBounds) {return}
-
- this.dragBounds = bounds;
- this.isResizing = true;
- // Update the rectangle
- this.resizeRectangle(this.dragBounds);
- },
-
- onResizeStart: function() {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_START});
- },
- onResizeEnd: function() {
-
- if (!(this.currentShapes instanceof Array)||this.currentShapes.length<=0) {
- return;
- }
-
- // If Resizing finished, the Shapes will be resize
- if(this.isResizing) {
-
- var commandClass = ORYX.Core.Command.extend({
- construct: function(shape, newBounds, plugin){
- this.shape = shape;
- this.oldBounds = shape.bounds.clone();
- this.newBounds = newBounds;
- this.plugin = plugin;
- },
- execute: function(){
- this.shape.bounds.set(this.newBounds.a, this.newBounds.b);
- this.update(this.getOffset(this.oldBounds, this.newBounds));
-
- },
- rollback: function(){
- this.shape.bounds.set(this.oldBounds.a, this.oldBounds.b);
- this.update(this.getOffset(this.newBounds, this.oldBounds))
- },
-
- getOffset:function(b1, b2){
- return {
- x: b2.a.x - b1.a.x,
- y: b2.a.y - b1.a.y,
- xs: b2.width()/b1.width(),
- ys: b2.height()/b1.height()
- }
- },
- update:function(offset){
- this.shape.getLabels().each(function(label) {
- label.changed();
- });
-
- var allEdges = [].concat(this.shape.getIncomingShapes())
- .concat(this.shape.getOutgoingShapes())
- // Remove all edges which are included in the selection from the list
- .findAll(function(r){ return r instanceof ORYX.Core.Edge }.bind(this))
-
- this.plugin.layoutEdges(this.shape, allEdges, offset);
- this.plugin.facade.setSelection([this.shape]);
- this.plugin.facade.getCanvas().update();
- this.plugin.facade.updateSelection();
- }
- });
-
- var bounds = this.dragBounds.clone();
- var shape = this.currentShapes[0];
-
- if(shape.parent) {
- var parentPosition = shape.parent.absoluteXY();
- bounds.moveBy(-parentPosition.x, -parentPosition.y);
- }
-
- var command = new commandClass(shape, bounds, this);
-
- this.facade.executeCommands([command]);
-
- this.isResizing = false;
-
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END});
- }
- },
-
- /**
- * Prepare the Dragging
- *
- */
- beforeDrag: function(){
- var undockEdgeCommand = ORYX.Core.Command.extend({
- construct: function(moveShapes){
- this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();
- },
- execute: function(){
- this.dockers.each(function(el){
- el.docker.setDockedShape(undefined);
- })
- },
- rollback: function(){
- this.dockers.each(function(el){
- el.docker.setDockedShape(el.dockedShape);
- el.docker.setReferencePoint(el.refPoint);
- //el.docker.update();
- })
- }
- });
-
- this._undockedEdgesCommand = new undockEdgeCommand( this.toMoveShapes );
- this._undockedEdgesCommand.execute();
-
- },
- hideAllLabels: function(shape) {
-
- // Hide all labels from the shape
- shape.getLabels().each(function(label) {
- label.hide();
- });
- // Hide all labels from docked shapes
- shape.getAllDockedShapes().each(function(dockedShape) {
- var labels = dockedShape.getLabels();
- if(labels.length > 0) {
- labels.each(function(label) {
- label.hide();
- });
- }
- });
- // Do this recursive for all child shapes
- // EXP-NICO use getShapes
- shape.getChildren().each((function(value) {
- if(value instanceof ORYX.Core.Shape)
- this.hideAllLabels(value);
- }).bind(this));
- },
- /**
- * Finished the Dragging
- *
- */
- afterDrag: function(){
-
- },
- /**
- * Show all Labels at these shape
- *
- */
- showAllLabels: function(shape) {
- // Show the label of these shape
- //shape.getLabels().each(function(label) {
- for(var i=0; i<shape.length ;i++){
- var label = shape[i];
- label.show();
- }//);
- // Show all labels at docked shapes
- //shape.getAllDockedShapes().each(function(dockedShape) {
- var allDockedShapes = shape.getAllDockedShapes()
- for(var i=0; i<allDockedShapes.length ;i++){
- var dockedShape = allDockedShapes[i];
- var labels = dockedShape.getLabels();
- if(labels.length > 0) {
- labels.each(function(label) {
- label.show();
- });
- }
- }//);
- // Do this recursive
- //shape.children.each((function(value) {
- for(var i=0; i<shape.children.length ;i++){
- var value = shape.children[i];
- if(value instanceof ORYX.Core.Shape)
- this.showAllLabels(value);
- }//).bind(this));
- },
- /**
- * Intialize Method, if there are new Plugins
- *
- */
- /*registryChanged: function(pluginsData) {
- // Save all new Plugin, sorted by group and index
- this.pluginsData = pluginsData.sortBy( function(value) {
- return (value.group + "" + value.index);
- });
- },*/
- /**
- * On the Selection-Changed
- *
- */
- onSelectionChanged: function(event) {
- var elements = event.elements;
-
- // Reset the drag-variables
- this.dragEnable = false;
- this.dragIntialized = false;
- this.resizerSE.hide();
- this.resizerNW.hide();
- // If there is no elements
- if(!elements || elements.length == 0) {
- // Hide all things and reset all variables
- this.selectedRect.hide();
- this.currentShapes = [];
- this.toMoveShapes = [];
- this.dragBounds = undefined;
- this.oldDragBounds = undefined;
- } else {
- // Set the current Shapes
- this.currentShapes = elements;
- // Get all shapes with the highest parent in object hierarchy (canvas is the top most parent)
- var topLevelElements = this.facade.getCanvas().getShapesWithSharedParent(elements);
- this.toMoveShapes = topLevelElements;
-
- this.toMoveShapes = this.toMoveShapes.findAll( function(shape) { return shape instanceof ORYX.Core.Node &&
- (shape.dockers.length === 0 || !elements.member(shape.dockers.first().getDockedShape()))});
-
- elements.each((function(shape){
- if(!(shape instanceof ORYX.Core.Edge)) {return}
-
- var dks = shape.getDockers()
-
- var hasF = elements.member(dks.first().getDockedShape());
- var hasL = elements.member(dks.last().getDockedShape());
-
- // if(!hasL) {
- // this.toMoveShapes.push(dks.last());
- // }
- // if(!hasF){
- // this.toMoveShapes.push(dks.first())
- // }
- /* Enable movement of undocked edges */
- if(!hasF && !hasL) {
- var isUndocked = !dks.first().getDockedShape() && !dks.last().getDockedShape()
- if(isUndocked) {
- this.toMoveShapes = this.toMoveShapes.concat(dks);
- }
- }
-
- if( shape.dockers.length > 2 && hasF && hasL){
- this.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function(el,index){ return index > 0 && index < dks.length-1}))
- }
-
- }).bind(this));
-
- // Calculate the new area-bounds of the selection
- var newBounds = undefined;
- this.toMoveShapes.each(function(value) {
- var shape = value;
- if(value instanceof ORYX.Core.Controls.Docker) {
- /* Get the Shape */
- shape = value.parent;
- }
-
- if(!newBounds){
- newBounds = shape.absoluteBounds();
- }
- else {
- newBounds.include(shape.absoluteBounds());
- }
- }.bind(this));
-
- if(!newBounds){
- elements.each(function(value){
- if(!newBounds) {
- newBounds = value.absoluteBounds();
- } else {
- newBounds.include(value.absoluteBounds());
- }
- });
- }
-
- // Set the new bounds
- this.dragBounds = newBounds;
- this.oldDragBounds = newBounds.clone();
- // Update and show the rectangle
- this.resizeRectangle(newBounds);
- this.selectedRect.show();
-
- // Show the resize button, if there is only one element and this is resizeable
- if(elements.length == 1 && elements[0].isResizable) {
- var aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined;
- this.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);
- this.resizerSE.show();
- this.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio);
- this.resizerNW.show();
- } else {
- this.resizerSE.setBounds(undefined);
- this.resizerNW.setBounds(undefined);
- }
- // If Snap-To-Grid is enabled, the Snap-Point will be calculate
- if(ORYX.CONFIG.GRID_ENABLED) {
- // Reset all points
- this.distPoints = [];
- if (this.distPointTimeout)
- window.clearTimeout(this.distPointTimeout)
-
- this.distPointTimeout = window.setTimeout(function(){
- // Get all the shapes, there will consider at snapping
- // Consider only those elements who shares the same parent element
- var distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function(value){
- var parentShape = value.parent;
- while(parentShape){
- if(elements.member(parentShape)) return false;
- parentShape = parentShape.parent
- }
- return true;
- })
-
- // The current selection will delete from this array
- //elements.each(function(shape) {
- // distShapes = distShapes.without(shape);
- //});
- // For all these shapes
- distShapes.each((function(value) {
- if(!(value instanceof ORYX.Core.Edge)) {
- var ul = value.absoluteXY();
- var width = value.bounds.width();
- var height = value.bounds.height();
- // Add the upperLeft, center and lowerRight - Point to the distancePoints
- this.distPoints.push({
- ul: {
- x: ul.x,
- y: ul.y
- },
- c: {
- x: ul.x + (width / 2),
- y: ul.y + (height / 2)
- },
- lr: {
- x: ul.x + width,
- y: ul.y + height
- }
- });
- }
- }).bind(this));
-
- }.bind(this), 10)
- }
- }
- },
- /**
- * Adjust an Point to the Snap Points
- *
- */
- snapToGrid: function(position) {
- // Get the current Bounds
- var bounds = this.dragBounds;
-
- var point = {};
- var ulThres = 6;
- var cThres = 10;
- var lrThres = 6;
- var scale = this.vLine ? this.vLine.getScale() : 1;
-
- var ul = { x: (position.x/scale), y: (position.y/scale)};
- var c = { x: (position.x/scale) + (bounds.width()/2), y: (position.y/scale) + (bounds.height()/2)};
- var lr = { x: (position.x/scale) + (bounds.width()), y: (position.y/scale) + (bounds.height())};
- var offsetX, offsetY;
- var gridX, gridY;
-
- // For each distant point
- this.distPoints.each(function(value) {
- var x, y, gx, gy;
- if (Math.abs(value.c.x-c.x) < cThres){
- x = value.c.x-c.x;
- gx = value.c.x;
- }/* else if (Math.abs(value.ul.x-ul.x) < ulThres){
- x = value.ul.x-ul.x;
- gx = value.ul.x;
- } else if (Math.abs(value.lr.x-lr.x) < lrThres){
- x = value.lr.x-lr.x;
- gx = value.lr.x;
- } */
-
- if (Math.abs(value.c.y-c.y) < cThres){
- y = value.c.y-c.y;
- gy = value.c.y;
- }/* else if (Math.abs(value.ul.y-ul.y) < ulThres){
- y = value.ul.y-ul.y;
- gy = value.ul.y;
- } else if (Math.abs(value.lr.y-lr.y) < lrThres){
- y = value.lr.y-lr.y;
- gy = value.lr.y;
- } */
- if (x !== undefined) {
- offsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX);
- if (offsetX === x)
- gridX = gx;
- }
- if (y !== undefined) {
- offsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY);
- if (offsetY === y)
- gridY = gy;
- }
- });
-
-
- if (offsetX !== undefined) {
- ul.x += offsetX;
- ul.x *= scale;
- if (this.vLine&&gridX)
- this.vLine.update(gridX);
- } else {
- ul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE/2)));
- if (this.vLine)
- this.vLine.hide()
- }
-
- if (offsetY !== undefined) {
- ul.y += offsetY;
- ul.y *= scale;
- if (this.hLine&&gridY)
- this.hLine.update(gridY);
- } else {
- ul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE/2)));
- if (this.hLine)
- this.hLine.hide();
- }
-
- return ul;
- },
-
- showGridLine: function(){
-
- },
- /**
- * Redraw of the Rectangle of the SelectedArea
- * @param {Object} bounds
- */
- resizeRectangle: function(bounds) {
- // Resize the Rectangle
- this.selectedRect.resize(bounds);
- }
- });
- ORYX.Plugins.SelectedRect = Clazz.extend({
- construct: function(parentId) {
- this.parentId = parentId;
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", $(parentId),
- ['g']);
- this.dashedArea = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
- ['rect', {x: 0, y: 0,
- 'stroke-width': 1, stroke: '#777777', fill: 'none',
- 'stroke-dasharray': '2,2',
- 'pointer-events': 'none'}]);
- this.hide();
- },
- hide: function() {
- this.node.setAttributeNS(null, 'display', 'none');
- },
- show: function() {
- this.node.setAttributeNS(null, 'display', '');
- },
- resize: function(bounds) {
- var upL = bounds.upperLeft();
- var padding = ORYX.CONFIG.SELECTED_AREA_PADDING;
- this.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2*padding);
- this.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2*padding);
- this.node.setAttributeNS(null, 'transform', "translate("+ (upL.x - padding) +", "+ (upL.y - padding) +")");
- }
- });
- ORYX.Plugins.GridLine = Clazz.extend({
-
- construct: function(parentId, direction) {
- if (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) {
- direction = ORYX.Plugins.GridLine.DIR_HORIZONTAL
- }
-
-
- this.parent = $(parentId);
- this.direction = direction;
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parent,
- ['g']);
- this.line = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
- ['path', {
- 'stroke-width': 1, stroke: 'silver', fill: 'none',
- 'stroke-dasharray': '5,5',
- 'pointer-events': 'none'}]);
- this.hide();
- },
- hide: function() {
- this.node.setAttributeNS(null, 'display', 'none');
- },
- show: function() {
- this.node.setAttributeNS(null, 'display', '');
- },
- getScale: function(){
- try {
- return this.parent.parentNode.transform.baseVal.getItem(0).matrix.a;
- } catch(e) {
- return 1;
- }
- },
-
- update: function(pos) {
-
- if (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) {
- var y = pos instanceof Object ? pos.y : pos;
- var cWidth = this.parent.parentNode.parentNode.width.baseVal.value/this.getScale();
- this.line.setAttributeNS(null, 'd', 'M 0 '+y+ ' L '+cWidth+' '+y);
- } else {
- var x = pos instanceof Object ? pos.x : pos;
- var cHeight = this.parent.parentNode.parentNode.height.baseVal.value/this.getScale();
- this.line.setAttributeNS(null, 'd', 'M'+x+ ' 0 L '+x+' '+cHeight);
- }
-
- this.show();
- }
- });
- ORYX.Plugins.GridLine.DIR_HORIZONTAL = "hor";
- ORYX.Plugins.GridLine.DIR_VERTICAL = "ver";
- ORYX.Plugins.Resizer = Clazz.extend({
- construct: function(parentId, orientation, facade) {
- this.parentId = parentId;
- this.orientation = orientation;
- this.facade = facade;
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $(this.parentId),
- ['div', {'class': 'resizer_'+ this.orientation, style:'left:0px; top:0px;'}]);
- this.node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this), true);
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.handleMouseMove.bind(this), false);
- this.dragEnable = false;
- this.offSetPosition = {x: 0, y: 0};
- this.bounds = undefined;
- this.canvasNode = this.facade.getCanvas().node;
- this.minSize = undefined;
- this.maxSize = undefined;
-
- this.aspectRatio = undefined;
- this.resizeCallbacks = [];
- this.resizeStartCallbacks = [];
- this.resizeEndCallbacks = [];
- this.hide();
-
- // Calculate the Offset
- this.scrollNode = this.node.parentNode.parentNode.parentNode;
- },
- handleMouseDown: function(event) {
- this.dragEnable = true;
- this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop};
-
- this.offSetPosition = {
- x: Event.pointerX(event) - this.position.x,
- y: Event.pointerY(event) - this.position.y};
-
- this.resizeStartCallbacks.each((function(value) {
- value(this.bounds);
- }).bind(this));
- },
- handleMouseUp: function(event) {
- this.dragEnable = false;
- this.containmentParentNode = null;
- this.resizeEndCallbacks.each((function(value) {
- value(this.bounds);
- }).bind(this));
-
- },
- handleMouseMove: function(event) {
- if(!this.dragEnable) { return }
-
- if(event.shiftKey || event.ctrlKey) {
- this.aspectRatio = this.bounds.width() / this.bounds.height();
- } else {
- this.aspectRatio = undefined;
- }
- var position = {
- x: Event.pointerX(event) - this.offSetPosition.x,
- y: Event.pointerY(event) - this.offSetPosition.y}
- position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft;
- position.y -= this.offsetScroll.y - this.scrollNode.scrollTop;
-
- position.x = Math.min( position.x, this.facade.getCanvas().bounds.width())
- position.y = Math.min( position.y, this.facade.getCanvas().bounds.height())
-
- var offset = {
- x: position.x - this.position.x,
- y: position.y - this.position.y
- }
-
- if(this.aspectRatio) {
- // fixed aspect ratio
- newAspectRatio = (this.bounds.width()+offset.x) / (this.bounds.height()+offset.y);
- if(newAspectRatio>this.aspectRatio) {
- offset.x = this.aspectRatio * (this.bounds.height()+offset.y) - this.bounds.width();
- } else if(newAspectRatio<this.aspectRatio) {
- offset.y = (this.bounds.width()+offset.x) / this.aspectRatio - this.bounds.height();
- }
- }
-
- // respect minimum and maximum sizes of stencil
- if(this.orientation==="northwest") {
- if(this.bounds.width()-offset.x > this.maxSize.width) {
- offset.x = -(this.maxSize.width - this.bounds.width());
- if(this.aspectRatio)
- offset.y = this.aspectRatio * offset.x;
- }
- if(this.bounds.width()-offset.x < this.minSize.width) {
- offset.x = -(this.minSize.width - this.bounds.width());
- if(this.aspectRatio)
- offset.y = this.aspectRatio * offset.x;
- }
- if(this.bounds.height()-offset.y > this.maxSize.height) {
- offset.y = -(this.maxSize.height - this.bounds.height());
- if(this.aspectRatio)
- offset.x = offset.y / this.aspectRatio;
- }
- if(this.bounds.height()-offset.y < this.minSize.height) {
- offset.y = -(this.minSize.height - this.bounds.height());
- if(this.aspectRatio)
- offset.x = offset.y / this.aspectRatio;
- }
- } else { // defaults to southeast
- if(this.bounds.width()+offset.x > this.maxSize.width) {
- offset.x = this.maxSize.width - this.bounds.width();
- if(this.aspectRatio)
- offset.y = this.aspectRatio * offset.x;
- }
- if(this.bounds.width()+offset.x < this.minSize.width) {
- offset.x = this.minSize.width - this.bounds.width();
- if(this.aspectRatio)
- offset.y = this.aspectRatio * offset.x;
- }
- if(this.bounds.height()+offset.y > this.maxSize.height) {
- offset.y = this.maxSize.height - this.bounds.height();
- if(this.aspectRatio)
- offset.x = offset.y / this.aspectRatio;
- }
- if(this.bounds.height()+offset.y < this.minSize.height) {
- offset.y = this.minSize.height - this.bounds.height();
- if(this.aspectRatio)
- offset.x = offset.y / this.aspectRatio;
- }
- }
- if(this.orientation==="northwest") {
- var oldLR = {x: this.bounds.lowerRight().x, y: this.bounds.lowerRight().y};
- this.bounds.extend({x:-offset.x, y:-offset.y});
- this.bounds.moveBy(offset);
- } else { // defaults to southeast
- this.bounds.extend(offset);
- }
- this.update();
- this.resizeCallbacks.each((function(value) {
- value(this.bounds);
- }).bind(this));
- Event.stop(event);
- },
-
- registerOnResizeStart: function(callback) {
- if(!this.resizeStartCallbacks.member(callback)) {
- this.resizeStartCallbacks.push(callback);
- }
- },
-
- unregisterOnResizeStart: function(callback) {
- if(this.resizeStartCallbacks.member(callback)) {
- this.resizeStartCallbacks = this.resizeStartCallbacks.without(callback);
- }
- },
- registerOnResizeEnd: function(callback) {
- if(!this.resizeEndCallbacks.member(callback)) {
- this.resizeEndCallbacks.push(callback);
- }
- },
-
- unregisterOnResizeEnd: function(callback) {
- if(this.resizeEndCallbacks.member(callback)) {
- this.resizeEndCallbacks = this.resizeEndCallbacks.without(callback);
- }
- },
-
- registerOnResize: function(callback) {
- if(!this.resizeCallbacks.member(callback)) {
- this.resizeCallbacks.push(callback);
- }
- },
- unregisterOnResize: function(callback) {
- if(this.resizeCallbacks.member(callback)) {
- this.resizeCallbacks = this.resizeCallbacks.without(callback);
- }
- },
- hide: function() {
- this.node.style.display = "none";
- },
- show: function() {
- if(this.bounds)
- this.node.style.display = "";
- },
- setBounds: function(bounds, min, max, aspectRatio) {
- this.bounds = bounds;
- if(!min)
- min = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE};
- if(!max)
- max = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE};
- this.minSize = min;
- this.maxSize = max;
-
- this.aspectRatio = aspectRatio;
- this.update();
- },
- update: function() {
- if(!this.bounds) { return; }
- var upL = this.bounds.upperLeft();
- if(this.bounds.width() < this.minSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height())};
- if(this.bounds.height() < this.minSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height)};
- if(this.bounds.width() > this.maxSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height())};
- if(this.bounds.height() > this.maxSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height)};
- var a = this.canvasNode.getScreenCTM();
-
- upL.x *= a.a;
- upL.y *= a.d;
-
- if(this.orientation==="northwest") {
- upL.x -= 13;
- upL.y -= 26;
- } else { // defaults to southeast
- upL.x += (a.a * this.bounds.width()) + 3 ;
- upL.y += (a.d * this.bounds.height()) + 3;
- }
-
- this.position = upL;
- this.node.style.left = this.position.x + "px";
- this.node.style.top = this.position.y + "px";
- }
- });
- /**
- * Implements a Command to move shapes
- *
- */
- ORYX.Core.Command.Move = ORYX.Core.Command.extend({
- construct: function(moveShapes, offset, parent, selectedShapes, plugin){
- this.moveShapes = moveShapes;
- this.selectedShapes = selectedShapes;
- this.offset = offset;
- this.plugin = plugin;
- // Defines the old/new parents for the particular shape
- this.newParents = moveShapes.collect(function(t){ return parent || t.parent });
- this.oldParents = moveShapes.collect(function(shape){ return shape.parent });
- 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} });
- },
- execute: function(){
- this.dockAllShapes()
- // Moves by the offset
- this.move( this.offset);
- // Addes to the new parents
- this.addShapeToParent( this.newParents );
- // Set the selection to the current selection
- this.selectCurrentShapes();
- this.plugin.facade.getCanvas().update();
- this.plugin.facade.updateSelection();
- },
- rollback: function(){
- // Moves by the inverted offset
- var offset = { x:-this.offset.x, y:-this.offset.y };
- this.move( offset );
- // Addes to the old parents
- this.addShapeToParent( this.oldParents );
- this.dockAllShapes(true)
-
- // Set the selection to the current selection
- this.selectCurrentShapes();
- this.plugin.facade.getCanvas().update();
- this.plugin.facade.updateSelection();
-
- },
- move:function(offset, doLayout){
-
- // Move all Shapes by these offset
- for(var i=0; i<this.moveShapes.length ;i++){
- var value = this.moveShapes[i];
- value.bounds.moveBy(offset);
-
- if (value instanceof ORYX.Core.Node) {
-
- (value.dockers||[]).each(function(d){
- d.bounds.moveBy(offset);
- })
-
- // Update all Dockers of Child shapes
- /*var childShapesNodes = value.getChildShapes(true).findAll(function(shape){ return shape instanceof ORYX.Core.Node });
- var childDockedShapes = childShapesNodes.collect(function(shape){ return shape.getAllDockedShapes() }).flatten().uniq();
- var childDockedEdge = childDockedShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Edge });
- childDockedEdge = childDockedEdge.findAll(function(shape){ return shape.getAllDockedShapes().all(function(dsh){ return childShapesNodes.include(dsh) }) });
- var childDockedDockers = childDockedEdge.collect(function(shape){ return shape.dockers }).flatten();
-
- for (var j = 0; j < childDockedDockers.length; j++) {
- var docker = childDockedDockers[j];
- if (!docker.getDockedShape() && !this.moveShapes.include(docker)) {
- //docker.bounds.moveBy(offset);
- //docker.update();
- }
- }*/
-
-
- var allEdges = [].concat(value.getIncomingShapes())
- .concat(value.getOutgoingShapes())
- // Remove all edges which are included in the selection from the list
- .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))
- // Remove all edges which are between the node and a node contained in the selection from the list
- .findAll(function(r){ return (r.dockers.first().getDockedShape() == value || !this.moveShapes.include(r.dockers.first().getDockedShape())) &&
- (r.dockers.last().getDockedShape() == value || !this.moveShapes.include(r.dockers.last().getDockedShape()))}.bind(this))
-
- // Layout all outgoing/incoming edges
- this.plugin.layoutEdges(value, allEdges, offset);
-
-
- var allSameEdges = [].concat(value.getIncomingShapes())
- .concat(value.getOutgoingShapes())
- // Remove all edges which are included in the selection from the list
- .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))
- // Remove all edges which are included in the selection from the list
- .findAll(function(r){ return this.moveShapes.indexOf(r.dockers.first().getDockedShape()) > i || this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i}.bind(this))
- for (var j = 0; j < allSameEdges.length; j++) {
- for (var k = 1; k < allSameEdges[j].dockers.length-1; k++) {
- var docker = allSameEdges[j].dockers[k];
- if (!docker.getDockedShape() && !this.moveShapes.include(docker)) {
- docker.bounds.moveBy(offset);
- }
- }
- }
-
- /*var i=-1;
- var nodes = value.getChildShapes(true);
- var allEdges = [];
- while(++i<nodes.length){
- var edges = [].concat(nodes[i].getIncomingShapes())
- .concat(nodes[i].getOutgoingShapes())
- // Remove all edges which are included in the selection from the list
- .findAll(function(r){ return r instanceof ORYX.Core.Edge && !allEdges.include(r) && r.dockers.any(function(d){ return !value.bounds.isIncluded(d.bounds.center)})})
- allEdges = allEdges.concat(edges);
- if (edges.length <= 0){ continue }
- //this.plugin.layoutEdges(nodes[i], edges, offset);
- }*/
- }
- }
-
- },
- dockAllShapes: function(shouldDocked){
- // Undock all Nodes
- for (var i = 0; i < this.dockedNodes.length; i++) {
- var docker = this.dockedNodes[i].docker;
-
- docker.setDockedShape( shouldDocked ? this.dockedNodes[i].dockedShape : undefined )
- if (docker.getDockedShape()) {
- docker.setReferencePoint(this.dockedNodes[i].refPoint);
- //docker.update();
- }
- }
- },
-
- addShapeToParent:function( parents ){
-
- // For every Shape, add this and reset the position
- for(var i=0; i<this.moveShapes.length ;i++){
- var currentShape = this.moveShapes[i];
- if(currentShape instanceof ORYX.Core.Node &&
- currentShape.parent !== parents[i]) {
-
- // Calc the new position
- var unul = parents[i].absoluteXY();
- var csul = currentShape.absoluteXY();
- var x = csul.x - unul.x;
- var y = csul.y - unul.y;
- // Add the shape to the new contained shape
- parents[i].add(currentShape);
- // Add all attached shapes as well
- currentShape.getOutgoingShapes((function(shape) {
- if(shape instanceof ORYX.Core.Node && !this.moveShapes.member(shape)) {
- parents[i].add(shape);
- }
- }).bind(this));
- // Set the new position
- if(currentShape instanceof ORYX.Core.Node && currentShape.dockers.length == 1){
- var b = currentShape.bounds;
- x += b.width()/2;y += b.height()/2
- currentShape.dockers.first().bounds.centerMoveTo(x, y);
- } else {
- currentShape.bounds.moveTo(x, y);
- }
-
- }
-
- // Update the shape
- //currentShape.update();
-
- }
- },
- selectCurrentShapes:function(){
- this.plugin.facade.setSelection( this.selectedShapes );
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.ShapeHighlighting = Clazz.extend({
- construct: function(facade) {
-
- this.parentNode = facade.getCanvas().getSvgContainer();
-
- // The parent Node
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parentNode,
- ['g']);
- this.highlightNodes = {};
-
- facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this));
- facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this));
- },
- setHighlight: function(options) {
- if(options && options.highlightId){
- var node = this.highlightNodes[options.highlightId];
-
- if(!node){
- node= ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
- ['path', {
- "stroke-width": 2.0, "fill":"none"
- }]);
-
- this.highlightNodes[options.highlightId] = node;
- }
- if(options.elements && options.elements.length > 0) {
-
- this.setAttributesByStyle( node, options );
- this.show(node);
-
- } else {
-
- this.hide(node);
-
- }
-
- }
- },
-
- hideHighlight: function(options) {
- if(options && options.highlightId && this.highlightNodes[options.highlightId]){
- this.hide(this.highlightNodes[options.highlightId]);
- }
- },
-
- hide: function(node) {
- node.setAttributeNS(null, 'display', 'none');
- },
- show: function(node) {
- node.setAttributeNS(null, 'display', '');
- },
-
- setAttributesByStyle: function( node, options ){
-
- // If the style say, that it should look like a rectangle
- if( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){
-
- // Set like this
- var bo = options.elements[0].absoluteBounds();
-
- var strWidth = options.strokewidth ? options.strokewidth : ORYX.CONFIG.BORDER_OFFSET
-
- node.setAttributeNS(null, "d", this.getPathRectangle( bo.a, bo.b , strWidth ) );
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
- node.setAttributeNS(null, "stroke-width", strWidth);
-
- } else if(options.elements.length == 1
- && options.elements[0] instanceof ORYX.Core.Edge &&
- options.highlightId != "selection") {
-
- /* Highlight containment of edge's childs */
- node.setAttributeNS(null, "d", this.getPathEdge(options.elements[0].dockers));
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
- node.setAttributeNS(null, "stroke-width", ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
-
- }else {
- // If not, set just the corners
- node.setAttributeNS(null, "d", this.getPathByElements(options.elements));
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 1.0);
- node.setAttributeNS(null, "stroke-width", options.strokewidth ? options.strokewidth : 2.0);
-
- }
- },
-
- getPathByElements: function(elements){
- if(!elements || elements.length <= 0) {return undefined}
-
- // Get the padding and the size
- var padding = ORYX.CONFIG.SELECTED_AREA_PADDING;
-
- var path = ""
-
- // Get thru all Elements
- elements.each((function(element) {
- if(!element) {return}
- // Get the absolute Bounds and the two Points
- var bounds = element.absoluteBounds();
- bounds.widen(padding)
- var a = bounds.upperLeft();
- var b = bounds.lowerRight();
-
- path = path + this.getPath(a ,b);
-
- }).bind(this));
- return path;
-
- },
- getPath: function(a, b){
-
- return this.getPathCorners(a, b);
-
- },
-
- getPathCorners: function(a, b){
- var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
-
- var path = ""
- // Set: Upper left
- path = path + "M" + a.x + " " + (a.y + size) + " l0 -" + size + " l" + size + " 0 ";
- // Set: Lower left
- path = path + "M" + a.x + " " + (b.y - size) + " l0 " + size + " l" + size + " 0 ";
- // Set: Lower right
- path = path + "M" + b.x + " " + (b.y - size) + " l0 " + size + " l-" + size + " 0 ";
- // Set: Upper right
- path = path + "M" + b.x + " " + (a.y + size) + " l0 -" + size + " l-" + size + " 0 ";
-
- return path;
- },
-
- getPathRectangle: function(a, b, strokeWidth){
- var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
- var path = ""
- var offset = strokeWidth / 2.0;
-
- // Set: Upper left
- path = path + "M" + (a.x + offset) + " " + (a.y);
- path = path + " L" + (a.x + offset) + " " + (b.y - offset);
- path = path + " L" + (b.x - offset) + " " + (b.y - offset);
- path = path + " L" + (b.x - offset) + " " + (a.y + offset);
- path = path + " L" + (a.x + offset) + " " + (a.y + offset);
- return path;
- },
-
- getPathEdge: function(edgeDockers) {
- var length = edgeDockers.length;
- var path = "M" + edgeDockers[0].bounds.center().x + " "
- + edgeDockers[0].bounds.center().y;
-
- for(i=1; i<length; i++) {
- var dockerPoint = edgeDockers[i].bounds.center();
- path = path + " L" + dockerPoint.x + " " + dockerPoint.y;
- }
-
- return path;
- }
-
- });
-
- ORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({
- construct: function(facade) {
- this.facade = facade;
- this.opacityFull = 0.9;
- this.opacityLow = 0.4;
- // Register on Dragging-Events for show/hide of ShapeMenu
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this));
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END, this.show.bind(this));
- },
- /**
- * On the Selection-Changed
- *
- */
- onSelectionChanged: function(event) {
- if(event.elements && event.elements.length > 1) {
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'selection',
- elements: event.elements.without(event.subSelection),
- color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
- opacity: !event.subSelection ? this.opacityFull : this.opacityLow
- });
- if(event.subSelection){
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'subselection',
- elements: [event.subSelection],
- color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
- opacity: this.opacityFull
- });
- } else {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
- }
-
- } else {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'selection'});
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
- }
- }
- });/**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.DragDocker = Clazz.extend({
- /**
- * Constructor
- * @param {Object} Facade: The Facade of the Editor
- */
- construct: function(facade) {
- this.facade = facade;
-
- // Set the valid and invalid color
- this.VALIDCOLOR = ORYX.CONFIG.SELECTION_VALID_COLOR;
- this.INVALIDCOLOR = ORYX.CONFIG.SELECTION_INVALID_COLOR;
-
- // Define Variables
- this.shapeSelection = undefined;
- this.docker = undefined;
- this.dockerParent = undefined;
- this.dockerSource = undefined;
- this.dockerTarget = undefined;
- this.lastUIObj = undefined;
- this.isStartDocker = undefined;
- this.isEndDocker = undefined;
- this.undockTreshold = 10;
- this.initialDockerPosition = undefined;
- this.outerDockerNotMoved = undefined;
- this.isValid = false;
-
- // For the Drag and Drop
- // Register on MouseDown-Event on a Docker
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG, this.handleDockerDrag.bind(this));
-
- // Register on over/out to show / hide a docker
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER, this.handleMouseOver.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT, this.handleMouseOut.bind(this));
-
-
- },
-
- /**
- * MouseOut Handler
- *
- */
- handleMouseOut: function(event, uiObj) {
- // If there is a Docker, hide this
- if(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {
- uiObj.hide()
- } else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {
- uiObj.dockers.each(function(docker){
- docker.hide();
- })
- }
- },
- /**
- * MouseOver Handler
- *
- */
- handleMouseOver: function(event, uiObj) {
- // If there is a Docker, show this
- if(!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) {
- uiObj.show()
- } else if(!this.docker && uiObj instanceof ORYX.Core.Edge) {
- uiObj.dockers.each(function(docker){
- docker.show();
- })
- }
- },
- /**
- * DockerDrag Handler
- * delegates the uiEvent of the drag event to the mouseDown function
- */
- handleDockerDrag: function(event, uiObj) {
- this.handleMouseDown(event.uiEvent, uiObj);
- },
-
- /**
- * MouseDown Handler
- *
- */
- handleMouseDown: function(event, uiObj) {
- // If there is a Docker
- if(uiObj instanceof ORYX.Core.Controls.Docker && uiObj.isMovable) {
-
- /* Buffering shape selection and clear selection*/
- this.shapeSelection = this.facade.getSelection();
- this.facade.setSelection();
-
- this.docker = uiObj;
- this.initialDockerPosition = this.docker.bounds.center();
- this.outerDockerNotMoved = false;
- this.dockerParent = uiObj.parent;
-
- // Define command arguments
- this._commandArg = {docker:uiObj, dockedShape:uiObj.getDockedShape(), refPoint:uiObj.referencePoint || uiObj.bounds.center()};
- // Show the Docker
- this.docker.show();
-
- // If the Dockers Parent is an Edge,
- // and the Docker is either the first or last Docker of the Edge
- if(uiObj.parent instanceof ORYX.Core.Edge &&
- (uiObj.parent.dockers.first() == uiObj || uiObj.parent.dockers.last() == uiObj)) {
-
- // Get the Edge Source or Target
- if(uiObj.parent.dockers.first() == uiObj && uiObj.parent.dockers.last().getDockedShape()) {
- this.dockerTarget = uiObj.parent.dockers.last().getDockedShape()
- } else if(uiObj.parent.dockers.last() == uiObj && uiObj.parent.dockers.first().getDockedShape()) {
- this.dockerSource = uiObj.parent.dockers.first().getDockedShape()
- }
-
- } else {
- // If there parent is not an Edge, undefined the Source and Target
- this.dockerSource = undefined;
- this.dockerTarget = undefined;
- }
-
- this.isStartDocker = this.docker.parent.dockers.first() === this.docker
- this.isEndDocker = this.docker.parent.dockers.last() === this.docker
-
- // add to canvas while dragging
- this.facade.getCanvas().add(this.docker.parent);
-
- // Hide all Labels from Docker
- this.docker.parent.getLabels().each(function(label) {
- label.hide();
- });
-
- // Undocked the Docker from current Shape
- if ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) {
-
- this.docker.setDockedShape(undefined)
- // Set the Docker to the center of the mouse pointer
- var evPos = this.facade.eventCoordinates(event);
- this.docker.bounds.centerMoveTo(evPos);
- //this.docker.update()
- //this.facade.getCanvas().update();
- this.dockerParent._update();
- } else {
- this.outerDockerNotMoved = true;
- }
-
- var option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)}
-
- // Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with
- ORYX.Core.UIEnableDrag(event, uiObj, option);
- }
- },
-
- /**
- * Docker MouseMove Handler
- *
- */
- dockerMoved: function(event) {
- this.outerDockerNotMoved = false;
- var snapToMagnet = undefined;
-
- if (this.docker.parent) {
- if (this.isStartDocker || this.isEndDocker) {
-
- // Get the EventPosition and all Shapes on these point
- var evPos = this.facade.eventCoordinates(event);
-
- if(this.docker.isDocked()) {
- /* Only consider start/end dockers if they are moved over a treshold */
- var distanceDockerPointer =
- ORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition);
- if(distanceDockerPointer < this.undockTreshold) {
- this.outerDockerNotMoved = true;
- return;
- }
-
- /* Undock the docker */
- this.docker.setDockedShape(undefined)
- // Set the Docker to the center of the mouse pointer
- //this.docker.bounds.centerMoveTo(evPos);
- this.dockerParent._update();
- }
-
- var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);
-
- // Get the top level Shape on these, but not the same as Dockers parent
- var uiObj = shapes.pop();
- if (this.docker.parent === uiObj) {
- uiObj = shapes.pop();
- }
-
-
-
- // If the top level Shape the same as the last Shape, then return
- if (this.lastUIObj == uiObj) {
- //return;
-
- // If the top level uiObj instance of Shape and this isn't the parent of the docker
- }
- else
- if (uiObj instanceof ORYX.Core.Shape) {
-
- // Get the StencilSet of the Edge
- var sset = this.docker.parent.getStencil().stencilSet();
-
- // Ask by the StencilSet if the source, the edge and the target valid connections.
- if (this.docker.parent instanceof ORYX.Core.Edge) {
-
- var highestParent = this.getHighestParentBeforeCanvas(uiObj);
- /* Ensure that the shape to dock is not a child shape
- * of the same edge.
- */
- if(highestParent instanceof ORYX.Core.Edge
- && this.docker.parent === highestParent) {
- this.isValid = false;
- this.dockerParent._update();
- return;
- }
- this.isValid = false;
- var curObj = uiObj, orgObj = uiObj;
- while(!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas)){
- uiObj = curObj;
- this.isValid = this.facade.getRules().canConnect({
- sourceShape: this.dockerSource ? // Is there a docked source
- this.dockerSource : // than set this
- (this.isStartDocker ? // if not and if the Docker is the start docker
- uiObj : // take the last uiObj
- undefined), // if not set it to undefined;
- edgeShape: this.docker.parent,
- targetShape: this.dockerTarget ? // Is there a docked target
- this.dockerTarget : // than set this
- (this.isEndDocker ? // if not and if the Docker is not the start docker
- uiObj : // take the last uiObj
- undefined) // if not set it to undefined;
- });
- curObj = curObj.parent;
- }
-
- // Reset uiObj if no
- // valid parent is found
- if (!this.isValid){
- uiObj = orgObj;
- }
- }
- else {
- this.isValid = this.facade.getRules().canConnect({
- sourceShape: uiObj,
- edgeShape: this.docker.parent,
- targetShape: this.docker.parent
- });
- }
-
- // If there is a lastUIObj, hide the magnets
- if (this.lastUIObj) {
- this.hideMagnets(this.lastUIObj)
- }
-
- // If there is a valid connection, show the magnets
- if (this.isValid) {
- this.showMagnets(uiObj)
- }
-
- // Set the Highlight Rectangle by these value
- this.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR);
-
- // Buffer the current Shape
- this.lastUIObj = uiObj;
- }
- else {
- // If there is no top level Shape, then hide the highligting of the last Shape
- this.hideHighlight();
- this.lastUIObj ? this.hideMagnets(this.lastUIObj) : null;
- this.lastUIObj = undefined;
- this.isValid = false;
- }
-
- // Snap to the nearest Magnet
- if (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) {
- snapToMagnet = this.lastUIObj.magnets.find(function(magnet){
- return magnet.absoluteBounds().isIncluded(evPos)
- });
-
- if (snapToMagnet) {
- this.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY());
- //this.docker.update()
- }
- }
- }
- }
- // Snap to on the nearest Docker of the same parent
- if(!(event.shiftKey || event.ctrlKey) && !snapToMagnet) {
- var minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET;
- var nearestX = minOffset + 1
- var nearestY = minOffset + 1
-
- var dockerCenter = this.docker.bounds.center();
-
- if (this.docker.parent) {
-
- this.docker.parent.dockers.each((function(docker){
- if (this.docker == docker) {
- return
- };
-
- var center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center();
-
- nearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX;
- nearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY;
-
-
- }).bind(this));
-
- if (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) {
- nearestX = Math.abs(nearestX) < minOffset ? nearestX : 0;
- nearestY = Math.abs(nearestY) < minOffset ? nearestY : 0;
-
- this.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY);
- //this.docker.update()
- } else {
-
-
-
- var previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1, 0)]
- var next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1, this.docker.parent.dockers.length-1)]
-
- if (previous && next && previous !== this.docker && next !== this.docker){
- var cp = previous.bounds.center();
- var cn = next.bounds.center();
- var cd = this.docker.bounds.center();
-
- // Checks if the point is on the line between previous and next
- if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) {
- // Get the rise
- var raise = (Number(cn.y)-Number(cp.y))/(Number(cn.x)-Number(cp.x));
- // Calculate the intersection point
- var intersecX = ((cp.y-(cp.x*raise))-(cd.y-(cd.x*(-Math.pow(raise,-1)))))/((-Math.pow(raise,-1))-raise);
- var intersecY = (cp.y-(cp.x*raise))+(raise*intersecX);
-
- if(isNaN(intersecX) || isNaN(intersecY)) {return;}
-
- this.docker.bounds.centerMoveTo(intersecX, intersecY);
- }
- }
-
- }
- }
- }
- //this.facade.getCanvas().update();
- this.dockerParent._update();
- },
- /**
- * Docker MouseUp Handler
- *
- */
- dockerMovedFinished: function(event) {
-
- /* Reset to buffered shape selection */
- this.facade.setSelection(this.shapeSelection);
-
- // Hide the border
- this.hideHighlight();
-
- // Show all Labels from Docker
- this.dockerParent.getLabels().each(function(label){
- label.show();
- //label.update();
- });
-
- // If there is a last top level Shape
- if(this.lastUIObj && (this.isStartDocker || this.isEndDocker)){
- // If there is a valid connection, the set as a docked Shape to them
- if(this.isValid) {
-
- this.docker.setDockedShape(this.lastUIObj);
-
- this.facade.raiseEvent({
- type :ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED,
- docker : this.docker,
- parent : this.docker.parent,
- target : this.lastUIObj
- });
- }
-
- this.hideMagnets(this.lastUIObj)
- }
-
- // Hide the Docker
- this.docker.hide();
-
- if(this.outerDockerNotMoved) {
- // Get the EventPosition and all Shapes on these point
- var evPos = this.facade.eventCoordinates(event);
- var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos);
-
- /* Remove edges from selection */
- var shapeWithoutEdges = shapes.findAll(function(node) {
- return node instanceof ORYX.Core.Node;
- });
- shapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes;
- this.facade.setSelection(shapes);
- } else {
- //Command-Pattern for dragging one docker
- var dragDockerCommand = ORYX.Core.Command.extend({
- construct: function(docker, newPos, oldPos, newDockedShape, oldDockedShape, facade){
- this.docker = docker;
- this.index = docker.parent.dockers.indexOf(docker);
- this.newPosition = newPos;
- this.newDockedShape = newDockedShape;
- this.oldPosition = oldPos;
- this.oldDockedShape = oldDockedShape;
- this.facade = facade;
- this.index = docker.parent.dockers.indexOf(docker);
- this.shape = docker.parent;
-
- },
- execute: function(){
- if (!this.docker.parent){
- this.docker = this.shape.dockers[this.index];
- }
- this.dock( this.newDockedShape, this.newPosition );
- this.removedDockers = this.shape.removeUnusedDockers();
- this.facade.updateSelection();
- },
- rollback: function(){
- this.dock( this.oldDockedShape, this.oldPosition );
- (this.removedDockers||$H({})).each(function(d){
- this.shape.add(d.value, Number(d.key));
- this.shape._update(true);
- }.bind(this))
- this.facade.updateSelection();
- },
- dock:function( toDockShape, pos ){
- // Set the Docker to the new Shape
- this.docker.setDockedShape( undefined );
- if( toDockShape ){
- this.docker.setDockedShape( toDockShape );
- this.docker.setReferencePoint( pos );
- //this.docker.update();
- //this.docker.parent._update();
- } else {
- this.docker.bounds.centerMoveTo( pos );
- }
-
- this.facade.getCanvas().update();
-
-
-
- }
- });
-
-
- if (this.docker.parent){
- // Instanziate the dockCommand
- 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);
- this.facade.executeCommands( [command] );
- }
- }
-
-
-
- // Update all Shapes
- //this.facade.updateSelection();
-
- // Undefined all variables
- this.docker = undefined;
- this.dockerParent = undefined;
- this.dockerSource = undefined;
- this.dockerTarget = undefined;
- this.lastUIObj = undefined;
- },
-
- /**
- * Hide the highlighting
- */
- hideHighlight: function() {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'validDockedShape'});
- },
- /**
- * Show the highlighting
- *
- */
- showHighlight: function(uiObj, color) {
-
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'validDockedShape',
- elements: [uiObj],
- color: color
- });
- },
-
- showMagnets: function(uiObj){
- uiObj.magnets.each(function(magnet) {
- magnet.show();
- });
- },
-
- hideMagnets: function(uiObj){
- uiObj.magnets.each(function(magnet) {
- magnet.hide();
- });
- },
-
- getHighestParentBeforeCanvas: function(shape) {
- if(!(shape instanceof ORYX.Core.Shape)) {return undefined;}
-
- var parent = shape.parent;
- while(parent && !(parent.parent instanceof ORYX.Core.Canvas)) {
- parent = parent.parent;
- }
-
- return parent;
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.AddDocker = Clazz.extend({
- /**
- * Constructor
- * @param {Object} Facade: The Facade of the Editor
- */
- construct: function(facade) {
- this.facade = facade;
- this.facade.offer({
- 'name':ORYX.I18N.AddDocker.add,
- 'functionality': this.enableAddDocker.bind(this),
- 'group': ORYX.I18N.AddDocker.group,
- 'icon': ORYX.PATH + "images/vector_add.png",
- 'description': ORYX.I18N.AddDocker.addDesc,
- 'index': 1,
- 'toggle': true,
- 'minShape': 0,
- 'maxShape': 0});
- this.facade.offer({
- 'name':ORYX.I18N.AddDocker.del,
- 'functionality': this.enableDeleteDocker.bind(this),
- 'group': ORYX.I18N.AddDocker.group,
- 'icon': ORYX.PATH + "images/vector_delete.png",
- 'description': ORYX.I18N.AddDocker.delDesc,
- 'index': 2,
- 'toggle': true,
- 'minShape': 0,
- 'maxShape': 0});
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
- },
-
- enableAddDocker: function(button, pressed) {
- //FIXME This should be done while construct, but this isn't possible right now!
- this.addDockerButton = button;
-
- // Unpress deleteDockerButton
- if(pressed && this.deleteDockerButton)
- this.deleteDockerButton.toggle(false);
- },
- enableDeleteDocker: function(button, pressed) {
- //FIXME This should be done while construct, but this isn't possible right now!
- this.deleteDockerButton = button;
-
- // Unpress addDockerButton
- if(pressed && this.addDockerButton)
- this.addDockerButton.toggle(false);
- },
-
- enabledAdd: function(){
- return this.addDockerButton ? this.addDockerButton.pressed : false;
- },
- enabledDelete: function(){
- return this.deleteDockerButton ? this.deleteDockerButton.pressed : false;
- },
-
- /**
- * MouseDown Handler
- *
- */
- handleMouseDown: function(event, uiObj) {
- if (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) {
- this.newDockerCommand({
- edge: uiObj,
- position: this.facade.eventCoordinates(event)
- });
- } else if (this.enabledDelete() &&
- uiObj instanceof ORYX.Core.Controls.Docker &&
- uiObj.parent instanceof ORYX.Core.Edge) {
- this.newDockerCommand({
- edge: uiObj.parent,
- docker: uiObj
- });
- } else if ( this.enabledAdd() ){
- this.addDockerButton.toggle(false);
- } else if ( this.enabledDelete() ) {
- this.deleteDockerButton.toggle(false);
- }
- },
-
- // Options: edge (required), position (required if add), docker (required if delete)
- newDockerCommand: function(options){
- if(!options.edge)
- return;
- var commandClass = ORYX.Core.Command.extend({
- construct: function(addEnabled, deleteEnabled, edge, docker, pos, facade){
- this.addEnabled = addEnabled;
- this.deleteEnabled = deleteEnabled;
- this.edge = edge;
- this.docker = docker;
- this.pos = pos;
- this.facade = facade;
- //this.index = docker.parent.dockers.indexOf(docker);
- },
- execute: function(){
- if (this.addEnabled) {
- if (!this.docker){
- this.docker = this.edge.addDocker(this.pos);
- this.index = this.edge.dockers.indexOf(this.docker);
- } else {
- this.edge.add(this.docker, this.index);
- }
- }
- else if (this.deleteEnabled) {
- this.index = this.edge.dockers.indexOf(this.docker);
- this.pos = this.docker.bounds.center();
- this.edge.removeDocker(this.docker);
- }
- this.edge.getLabels().invoke("show");
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- },
- rollback: function(){
- if (this.addEnabled) {
- if (this.docker instanceof ORYX.Core.Controls.Docker) {
- this.edge.removeDocker(this.docker);
- }
- }
- else if (this.deleteEnabled) {
- this.edge.add(this.docker, this.index);
- }
- this.edge.getLabels().invoke("show");
- this.facade.getCanvas().update();
- this.facade.updateSelection();
- }
- })
-
- var command = new commandClass(this.enabledAdd(), this.enabledDelete(), options.edge, options.docker, options.position, this.facade);
-
- this.facade.executeCommands([command]);
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.SelectionFrame = Clazz.extend({
- construct: function(facade) {
- this.facade = facade;
- // Register on MouseEvents
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this));
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true);
- // Some initiale variables
- this.position = {x:0, y:0};
- this.size = {width:0, height:0};
- this.offsetPosition = {x: 0, y: 0}
- // (Un)Register Mouse-Move Event
- this.moveCallback = undefined;
- this.offsetScroll = {x:0,y:0}
- // HTML-Node of Selection-Frame
- this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", this.facade.getCanvas().getHTMLContainer(),
- ['div', {'class':'Oryx_SelectionFrame'}]);
- this.hide();
- },
- handleMouseDown: function(event, uiObj) {
- // If there is the Canvas
- if( uiObj instanceof ORYX.Core.Canvas ) {
- // Calculate the Offset
- var scrollNode = uiObj.rootNode.parentNode.parentNode;
-
- var a = this.facade.getCanvas().node.getScreenCTM();
- this.offsetPosition = {
- x: a.e,
- y: a.f
- }
- // Set the new Position
- this.setPos({x: Event.pointerX(event)-this.offsetPosition.x, y:Event.pointerY(event)-this.offsetPosition.y});
- // Reset the size
- this.resize({width:0, height:0});
- this.moveCallback = this.handleMouseMove.bind(this);
-
- // Register Mouse-Move Event
- document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);
- this.offsetScroll = {x:scrollNode.scrollLeft,y:scrollNode.scrollTop};
-
- // Show the Frame
- this.show();
-
-
- }
- Event.stop(event);
- },
- handleMouseUp: function(event) {
- // If there was an MouseMoving
- if(this.moveCallback) {
- // Hide the Frame
- this.hide();
- // Unregister Mouse-Move
- document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false);
-
- this.moveCallback = undefined;
- var corrSVG = this.facade.getCanvas().node.getScreenCTM();
- // Calculate the positions of the Frame
- var a = {
- x: this.size.width > 0 ? this.position.x : this.position.x + this.size.width,
- y: this.size.height > 0 ? this.position.y : this.position.y + this.size.height
- }
- var b = {
- x: a.x + Math.abs(this.size.width),
- y: a.y + Math.abs(this.size.height)
- }
- // Fit to SVG-Coordinates
- a.x /= corrSVG.a; a.y /= corrSVG.d;
- b.x /= corrSVG.a; b.y /= corrSVG.d;
- // Calculate the elements from the childs of the canvas
- var elements = this.facade.getCanvas().getChildShapes(true).findAll(function(value) {
- var absBounds = value.absoluteBounds();
- var bA = absBounds.upperLeft();
- var bB = absBounds.lowerRight();
- if(bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y)
- return true;
- return false
- });
- // Set the selection
- this.facade.setSelection(elements);
- }
- },
- handleMouseMove: function(event) {
- // Calculate the size
- var size = {
- width : Event.pointerX(event) - this.position.x - this.offsetPosition.x,
- height : Event.pointerY(event) - this.position.y - this.offsetPosition.y,
- }
- var scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode;
- size.width -= this.offsetScroll.x - scrollNode.scrollLeft;
- size.height -= this.offsetScroll.y - scrollNode.scrollTop;
-
- // Set the size
- this.resize(size);
- Event.stop(event);
- },
- hide: function() {
- this.node.style.display = "none";
- },
- show: function() {
- this.node.style.display = "";
- },
- setPos: function(pos) {
- // Set the Position
- this.node.style.top = pos.y + "px";
- this.node.style.left = pos.x + "px";
- this.position = pos;
- },
- resize: function(size) {
- // Calculate the negative offset
- this.setPos(this.position);
- this.size = Object.clone(size);
-
- if(size.width < 0) {
- this.node.style.left = (this.position.x + size.width) + "px";
- size.width = - size.width;
- }
- if(size.height < 0) {
- this.node.style.top = (this.position.y + size.height) + "px";
- size.height = - size.height;
- }
- // Set the size
- this.node.style.width = size.width + "px";
- this.node.style.height = size.height + "px";
- }
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.ShapeHighlighting = Clazz.extend({
- construct: function(facade) {
-
- this.parentNode = facade.getCanvas().getSvgContainer();
-
- // The parent Node
- this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parentNode,
- ['g']);
- this.highlightNodes = {};
-
- facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this));
- facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this));
- },
- setHighlight: function(options) {
- if(options && options.highlightId){
- var node = this.highlightNodes[options.highlightId];
-
- if(!node){
- node= ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node,
- ['path', {
- "stroke-width": 2.0, "fill":"none"
- }]);
-
- this.highlightNodes[options.highlightId] = node;
- }
- if(options.elements && options.elements.length > 0) {
-
- this.setAttributesByStyle( node, options );
- this.show(node);
-
- } else {
-
- this.hide(node);
-
- }
-
- }
- },
-
- hideHighlight: function(options) {
- if(options && options.highlightId && this.highlightNodes[options.highlightId]){
- this.hide(this.highlightNodes[options.highlightId]);
- }
- },
-
- hide: function(node) {
- node.setAttributeNS(null, 'display', 'none');
- },
- show: function(node) {
- node.setAttributeNS(null, 'display', '');
- },
-
- setAttributesByStyle: function( node, options ){
-
- // If the style say, that it should look like a rectangle
- if( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){
-
- // Set like this
- var bo = options.elements[0].absoluteBounds();
-
- var strWidth = options.strokewidth ? options.strokewidth : ORYX.CONFIG.BORDER_OFFSET
-
- node.setAttributeNS(null, "d", this.getPathRectangle( bo.a, bo.b , strWidth ) );
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
- node.setAttributeNS(null, "stroke-width", strWidth);
-
- } else if(options.elements.length == 1
- && options.elements[0] instanceof ORYX.Core.Edge &&
- options.highlightId != "selection") {
-
- /* Highlight containment of edge's childs */
- node.setAttributeNS(null, "d", this.getPathEdge(options.elements[0].dockers));
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2);
- node.setAttributeNS(null, "stroke-width", ORYX.CONFIG.OFFSET_EDGE_BOUNDS);
-
- }else {
- // If not, set just the corners
- node.setAttributeNS(null, "d", this.getPathByElements(options.elements));
- node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR);
- node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 1.0);
- node.setAttributeNS(null, "stroke-width", options.strokewidth ? options.strokewidth : 2.0);
-
- }
- },
-
- getPathByElements: function(elements){
- if(!elements || elements.length <= 0) {return undefined}
-
- // Get the padding and the size
- var padding = ORYX.CONFIG.SELECTED_AREA_PADDING;
-
- var path = ""
-
- // Get thru all Elements
- elements.each((function(element) {
- if(!element) {return}
- // Get the absolute Bounds and the two Points
- var bounds = element.absoluteBounds();
- bounds.widen(padding)
- var a = bounds.upperLeft();
- var b = bounds.lowerRight();
-
- path = path + this.getPath(a ,b);
-
- }).bind(this));
- return path;
-
- },
- getPath: function(a, b){
-
- return this.getPathCorners(a, b);
-
- },
-
- getPathCorners: function(a, b){
- var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
-
- var path = ""
- // Set: Upper left
- path = path + "M" + a.x + " " + (a.y + size) + " l0 -" + size + " l" + size + " 0 ";
- // Set: Lower left
- path = path + "M" + a.x + " " + (b.y - size) + " l0 " + size + " l" + size + " 0 ";
- // Set: Lower right
- path = path + "M" + b.x + " " + (b.y - size) + " l0 " + size + " l-" + size + " 0 ";
- // Set: Upper right
- path = path + "M" + b.x + " " + (a.y + size) + " l0 -" + size + " l-" + size + " 0 ";
-
- return path;
- },
-
- getPathRectangle: function(a, b, strokeWidth){
- var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE;
- var path = ""
- var offset = strokeWidth / 2.0;
-
- // Set: Upper left
- path = path + "M" + (a.x + offset) + " " + (a.y);
- path = path + " L" + (a.x + offset) + " " + (b.y - offset);
- path = path + " L" + (b.x - offset) + " " + (b.y - offset);
- path = path + " L" + (b.x - offset) + " " + (a.y + offset);
- path = path + " L" + (a.x + offset) + " " + (a.y + offset);
- return path;
- },
-
- getPathEdge: function(edgeDockers) {
- var length = edgeDockers.length;
- var path = "M" + edgeDockers[0].bounds.center().x + " "
- + edgeDockers[0].bounds.center().y;
-
- for(i=1; i<length; i++) {
- var dockerPoint = edgeDockers[i].bounds.center();
- path = path + " L" + dockerPoint.x + " " + dockerPoint.y;
- }
-
- return path;
- }
-
- });
-
- ORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({
- construct: function(facade) {
- this.facade = facade;
- this.opacityFull = 0.9;
- this.opacityLow = 0.4;
- // Register on Dragging-Events for show/hide of ShapeMenu
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this));
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END, this.show.bind(this));
- },
- /**
- * On the Selection-Changed
- *
- */
- onSelectionChanged: function(event) {
- if(event.elements && event.elements.length > 1) {
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'selection',
- elements: event.elements.without(event.subSelection),
- color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
- opacity: !event.subSelection ? this.opacityFull : this.opacityLow
- });
- if(event.subSelection){
- this.facade.raiseEvent({
- type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW,
- highlightId:'subselection',
- elements: [event.subSelection],
- color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR,
- opacity: this.opacityFull
- });
- } else {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
- }
-
- } else {
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'selection'});
- this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'subselection'});
- }
- }
- });/**
- * Copyright (c) 2008
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * HOW to USE the OVERLAY PLUGIN:
- * You can use it via the event mechanism from the editor
- * by using facade.raiseEvent( <option> )
- *
- * As an example please have a look in the overlayexample.js
- *
- * The option object should/have to have following attributes:
- *
- * Key Value-Type Description
- * ================================================================
- *
- * type ORYX.CONFIG.EVENT_OVERLAY_SHOW | ORYX.CONFIG.EVENT_OVERLAY_HIDE This is the type of the event
- * id <String> You have to use an unified id for later on hiding this overlay
- * shapes <ORYX.Core.Shape[]> The Shapes where the attributes should be changed
- * attributes <Object> An object with svg-style attributes as key-value pair
- * node <SVGElement> An SVG-Element could be specified for adding this to the Shape
- * nodePosition "N"|"NE"|"E"|"SE"|"S"|"SW"|"W"|"NW"|"START"|"END" The position for the SVG-Element relative to the
- * specified Shape. "START" and "END" are just using for a Edges, then
- * the relation is the start or ending Docker of this edge.
- *
- *
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.Overlay = Clazz.extend({
- facade: undefined,
-
- styleNode: undefined,
-
- construct: function(facade){
-
- this.facade = facade;
- this.changes = [];
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this));
- this.styleNode = document.createElement('style')
- this.styleNode.setAttributeNS(null, 'type', 'text/css')
-
- document.getElementsByTagName('head')[0].appendChild( this.styleNode )
- },
-
- /**
- * Show the overlay for specific nodes
- * @param {Object} options
- *
- * String options.id - MUST - Define the id of the overlay (is needed for the hiding of this overlay)
- * ORYX.Core.Shape[] options.shapes - MUST - Define the Shapes for the changes
- * attr-name:value options.changes - Defines all the changes which should be shown
- *
- *
- */
- show: function( options ){
-
- // Checks if all arguments are available
- if( !options ||
- !options.shapes || !options.shapes instanceof Array ||
- !options.id || !options.id instanceof String || options.id.length == 0) {
-
- return
-
- }
-
- //if( this.changes[options.id]){
- // this.hide( options )
- //}
-
- // Checked if attributes are setted
- if( options.attributes ){
-
- // FOR EACH - Shape
- options.shapes.each(function(el){
-
- // Checks if the node is a Shape
- if( !el instanceof ORYX.Core.Shape){ return }
-
- this.setAttributes( el.node , options.attributes )
-
- }.bind(this))
- }
-
- var isSVG = true
- try {
- isSVG = options.node && options.node instanceof SVGElement;
- } catch(e){}
-
- // Checks if node is setted and if this is an SVGElement
- if ( options.node && isSVG) {
-
- options["_temps"] = []
-
- // FOR EACH - Node
- options.shapes.each(function(el, index){
-
- // Checks if the node is a Shape
- if( !el instanceof ORYX.Core.Shape){ return }
-
- var _temp = {}
- _temp.svg = options.dontCloneNode ? options.node : options.node.cloneNode( true );
-
- // Add the svg node to the ORYX-Shape
- el.node.firstChild.appendChild( _temp.svg )
-
- // If
- if (el instanceof ORYX.Core.Edge && !options.nodePosition) {
- options['nodePosition'] = "START"
- }
-
- // If the node position is setted, it has to be transformed
- if( options.nodePosition ){
-
- var b = el.bounds;
- var p = options.nodePosition.toUpperCase();
-
- // Check the values of START and END
- if( el instanceof ORYX.Core.Node && p == "START"){
- p = "NW";
- } else if(el instanceof ORYX.Core.Node && p == "END"){
- p = "SE";
- } else if(el instanceof ORYX.Core.Edge && p == "START"){
- b = el.getDockers().first().bounds
- } else if(el instanceof ORYX.Core.Edge && p == "END"){
- b = el.getDockers().last().bounds
- }
- // Create a callback for the changing the position
- // depending on the position string
- _temp.callback = function(){
-
- var x = 0; var y = 0;
-
- if( p == "NW" ){
- // Do Nothing
- } else if( p == "N" ) {
- x = b.width() / 2;
- } else if( p == "NE" ) {
- x = b.width();
- } else if( p == "E" ) {
- x = b.width(); y = b.height() / 2;
- } else if( p == "SE" ) {
- x = b.width(); y = b.height();
- } else if( p == "S" ) {
- x = b.width() / 2; y = b.height();
- } else if( p == "SW" ) {
- y = b.height();
- } else if( p == "W" ) {
- y = b.height() / 2;
- } else if( p == "START" || p == "END") {
- x = b.width() / 2; y = b.height() / 2;
- } else {
- return
- }
-
- if( el instanceof ORYX.Core.Edge){
- x += b.upperLeft().x ; y += b.upperLeft().y ;
- }
-
- _temp.svg.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")")
-
- }.bind(this)
-
- _temp.element = el;
- _temp.callback();
-
- b.registerCallback( _temp.callback );
-
- }
-
-
- options._temps.push( _temp )
-
- }.bind(this))
-
-
-
- }
-
- // Store the changes
- if( !this.changes[options.id] ){
- this.changes[options.id] = [];
- }
-
- this.changes[options.id].push( options );
-
- },
-
- /**
- * Hide the overlay with the spefic id
- * @param {Object} options
- */
- hide: function( options ){
-
- // Checks if all arguments are available
- if( !options ||
- !options.id || !options.id instanceof String || options.id.length == 0 ||
- !this.changes[options.id]) {
-
- return
-
- }
-
-
- // Delete all added attributes
- // FOR EACH - Shape
- this.changes[options.id].each(function(option){
-
- option.shapes.each(function(el, index){
-
- // Checks if the node is a Shape
- if( !el instanceof ORYX.Core.Shape){ return }
-
- this.deleteAttributes( el.node )
-
- }.bind(this));
-
- if( option._temps ){
-
- option._temps.each(function(tmp){
- // Delete the added Node, if there is one
- if( tmp.svg && tmp.svg.parentNode ){
- tmp.svg.parentNode.removeChild( tmp.svg )
- }
-
- // If
- if( tmp.callback && tmp.element){
- // It has to be unregistered from the edge
- tmp.element.bounds.unregisterCallback( tmp.callback )
- }
-
- }.bind(this))
-
- }
-
-
- }.bind(this));
-
- this.changes[options.id] = null;
-
-
- },
-
-
- /**
- * Set the given css attributes to that node
- * @param {HTMLElement} node
- * @param {Object} attributes
- */
- setAttributes: function( node, attributes ) {
-
-
- // Get all the childs from ME
- var childs = this.getAllChilds( node.firstChild.firstChild )
-
- var ids = []
-
- // Add all Attributes which have relation to another node in this document and concate the pure id out of it
- // This is for example important for the markers of a edge
- childs.each(function(e){ ids.push( $A(e.attributes).findAll(function(attr){ return attr.nodeValue.startsWith('url(#')}) )})
- ids = ids.flatten().compact();
- ids = ids.collect(function(s){return s.nodeValue}).uniq();
- ids = ids.collect(function(s){return s.slice(5, s.length-1)})
-
- // Add the node ID to the id
- ids.unshift( node.id + ' .me')
-
- var attr = $H(attributes);
- var attrValue = attr.toJSON().gsub(',', ';').gsub('"', '');
- var attrMarkerValue = attributes.stroke ? attrValue.slice(0, attrValue.length-1) + "; fill:" + attributes.stroke + ";}" : attrValue;
- var attrTextValue;
- if( attributes.fill ){
- var copyAttr = Object.clone(attributes);
- copyAttr.fill = "black";
- attrTextValue = $H(copyAttr).toJSON().gsub(',', ';').gsub('"', '');
- }
-
- // Create the CSS-Tags Style out of the ids and the attributes
- csstags = ids.collect(function(s, i){return "#" + s + " * " + (!i? attrValue : attrMarkerValue) + "" + (attrTextValue ? " #" + s + " text * " + attrTextValue : "") })
-
- // Join all the tags
- var s = csstags.join(" ") + "\n"
-
- // And add to the end of the style tag
- this.styleNode.appendChild(document.createTextNode(s));
-
-
- },
-
- /**
- * Deletes all attributes which are
- * added in a special style sheet for that node
- * @param {HTMLElement} node
- */
- deleteAttributes: function( node ) {
-
- // Get all children which contains the node id
- var delEl = $A(this.styleNode.childNodes)
- .findAll(function(e){ return e.textContent.include( '#' + node.id ) });
-
- // Remove all of them
- delEl.each(function(el){
- el.parentNode.removeChild(el);
- });
- },
-
- getAllChilds: function( node ){
-
- var childs = $A(node.childNodes)
-
- $A(node.childNodes).each(function( e ){
- childs.push( this.getAllChilds( e ) )
- }.bind(this))
- return childs.flatten();
- }
-
- });
- /**
- * Copyright (c) 2006
- * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.Edit = Clazz.extend({
-
- construct: function(facade){
-
- this.facade = facade;
- this.clipboard = new ORYX.Plugins.Edit.ClipBoard();
-
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));
-
- this.facade.offer({
- name: ORYX.I18N.Edit.cut,
- description: ORYX.I18N.Edit.cutDesc,
- icon: ORYX.PATH + "images/cut.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 88,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.callEdit.bind(this, this.editCut),
- group: ORYX.I18N.Edit.group,
- index: 1,
- minShape: 1
- });
-
- this.facade.offer({
- name: ORYX.I18N.Edit.copy,
- description: ORYX.I18N.Edit.copyDesc,
- icon: ORYX.PATH + "images/page_copy.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 67,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.callEdit.bind(this, this.editCopy, [true, false]),
- group: ORYX.I18N.Edit.group,
- index: 2,
- minShape: 1
- });
-
- this.facade.offer({
- name: ORYX.I18N.Edit.paste,
- description: ORYX.I18N.Edit.pasteDesc,
- icon: ORYX.PATH + "images/page_paste.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 86,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.callEdit.bind(this, this.editPaste),
- isEnabled: this.clipboard.isOccupied.bind(this.clipboard),
- group: ORYX.I18N.Edit.group,
- index: 3,
- minShape: 0,
- maxShape: 0
- });
-
- this.facade.offer({
- name: ORYX.I18N.Edit.del,
- description: ORYX.I18N.Edit.delDesc,
- icon: ORYX.PATH + "images/cross.png",
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 8,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- },
- {
- keyCode: 46,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.callEdit.bind(this, this.editDelete),
- group: ORYX.I18N.Edit.group,
- index: 4,
- minShape: 1
- });
- },
-
- callEdit: function(fn, args){
- window.setTimeout(function(){
- fn.apply(this, (args instanceof Array ? args : []));
- }.bind(this), 1);
- },
-
- /**
- * Handles the mouse down event and starts the copy-move-paste action, if
- * control or meta key is pressed.
- */
- handleMouseDown: function(event) {
- if(this._controlPressed) {
- this._controlPressed = false;
- this.editCopy();
- // console.log("copiedEle: %0",this.clipboard.shapesAsJson)
- // console.log("mousevent: %o",event)
- this.editPaste();
- event.forceExecution = true;
- this.facade.raiseEvent(event, this.clipboard.shapesAsJson);
-
- }
- },
-
- /**
- * The key handler for this plugin. Every action from the set of cut, copy,
- * paste and delete should be accessible trough simple keyboard shortcuts.
- * This method checks whether any event triggers one of those actions.
- *
- * @param {Object} event The keyboard event that should be analysed for
- * triggering of this plugin.
- */
- // keyHandler: function(event){
- // //TODO document what event.which is.
- //
- // ORYX.Log.debug("edit.js handles a keyEvent.");
- //
- // // assure we have the current event.
- // if (!event)
- // event = window.event;
- //
- //
- // // get the currently pressed key and state of control key.
- // var pressedKey = event.which || event.keyCode;
- // var ctrlPressed = event.ctrlKey;
- //
- // // if the object is to be deleted, do so, and return immediately.
- // if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) ||
- // ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) &&
- // (event.metaKey || event.appleMetaKey))) {
- //
- // ORYX.Log.debug("edit.js deletes the shape.");
- // this.editDelete();
- // return;
- // }
- //
- // // if control key is not pressed, we're not interested anymore.
- // if (!ctrlPressed)
- // return;
- //
- // // when ctrl is pressed, switch trough the possibilities.
- // switch (pressedKey) {
- //
- // // cut.
- // case ORYX.CONFIG.KEY_CODE_X:
- // this.editCut();
- // break;
- //
- // // copy.
- // case ORYX.CONFIG.KEY_CODE_C:
- // this.editCopy();
- // break;
- //
- // // paste.
- // case ORYX.CONFIG.KEY_CODE_V:
- // this.editPaste();
- // break;
- // }
- // },
-
- /**
- * Returns a list of shapes which should be considered while copying.
- * Besides the shapes of given ones, edges and attached nodes are added to the result set.
- * If one of the given shape is a child of another given shape, it is not put into the result.
- */
- getAllShapesToConsider: function(shapes){
- var shapesToConsider = []; // only top-level shapes
- var childShapesToConsider = []; // all child shapes of top-level shapes
-
- shapes.each(function(shape){
- //Throw away these shapes which have a parent in given shapes
- isChildShapeOfAnother = shapes.any(function(s2){
- return s2.hasChildShape(shape);
- });
- if(isChildShapeOfAnother) return;
-
- // This shape should be considered
- shapesToConsider.push(shape);
- // Consider attached nodes (e.g. intermediate events)
- if (shape instanceof ORYX.Core.Node) {
- var attached = shape.getOutgoingNodes();
- attached = attached.findAll(function(a){ return !shapes.include(a) });
- shapesToConsider = shapesToConsider.concat(attached);
- }
-
- childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true));
- }.bind(this));
-
- // All edges between considered child shapes should be considered
- // Look for these edges having incoming and outgoing in childShapesToConsider
- var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function(edge){
- // Ignore if already added
- if(shapesToConsider.include(edge)) return false;
- // Ignore if there are no docked shapes
- if(edge.getAllDockedShapes().size() === 0) return false;
- // True if all docked shapes are in considered child shapes
- return edge.getAllDockedShapes().all(function(shape){
- // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider
- return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape);
- });
- });
- shapesToConsider = shapesToConsider.concat(edgesToConsider);
-
- return shapesToConsider;
- },
-
- /**
- * Performs the cut operation by first copy-ing and then deleting the
- * current selection.
- */
- editCut: function(){
- //TODO document why this returns false.
- //TODO document what the magic boolean parameters are supposed to do.
-
- this.editCopy(false, true);
- this.editDelete(true);
- return false;
- },
-
- /**
- * Performs the copy operation.
- * @param {Object} will_not_update ??
- */
- editCopy: function( will_update, useNoOffset ){
- var selection = this.facade.getSelection();
-
- //if the selection is empty, do not remove the previously copied elements
- if(selection.length == 0) return;
-
- this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset);
- if( will_update ) this.facade.updateSelection();
- },
-
- /**
- * Performs the paste operation.
- */
- editPaste: function(){
- // Create a new canvas with childShapes
- //and stencilset namespace to be JSON Import conform
- var canvas = {
- childShapes: this.clipboard.shapesAsJson,
- stencilset:{
- namespace:this.clipboard.SSnamespace
- }
- }
- // Apply json helper to iterate over json object
- Ext.apply(canvas, ORYX.Core.AbstractShape.JSONHelper);
-
- var childShapeResourceIds = canvas.getChildShapes(true).pluck("resourceId");
- var outgoings = {};
- // Iterate over all shapes
- canvas.eachChild(function(shape, parent){
- // Throw away these references where referenced shape isn't copied
- shape.outgoing = shape.outgoing.select(function(out){
- return childShapeResourceIds.include(out.resourceId);
- });
- shape.outgoing.each(function(out){
- if (!outgoings[out.resourceId]){ outgoings[out.resourceId] = [] }
- outgoings[out.resourceId].push(shape)
- });
-
- return shape;
- }.bind(this), true, true);
-
- // Iterate over all shapes
- canvas.eachChild(function(shape, parent){
-
- // Check if there has a valid target
- if(shape.target && !(childShapeResourceIds.include(shape.target.resourceId))){
- shape.target = undefined;
- shape.targetRemoved = true;
- }
-
- // Check if the first docker is removed
- if( shape.dockers &&
- shape.dockers.length >= 1 &&
- shape.dockers[0].getDocker &&
- ((shape.dockers[0].getDocker().getDockedShape() &&
- !childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) ||
- !shape.getShape().dockers[0].getDockedShape()&&!outgoings[shape.resourceId])) {
-
- shape.sourceRemoved = true;
- }
-
- return shape;
- }.bind(this), true, true);
-
- // Iterate over top-level shapes
- canvas.eachChild(function(shape, parent){
- // All top-level shapes should get an offset in their bounds
- // Move the shape occording to COPY_MOVE_OFFSET
- if (this.clipboard.useOffset) {
- shape.bounds = {
- lowerRight: {
- x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
- y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET
- },
- upperLeft: {
- x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
- y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET
- }
- };
- }
- // Only apply offset to shapes with a target
- if (shape.dockers){
- shape.dockers = shape.dockers.map(function(docker, i){
- // If shape had a target but the copied does not have anyone anymore,
- // migrate the relative dockers to absolute ones.
- if( (shape.targetRemoved === true && i == shape.dockers.length - 1&&docker.getDocker) ||
- (shape.sourceRemoved === true && i == 0&&docker.getDocker)){
- docker = docker.getDocker().bounds.center();
- }
- // If it is the first docker and it has a docked shape,
- // just return the coordinates
- if ((i == 0 && docker.getDocker instanceof Function &&
- 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)))) ||
- (i == shape.dockers.length - 1 && docker.getDocker instanceof Function &&
- shape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))){
-
- return {
- x: docker.x,
- y: docker.y,
- getDocker: docker.getDocker
- }
- } else if (this.clipboard.useOffset) {
- return {
- x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
- y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,
- getDocker: docker.getDocker
- };
- } else {
- return {
- x: docker.x,
- y: docker.y,
- getDocker: docker.getDocker
- };
- }
- }.bind(this));
- } 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]))){
-
- shape.dockers = shape.dockers.map(function(docker, i){
-
- if((shape.sourceRemoved === true && i == 0&&docker.getDocker)){
- docker = docker.getDocker().bounds.center();
- }
-
- if (this.clipboard.useOffset) {
- return {
- x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET,
- y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET,
- getDocker: docker.getDocker
- };
- } else {
- return {
- x: docker.x,
- y: docker.y,
- getDocker: docker.getDocker
- };
- }
- }.bind(this));
- }
-
- return shape;
- }.bind(this), false, true);
- this.clipboard.useOffset = true;
- this.facade.importJSON(canvas);
- },
-
- /**
- * Performs the delete operation. No more asking.
- */
- editDelete: function(){
- var selection = this.facade.getSelection();
-
- var clipboard = new ORYX.Plugins.Edit.ClipBoard();
- clipboard.refresh(selection, this.getAllShapesToConsider(selection));
-
- var command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade);
-
- this.facade.executeCommands([command]);
- }
- });
- ORYX.Plugins.Edit.ClipBoard = Clazz.extend({
- construct: function(){
- this.shapesAsJson = [];
- this.selection = [];
- this.SSnamespace="";
- this.useOffset=true;
- },
- isOccupied: function(){
- return this.shapesAsJson.length > 0;
- },
- refresh: function(selection, shapes, namespace, useNoOffset){
- this.selection = selection;
- this.SSnamespace=namespace;
- // Store outgoings, targets and parents to restore them later on
- this.outgoings = {};
- this.parents = {};
- this.targets = {};
- this.useOffset = useNoOffset !== true;
-
- this.shapesAsJson = shapes.map(function(shape){
- var s = shape.toJSON();
- s.parent = {resourceId : shape.getParentShape().resourceId};
- s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape)
- return s;
- });
- }
- });
- ORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({
- construct: function(clipboard, facade){
- this.clipboard = clipboard;
- this.shapesAsJson = clipboard.shapesAsJson;
- this.facade = facade;
-
- // Store dockers of deleted shapes to restore connections
- this.dockers = this.shapesAsJson.map(function(shapeAsJson){
- var shape = shapeAsJson.getShape();
- var incomingDockers = shape.getIncomingShapes().map(function(s){return s.getDockers().last()})
- var outgoingDockers = shape.getOutgoingShapes().map(function(s){return s.getDockers().first()})
- var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function(docker){
- return {
- object: docker,
- referencePoint: docker.referencePoint,
- dockedShape: docker.getDockedShape()
- };
- });
- return dockers;
- }).flatten();
- },
- execute: function(){
- this.shapesAsJson.each(function(shapeAsJson){
- // Delete shape
- this.facade.deleteShape(shapeAsJson.getShape());
- }.bind(this));
-
- this.facade.setSelection([]);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
- },
- rollback: function(){
- this.shapesAsJson.each(function(shapeAsJson) {
- var shape = shapeAsJson.getShape();
- var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas();
- parent.add(shape, shape.parentIndex);
- }.bind(this));
-
- //reconnect shapes
- this.dockers.each(function(d) {
- d.object.setDockedShape(d.dockedShape);
- d.object.setReferencePoint(d.referencePoint);
- }.bind(this));
-
- this.facade.setSelection(this.selectedShapes);
- this.facade.getCanvas().update();
- this.facade.updateSelection();
-
- }
- });/**
- * Copyright (c) 2009
- * Jan-Felix Schwarz
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if (!ORYX.Plugins)
- ORYX.Plugins = new Object();
- ORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({
- facade: undefined,
-
- construct: function(facade){
-
- this.facade = facade;
- this.copyElements = [];
-
- //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this));
- // SELECT ALL
- this.facade.offer({
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: 65,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.selectAll.bind(this)
- });
-
- // MOVE LEFT SMALL
- this.facade.offer({
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: ORYX.CONFIG.KEY_CODE_LEFT,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, false)
- });
-
- // MOVE LEFT
- this.facade.offer({
- keyCodes: [{
- keyCode: ORYX.CONFIG.KEY_CODE_LEFT,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_LEFT, true)
- });
-
- // MOVE RIGHT SMALL
- this.facade.offer({
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: ORYX.CONFIG.KEY_CODE_RIGHT,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, false)
- });
-
- // MOVE RIGHT
- this.facade.offer({
- keyCodes: [{
- keyCode: ORYX.CONFIG.KEY_CODE_RIGHT,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_RIGHT, true)
- });
-
- // MOVE UP SMALL
- this.facade.offer({
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: ORYX.CONFIG.KEY_CODE_UP,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, false)
- });
-
- // MOVE UP
- this.facade.offer({
- keyCodes: [{
- keyCode: ORYX.CONFIG.KEY_CODE_UP,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_UP, true)
- });
-
- // MOVE DOWN SMALL
- this.facade.offer({
- keyCodes: [{
- metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL],
- keyCode: ORYX.CONFIG.KEY_CODE_DOWN,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, false)
- });
-
- // MOVE DOWN
- this.facade.offer({
- keyCodes: [{
- keyCode: ORYX.CONFIG.KEY_CODE_DOWN,
- keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
- }
- ],
- functionality: this.move.bind(this, ORYX.CONFIG.KEY_CODE_DOWN, true)
- });
-
-
- },
-
- /**
- * Select all shapes in the editor
- *
- */
- selectAll: function(e){
- Event.stop(e.event);
- this.facade.setSelection(this.facade.getCanvas().getChildShapes(true))
- },
-
- move: function(key, far, e) {
-
- Event.stop(e.event);
- // calculate the distance to move the objects and get the selection.
- var distance = far? 20 : 5;
- var selection = this.facade.getSelection();
- var currentSelection = this.facade.getSelection();
- var p = {x: 0, y: 0};
-
- // switch on the key pressed and populate the point to move by.
- switch(key) {
- case ORYX.CONFIG.KEY_CODE_LEFT:
- p.x = -1*distance;
- break;
- case ORYX.CONFIG.KEY_CODE_RIGHT:
- p.x = distance;
- break;
- case ORYX.CONFIG.KEY_CODE_UP:
- p.y = -1*distance;
- break;
- case ORYX.CONFIG.KEY_CODE_DOWN:
- p.y = distance;
- break;
- }
-
- // move each shape in the selection by the point calculated and update it.
- selection = selection.findAll(function(shape){
- // Check if this shape is docked to an shape in the selection
- if(shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include( shape.dockers.first().getDockedShape() )){
- return false
- }
-
- // Check if any of the parent shape is included in the selection
- var s = shape.parent;
- do{
- if(selection.include(s)){
- return false
- }
- }while(s = s.parent);
-
- // Otherwise, return true
- return true;
-
- });
-
- /* Edges must not be movable, if only edges are selected and at least
- * one of them is docked.
- */
- var edgesMovable = true;
- var onlyEdgesSelected = selection.all(function(shape) {
- if(shape instanceof ORYX.Core.Edge) {
- if(shape.isDocked()) {
- edgesMovable = false;
- }
- return true;
- }
- return false;
- });
-
- if(onlyEdgesSelected && !edgesMovable) {
- /* Abort moving shapes */
- return;
- }
-
- selection = selection.map(function(shape){
- if( shape instanceof ORYX.Core.Node ){
- /*if( shape.dockers.length == 1 ){
- return shape.dockers.first()
- } else {*/
- return shape
- //}
- } else if( shape instanceof ORYX.Core.Edge ) {
-
- var dockers = shape.dockers;
-
- if( selection.include( shape.dockers.first().getDockedShape() ) ){
- dockers = dockers.without( shape.dockers.first() )
- }
- if( selection.include( shape.dockers.last().getDockedShape() ) ){
- dockers = dockers.without( shape.dockers.last() )
- }
-
- return dockers
-
- } else {
- return null
- }
-
- }).flatten().compact();
-
- if (selection.size() > 0) {
-
- //Stop moving at canvas borders
- var selectionBounds = [ this.facade.getCanvas().bounds.lowerRight().x,
- this.facade.getCanvas().bounds.lowerRight().y,
- 0,
- 0 ];
- selection.each(function(s) {
- selectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x);
- selectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y);
- selectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x);
- selectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y);
- });
- if(selectionBounds[0]+p.x < 0)
- p.x = -selectionBounds[0];
- if(selectionBounds[1]+p.y < 0)
- p.y = -selectionBounds[1];
- if(selectionBounds[2]+p.x > this.facade.getCanvas().bounds.lowerRight().x)
- p.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2];
- if(selectionBounds[3]+p.y > this.facade.getCanvas().bounds.lowerRight().y)
- p.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3];
-
- if(p.x!=0 || p.y!=0) {
- // Instantiate the moveCommand
- var commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)];
- // Execute the commands
- this.facade.executeCommands(commands);
- }
-
- }
- },
-
- getUndockedCommant: function(shapes){
- var undockEdgeCommand = ORYX.Core.Command.extend({
- construct: function(moveShapes){
- this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact();
- },
- execute: function(){
- this.dockers.each(function(el){
- el.docker.setDockedShape(undefined);
- })
- },
- rollback: function(){
- this.dockers.each(function(el){
- el.docker.setDockedShape(el.dockedShape);
- el.docker.setReferencePoint(el.refPoint);
- //el.docker.update();
- })
- }
- });
-
- command = new undockEdgeCommand( shapes );
- command.execute();
- return command;
- },
-
- // /**
- // * The key handler for this plugin. Every action from the set of cut, copy,
- // * paste and delete should be accessible trough simple keyboard shortcuts.
- // * This method checks whether any event triggers one of those actions.
- // *
- // * @param {Object} event The keyboard event that should be analysed for
- // * triggering of this plugin.
- // */
- // keyHandler: function(event){
- // //TODO document what event.which is.
- //
- // ORYX.Log.debug("keysMove.js handles a keyEvent.");
- //
- // // assure we have the current event.
- // if (!event)
- // event = window.event;
- //
- // // get the currently pressed key and state of control key.
- // var pressedKey = event.which || event.keyCode;
- // var ctrlPressed = event.ctrlKey;
- //
- // // if the key is one of the arrow keys, forward to move and return.
- // if ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT,
- // ORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) {
- //
- // this.move(pressedKey, !ctrlPressed);
- // return;
- // }
- //
- // }
-
- });
- /**
- * Copyright (c) 2009
- * Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins) { ORYX.Plugins = {} }
- if(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} }
- new function(){
-
- /**
- * Edge layouter is an implementation to layout an edge
- * @class ORYX.Plugins.Layouter.EdgeLayouter
- * @author Willi Tscheschner
- */
- ORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({
-
- /**
- * Layout only Edges
- */
- layouted : [ "http://b3mn.org/stencilset/bpmn1.1#SequenceFlow",
- "http://b3mn.org/stencilset/bpmn1.1#MessageFlow",
- "http://b3mn.org/stencilset/timjpdl3#SequenceFlow",
- "http://b3mn.org/stencilset/jbpm4#SequenceFlow",
- "http://b3mn.org/stencilset/bpmn2.0#MessageFlow",
- "http://b3mn.org/stencilset/bpmn2.0#SequenceFlow",
- "http://b3mn.org/stencilset/bpmn2.0choreography#MessageFlow",
- "http://b3mn.org/stencilset/bpmn2.0choreography#SequenceFlow",
- "http://b3mn.org/stencilset/bpmn2.0conversation#ConversationLink",
- "http://b3mn.org/stencilset/epc#ControlFlow",
- "http://www.signavio.com/stencilsets/processmap#ProcessLink",
- "http://www.signavio.com/stencilsets/organigram#connection"],
-
- /**
- * Layout a set on edges
- * @param {Object} edges
- */
- layout: function(edges){
- edges.each(function(edge){
- this.doLayout(edge)
- }.bind(this))
- },
-
- /**
- * Layout one edge
- * @param {Object} edge
- */
- doLayout: function(edge){
- // Get from and to node
- var from = edge.getIncomingNodes()[0];
- var to = edge.getOutgoingNodes()[0];
-
- // Return if one is null
- if (!from || !to) { return }
-
- var positions = this.getPositions(from, to, edge);
-
- if (positions.length > 0){
- this.setDockers(edge, positions[0].a, positions[0].b);
- }
-
- },
-
- /**
- * Returns a set on positions which are not containt either
- * in the bounds in from or to.
- * @param {Object} from Shape where the edge is come from
- * @param {Object} to Shape where the edge is leading to
- * @param {Object} edge Edge between from and to
- */
- getPositions : function(from, to, edge){
-
- // Get absolute bounds
- var ab = from.absoluteBounds();
- var bb = to.absoluteBounds();
-
- // Get center from and to
- var a = ab.center();
- var b = bb.center();
-
- var am = ab.midPoint();
- var bm = bb.midPoint();
-
- // Get first and last reference point
- var first = Object.clone(edge.dockers.first().referencePoint);
- var last = Object.clone(edge.dockers.last().referencePoint);
- // Get the absolute one
- var aFirst = edge.dockers.first().getAbsoluteReferencePoint();
- var aLast = edge.dockers.last().getAbsoluteReferencePoint();
-
- // IF ------>
- // or |
- // V
- // Do nothing
- if (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) {
- return []
- }
-
- // Calc center position, between a and b
- // depending on there weight
- var m = {}
- m.x = a.x < b.x ?
- (((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2):
- (((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2);
- m.y = a.y < b.y ?
- (((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2):
- (((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2);
-
-
- // Enlarge both bounds with 10
- ab.widen(5); // Wide the from less than
- bb.widen(20);// the to because of the arrow from the edge
-
- var positions = [];
- var off = this.getOffset.bind(this);
-
- // Checks ----+
- // |
- // V
- if (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) {
- positions.push({
- a : {x:b.x+off(last,bm,"x"),y:a.y+off(first,am,"y")},
- z : this.getWeight(from, a.x < b.x ? "r" : "l", to, a.y < b.y ? "t" : "b", edge)
- });
- }
-
- // Checks |
- // +--->
- if (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) {
- positions.push({
- a : {x:a.x+off(first,am,"x"),y:b.y+off(last,bm,"y")},
- z : this.getWeight(from, a.y < b.y ? "b" : "t", to, a.x < b.x ? "l" : "r", edge)
- });
- }
-
- // Checks --+
- // |
- // +--->
- if (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) {
- positions.push({
- a : {x:m.x,y:a.y+off(first,am,"y")},
- b : {x:m.x,y:b.y+off(last,bm,"y")},
- z : this.getWeight(from, "r", to, "l", edge, a.x > b.x)
- });
- }
-
- // Checks |
- // +---+
- // |
- // V
- if (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) {
- positions.push({
- a : {x:a.x+off(first,am,"x"),y:m.y},
- b : {x:b.x+off(last,bm,"x"),y:m.y},
- z : this.getWeight(from, "b", to, "t", edge, a.y > b.y)
- });
- }
-
- // Sort DESC of weights
- return positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)});
- },
-
- /**
- * Returns a offset for the pos to the center of the bounds
- *
- * @param {Object} val
- * @param {Object} pos2
- * @param {String} dir Direction x|y
- */
- getOffset: function(pos, pos2, dir){
- return pos[dir] - pos2[dir];
- },
-
- /**
- * Returns a value which shows the weight for this configuration
- *
- * @param {Object} from Shape which is coming from
- * @param {String} d1 Direction where is goes
- * @param {Object} to Shape which goes to
- * @param {String} d2 Direction where it comes to
- * @param {Object} edge Edge between from and to
- * @param {Boolean} reverse Reverse the direction (e.g. "r" -> "l")
- */
- getWeight: function(from, d1, to, d2, edge, reverse){
-
- d1 = (d1||"").toLowerCase();
- d2 = (d2||"").toLowerCase();
-
- if (!["t","r","b","l"].include(d1)){ d1 = "r"}
- if (!["t","r","b","l"].include(d2)){ d1 = "l"}
-
- // If reverse is set
- if (reverse) {
- // Reverse d1 and d2
- d1 = d1=="t"?"b":(d1=="r"?"l":(d1=="b"?"t":(d1=="l"?"r":"r")))
- d2 = d2=="t"?"b":(d2=="r"?"l":(d2=="b"?"t":(d2=="l"?"r":"r")))
- }
-
-
- var weight = 0;
- // Get rules for from "out" and to "in"
- var dr1 = this.facade.getRules().getLayoutingRules(from, edge)["out"];
- var dr2 = this.facade.getRules().getLayoutingRules(to, edge)["in"];
- var fromWeight = dr1[d1];
- var toWeight = dr2[d2];
- /**
- * Return a true if the center 1 is in the same direction than center 2
- * @param {Object} direction
- * @param {Object} center1
- * @param {Object} center2
- */
- var sameDirection = function(direction, center1, center2){
- switch(direction){
- case "t": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y
- case "r": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2
- case "b": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y
- case "l": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2
- default: return false;
- }
- }
- // Check if there are same incoming edges from 'from'
- var sameIncomingFrom = from
- .getIncomingShapes()
- .findAll(function(a){ return a instanceof ORYX.Core.Edge})
- .any(function(e){
- return sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center());
- });
- // Check if there are same outgoing edges from 'to'
- var sameOutgoingTo = to
- .getOutgoingShapes()
- .findAll(function(a){ return a instanceof ORYX.Core.Edge})
- .any(function(e){
- return sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center());
- });
-
- // If there are equivalent edges, set 0
- //fromWeight = sameIncomingFrom ? 0 : fromWeight;
- //toWeight = sameOutgoingTo ? 0 : toWeight;
-
- // Get the sum of "out" and the direction plus "in" and the direction
- return (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight);
- },
-
- /**
- * Removes all current dockers from the node
- * (except the start and end) and adds two new
- * dockers, on the position a and b.
- * @param {Object} edge
- * @param {Object} a
- * @param {Object} b
- */
- setDockers: function(edge, a, b){
- if (!edge){ return }
-
- // Remove all dockers (implicit,
- // start and end dockers will not removed)
- edge.dockers.each(function(r){
- edge.removeDocker(r);
- });
-
- // For a and b (if exists), create
- // a new docker and set position
- [a, b].compact().each(function(pos){
- var docker = edge.createDocker(undefined, pos);
- docker.bounds.centerMoveTo(pos);
- });
-
- // Update all dockers from the edge
- edge.dockers.each(function(docker){
- docker.update()
- })
-
- // Update edge
- //edge.refresh();
- edge._update(true);
-
- }
- });
-
-
- }()
- /**
- * Copyright (c) 2009
- * Sven Wagner-Boysen, Willi Tscheschner
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- **/
- if(!ORYX.Plugins)
- ORYX.Plugins = new Object();
- new function(){
-
- ORYX.Plugins.BPMN2_0 = {
-
- /**
- * Constructor
- * @param {Object} Facade: The Facade of the Editor
- */
- construct: function(facade){
- this.facade = facade;
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED, this.handleDockerDocked.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED, this.handlePropertyChanged.bind(this));
- this.facade.registerOnEvent('layout.bpmn2_0.subprocess', this.handleSubProcess.bind(this));
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, this.handleShapeRemove.bind(this));
-
- this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.afterLoad.bind(this));
-
- this.namespace = undefined;
- },
-
- hashedSubProcesses: {},
-
- hashChildShapes: function(shape){
- var children = shape.getChildNodes();
- children.each(function(child){
- if (this.hashedSubProcesses[child.id]){
- this.hashedSubProcesses[child.id] = child.absoluteXY();
- this.hashedSubProcesses[child.id].width = child.bounds.width();
- this.hashedSubProcesses[child.id].height = child.bounds.height();
- this.hashChildShapes(child);
- }
- }.bind(this));
- },
-
- /**
- * Handle the layouting of a sub process.
- * Mainly to adjust the child dockers of a sub process.
- *
- */
- handleSubProcess : function(option) {
-
- var sh = option.shape;
-
- if (!this.hashedSubProcesses[sh.id]) {
- this.hashedSubProcesses[sh.id] = sh.absoluteXY();
- this.hashedSubProcesses[sh.id].width = sh.bounds.width();
- this.hashedSubProcesses[sh.id].height = sh.bounds.height();
- return;
- }
-
- var offset = sh.absoluteXY();
- offset.x -= this.hashedSubProcesses[sh.id].x;
- offset.y -= this.hashedSubProcesses[sh.id].y;
-
- var resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height();
-
- this.hashedSubProcesses[sh.id] = sh.absoluteXY();
- this.hashedSubProcesses[sh.id].width = sh.bounds.width();
- this.hashedSubProcesses[sh.id].height = sh.bounds.height();
- this.hashChildShapes(sh);
-
-
- // Move dockers only if currently is not resizing
- if (this.facade.isExecutingCommands()&&!resized) {
- this.moveChildDockers(sh, offset);
- }
- },
-
- moveChildDockers: function(shape, offset){
-
- if (!offset.x && !offset.y) {
- return;
- }
-
- var children = shape.getChildNodes(true);
-
- // Get all nodes
- var dockers = children
- // Get all incoming and outgoing edges
- .map(function(node){
- return [].concat(node.getIncomingShapes())
- .concat(node.getOutgoingShapes())
- })
- // Flatten all including arrays into one
- .flatten()
- // Get every edge only once
- .uniq()
- // Get all dockers
- .map(function(edge){
- return edge.dockers.length > 2 ?
- edge.dockers.slice(1, edge.dockers.length-1) :
- [];
- })
- // Flatten the dockers lists
- .flatten();
-
- var abs = shape.absoluteBounds();
- abs.moveBy(-offset.x, -offset.y)
- var obj = {};
- dockers.each(function(docker){
-
- if (docker.isChanged){
- return;
- }
-
- var off = Object.clone(offset);
-
- if (!abs.isIncluded(docker.bounds.center())){
- var index = docker.parent.dockers.indexOf(docker);
- var size = docker.parent.dockers.length;
- var from = docker.parent.getSource();
- var to = docker.parent.getTarget();
-
- var bothAreIncluded = children.include(from) && children.include(to);
-
- if (!bothAreIncluded){
- var previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index-1].bounds.center()) : false;
- var nextIsOver = index !== size-1 ? abs.isIncluded(docker.parent.dockers[index+1].bounds.center()) : false;
-
- if (!previousIsOver && !nextIsOver){ return; }
-
- var ref = docker.parent.dockers[previousIsOver ? index-1 : index+1];
- if (Math.abs(-Math.abs(ref.bounds.center().x-docker.bounds.center().x)) < 2){
- off.y = 0;
- } else if(Math.abs(-Math.abs(ref.bounds.center().y-docker.bounds.center().y)) < 2){
- off.x = 0;
- } else {
- return;
- }
- }
-
- }
-
- obj[docker.getId()] = {
- docker:docker,
- offset:off
- }
- })
-
- // Set dockers
- this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]);
-
- },
-
- /**
- * DragDocker.Docked Handler
- *
- */
- handleDockerDocked: function(options) {
- var namespace = this.getNamespace();
-
- var edge = options.parent;
- var edgeSource = options.target;
-
- if(edge.getStencil().id() === namespace + "SequenceFlow") {
- var isGateway = edgeSource.getStencil().groups().find(function(group) {
- if(group == "Gateways")
- return group;
- });
- if(!isGateway && (edge.properties["oryx-conditiontype"] == "Expression"))
- // show diamond on edge source
- edge.setProperty("oryx-showdiamondmarker", true);
- else
- // do not show diamond on edge source
- edge.setProperty("oryx-showdiamondmarker", false);
-
- // update edge rendering
- //edge.update();
-
- this.facade.getCanvas().update();
- }
- },
-
- /**
- * PropertyWindow.PropertyChanged Handler
- */
- handlePropertyChanged: function(option) {
- var namespace = this.getNamespace();
-
- var shapes = option.elements;
- var propertyKey = option.key;
- var propertyValue = option.value;
-
- var changed = false;
- shapes.each(function(shape){
- if((shape.getStencil().id() === namespace + "SequenceFlow") &&
- (propertyKey === "oryx-conditiontype")) {
-
- if(propertyValue != "Expression")
- // Do not show the Diamond
- shape.setProperty("oryx-showdiamondmarker", false);
- else {
- var incomingShapes = shape.getIncomingShapes();
-
- if(!incomingShapes) {
- shape.setProperty("oryx-showdiamondmarker", true);
- }
-
- var incomingGateway = incomingShapes.find(function(aShape) {
- var foundGateway = aShape.getStencil().groups().find(function(group) {
- if(group == "Gateways")
- return group;
- });
- if(foundGateway)
- return foundGateway;
- });
-
- if(!incomingGateway)
- // show diamond on edge source
- shape.setProperty("oryx-showdiamondmarker", true);
- else
- // do not show diamond
- shape.setProperty("oryx-showdiamondmarker", false);
- }
-
- changed = true;
- }
- }.bind(this));
-
- if(changed) {this.facade.getCanvas().update();}
-
- },
-
- hashedPoolPositions : {},
- hashedLaneDepth : {},
- hashedBounds : {},
- hashedPositions: {},
-
- isResized: function(shape, bounds){
-
- if (!bounds||!shape){
- return false;
- }
-
- var oldB = bounds;
- //var oldXY = oldB.upperLeft();
- //var xy = shape.absoluteXY();
- return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0
- },
-
- getDepth: function(child, parent){
-
- var i=0;
- while(child && child.parent && child !== parent){
- child = child.parent;
- ++i
- }
- return i;
- },
-
- updateDepth: function(lane, fromDepth, toDepth){
-
- var xOffset = (fromDepth - toDepth) * 30;
-
- lane.getChildNodes().each(function(shape){
- shape.bounds.moveBy(xOffset, 0);
-
- [].concat(children[j].getIncomingShapes())
- .concat(children[j].getOutgoingShapes())
-
- })
-
- },
-
- moveBy: function(pos, offset){
- pos.x += offset.x;
- pos.y += offset.y;
- return pos;
- },
-
- getHashedBounds: function(shape){
- return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds();
- },
-
- getNamespace: function() {
- if(!this.namespace) {
- var stencilsets = this.facade.getStencilSets();
- if(stencilsets.keys()) {
- this.namespace = stencilsets.keys()[0];
- } else {
- return undefined;
- }
- }
- return this.namespace;
- }
- };
-
- ORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0);
-
- }()
|