Format.js 139 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701
  1. /**
  2. * Copyright (c) 2006-2012, JGraph Ltd
  3. */
  4. Format = function(editorUi, container)
  5. {
  6. this.editorUi = editorUi;
  7. this.container = container;
  8. };
  9. /**
  10. * Returns information about the current selection.
  11. */
  12. Format.prototype.labelIndex = 0;
  13. /**
  14. * Returns information about the current selection.
  15. */
  16. Format.prototype.currentIndex = 0;
  17. /**
  18. * Adds the label menu items to the given menu and parent.
  19. */
  20. Format.prototype.init = function()
  21. {
  22. var ui = this.editorUi;
  23. var editor = ui.editor;
  24. var graph = editor.graph;
  25. this.update = mxUtils.bind(this, function(sender, evt)
  26. {
  27. this.clearSelectionState();
  28. this.refresh();
  29. });
  30. graph.getSelectionModel().addListener(mxEvent.CHANGE, this.update);
  31. graph.addListener(mxEvent.EDITING_STARTED, this.update);
  32. graph.addListener(mxEvent.EDITING_STOPPED, this.update);
  33. graph.getModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function()
  34. {
  35. this.clearSelectionState();
  36. }));
  37. graph.addListener(mxEvent.ROOT, mxUtils.bind(this, function()
  38. {
  39. this.refresh();
  40. }));
  41. this.refresh();
  42. };
  43. /**
  44. * Returns information about the current selection.
  45. */
  46. Format.prototype.clearSelectionState = function()
  47. {
  48. this.selectionState = null;
  49. };
  50. /**
  51. * Returns information about the current selection.
  52. */
  53. Format.prototype.getSelectionState = function()
  54. {
  55. if (this.selectionState == null)
  56. {
  57. this.selectionState = this.createSelectionState();
  58. }
  59. return this.selectionState;
  60. };
  61. /**
  62. * Returns information about the current selection.
  63. */
  64. Format.prototype.createSelectionState = function()
  65. {
  66. var cells = this.editorUi.editor.graph.getSelectionCells();
  67. var result = this.initSelectionState();
  68. for (var i = 0; i < cells.length; i++)
  69. {
  70. this.updateSelectionStateForCell(result, cells[i], cells);
  71. }
  72. return result;
  73. };
  74. /**
  75. * Returns information about the current selection.
  76. */
  77. Format.prototype.initSelectionState = function()
  78. {
  79. return {vertices: [], edges: [], x: null, y: null, width: null, height: null, style: {},
  80. containsImage: false, containsLabel: false, fill: true, glass: true, rounded: true,
  81. comic: true, autoSize: false, image: true, shadow: true};
  82. };
  83. /**
  84. * Returns information about the current selection.
  85. */
  86. Format.prototype.updateSelectionStateForCell = function(result, cell, cells)
  87. {
  88. var graph = this.editorUi.editor.graph;
  89. if (graph.getModel().isVertex(cell))
  90. {
  91. result.vertices.push(cell);
  92. var geo = graph.getCellGeometry(cell);
  93. if (geo != null)
  94. {
  95. if (geo.width > 0)
  96. {
  97. if (result.width == null)
  98. {
  99. result.width = geo.width;
  100. }
  101. else if (result.width != geo.width)
  102. {
  103. result.width = '';
  104. }
  105. }
  106. else
  107. {
  108. result.containsLabel = true;
  109. }
  110. if (geo.height > 0)
  111. {
  112. if (result.height == null)
  113. {
  114. result.height = geo.height;
  115. }
  116. else if (result.height != geo.height)
  117. {
  118. result.height = '';
  119. }
  120. }
  121. else
  122. {
  123. result.containsLabel = true;
  124. }
  125. if (!geo.relative || geo.offset != null)
  126. {
  127. var x = (geo.relative) ? geo.offset.x : geo.x;
  128. var y = (geo.relative) ? geo.offset.y : geo.y;
  129. if (result.x == null)
  130. {
  131. result.x = x;
  132. }
  133. else if (result.x != x)
  134. {
  135. result.x = '';
  136. }
  137. if (result.y == null)
  138. {
  139. result.y = y;
  140. }
  141. else if (result.y != y)
  142. {
  143. result.y = '';
  144. }
  145. }
  146. }
  147. }
  148. else if (graph.getModel().isEdge(cell))
  149. {
  150. result.edges.push(cell);
  151. }
  152. var state = graph.view.getState(cell);
  153. if (state != null)
  154. {
  155. result.autoSize = result.autoSize || this.isAutoSizeState(state);
  156. result.glass = result.glass && this.isGlassState(state);
  157. result.rounded = result.rounded && this.isRoundedState(state);
  158. result.comic = result.comic && this.isComicState(state);
  159. result.image = result.image && this.isImageState(state);
  160. result.shadow = result.shadow && this.isShadowState(state);
  161. result.fill = result.fill && this.isFillState(state);
  162. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  163. result.containsImage = result.containsImage || shape == 'image';
  164. for (var key in state.style)
  165. {
  166. var value = state.style[key];
  167. if (value != null)
  168. {
  169. if (result.style[key] == null)
  170. {
  171. result.style[key] = value;
  172. }
  173. else if (result.style[key] != value)
  174. {
  175. result.style[key] = '';
  176. }
  177. }
  178. }
  179. }
  180. };
  181. /**
  182. * Returns information about the current selection.
  183. */
  184. Format.prototype.isFillState = function(state)
  185. {
  186. return state.view.graph.model.isVertex(state.cell) ||
  187. mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'arrow' ||
  188. mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'flexArrow';
  189. };
  190. /**
  191. * Returns information about the current selection.
  192. */
  193. Format.prototype.isGlassState = function(state)
  194. {
  195. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  196. return (shape == 'label' || shape == 'rectangle' || shape == 'internalStorage' ||
  197. shape == 'ext' || shape == 'umlLifeline' || shape == 'swimlane' ||
  198. shape == 'process');
  199. };
  200. /**
  201. * Returns information about the current selection.
  202. */
  203. Format.prototype.isRoundedState = function(state)
  204. {
  205. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  206. return (shape == 'label' || shape == 'rectangle' || shape == 'internalStorage' || shape == 'corner' ||
  207. shape == 'parallelogram' || shape == 'swimlane' || shape == 'triangle' || shape == 'trapezoid' ||
  208. shape == 'ext' || shape == 'step' || shape == 'tee' || shape == 'process' || shape == 'link' ||
  209. shape == 'rhombus' || shape == 'offPageConnector' || shape == 'loopLimit' || shape == 'hexagon' ||
  210. shape == 'manualInput' || shape == 'curlyBracket' || shape == 'singleArrow' ||
  211. shape == 'doubleArrow' || shape == 'flexArrow' || shape == 'card' || shape == 'umlLifeline');
  212. };
  213. /**
  214. * Returns information about the current selection.
  215. */
  216. Format.prototype.isComicState = function(state)
  217. {
  218. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  219. return mxUtils.indexOf(['label', 'rectangle', 'internalStorage', 'corner', 'parallelogram', 'note', 'collate',
  220. 'swimlane', 'triangle', 'trapezoid', 'ext', 'step', 'tee', 'process', 'link', 'rhombus',
  221. 'offPageConnector', 'loopLimit', 'hexagon', 'manualInput', 'singleArrow', 'doubleArrow',
  222. 'flexArrow', 'card', 'umlLifeline', 'connector', 'folder', 'component', 'sortShape',
  223. 'cross', 'umlFrame', 'cube', 'isoCube', 'isoRectangle'], shape) >= 0;
  224. };
  225. /**
  226. * Returns information about the current selection.
  227. */
  228. Format.prototype.isAutoSizeState = function(state)
  229. {
  230. return mxUtils.getValue(state.style, mxConstants.STYLE_AUTOSIZE, null) == '1';
  231. };
  232. /**
  233. * Returns information about the current selection.
  234. */
  235. Format.prototype.isImageState = function(state)
  236. {
  237. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  238. return (shape == 'label' || shape == 'image');
  239. };
  240. /**
  241. * Returns information about the current selection.
  242. */
  243. Format.prototype.isShadowState = function(state)
  244. {
  245. var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  246. return (shape != 'image');
  247. };
  248. /**
  249. * Adds the label menu items to the given menu and parent.
  250. */
  251. Format.prototype.clear = function()
  252. {
  253. this.container.innerHTML = '';
  254. // Destroy existing panels
  255. if (this.panels != null)
  256. {
  257. for (var i = 0; i < this.panels.length; i++)
  258. {
  259. this.panels[i].destroy();
  260. }
  261. }
  262. this.panels = [];
  263. };
  264. /**
  265. * Adds the label menu items to the given menu and parent.
  266. */
  267. Format.prototype.refresh = function()
  268. {
  269. // Performance tweak: No refresh needed if not visible
  270. if (this.container.style.width == '0px')
  271. {
  272. return;
  273. }
  274. this.clear();
  275. var ui = this.editorUi;
  276. var graph = ui.editor.graph;
  277. var div = document.createElement('div');
  278. div.style.whiteSpace = 'nowrap';
  279. div.style.color = 'rgb(112, 112, 112)';
  280. div.style.textAlign = 'left';
  281. div.style.cursor = 'default';
  282. var label = document.createElement('div');
  283. label.style.border = '1px solid #c0c0c0';
  284. label.style.borderWidth = '0px 0px 1px 0px';
  285. label.style.textAlign = 'center';
  286. label.style.fontWeight = 'bold';
  287. label.style.overflow = 'hidden';
  288. label.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  289. label.style.paddingTop = '8px';
  290. label.style.height = (mxClient.IS_QUIRKS) ? '34px' : '25px';
  291. label.style.width = '100%';
  292. this.container.appendChild(div);
  293. if (graph.isSelectionEmpty())
  294. {
  295. mxUtils.write(label, mxResources.get('diagram'));
  296. // Adds button to hide the format panel since
  297. // people don't seem to find the toolbar button
  298. // and the menu item in the format menu
  299. var img = document.createElement('img');
  300. img.setAttribute('border', '0');
  301. img.setAttribute('src', Dialog.prototype.closeImage);
  302. img.setAttribute('title', mxResources.get('hide'));
  303. img.style.position = 'absolute';
  304. img.style.display = 'block';
  305. img.style.right = '0px';
  306. img.style.top = '8px';
  307. img.style.cursor = 'pointer';
  308. img.style.marginTop = '1px';
  309. img.style.marginRight = '17px';
  310. img.style.border = '1px solid transparent';
  311. img.style.padding = '1px';
  312. img.style.opacity = 0.5;
  313. label.appendChild(img)
  314. mxEvent.addListener(img, 'click', function()
  315. {
  316. ui.actions.get('formatPanel').funct();
  317. });
  318. div.appendChild(label);
  319. this.panels.push(new DiagramFormatPanel(this, ui, div));
  320. }
  321. else if (graph.isEditing())
  322. {
  323. mxUtils.write(label, mxResources.get('text'));
  324. div.appendChild(label);
  325. this.panels.push(new TextFormatPanel(this, ui, div));
  326. }
  327. else
  328. {
  329. var containsLabel = this.getSelectionState().containsLabel;
  330. var currentLabel = null;
  331. var currentPanel = null;
  332. var addClickHandler = mxUtils.bind(this, function(elt, panel, index)
  333. {
  334. var clickHandler = mxUtils.bind(this, function(evt)
  335. {
  336. if (currentLabel != elt)
  337. {
  338. if (containsLabel)
  339. {
  340. this.labelIndex = index;
  341. }
  342. else
  343. {
  344. this.currentIndex = index;
  345. }
  346. if (currentLabel != null)
  347. {
  348. currentLabel.style.backgroundColor = '#d7d7d7';
  349. currentLabel.style.borderBottomWidth = '1px';
  350. }
  351. currentLabel = elt;
  352. currentLabel.style.backgroundColor = '';
  353. currentLabel.style.borderBottomWidth = '0px';
  354. if (currentPanel != panel)
  355. {
  356. if (currentPanel != null)
  357. {
  358. currentPanel.style.display = 'none';
  359. }
  360. currentPanel = panel;
  361. currentPanel.style.display = '';
  362. }
  363. }
  364. });
  365. mxEvent.addListener(elt, 'click', clickHandler);
  366. if (index == ((containsLabel) ? this.labelIndex : this.currentIndex))
  367. {
  368. // Invokes handler directly as a workaround for no click on DIV in KHTML.
  369. clickHandler();
  370. }
  371. });
  372. var idx = 0;
  373. label.style.backgroundColor = '#d7d7d7';
  374. label.style.borderLeftWidth = '1px';
  375. label.style.width = (containsLabel) ? '50%' : '33.3%';
  376. label.style.width = (containsLabel) ? '50%' : '33.3%';
  377. var label2 = label.cloneNode(false);
  378. var label3 = label2.cloneNode(false);
  379. // Workaround for ignored background in IE
  380. label2.style.backgroundColor = '#d7d7d7';
  381. label3.style.backgroundColor = '#d7d7d7';
  382. // Style
  383. if (containsLabel)
  384. {
  385. label2.style.borderLeftWidth = '0px';
  386. }
  387. else
  388. {
  389. label.style.borderLeftWidth = '0px';
  390. mxUtils.write(label, mxResources.get('style'));
  391. div.appendChild(label);
  392. var stylePanel = div.cloneNode(false);
  393. stylePanel.style.display = 'none';
  394. this.panels.push(new StyleFormatPanel(this, ui, stylePanel));
  395. this.container.appendChild(stylePanel);
  396. addClickHandler(label, stylePanel, idx++);
  397. }
  398. // Text
  399. mxUtils.write(label2, mxResources.get('text'));
  400. div.appendChild(label2);
  401. var textPanel = div.cloneNode(false);
  402. textPanel.style.display = 'none';
  403. this.panels.push(new TextFormatPanel(this, ui, textPanel));
  404. this.container.appendChild(textPanel);
  405. // Arrange
  406. mxUtils.write(label3, mxResources.get('arrange'));
  407. div.appendChild(label3);
  408. var arrangePanel = div.cloneNode(false);
  409. arrangePanel.style.display = 'none';
  410. this.panels.push(new ArrangePanel(this, ui, arrangePanel));
  411. this.container.appendChild(arrangePanel);
  412. addClickHandler(label2, textPanel, idx++);
  413. addClickHandler(label3, arrangePanel, idx++);
  414. }
  415. };
  416. /**
  417. * Base class for format panels.
  418. */
  419. BaseFormatPanel = function(format, editorUi, container)
  420. {
  421. this.format = format;
  422. this.editorUi = editorUi;
  423. this.container = container;
  424. this.listeners = [];
  425. };
  426. /**
  427. * Adds the given color option.
  428. */
  429. BaseFormatPanel.prototype.getSelectionState = function()
  430. {
  431. var graph = this.editorUi.editor.graph;
  432. var cells = graph.getSelectionCells();
  433. var shape = null;
  434. for (var i = 0; i < cells.length; i++)
  435. {
  436. var state = graph.view.getState(cells[i]);
  437. if (state != null)
  438. {
  439. var tmp = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
  440. if (tmp != null)
  441. {
  442. if (shape == null)
  443. {
  444. shape = tmp;
  445. }
  446. else if (shape != tmp)
  447. {
  448. return null;
  449. }
  450. }
  451. }
  452. }
  453. return shape;
  454. };
  455. /**
  456. * Install input handler.
  457. */
  458. BaseFormatPanel.prototype.installInputHandler = function(input, key, defaultValue, min, max, unit, textEditFallback, isFloat)
  459. {
  460. unit = (unit != null) ? unit : '';
  461. isFloat = (isFloat != null) ? isFloat : false;
  462. var ui = this.editorUi;
  463. var graph = ui.editor.graph;
  464. min = (min != null) ? min : 1;
  465. max = (max != null) ? max : 999;
  466. var selState = null;
  467. var updating = false;
  468. var update = mxUtils.bind(this, function(evt)
  469. {
  470. var value = (isFloat) ? parseFloat(input.value) : parseInt(input.value);
  471. // Special case: angle mod 360
  472. if (!isNaN(value) && key == mxConstants.STYLE_ROTATION)
  473. {
  474. // Workaround for decimal rounding errors in floats is to
  475. // use integer and round all numbers to two decimal point
  476. value = mxUtils.mod(Math.round(value * 100), 36000) / 100;
  477. }
  478. value = Math.min(max, Math.max(min, (isNaN(value)) ? defaultValue : value));
  479. if (graph.cellEditor.isContentEditing() && textEditFallback)
  480. {
  481. if (!updating)
  482. {
  483. updating = true;
  484. if (selState != null)
  485. {
  486. graph.cellEditor.restoreSelection(selState);
  487. selState = null;
  488. }
  489. textEditFallback(value);
  490. input.value = value + unit;
  491. // Restore focus and selection in input
  492. updating = false;
  493. }
  494. }
  495. else if (value != mxUtils.getValue(this.format.getSelectionState().style, key, defaultValue))
  496. {
  497. if (graph.isEditing())
  498. {
  499. graph.stopEditing(true);
  500. }
  501. graph.getModel().beginUpdate();
  502. try
  503. {
  504. graph.setCellStyles(key, value, graph.getSelectionCells());
  505. // Handles special case for fontSize where HTML labels are parsed and updated
  506. if (key == mxConstants.STYLE_FONTSIZE)
  507. {
  508. var cells = graph.getSelectionCells();
  509. for (var i = 0; i < cells.length; i++)
  510. {
  511. var cell = cells[i];
  512. // Changes font tags inside HTML labels
  513. if (graph.isHtmlLabel(cell))
  514. {
  515. var div = document.createElement('div');
  516. div.innerHTML = graph.convertValueToString(cell);
  517. var elts = div.getElementsByTagName('font');
  518. for (var j = 0; j < elts.length; j++)
  519. {
  520. elts[j].removeAttribute('size');
  521. elts[j].style.fontSize = value + 'px';
  522. }
  523. graph.cellLabelChanged(cell, div.innerHTML)
  524. }
  525. }
  526. }
  527. }
  528. finally
  529. {
  530. graph.getModel().endUpdate();
  531. }
  532. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [key],
  533. 'values', [value], 'cells', graph.getSelectionCells()));
  534. }
  535. input.value = value + unit;
  536. mxEvent.consume(evt);
  537. });
  538. if (textEditFallback && graph.cellEditor.isContentEditing())
  539. {
  540. // KNOWN: Arrow up/down clear selection text in quirks/IE 8
  541. // Text size via arrow button limits to 16 in IE11. Why?
  542. mxEvent.addListener(input, 'mousedown', function()
  543. {
  544. selState = graph.cellEditor.saveSelection();
  545. });
  546. mxEvent.addListener(input, 'touchstart', function()
  547. {
  548. selState = graph.cellEditor.saveSelection();
  549. });
  550. }
  551. mxEvent.addListener(input, 'change', update);
  552. mxEvent.addListener(input, 'blur', update);
  553. return update;
  554. };
  555. /**
  556. * Adds the given option.
  557. */
  558. BaseFormatPanel.prototype.createPanel = function()
  559. {
  560. var div = document.createElement('div');
  561. div.style.padding = '12px 0px 12px 18px';
  562. div.style.borderBottom = '1px solid #c0c0c0';
  563. return div;
  564. };
  565. /**
  566. * Adds the given option.
  567. */
  568. BaseFormatPanel.prototype.createTitle = function(title)
  569. {
  570. var div = document.createElement('div');
  571. div.style.padding = '0px 0px 6px 0px';
  572. div.style.whiteSpace = 'nowrap';
  573. div.style.overflow = 'hidden';
  574. div.style.width = '200px';
  575. div.style.fontWeight = 'bold';
  576. mxUtils.write(div, title);
  577. return div;
  578. };
  579. /**
  580. *
  581. */
  582. BaseFormatPanel.prototype.createStepper = function(input, update, step, height, disableFocus, defaultValue)
  583. {
  584. step = (step != null) ? step : 1;
  585. height = (height != null) ? height : 8;
  586. if (mxClient.IS_QUIRKS)
  587. {
  588. height = height - 2;
  589. }
  590. else if (mxClient.IS_MT || document.documentMode >= 8)
  591. {
  592. height = height + 1;
  593. }
  594. var stepper = document.createElement('div');
  595. mxUtils.setPrefixedStyle(stepper.style, 'borderRadius', '3px');
  596. stepper.style.border = '1px solid rgb(192, 192, 192)';
  597. stepper.style.position = 'absolute';
  598. var up = document.createElement('div');
  599. up.style.borderBottom = '1px solid rgb(192, 192, 192)';
  600. up.style.position = 'relative';
  601. up.style.height = height + 'px';
  602. up.style.width = '10px';
  603. up.className = 'geBtnUp';
  604. stepper.appendChild(up);
  605. var down = up.cloneNode(false);
  606. down.style.border = 'none';
  607. down.style.height = height + 'px';
  608. down.className = 'geBtnDown';
  609. stepper.appendChild(down);
  610. mxEvent.addListener(down, 'click', function(evt)
  611. {
  612. if (input.value == '')
  613. {
  614. input.value = defaultValue || '2';
  615. }
  616. var val = parseInt(input.value);
  617. if (!isNaN(val))
  618. {
  619. input.value = val - step;
  620. if (update != null)
  621. {
  622. update(evt);
  623. }
  624. }
  625. mxEvent.consume(evt);
  626. });
  627. mxEvent.addListener(up, 'click', function(evt)
  628. {
  629. if (input.value == '')
  630. {
  631. input.value = defaultValue || '0';
  632. }
  633. var val = parseInt(input.value);
  634. if (!isNaN(val))
  635. {
  636. input.value = val + step;
  637. if (update != null)
  638. {
  639. update(evt);
  640. }
  641. }
  642. mxEvent.consume(evt);
  643. });
  644. // Disables transfer of focus to DIV but also :active CSS
  645. // so it's only used for fontSize where the focus should
  646. // stay on the selected text, but not for any other input.
  647. if (disableFocus)
  648. {
  649. var currentSelection = null;
  650. mxEvent.addGestureListeners(stepper,
  651. function(evt)
  652. {
  653. // Workaround for lost current selection in page because of focus in IE
  654. if (mxClient.IS_QUIRKS || document.documentMode == 8)
  655. {
  656. currentSelection = document.selection.createRange();
  657. }
  658. mxEvent.consume(evt);
  659. },
  660. null,
  661. function(evt)
  662. {
  663. // Workaround for lost current selection in page because of focus in IE
  664. if (currentSelection != null)
  665. {
  666. try
  667. {
  668. currentSelection.select();
  669. }
  670. catch (e)
  671. {
  672. // ignore
  673. }
  674. currentSelection = null;
  675. mxEvent.consume(evt);
  676. }
  677. }
  678. );
  679. }
  680. return stepper;
  681. };
  682. /**
  683. * Adds the given option.
  684. */
  685. BaseFormatPanel.prototype.createOption = function(label, isCheckedFn, setCheckedFn, listener)
  686. {
  687. var div = document.createElement('div');
  688. div.style.padding = '6px 0px 1px 0px';
  689. div.style.whiteSpace = 'nowrap';
  690. div.style.overflow = 'hidden';
  691. div.style.width = '200px';
  692. div.style.height = (mxClient.IS_QUIRKS) ? '27px' : '18px';
  693. var cb = document.createElement('input');
  694. cb.setAttribute('type', 'checkbox');
  695. cb.style.margin = '0px 6px 0px 0px';
  696. div.appendChild(cb);
  697. var span = document.createElement('span');
  698. mxUtils.write(span, label);
  699. div.appendChild(span);
  700. var applying = false;
  701. var value = isCheckedFn();
  702. var apply = function(newValue)
  703. {
  704. if (!applying)
  705. {
  706. applying = true;
  707. if (newValue)
  708. {
  709. cb.setAttribute('checked', 'checked');
  710. cb.defaultChecked = true;
  711. cb.checked = true;
  712. }
  713. else
  714. {
  715. cb.removeAttribute('checked');
  716. cb.defaultChecked = false;
  717. cb.checked = false;
  718. }
  719. if (value != newValue)
  720. {
  721. value = newValue;
  722. // Checks if the color value needs to be updated in the model
  723. if (isCheckedFn() != value)
  724. {
  725. setCheckedFn(value);
  726. }
  727. }
  728. applying = false;
  729. }
  730. };
  731. mxEvent.addListener(div, 'click', function(evt)
  732. {
  733. // Toggles checkbox state for click on label
  734. var source = mxEvent.getSource(evt);
  735. if (source == div || source == span)
  736. {
  737. cb.checked = !cb.checked;
  738. }
  739. apply(cb.checked);
  740. });
  741. apply(value);
  742. if (listener != null)
  743. {
  744. listener.install(apply);
  745. this.listeners.push(listener);
  746. }
  747. return div;
  748. };
  749. /**
  750. * The string 'null' means use null in values.
  751. */
  752. BaseFormatPanel.prototype.createCellOption = function(label, key, defaultValue, enabledValue, disabledValue, fn, action, stopEditing)
  753. {
  754. enabledValue = (enabledValue != null) ? ((enabledValue == 'null') ? null : enabledValue) : '1';
  755. disabledValue = (disabledValue != null) ? ((disabledValue == 'null') ? null : disabledValue) : '0';
  756. var ui = this.editorUi;
  757. var editor = ui.editor;
  758. var graph = editor.graph;
  759. return this.createOption(label, function()
  760. {
  761. // Seems to be null sometimes, not sure why...
  762. var state = graph.view.getState(graph.getSelectionCell());
  763. if (state != null)
  764. {
  765. return mxUtils.getValue(state.style, key, defaultValue) != disabledValue;
  766. }
  767. return null;
  768. }, function(checked)
  769. {
  770. if (stopEditing)
  771. {
  772. graph.stopEditing();
  773. }
  774. if (action != null)
  775. {
  776. action.funct();
  777. }
  778. else
  779. {
  780. graph.getModel().beginUpdate();
  781. try
  782. {
  783. var value = (checked) ? enabledValue : disabledValue;
  784. graph.setCellStyles(key, value, graph.getSelectionCells());
  785. if (fn != null)
  786. {
  787. fn(graph.getSelectionCells(), value);
  788. }
  789. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [key],
  790. 'values', [value], 'cells', graph.getSelectionCells()));
  791. }
  792. finally
  793. {
  794. graph.getModel().endUpdate();
  795. }
  796. }
  797. },
  798. {
  799. install: function(apply)
  800. {
  801. this.listener = function()
  802. {
  803. // Seems to be null sometimes, not sure why...
  804. var state = graph.view.getState(graph.getSelectionCell());
  805. if (state != null)
  806. {
  807. apply(mxUtils.getValue(state.style, key, defaultValue) != disabledValue);
  808. }
  809. };
  810. graph.getModel().addListener(mxEvent.CHANGE, this.listener);
  811. },
  812. destroy: function()
  813. {
  814. graph.getModel().removeListener(this.listener);
  815. }
  816. });
  817. };
  818. /**
  819. * Adds the given color option.
  820. */
  821. BaseFormatPanel.prototype.createColorOption = function(label, getColorFn, setColorFn, defaultColor, listener, callbackFn, hideCheckbox)
  822. {
  823. var div = document.createElement('div');
  824. div.style.padding = '6px 0px 1px 0px';
  825. div.style.whiteSpace = 'nowrap';
  826. div.style.overflow = 'hidden';
  827. div.style.width = '200px';
  828. div.style.height = (mxClient.IS_QUIRKS) ? '27px' : '18px';
  829. var cb = document.createElement('input');
  830. cb.setAttribute('type', 'checkbox');
  831. cb.style.margin = '0px 6px 0px 0px';
  832. if (!hideCheckbox)
  833. {
  834. div.appendChild(cb);
  835. }
  836. var span = document.createElement('span');
  837. mxUtils.write(span, label);
  838. div.appendChild(span);
  839. var applying = false;
  840. var value = getColorFn();
  841. var btn = null;
  842. var apply = function(color, disableUpdate)
  843. {
  844. if (!applying)
  845. {
  846. applying = true;
  847. btn.innerHTML = '<div style="width:' + ((mxClient.IS_QUIRKS) ? '30' : '36') +
  848. 'px;height:12px;margin:3px;border:1px solid black;background-color:' +
  849. ((color != null && color != mxConstants.NONE) ? color : defaultColor) + ';"></div>';
  850. // Fine-tuning in Firefox, quirks mode and IE8 standards
  851. if (mxClient.IS_MT || mxClient.IS_QUIRKS || document.documentMode == 8)
  852. {
  853. btn.firstChild.style.margin = '0px';
  854. }
  855. if (color != null && color != mxConstants.NONE)
  856. {
  857. cb.setAttribute('checked', 'checked');
  858. cb.defaultChecked = true;
  859. cb.checked = true;
  860. }
  861. else
  862. {
  863. cb.removeAttribute('checked');
  864. cb.defaultChecked = false;
  865. cb.checked = false;
  866. }
  867. btn.style.display = (cb.checked || hideCheckbox) ? '' : 'none';
  868. if (callbackFn != null)
  869. {
  870. callbackFn(color);
  871. }
  872. if (!disableUpdate && (hideCheckbox || value != color))
  873. {
  874. value = color;
  875. // Checks if the color value needs to be updated in the model
  876. if (hideCheckbox || getColorFn() != value)
  877. {
  878. setColorFn(value);
  879. }
  880. }
  881. applying = false;
  882. }
  883. };
  884. btn = mxUtils.button('', mxUtils.bind(this, function(evt)
  885. {
  886. this.editorUi.pickColor(value, apply);
  887. mxEvent.consume(evt);
  888. }));
  889. btn.style.position = 'absolute';
  890. btn.style.marginTop = '-4px';
  891. btn.style.right = (mxClient.IS_QUIRKS) ? '0px' : '20px';
  892. btn.style.height = '22px';
  893. btn.className = 'geColorBtn';
  894. btn.style.display = (cb.checked || hideCheckbox) ? '' : 'none';
  895. div.appendChild(btn);
  896. mxEvent.addListener(div, 'click', function(evt)
  897. {
  898. var source = mxEvent.getSource(evt);
  899. if (source == cb || source.nodeName != 'INPUT')
  900. {
  901. // Toggles checkbox state for click on label
  902. if (source != cb)
  903. {
  904. cb.checked = !cb.checked;
  905. }
  906. // Overrides default value with current value to make it easier
  907. // to restore previous value if the checkbox is clicked twice
  908. if (!cb.checked && value != null && value != mxConstants.NONE &&
  909. defaultColor != mxConstants.NONE)
  910. {
  911. defaultColor = value;
  912. }
  913. apply((cb.checked) ? defaultColor : mxConstants.NONE);
  914. }
  915. });
  916. apply(value, true);
  917. if (listener != null)
  918. {
  919. listener.install(apply);
  920. this.listeners.push(listener);
  921. }
  922. return div;
  923. };
  924. /**
  925. *
  926. */
  927. BaseFormatPanel.prototype.createCellColorOption = function(label, colorKey, defaultColor, callbackFn, setStyleFn)
  928. {
  929. var ui = this.editorUi;
  930. var editor = ui.editor;
  931. var graph = editor.graph;
  932. return this.createColorOption(label, function()
  933. {
  934. // Seems to be null sometimes, not sure why...
  935. var state = graph.view.getState(graph.getSelectionCell());
  936. if (state != null)
  937. {
  938. return mxUtils.getValue(state.style, colorKey, null);
  939. }
  940. return null;
  941. }, function(color)
  942. {
  943. graph.getModel().beginUpdate();
  944. try
  945. {
  946. if (setStyleFn != null)
  947. {
  948. setStyleFn(color);
  949. }
  950. graph.setCellStyles(colorKey, color, graph.getSelectionCells());
  951. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [colorKey],
  952. 'values', [color], 'cells', graph.getSelectionCells()));
  953. }
  954. finally
  955. {
  956. graph.getModel().endUpdate();
  957. }
  958. }, defaultColor || mxConstants.NONE,
  959. {
  960. install: function(apply)
  961. {
  962. this.listener = function()
  963. {
  964. // Seems to be null sometimes, not sure why...
  965. var state = graph.view.getState(graph.getSelectionCell());
  966. if (state != null)
  967. {
  968. apply(mxUtils.getValue(state.style, colorKey, null));
  969. }
  970. };
  971. graph.getModel().addListener(mxEvent.CHANGE, this.listener);
  972. },
  973. destroy: function()
  974. {
  975. graph.getModel().removeListener(this.listener);
  976. }
  977. }, callbackFn);
  978. };
  979. /**
  980. *
  981. */
  982. BaseFormatPanel.prototype.addArrow = function(elt, height)
  983. {
  984. height = (height != null) ? height : 10;
  985. var arrow = document.createElement('div');
  986. arrow.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  987. arrow.style.padding = '6px';
  988. arrow.style.paddingRight = '4px';
  989. var m = (10 - height);
  990. if (m == 2)
  991. {
  992. arrow.style.paddingTop = 6 + 'px';
  993. }
  994. else if (m > 0)
  995. {
  996. arrow.style.paddingTop = (6 - m) + 'px';
  997. }
  998. else
  999. {
  1000. arrow.style.marginTop = '-2px';
  1001. }
  1002. arrow.style.height = height + 'px';
  1003. arrow.style.borderLeft = '1px solid #a0a0a0';
  1004. arrow.innerHTML = '<img border="0" src="' + ((mxClient.IS_SVG) ? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHBJREFUeNpidHB2ZyAGsACxDRBPIKCuA6TwCBB/h2rABu4A8SYmKCcXiP/iUFgAxL9gCi8A8SwsirZCMQMTkmANEH9E4v+CmsaArvAdyNFI/FlQ92EoBIE+qCRIUz168DBgsU4OqhinQpgHMABAgAEALY4XLIsJ20oAAAAASUVORK5CYII=' :
  1005. IMAGE_PATH + '/dropdown.png') + '" style="margin-bottom:4px;">';
  1006. mxUtils.setOpacity(arrow, 70);
  1007. var symbol = elt.getElementsByTagName('div')[0];
  1008. if (symbol != null)
  1009. {
  1010. symbol.style.paddingRight = '6px';
  1011. symbol.style.marginLeft = '4px';
  1012. symbol.style.marginTop = '-1px';
  1013. symbol.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  1014. mxUtils.setOpacity(symbol, 60);
  1015. }
  1016. mxUtils.setOpacity(elt, 100);
  1017. elt.style.border = '1px solid #a0a0a0';
  1018. elt.style.backgroundColor = 'white';
  1019. elt.style.backgroundImage = 'none';
  1020. elt.style.width = 'auto';
  1021. elt.className += ' geColorBtn';
  1022. mxUtils.setPrefixedStyle(elt.style, 'borderRadius', '3px');
  1023. elt.appendChild(arrow);
  1024. return symbol;
  1025. };
  1026. /**
  1027. *
  1028. */
  1029. BaseFormatPanel.prototype.addUnitInput = function(container, unit, right, width, update, step, marginTop, disableFocus)
  1030. {
  1031. marginTop = (marginTop != null) ? marginTop : 0;
  1032. var input = document.createElement('input');
  1033. input.style.position = 'absolute';
  1034. input.style.textAlign = 'right';
  1035. input.style.marginTop = '-2px';
  1036. input.style.right = (right + 12) + 'px';
  1037. input.style.width = width + 'px';
  1038. container.appendChild(input);
  1039. var stepper = this.createStepper(input, update, step, null, disableFocus);
  1040. stepper.style.marginTop = (marginTop - 2) + 'px';
  1041. stepper.style.right = right + 'px';
  1042. container.appendChild(stepper);
  1043. return input;
  1044. };
  1045. /**
  1046. *
  1047. */
  1048. BaseFormatPanel.prototype.createRelativeOption = function(label, key, width, handler, init)
  1049. {
  1050. width = (width != null) ? width : 44;
  1051. var graph = this.editorUi.editor.graph;
  1052. var div = this.createPanel();
  1053. div.style.paddingTop = '10px';
  1054. div.style.paddingBottom = '10px';
  1055. mxUtils.write(div, label);
  1056. div.style.fontWeight = 'bold';
  1057. function update(evt)
  1058. {
  1059. if (handler != null)
  1060. {
  1061. handler(input);
  1062. }
  1063. else
  1064. {
  1065. var value = parseInt(input.value);
  1066. value = Math.min(100, Math.max(0, (isNaN(value)) ? 100 : value));
  1067. var state = graph.view.getState(graph.getSelectionCell());
  1068. if (state != null && value != mxUtils.getValue(state.style, key, 100))
  1069. {
  1070. // Removes entry in style (assumes 100 is default for relative values)
  1071. if (value == 100)
  1072. {
  1073. value = null;
  1074. }
  1075. graph.setCellStyles(key, value, graph.getSelectionCells());
  1076. }
  1077. input.value = ((value != null) ? value : '100') + ' %';
  1078. }
  1079. mxEvent.consume(evt);
  1080. };
  1081. var input = this.addUnitInput(div, '%', 20, width, update, 10, -15, handler != null);
  1082. if (key != null)
  1083. {
  1084. var listener = mxUtils.bind(this, function(sender, evt, force)
  1085. {
  1086. if (force || input != document.activeElement)
  1087. {
  1088. var ss = this.format.getSelectionState();
  1089. var tmp = parseInt(mxUtils.getValue(ss.style, key, 100));
  1090. input.value = (isNaN(tmp)) ? '' : tmp + ' %';
  1091. }
  1092. });
  1093. mxEvent.addListener(input, 'keydown', function(e)
  1094. {
  1095. if (e.keyCode == 13)
  1096. {
  1097. graph.container.focus();
  1098. mxEvent.consume(e);
  1099. }
  1100. else if (e.keyCode == 27)
  1101. {
  1102. listener(null, null, true);
  1103. graph.container.focus();
  1104. mxEvent.consume(e);
  1105. }
  1106. });
  1107. graph.getModel().addListener(mxEvent.CHANGE, listener);
  1108. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  1109. listener();
  1110. }
  1111. mxEvent.addListener(input, 'blur', update);
  1112. mxEvent.addListener(input, 'change', update);
  1113. if (init != null)
  1114. {
  1115. init(input);
  1116. }
  1117. return div;
  1118. };
  1119. /**
  1120. *
  1121. */
  1122. BaseFormatPanel.prototype.addLabel = function(div, title, right, width)
  1123. {
  1124. width = (width != null) ? width : 61;
  1125. var label = document.createElement('div');
  1126. mxUtils.write(label, title);
  1127. label.style.position = 'absolute';
  1128. label.style.right = right + 'px';
  1129. label.style.width = width + 'px';
  1130. label.style.marginTop = '6px';
  1131. label.style.textAlign = 'center';
  1132. div.appendChild(label);
  1133. };
  1134. /**
  1135. *
  1136. */
  1137. BaseFormatPanel.prototype.addKeyHandler = function(input, listener)
  1138. {
  1139. mxEvent.addListener(input, 'keydown', mxUtils.bind(this, function(e)
  1140. {
  1141. if (e.keyCode == 13)
  1142. {
  1143. this.editorUi.editor.graph.container.focus();
  1144. mxEvent.consume(e);
  1145. }
  1146. else if (e.keyCode == 27)
  1147. {
  1148. if (listener != null)
  1149. {
  1150. listener(null, null, true);
  1151. }
  1152. this.editorUi.editor.graph.container.focus();
  1153. mxEvent.consume(e);
  1154. }
  1155. }));
  1156. };
  1157. /**
  1158. *
  1159. */
  1160. BaseFormatPanel.prototype.styleButtons = function(elts)
  1161. {
  1162. for (var i = 0; i < elts.length; i++)
  1163. {
  1164. mxUtils.setPrefixedStyle(elts[i].style, 'borderRadius', '3px');
  1165. mxUtils.setOpacity(elts[i], 100);
  1166. elts[i].style.border = '1px solid #a0a0a0';
  1167. elts[i].style.padding = '4px';
  1168. elts[i].style.paddingTop = '3px';
  1169. elts[i].style.paddingRight = '1px';
  1170. elts[i].style.margin = '1px';
  1171. elts[i].style.width = '24px';
  1172. elts[i].style.height = '20px';
  1173. elts[i].className += ' geColorBtn';
  1174. }
  1175. };
  1176. /**
  1177. * Adds the label menu items to the given menu and parent.
  1178. */
  1179. BaseFormatPanel.prototype.destroy = function()
  1180. {
  1181. if (this.listeners != null)
  1182. {
  1183. for (var i = 0; i < this.listeners.length; i++)
  1184. {
  1185. this.listeners[i].destroy();
  1186. }
  1187. this.listeners = null;
  1188. }
  1189. };
  1190. /**
  1191. * Adds the label menu items to the given menu and parent.
  1192. */
  1193. ArrangePanel = function(format, editorUi, container)
  1194. {
  1195. BaseFormatPanel.call(this, format, editorUi, container);
  1196. this.init();
  1197. };
  1198. mxUtils.extend(ArrangePanel, BaseFormatPanel);
  1199. /**
  1200. * Adds the label menu items to the given menu and parent.
  1201. */
  1202. ArrangePanel.prototype.init = function()
  1203. {
  1204. var graph = this.editorUi.editor.graph;
  1205. var ss = this.format.getSelectionState();
  1206. this.container.appendChild(this.addLayerOps(this.createPanel()));
  1207. // Special case that adds two panels
  1208. this.addGeometry(this.container);
  1209. this.addEdgeGeometry(this.container);
  1210. this.container.appendChild(this.addAngle(this.createPanel()));
  1211. if (!ss.containsLabel)
  1212. {
  1213. this.container.appendChild(this.addFlip(this.createPanel()));
  1214. }
  1215. if (ss.vertices.length > 1)
  1216. {
  1217. this.container.appendChild(this.addAlign(this.createPanel()));
  1218. this.container.appendChild(this.addDistribute(this.createPanel()));
  1219. }
  1220. this.container.appendChild(this.addGroupOps(this.createPanel()));
  1221. };
  1222. /**
  1223. *
  1224. */
  1225. ArrangePanel.prototype.addLayerOps = function(div)
  1226. {
  1227. var ui = this.editorUi;
  1228. var btn = mxUtils.button(mxResources.get('toFront'), function(evt)
  1229. {
  1230. ui.actions.get('toFront').funct();
  1231. })
  1232. btn.setAttribute('title', mxResources.get('toFront') + ' (' + this.editorUi.actions.get('toFront').shortcut + ')');
  1233. btn.style.width = '100px';
  1234. btn.style.marginRight = '2px';
  1235. div.appendChild(btn);
  1236. var btn = mxUtils.button(mxResources.get('toBack'), function(evt)
  1237. {
  1238. ui.actions.get('toBack').funct();
  1239. })
  1240. btn.setAttribute('title', mxResources.get('toBack') + ' (' + this.editorUi.actions.get('toBack').shortcut + ')');
  1241. btn.style.width = '100px';
  1242. div.appendChild(btn);
  1243. return div;
  1244. };
  1245. /**
  1246. *
  1247. */
  1248. ArrangePanel.prototype.addGroupOps = function(div)
  1249. {
  1250. var ui = this.editorUi;
  1251. var graph = ui.editor.graph;
  1252. var cell = graph.getSelectionCell();
  1253. var ss = this.format.getSelectionState();
  1254. var count = 0;
  1255. div.style.paddingTop = '8px';
  1256. div.style.paddingBottom = '6px';
  1257. if (graph.getSelectionCount() > 1)
  1258. {
  1259. btn = mxUtils.button(mxResources.get('group'), function(evt)
  1260. {
  1261. ui.actions.get('group').funct();
  1262. })
  1263. btn.setAttribute('title', mxResources.get('group') + ' (' + this.editorUi.actions.get('group').shortcut + ')');
  1264. btn.style.width = '202px';
  1265. btn.style.marginBottom = '2px';
  1266. div.appendChild(btn);
  1267. count++;
  1268. }
  1269. else if (graph.getSelectionCount() == 1 && !graph.getModel().isEdge(cell) && !graph.isSwimlane(cell) &&
  1270. graph.getModel().getChildCount(cell) > 0)
  1271. {
  1272. btn = mxUtils.button(mxResources.get('ungroup'), function(evt)
  1273. {
  1274. ui.actions.get('ungroup').funct();
  1275. })
  1276. btn.setAttribute('title', mxResources.get('ungroup') + ' (' + this.editorUi.actions.get('ungroup').shortcut + ')');
  1277. btn.style.width = '202px';
  1278. btn.style.marginBottom = '2px';
  1279. div.appendChild(btn);
  1280. count++;
  1281. }
  1282. if (graph.getSelectionCount() == 1 && graph.getModel().isVertex(cell) &&
  1283. graph.getModel().isVertex(graph.getModel().getParent(cell)))
  1284. {
  1285. if (count > 0)
  1286. {
  1287. mxUtils.br(div);
  1288. }
  1289. btn = mxUtils.button(mxResources.get('removeFromGroup'), function(evt)
  1290. {
  1291. ui.actions.get('removeFromGroup').funct();
  1292. })
  1293. btn.setAttribute('title', mxResources.get('removeFromGroup'));
  1294. btn.style.width = '202px';
  1295. btn.style.marginBottom = '2px';
  1296. div.appendChild(btn);
  1297. count++;
  1298. }
  1299. else if (ss.edges.length > 0)
  1300. {
  1301. if (count > 0)
  1302. {
  1303. mxUtils.br(div);
  1304. }
  1305. btn = mxUtils.button(mxResources.get('clearWaypoints'), mxUtils.bind(this, function(evt)
  1306. {
  1307. this.editorUi.actions.get('clearWaypoints').funct();
  1308. }));
  1309. btn.setAttribute('title', mxResources.get('clearWaypoints'));
  1310. btn.style.width = '202px';
  1311. btn.style.marginBottom = '2px';
  1312. div.appendChild(btn);
  1313. count++;
  1314. }
  1315. if (graph.getSelectionCount() == 1)
  1316. {
  1317. if (count > 0)
  1318. {
  1319. mxUtils.br(div);
  1320. }
  1321. btn = mxUtils.button(mxResources.get('editData'), mxUtils.bind(this, function(evt)
  1322. {
  1323. this.editorUi.actions.get('editData').funct();
  1324. }));
  1325. btn.setAttribute('title', mxResources.get('editData') + ' (' + this.editorUi.actions.get('editData').shortcut + ')');
  1326. btn.style.width = '100px';
  1327. btn.style.marginBottom = '2px';
  1328. div.appendChild(btn);
  1329. count++;
  1330. btn = mxUtils.button(mxResources.get('editLink'), mxUtils.bind(this, function(evt)
  1331. {
  1332. this.editorUi.actions.get('editLink').funct();
  1333. }));
  1334. btn.setAttribute('title', mxResources.get('editLink'));
  1335. btn.style.width = '100px';
  1336. btn.style.marginLeft = '2px';
  1337. btn.style.marginBottom = '2px';
  1338. div.appendChild(btn);
  1339. count++;
  1340. }
  1341. if (count == 0)
  1342. {
  1343. div.style.display = 'none';
  1344. }
  1345. return div;
  1346. };
  1347. /**
  1348. *
  1349. */
  1350. ArrangePanel.prototype.addAlign = function(div)
  1351. {
  1352. var graph = this.editorUi.editor.graph;
  1353. div.style.paddingTop = '6px';
  1354. div.style.paddingBottom = '12px';
  1355. div.appendChild(this.createTitle(mxResources.get('align')));
  1356. var stylePanel = document.createElement('div');
  1357. stylePanel.style.position = 'relative';
  1358. stylePanel.style.paddingLeft = '0px';
  1359. stylePanel.style.borderWidth = '0px';
  1360. stylePanel.className = 'geToolbarContainer';
  1361. if (mxClient.IS_QUIRKS)
  1362. {
  1363. div.style.height = '60px';
  1364. }
  1365. var left = this.editorUi.toolbar.addButton('geSprite-alignleft', mxResources.get('left'),
  1366. function() { graph.alignCells(mxConstants.ALIGN_LEFT); }, stylePanel);
  1367. var center = this.editorUi.toolbar.addButton('geSprite-aligncenter', mxResources.get('center'),
  1368. function() { graph.alignCells(mxConstants.ALIGN_CENTER); }, stylePanel);
  1369. var right = this.editorUi.toolbar.addButton('geSprite-alignright', mxResources.get('right'),
  1370. function() { graph.alignCells(mxConstants.ALIGN_RIGHT); }, stylePanel);
  1371. var top = this.editorUi.toolbar.addButton('geSprite-aligntop', mxResources.get('top'),
  1372. function() { graph.alignCells(mxConstants.ALIGN_TOP); }, stylePanel);
  1373. var middle = this.editorUi.toolbar.addButton('geSprite-alignmiddle', mxResources.get('middle'),
  1374. function() { graph.alignCells(mxConstants.ALIGN_MIDDLE); }, stylePanel);
  1375. var bottom = this.editorUi.toolbar.addButton('geSprite-alignbottom', mxResources.get('bottom'),
  1376. function() { graph.alignCells(mxConstants.ALIGN_BOTTOM); }, stylePanel);
  1377. this.styleButtons([left, center, right, top, middle, bottom]);
  1378. right.style.marginRight = '6px';
  1379. div.appendChild(stylePanel);
  1380. return div;
  1381. };
  1382. /**
  1383. *
  1384. */
  1385. ArrangePanel.prototype.addFlip = function(div)
  1386. {
  1387. var ui = this.editorUi;
  1388. var editor = ui.editor;
  1389. var graph = editor.graph;
  1390. div.style.paddingTop = '6px';
  1391. div.style.paddingBottom = '10px';
  1392. var span = document.createElement('div');
  1393. span.style.marginTop = '2px';
  1394. span.style.marginBottom = '8px';
  1395. span.style.fontWeight = 'bold';
  1396. mxUtils.write(span, mxResources.get('flip'));
  1397. div.appendChild(span);
  1398. var btn = mxUtils.button(mxResources.get('horizontal'), function(evt)
  1399. {
  1400. graph.toggleCellStyles(mxConstants.STYLE_FLIPH, false);
  1401. })
  1402. btn.setAttribute('title', mxResources.get('horizontal'));
  1403. btn.style.width = '100px';
  1404. btn.style.marginRight = '2px';
  1405. div.appendChild(btn);
  1406. var btn = mxUtils.button(mxResources.get('vertical'), function(evt)
  1407. {
  1408. graph.toggleCellStyles(mxConstants.STYLE_FLIPV, false);
  1409. })
  1410. btn.setAttribute('title', mxResources.get('vertical'));
  1411. btn.style.width = '100px';
  1412. div.appendChild(btn);
  1413. return div;
  1414. };
  1415. /**
  1416. *
  1417. */
  1418. ArrangePanel.prototype.addDistribute = function(div)
  1419. {
  1420. var ui = this.editorUi;
  1421. var editor = ui.editor;
  1422. var graph = editor.graph;
  1423. div.style.paddingTop = '6px';
  1424. div.style.paddingBottom = '12px';
  1425. div.appendChild(this.createTitle(mxResources.get('distribute')));
  1426. var btn = mxUtils.button(mxResources.get('horizontal'), function(evt)
  1427. {
  1428. graph.distributeCells(true);
  1429. })
  1430. btn.setAttribute('title', mxResources.get('horizontal'));
  1431. btn.style.width = '100px';
  1432. btn.style.marginRight = '2px';
  1433. div.appendChild(btn);
  1434. var btn = mxUtils.button(mxResources.get('vertical'), function(evt)
  1435. {
  1436. graph.distributeCells(false);
  1437. })
  1438. btn.setAttribute('title', mxResources.get('vertical'));
  1439. btn.style.width = '100px';
  1440. div.appendChild(btn);
  1441. return div;
  1442. };
  1443. /**
  1444. *
  1445. */
  1446. ArrangePanel.prototype.addAngle = function(div)
  1447. {
  1448. var ui = this.editorUi;
  1449. var editor = ui.editor;
  1450. var graph = editor.graph;
  1451. var ss = this.format.getSelectionState();
  1452. div.style.paddingBottom = '28px';
  1453. var span = document.createElement('div');
  1454. span.style.position = 'absolute';
  1455. span.style.width = '70px';
  1456. span.style.marginTop = '0px';
  1457. span.style.fontWeight = 'bold';
  1458. mxUtils.write(span, mxResources.get('angle'));
  1459. div.appendChild(span);
  1460. var update = null;
  1461. var input = this.addUnitInput(div, '°', 84, 44, function()
  1462. {
  1463. update.apply(this, arguments);
  1464. });
  1465. if (!ss.containsLabel)
  1466. {
  1467. var btn = mxUtils.button(mxResources.get('turn'), function(evt)
  1468. {
  1469. ui.actions.get('turn').funct();
  1470. })
  1471. btn.setAttribute('title', mxResources.get('turn') + ' (' + this.editorUi.actions.get('turn').shortcut + ')');
  1472. btn.style.position = 'absolute';
  1473. btn.style.marginTop = '-2px';
  1474. btn.style.right = '20px';
  1475. btn.style.width = '61px';
  1476. div.appendChild(btn);
  1477. }
  1478. var listener = mxUtils.bind(this, function(sender, evt, force)
  1479. {
  1480. if (force || document.activeElement != input)
  1481. {
  1482. ss = this.format.getSelectionState();
  1483. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_ROTATION, 0));
  1484. input.value = (isNaN(tmp)) ? '' : tmp + '°';
  1485. }
  1486. });
  1487. update = this.installInputHandler(input, mxConstants.STYLE_ROTATION, 0, 0, 360, '°', null, true);
  1488. this.addKeyHandler(input, listener);
  1489. graph.getModel().addListener(mxEvent.CHANGE, listener);
  1490. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  1491. listener();
  1492. return div;
  1493. };
  1494. /**
  1495. *
  1496. */
  1497. ArrangePanel.prototype.addGeometry = function(container)
  1498. {
  1499. var ui = this.editorUi;
  1500. var graph = ui.editor.graph;
  1501. var rect = this.format.getSelectionState();
  1502. var div = this.createPanel();
  1503. div.style.paddingBottom = '8px';
  1504. var span = document.createElement('div');
  1505. span.style.position = 'absolute';
  1506. span.style.width = '50px';
  1507. span.style.marginTop = '0px';
  1508. span.style.fontWeight = 'bold';
  1509. mxUtils.write(span, mxResources.get('size'));
  1510. div.appendChild(span);
  1511. var widthUpdate, heightUpdate, leftUpdate, topUpdate;
  1512. var width = this.addUnitInput(div, 'pt', 84, 44, function()
  1513. {
  1514. widthUpdate.apply(this, arguments);
  1515. });
  1516. var height = this.addUnitInput(div, 'pt', 20, 44, function()
  1517. {
  1518. heightUpdate.apply(this, arguments);
  1519. });
  1520. var autosizeBtn = document.createElement('div');
  1521. autosizeBtn.className = 'geSprite geSprite-fit';
  1522. autosizeBtn.setAttribute('title', mxResources.get('autosize') + ' (' + this.editorUi.actions.get('autosize').shortcut + ')');
  1523. autosizeBtn.style.position = 'relative';
  1524. autosizeBtn.style.cursor = 'pointer';
  1525. autosizeBtn.style.marginTop = '-3px';
  1526. autosizeBtn.style.border = '0px';
  1527. autosizeBtn.style.left = '52px';
  1528. mxUtils.setOpacity(autosizeBtn, 50);
  1529. mxEvent.addListener(autosizeBtn, 'mouseenter', function()
  1530. {
  1531. mxUtils.setOpacity(autosizeBtn, 100);
  1532. });
  1533. mxEvent.addListener(autosizeBtn, 'mouseleave', function()
  1534. {
  1535. mxUtils.setOpacity(autosizeBtn, 50);
  1536. });
  1537. mxEvent.addListener(autosizeBtn, 'click', function()
  1538. {
  1539. ui.actions.get('autosize').funct();
  1540. });
  1541. div.appendChild(autosizeBtn);
  1542. this.addLabel(div, mxResources.get('width'), 84);
  1543. this.addLabel(div, mxResources.get('height'), 20);
  1544. mxUtils.br(div);
  1545. var wrapper = document.createElement('div');
  1546. wrapper.style.paddingTop = '8px';
  1547. wrapper.style.paddingRight = '20px';
  1548. wrapper.style.whiteSpace = 'nowrap';
  1549. wrapper.style.textAlign = 'right';
  1550. var opt = this.createCellOption(mxResources.get('constrainProportions'),
  1551. mxConstants.STYLE_ASPECT, null, 'fixed', 'null');
  1552. opt.style.width = '100%';
  1553. wrapper.appendChild(opt);
  1554. div.appendChild(wrapper);
  1555. this.addKeyHandler(width, listener);
  1556. this.addKeyHandler(height, listener);
  1557. widthUpdate = this.addGeometryHandler(width, function(geo, value)
  1558. {
  1559. if (geo.width > 0)
  1560. {
  1561. geo.width = Math.max(1, value);
  1562. }
  1563. });
  1564. heightUpdate = this.addGeometryHandler(height, function(geo, value)
  1565. {
  1566. if (geo.height > 0)
  1567. {
  1568. geo.height = Math.max(1, value);
  1569. }
  1570. });
  1571. container.appendChild(div);
  1572. var div2 = this.createPanel();
  1573. div2.style.paddingBottom = '30px';
  1574. var span = document.createElement('div');
  1575. span.style.position = 'absolute';
  1576. span.style.width = '70px';
  1577. span.style.marginTop = '0px';
  1578. span.style.fontWeight = 'bold';
  1579. mxUtils.write(span, mxResources.get('position'));
  1580. div2.appendChild(span);
  1581. var left = this.addUnitInput(div2, 'pt', 84, 44, function()
  1582. {
  1583. leftUpdate.apply(this, arguments);
  1584. });
  1585. var top = this.addUnitInput(div2, 'pt', 20, 44, function()
  1586. {
  1587. topUpdate.apply(this, arguments);
  1588. });
  1589. mxUtils.br(div2);
  1590. this.addLabel(div2, mxResources.get('left'), 84);
  1591. this.addLabel(div2, mxResources.get('top'), 20);
  1592. var listener = mxUtils.bind(this, function(sender, evt, force)
  1593. {
  1594. rect = this.format.getSelectionState();
  1595. if (!rect.containsLabel && rect.vertices.length == graph.getSelectionCount() &&
  1596. rect.width != null && rect.height != null)
  1597. {
  1598. div.style.display = '';
  1599. if (force || document.activeElement != width)
  1600. {
  1601. width.value = rect.width + ((rect.width == '') ? '' : ' pt');
  1602. }
  1603. if (force || document.activeElement != height)
  1604. {
  1605. height.value = rect.height + ((rect.height == '') ? '' : ' pt');
  1606. }
  1607. }
  1608. else
  1609. {
  1610. div.style.display = 'none';
  1611. }
  1612. if (rect.vertices.length == graph.getSelectionCount() &&
  1613. rect.x != null && rect.y != null)
  1614. {
  1615. div2.style.display = '';
  1616. if (force || document.activeElement != left)
  1617. {
  1618. left.value = rect.x + ((rect.x == '') ? '' : ' pt');
  1619. }
  1620. if (force || document.activeElement != top)
  1621. {
  1622. top.value = rect.y + ((rect.y == '') ? '' : ' pt');
  1623. }
  1624. }
  1625. else
  1626. {
  1627. div2.style.display = 'none';
  1628. }
  1629. });
  1630. this.addKeyHandler(left, listener);
  1631. this.addKeyHandler(top, listener);
  1632. graph.getModel().addListener(mxEvent.CHANGE, listener);
  1633. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  1634. listener();
  1635. leftUpdate = this.addGeometryHandler(left, function(geo, value)
  1636. {
  1637. if (geo.relative)
  1638. {
  1639. geo.offset.x = value;
  1640. }
  1641. else
  1642. {
  1643. geo.x = value;
  1644. }
  1645. });
  1646. topUpdate = this.addGeometryHandler(top, function(geo, value)
  1647. {
  1648. if (geo.relative)
  1649. {
  1650. geo.offset.y = value;
  1651. }
  1652. else
  1653. {
  1654. geo.y = value;
  1655. }
  1656. });
  1657. container.appendChild(div2);
  1658. };
  1659. /**
  1660. *
  1661. */
  1662. ArrangePanel.prototype.addGeometryHandler = function(input, fn)
  1663. {
  1664. var ui = this.editorUi;
  1665. var graph = ui.editor.graph;
  1666. var initialValue = null;
  1667. function update(evt)
  1668. {
  1669. if (input.value != '')
  1670. {
  1671. var value = parseFloat(input.value);
  1672. if (value != initialValue)
  1673. {
  1674. graph.getModel().beginUpdate();
  1675. try
  1676. {
  1677. var cells = graph.getSelectionCells();
  1678. for (var i = 0; i < cells.length; i++)
  1679. {
  1680. if (graph.getModel().isVertex(cells[i]))
  1681. {
  1682. var geo = graph.getCellGeometry(cells[i]);
  1683. if (geo != null)
  1684. {
  1685. geo = geo.clone();
  1686. fn(geo, value);
  1687. graph.getModel().setGeometry(cells[i], geo);
  1688. }
  1689. }
  1690. }
  1691. }
  1692. finally
  1693. {
  1694. graph.getModel().endUpdate();
  1695. }
  1696. initialValue = value;
  1697. input.value = value + ' pt';
  1698. }
  1699. else if (isNaN(value))
  1700. {
  1701. input.value = initialValue + ' pt';
  1702. }
  1703. }
  1704. mxEvent.consume(evt);
  1705. };
  1706. mxEvent.addListener(input, 'blur', update);
  1707. mxEvent.addListener(input, 'change', update);
  1708. mxEvent.addListener(input, 'focus', function()
  1709. {
  1710. initialValue = input.value;
  1711. });
  1712. return update;
  1713. };
  1714. /**
  1715. *
  1716. */
  1717. ArrangePanel.prototype.addEdgeGeometry = function(container)
  1718. {
  1719. var ui = this.editorUi;
  1720. var graph = ui.editor.graph;
  1721. var rect = this.format.getSelectionState();
  1722. var div = this.createPanel();
  1723. var span = document.createElement('div');
  1724. span.style.position = 'absolute';
  1725. span.style.width = '70px';
  1726. span.style.marginTop = '0px';
  1727. span.style.fontWeight = 'bold';
  1728. mxUtils.write(span, mxResources.get('width'));
  1729. div.appendChild(span);
  1730. var widthUpdate, leftUpdate, topUpdate;
  1731. var width = this.addUnitInput(div, 'pt', 20, 44, function()
  1732. {
  1733. widthUpdate.apply(this, arguments);
  1734. });
  1735. mxUtils.br(div);
  1736. this.addKeyHandler(width, listener);
  1737. function widthUpdate(evt)
  1738. {
  1739. // Maximum stroke width is 999
  1740. var value = parseInt(width.value);
  1741. value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value));
  1742. if (value != mxUtils.getValue(rect.style, 'width', mxCellRenderer.prototype.defaultShapes['flexArrow'].prototype.defaultWidth))
  1743. {
  1744. graph.setCellStyles('width', value, graph.getSelectionCells());
  1745. ui.fireEvent(new mxEventObject('styleChanged', 'keys', ['width'],
  1746. 'values', [value], 'cells', graph.getSelectionCells()));
  1747. }
  1748. width.value = value + ' pt';
  1749. mxEvent.consume(evt);
  1750. };
  1751. mxEvent.addListener(width, 'blur', widthUpdate);
  1752. mxEvent.addListener(width, 'change', widthUpdate);
  1753. container.appendChild(div);
  1754. var listener = mxUtils.bind(this, function(sender, evt, force)
  1755. {
  1756. rect = this.format.getSelectionState();
  1757. if (rect.style.shape == 'link' || rect.style.shape == 'flexArrow')
  1758. {
  1759. div.style.display = '';
  1760. if (force || document.activeElement != width)
  1761. {
  1762. var value = mxUtils.getValue(rect.style, 'width',
  1763. mxCellRenderer.prototype.defaultShapes['flexArrow'].prototype.defaultWidth);
  1764. width.value = value + ' pt';
  1765. }
  1766. }
  1767. else
  1768. {
  1769. div.style.display = 'none';
  1770. }
  1771. });
  1772. graph.getModel().addListener(mxEvent.CHANGE, listener);
  1773. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  1774. listener();
  1775. };
  1776. /**
  1777. * Adds the label menu items to the given menu and parent.
  1778. */
  1779. TextFormatPanel = function(format, editorUi, container)
  1780. {
  1781. BaseFormatPanel.call(this, format, editorUi, container);
  1782. this.init();
  1783. };
  1784. mxUtils.extend(TextFormatPanel, BaseFormatPanel);
  1785. /**
  1786. * Adds the label menu items to the given menu and parent.
  1787. */
  1788. TextFormatPanel.prototype.init = function()
  1789. {
  1790. this.container.style.borderBottom = 'none';
  1791. this.addFont(this.container);
  1792. };
  1793. /**
  1794. * Adds the label menu items to the given menu and parent.
  1795. */
  1796. TextFormatPanel.prototype.addFont = function(container)
  1797. {
  1798. var ui = this.editorUi;
  1799. var editor = ui.editor;
  1800. var graph = editor.graph;
  1801. var ss = this.format.getSelectionState();
  1802. var title = this.createTitle(mxResources.get('font'));
  1803. title.style.paddingLeft = '18px';
  1804. title.style.paddingTop = '10px';
  1805. title.style.paddingBottom = '6px';
  1806. container.appendChild(title);
  1807. var stylePanel = this.createPanel();
  1808. stylePanel.style.paddingTop = '2px';
  1809. stylePanel.style.paddingBottom = '2px';
  1810. stylePanel.style.position = 'relative';
  1811. stylePanel.style.marginLeft = '-2px';
  1812. stylePanel.style.borderWidth = '0px';
  1813. stylePanel.className = 'geToolbarContainer';
  1814. if (mxClient.IS_QUIRKS)
  1815. {
  1816. stylePanel.style.display = 'block';
  1817. }
  1818. if (graph.cellEditor.isContentEditing())
  1819. {
  1820. var cssPanel = stylePanel.cloneNode();
  1821. var cssMenu = this.editorUi.toolbar.addMenu(mxResources.get('style'),
  1822. mxResources.get('style'), true, 'formatBlock', cssPanel);
  1823. cssMenu.style.color = 'rgb(112, 112, 112)';
  1824. cssMenu.style.whiteSpace = 'nowrap';
  1825. cssMenu.style.overflow = 'hidden';
  1826. cssMenu.style.margin = '0px';
  1827. this.addArrow(cssMenu);
  1828. cssMenu.style.width = '192px';
  1829. cssMenu.style.height = '15px';
  1830. var arrow = cssMenu.getElementsByTagName('div')[0];
  1831. arrow.style.cssFloat = 'right';
  1832. container.appendChild(cssPanel);
  1833. }
  1834. container.appendChild(stylePanel);
  1835. var colorPanel = this.createPanel();
  1836. colorPanel.style.marginTop = '8px';
  1837. colorPanel.style.borderTop = '1px solid #c0c0c0';
  1838. colorPanel.style.paddingTop = '6px';
  1839. colorPanel.style.paddingBottom = '6px';
  1840. var fontMenu = this.editorUi.toolbar.addMenu('Helvetica', mxResources.get('fontFamily'), true, 'fontFamily', stylePanel);
  1841. fontMenu.style.color = 'rgb(112, 112, 112)';
  1842. fontMenu.style.whiteSpace = 'nowrap';
  1843. fontMenu.style.overflow = 'hidden';
  1844. fontMenu.style.margin = '0px';
  1845. this.addArrow(fontMenu);
  1846. fontMenu.style.width = '192px';
  1847. fontMenu.style.height = '15px';
  1848. var stylePanel2 = stylePanel.cloneNode(false);
  1849. stylePanel2.style.marginLeft = '-3px';
  1850. var fontStyleItems = this.editorUi.toolbar.addItems(['bold', 'italic', 'underline'], stylePanel2, true);
  1851. fontStyleItems[0].setAttribute('title', mxResources.get('bold') + ' (' + this.editorUi.actions.get('bold').shortcut + ')');
  1852. fontStyleItems[1].setAttribute('title', mxResources.get('italic') + ' (' + this.editorUi.actions.get('italic').shortcut + ')');
  1853. fontStyleItems[2].setAttribute('title', mxResources.get('underline') + ' (' + this.editorUi.actions.get('underline').shortcut + ')');
  1854. var verticalItem = this.editorUi.toolbar.addItems(['vertical'], stylePanel2, true)[0];
  1855. if (mxClient.IS_QUIRKS)
  1856. {
  1857. mxUtils.br(container);
  1858. }
  1859. container.appendChild(stylePanel2);
  1860. this.styleButtons(fontStyleItems);
  1861. this.styleButtons([verticalItem]);
  1862. var stylePanel3 = stylePanel.cloneNode(false);
  1863. stylePanel3.style.marginLeft = '-3px';
  1864. stylePanel3.style.paddingBottom = '0px';
  1865. var left = this.editorUi.toolbar.addButton('geSprite-left', mxResources.get('left'),
  1866. (graph.cellEditor.isContentEditing()) ?
  1867. function()
  1868. {
  1869. document.execCommand('justifyleft', false, null);
  1870. } : this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_LEFT]), stylePanel3);
  1871. var center = this.editorUi.toolbar.addButton('geSprite-center', mxResources.get('center'),
  1872. (graph.cellEditor.isContentEditing()) ?
  1873. function()
  1874. {
  1875. document.execCommand('justifycenter', false, null);
  1876. } : this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_CENTER]), stylePanel3);
  1877. var right = this.editorUi.toolbar.addButton('geSprite-right', mxResources.get('right'),
  1878. (graph.cellEditor.isContentEditing()) ?
  1879. function()
  1880. {
  1881. document.execCommand('justifyright', false, null);
  1882. } : this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_RIGHT]), stylePanel3);
  1883. this.styleButtons([left, center, right]);
  1884. if (graph.cellEditor.isContentEditing())
  1885. {
  1886. var clear = this.editorUi.toolbar.addButton('geSprite-removeformat', mxResources.get('removeFormat'),
  1887. function()
  1888. {
  1889. document.execCommand('removeformat', false, null);
  1890. }, stylePanel2);
  1891. this.styleButtons([clear]);
  1892. }
  1893. var top = this.editorUi.toolbar.addButton('geSprite-top', mxResources.get('top'),
  1894. this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_TOP]), stylePanel3);
  1895. var middle = this.editorUi.toolbar.addButton('geSprite-middle', mxResources.get('middle'),
  1896. this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_MIDDLE]), stylePanel3);
  1897. var bottom = this.editorUi.toolbar.addButton('geSprite-bottom', mxResources.get('bottom'),
  1898. this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_BOTTOM]), stylePanel3);
  1899. this.styleButtons([top, middle, bottom]);
  1900. if (mxClient.IS_QUIRKS)
  1901. {
  1902. mxUtils.br(container);
  1903. }
  1904. container.appendChild(stylePanel3);
  1905. // Hack for updating UI state below based on current text selection
  1906. // currentTable is the current selected DOM table updated below
  1907. var sub, sup, full, tableWrapper, currentTable, tableCell, tableRow;
  1908. if (graph.cellEditor.isContentEditing())
  1909. {
  1910. top.style.display = 'none';
  1911. middle.style.display = 'none';
  1912. bottom.style.display = 'none';
  1913. verticalItem.style.display = 'none';
  1914. full = this.editorUi.toolbar.addButton('geSprite-justifyfull', null,
  1915. function()
  1916. {
  1917. document.execCommand('justifyfull', false, null);
  1918. }, stylePanel3);
  1919. this.styleButtons([full,
  1920. sub = this.editorUi.toolbar.addButton('geSprite-subscript', mxResources.get('subscript') + ' (Ctrl+,)',
  1921. function()
  1922. {
  1923. document.execCommand('subscript', false, null);
  1924. }, stylePanel3), sup = this.editorUi.toolbar.addButton('geSprite-superscript', mxResources.get('superscript') + ' (Ctrl+.)',
  1925. function()
  1926. {
  1927. document.execCommand('superscript', false, null);
  1928. }, stylePanel3)]);
  1929. full.style.marginRight = '9px';
  1930. var tmp = stylePanel3.cloneNode(false);
  1931. tmp.style.paddingTop = '4px';
  1932. var btns = [this.editorUi.toolbar.addButton('geSprite-orderedlist', mxResources.get('numberedList'),
  1933. function()
  1934. {
  1935. document.execCommand('insertorderedlist', false, null);
  1936. }, tmp),
  1937. this.editorUi.toolbar.addButton('geSprite-unorderedlist', mxResources.get('bulletedList'),
  1938. function()
  1939. {
  1940. document.execCommand('insertunorderedlist', false, null);
  1941. }, tmp),
  1942. this.editorUi.toolbar.addButton('geSprite-outdent', mxResources.get('decreaseIndent'),
  1943. function()
  1944. {
  1945. document.execCommand('outdent', false, null);
  1946. }, tmp),
  1947. this.editorUi.toolbar.addButton('geSprite-indent', mxResources.get('increaseIndent'),
  1948. function()
  1949. {
  1950. document.execCommand('indent', false, null);
  1951. }, tmp),
  1952. this.editorUi.toolbar.addButton('geSprite-code', mxResources.get('html'),
  1953. function()
  1954. {
  1955. graph.cellEditor.toggleViewMode();
  1956. }, tmp)];
  1957. this.styleButtons(btns);
  1958. btns[btns.length - 1].style.marginLeft = '9px';
  1959. if (mxClient.IS_QUIRKS)
  1960. {
  1961. mxUtils.br(container);
  1962. tmp.style.height = '40';
  1963. }
  1964. container.appendChild(tmp);
  1965. }
  1966. else
  1967. {
  1968. fontStyleItems[2].style.marginRight = '9px';
  1969. right.style.marginRight = '9px';
  1970. }
  1971. // Label position
  1972. var stylePanel4 = stylePanel.cloneNode(false);
  1973. stylePanel4.style.marginLeft = '0px';
  1974. stylePanel4.style.paddingTop = '8px';
  1975. stylePanel4.style.paddingBottom = '4px';
  1976. stylePanel4.style.fontWeight = 'normal';
  1977. mxUtils.write(stylePanel4, mxResources.get('position'));
  1978. // Adds label position options
  1979. var positionSelect = document.createElement('select');
  1980. positionSelect.style.position = 'absolute';
  1981. positionSelect.style.right = '20px';
  1982. positionSelect.style.width = '97px';
  1983. positionSelect.style.marginTop = '-2px';
  1984. var directions = ['topLeft', 'top', 'topRight', 'left', 'center', 'right', 'bottomLeft', 'bottom', 'bottomRight'];
  1985. var lset = {'topLeft': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM],
  1986. 'top': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_TOP, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_BOTTOM],
  1987. 'topRight': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_TOP, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_BOTTOM],
  1988. 'left': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE],
  1989. 'center': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE],
  1990. 'right': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE],
  1991. 'bottomLeft': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_TOP],
  1992. 'bottom': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_TOP],
  1993. 'bottomRight': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP]};
  1994. for (var i = 0; i < directions.length; i++)
  1995. {
  1996. var positionOption = document.createElement('option');
  1997. positionOption.setAttribute('value', directions[i]);
  1998. mxUtils.write(positionOption, mxResources.get(directions[i]));
  1999. positionSelect.appendChild(positionOption);
  2000. }
  2001. stylePanel4.appendChild(positionSelect);
  2002. // Writing direction
  2003. var stylePanel5 = stylePanel.cloneNode(false);
  2004. stylePanel5.style.marginLeft = '0px';
  2005. stylePanel5.style.paddingTop = '4px';
  2006. stylePanel5.style.paddingBottom = '4px';
  2007. stylePanel5.style.fontWeight = 'normal';
  2008. mxUtils.write(stylePanel5, mxResources.get('writingDirection'));
  2009. // Adds writing direction options
  2010. // LATER: Handle reselect of same option in all selects (change event
  2011. // is not fired for same option so have opened state on click) and
  2012. // handle multiple different styles for current selection
  2013. var dirSelect = document.createElement('select');
  2014. dirSelect.style.position = 'absolute';
  2015. dirSelect.style.right = '20px';
  2016. dirSelect.style.width = '97px';
  2017. dirSelect.style.marginTop = '-2px';
  2018. // NOTE: For automatic we use the value null since automatic
  2019. // requires the text to be non formatted and non-wrappedto
  2020. var dirs = ['automatic', 'leftToRight', 'rightToLeft'];
  2021. var dirSet = {'automatic': null,
  2022. 'leftToRight': mxConstants.TEXT_DIRECTION_LTR,
  2023. 'rightToLeft': mxConstants.TEXT_DIRECTION_RTL};
  2024. for (var i = 0; i < dirs.length; i++)
  2025. {
  2026. var dirOption = document.createElement('option');
  2027. dirOption.setAttribute('value', dirs[i]);
  2028. mxUtils.write(dirOption, mxResources.get(dirs[i]));
  2029. dirSelect.appendChild(dirOption);
  2030. }
  2031. stylePanel5.appendChild(dirSelect);
  2032. if (!graph.isEditing())
  2033. {
  2034. container.appendChild(stylePanel4);
  2035. mxEvent.addListener(positionSelect, 'change', function(evt)
  2036. {
  2037. graph.getModel().beginUpdate();
  2038. try
  2039. {
  2040. var vals = lset[positionSelect.value];
  2041. if (vals != null)
  2042. {
  2043. graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION, vals[0], graph.getSelectionCells());
  2044. graph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, vals[1], graph.getSelectionCells());
  2045. graph.setCellStyles(mxConstants.STYLE_ALIGN, vals[2], graph.getSelectionCells());
  2046. graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, vals[3], graph.getSelectionCells());
  2047. }
  2048. }
  2049. finally
  2050. {
  2051. graph.getModel().endUpdate();
  2052. }
  2053. mxEvent.consume(evt);
  2054. });
  2055. // LATER: Update dir in text editor while editing and update style with label
  2056. // NOTE: The tricky part is handling and passing on the auto value
  2057. container.appendChild(stylePanel5);
  2058. mxEvent.addListener(dirSelect, 'change', function(evt)
  2059. {
  2060. graph.setCellStyles(mxConstants.STYLE_TEXT_DIRECTION, dirSet[dirSelect.value], graph.getSelectionCells());
  2061. mxEvent.consume(evt);
  2062. });
  2063. }
  2064. // Font size
  2065. var input = document.createElement('input');
  2066. input.style.textAlign = 'right';
  2067. input.style.marginTop = '4px';
  2068. if (!mxClient.IS_QUIRKS)
  2069. {
  2070. input.style.position = 'absolute';
  2071. input.style.right = '32px';
  2072. }
  2073. input.style.width = '46px';
  2074. input.style.height = (mxClient.IS_QUIRKS) ? '21px' : '17px';
  2075. stylePanel2.appendChild(input);
  2076. // Workaround for font size 4 if no text is selected is update font size below
  2077. // after first character was entered (as the font element is lazy created)
  2078. var pendingFontSize = null;
  2079. var inputUpdate = this.installInputHandler(input, mxConstants.STYLE_FONTSIZE, Menus.prototype.defaultFontSize, 1, 999, ' pt',
  2080. function(fontsize)
  2081. {
  2082. pendingFontSize = fontsize;
  2083. // Workaround for can't set font size in px is to change font size afterwards
  2084. document.execCommand('fontSize', false, '4');
  2085. var elts = graph.cellEditor.textarea.getElementsByTagName('font');
  2086. for (var i = 0; i < elts.length; i++)
  2087. {
  2088. if (elts[i].getAttribute('size') == '4')
  2089. {
  2090. elts[i].removeAttribute('size');
  2091. elts[i].style.fontSize = pendingFontSize + 'px';
  2092. // Overrides fontSize in input with the one just assigned as a workaround
  2093. // for potential fontSize values of parent elements that don't match
  2094. window.setTimeout(function()
  2095. {
  2096. input.value = pendingFontSize + ' pt';
  2097. pendingFontSize = null;
  2098. }, 0);
  2099. break;
  2100. }
  2101. }
  2102. }, true);
  2103. var stepper = this.createStepper(input, inputUpdate, 1, 10, true, Menus.prototype.defaultFontSize);
  2104. stepper.style.display = input.style.display;
  2105. stepper.style.marginTop = '4px';
  2106. if (!mxClient.IS_QUIRKS)
  2107. {
  2108. stepper.style.right = '20px';
  2109. }
  2110. stylePanel2.appendChild(stepper);
  2111. var arrow = fontMenu.getElementsByTagName('div')[0];
  2112. arrow.style.cssFloat = 'right';
  2113. var bgColorApply = null;
  2114. var currentBgColor = '#ffffff';
  2115. var fontColorApply = null;
  2116. var currentFontColor = '#000000';
  2117. var bgPanel = (graph.cellEditor.isContentEditing()) ? this.createColorOption(mxResources.get('backgroundColor'), function()
  2118. {
  2119. return currentBgColor;
  2120. }, function(color)
  2121. {
  2122. document.execCommand('backcolor', false, (color != mxConstants.NONE) ? color : 'transparent');
  2123. }, '#ffffff',
  2124. {
  2125. install: function(apply) { bgColorApply = apply; },
  2126. destroy: function() { bgColorApply = null; }
  2127. }, null, true) : this.createCellColorOption(mxResources.get('backgroundColor'), mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, '#ffffff');
  2128. bgPanel.style.fontWeight = 'bold';
  2129. var borderPanel = this.createCellColorOption(mxResources.get('borderColor'), mxConstants.STYLE_LABEL_BORDERCOLOR, '#000000');
  2130. borderPanel.style.fontWeight = 'bold';
  2131. var panel = (graph.cellEditor.isContentEditing()) ? this.createColorOption(mxResources.get('fontColor'), function()
  2132. {
  2133. return currentFontColor;
  2134. }, function(color)
  2135. {
  2136. document.execCommand('forecolor', false, (color != mxConstants.NONE) ? color : 'transparent');
  2137. }, '#000000',
  2138. {
  2139. install: function(apply) { fontColorApply = apply; },
  2140. destroy: function() { fontColorApply = null; }
  2141. }, null, true) : this.createCellColorOption(mxResources.get('fontColor'), mxConstants.STYLE_FONTCOLOR, '#000000', function(color)
  2142. {
  2143. if (color == null || color == mxConstants.NONE)
  2144. {
  2145. bgPanel.style.display = 'none';
  2146. }
  2147. else
  2148. {
  2149. bgPanel.style.display = '';
  2150. }
  2151. borderPanel.style.display = bgPanel.style.display;
  2152. }, function(color)
  2153. {
  2154. if (color == null || color == mxConstants.NONE)
  2155. {
  2156. graph.setCellStyles(mxConstants.STYLE_NOLABEL, '1', graph.getSelectionCells());
  2157. }
  2158. else
  2159. {
  2160. graph.setCellStyles(mxConstants.STYLE_NOLABEL, null, graph.getSelectionCells());
  2161. }
  2162. });
  2163. panel.style.fontWeight = 'bold';
  2164. colorPanel.appendChild(panel);
  2165. colorPanel.appendChild(bgPanel);
  2166. if (!graph.cellEditor.isContentEditing())
  2167. {
  2168. colorPanel.appendChild(borderPanel);
  2169. }
  2170. container.appendChild(colorPanel);
  2171. var extraPanel = this.createPanel();
  2172. extraPanel.style.paddingTop = '2px';
  2173. extraPanel.style.paddingBottom = '4px';
  2174. // LATER: Fix toggle using '' instead of 'null'
  2175. var wwOpt = this.createCellOption(mxResources.get('wordWrap'), mxConstants.STYLE_WHITE_SPACE, null, 'wrap', 'null', null, null, true);
  2176. wwOpt.style.fontWeight = 'bold';
  2177. // Word wrap in edge labels only supported via labelWidth style
  2178. if (!ss.containsLabel && !ss.autoSize && ss.edges.length == 0)
  2179. {
  2180. extraPanel.appendChild(wwOpt);
  2181. }
  2182. // Delegates switch of style to formattedText action as it also convertes newlines
  2183. var htmlOpt = this.createCellOption(mxResources.get('formattedText'), 'html', '0',
  2184. null, null, null, ui.actions.get('formattedText'));
  2185. htmlOpt.style.fontWeight = 'bold';
  2186. extraPanel.appendChild(htmlOpt);
  2187. var spacingPanel = this.createPanel();
  2188. spacingPanel.style.paddingTop = '10px';
  2189. spacingPanel.style.paddingBottom = '28px';
  2190. spacingPanel.style.fontWeight = 'normal';
  2191. var span = document.createElement('div');
  2192. span.style.position = 'absolute';
  2193. span.style.width = '70px';
  2194. span.style.marginTop = '0px';
  2195. span.style.fontWeight = 'bold';
  2196. mxUtils.write(span, mxResources.get('spacing'));
  2197. spacingPanel.appendChild(span);
  2198. var topUpdate, globalUpdate, leftUpdate, bottomUpdate, rightUpdate;
  2199. var topSpacing = this.addUnitInput(spacingPanel, 'pt', 91, 44, function()
  2200. {
  2201. topUpdate.apply(this, arguments);
  2202. });
  2203. var globalSpacing = this.addUnitInput(spacingPanel, 'pt', 20, 44, function()
  2204. {
  2205. globalUpdate.apply(this, arguments);
  2206. });
  2207. mxUtils.br(spacingPanel);
  2208. this.addLabel(spacingPanel, mxResources.get('top'), 91);
  2209. this.addLabel(spacingPanel, mxResources.get('global'), 20);
  2210. mxUtils.br(spacingPanel);
  2211. mxUtils.br(spacingPanel);
  2212. var leftSpacing = this.addUnitInput(spacingPanel, 'pt', 162, 44, function()
  2213. {
  2214. leftUpdate.apply(this, arguments);
  2215. });
  2216. var bottomSpacing = this.addUnitInput(spacingPanel, 'pt', 91, 44, function()
  2217. {
  2218. bottomUpdate.apply(this, arguments);
  2219. });
  2220. var rightSpacing = this.addUnitInput(spacingPanel, 'pt', 20, 44, function()
  2221. {
  2222. rightUpdate.apply(this, arguments);
  2223. });
  2224. mxUtils.br(spacingPanel);
  2225. this.addLabel(spacingPanel, mxResources.get('left'), 162);
  2226. this.addLabel(spacingPanel, mxResources.get('bottom'), 91);
  2227. this.addLabel(spacingPanel, mxResources.get('right'), 20);
  2228. if (!graph.cellEditor.isContentEditing())
  2229. {
  2230. container.appendChild(extraPanel);
  2231. container.appendChild(this.createRelativeOption(mxResources.get('opacity'), mxConstants.STYLE_TEXT_OPACITY));
  2232. container.appendChild(spacingPanel);
  2233. }
  2234. else
  2235. {
  2236. var selState = null;
  2237. var lineHeightInput = null;
  2238. container.appendChild(this.createRelativeOption(mxResources.get('lineheight'), null, null, function(input)
  2239. {
  2240. var value = (input.value == '') ? 120 : parseInt(input.value);
  2241. value = Math.max(120, (isNaN(value)) ? 120 : value);
  2242. if (selState != null)
  2243. {
  2244. graph.cellEditor.restoreSelection(selState);
  2245. selState = null;
  2246. }
  2247. var selectedElement = graph.getSelectedElement();
  2248. var node = selectedElement;
  2249. while (node != null && node.nodeType != mxConstants.NODETYPE_ELEMENT)
  2250. {
  2251. node = node.parentNode;
  2252. }
  2253. if (node != null && node == graph.cellEditor.textarea && graph.cellEditor.textarea.firstChild != null)
  2254. {
  2255. if (graph.cellEditor.textarea.firstChild.nodeName != 'FONT')
  2256. {
  2257. graph.cellEditor.textarea.innerHTML = '<font>' + graph.cellEditor.textarea.innerHTML + '</font>';
  2258. }
  2259. node = graph.cellEditor.textarea.firstChild;
  2260. }
  2261. if (node != null && node != graph.cellEditor.textarea)
  2262. {
  2263. node.style.lineHeight = value + '%';
  2264. }
  2265. input.value = value + ' %';
  2266. }, function(input)
  2267. {
  2268. // Used in CSS handler to update current value
  2269. lineHeightInput = input;
  2270. // KNOWN: Arrow up/down clear selection text in quirks/IE 8
  2271. // Text size via arrow button limits to 16 in IE11. Why?
  2272. mxEvent.addListener(input, 'mousedown', function()
  2273. {
  2274. selState = graph.cellEditor.saveSelection();
  2275. });
  2276. mxEvent.addListener(input, 'touchstart', function()
  2277. {
  2278. selState = graph.cellEditor.saveSelection();
  2279. });
  2280. input.value = '120 %';
  2281. }));
  2282. var insertPanel = stylePanel.cloneNode(false);
  2283. insertPanel.style.paddingLeft = '0px';
  2284. var insertBtns = this.editorUi.toolbar.addItems(['link', 'image'], insertPanel, true);
  2285. var btns = [
  2286. this.editorUi.toolbar.addButton('geSprite-horizontalrule', mxResources.get('insertHorizontalRule'),
  2287. function()
  2288. {
  2289. document.execCommand('inserthorizontalrule', false, null);
  2290. }, insertPanel),
  2291. this.editorUi.toolbar.addMenuFunctionInContainer(insertPanel, 'geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu)
  2292. {
  2293. this.editorUi.menus.addInsertTableItem(menu);
  2294. }))];
  2295. this.styleButtons(insertBtns);
  2296. this.styleButtons(btns);
  2297. var wrapper2 = this.createPanel();
  2298. wrapper2.style.paddingTop = '10px';
  2299. wrapper2.style.paddingBottom = '10px';
  2300. wrapper2.appendChild(this.createTitle(mxResources.get('insert')));
  2301. wrapper2.appendChild(insertPanel);
  2302. container.appendChild(wrapper2);
  2303. if (mxClient.IS_QUIRKS)
  2304. {
  2305. wrapper2.style.height = '70';
  2306. }
  2307. var tablePanel = stylePanel.cloneNode(false);
  2308. tablePanel.style.paddingLeft = '0px';
  2309. var btns = [
  2310. this.editorUi.toolbar.addButton('geSprite-insertcolumnbefore', mxResources.get('insertColumnBefore'),
  2311. function()
  2312. {
  2313. try
  2314. {
  2315. if (currentTable != null)
  2316. {
  2317. graph.selectNode(graph.insertColumn(currentTable, (tableCell != null) ? tableCell.cellIndex : 0));
  2318. }
  2319. }
  2320. catch (e)
  2321. {
  2322. alert(e);
  2323. }
  2324. }, tablePanel),
  2325. this.editorUi.toolbar.addButton('geSprite-insertcolumnafter', mxResources.get('insertColumnAfter'),
  2326. function()
  2327. {
  2328. try
  2329. {
  2330. if (currentTable != null)
  2331. {
  2332. graph.selectNode(graph.insertColumn(currentTable, (tableCell != null) ? tableCell.cellIndex + 1 : -1));
  2333. }
  2334. }
  2335. catch (e)
  2336. {
  2337. alert(e);
  2338. }
  2339. }, tablePanel),
  2340. this.editorUi.toolbar.addButton('geSprite-deletecolumn', mxResources.get('deleteColumn'),
  2341. function()
  2342. {
  2343. try
  2344. {
  2345. if (currentTable != null && tableCell != null)
  2346. {
  2347. graph.deleteColumn(currentTable, tableCell.cellIndex);
  2348. }
  2349. }
  2350. catch (e)
  2351. {
  2352. alert(e);
  2353. }
  2354. }, tablePanel),
  2355. this.editorUi.toolbar.addButton('geSprite-insertrowbefore', mxResources.get('insertRowBefore'),
  2356. function()
  2357. {
  2358. try
  2359. {
  2360. if (currentTable != null && tableRow != null)
  2361. {
  2362. graph.selectNode(graph.insertRow(currentTable, tableRow.sectionRowIndex));
  2363. }
  2364. }
  2365. catch (e)
  2366. {
  2367. alert(e);
  2368. }
  2369. }, tablePanel),
  2370. this.editorUi.toolbar.addButton('geSprite-insertrowafter', mxResources.get('insertRowAfter'),
  2371. function()
  2372. {
  2373. try
  2374. {
  2375. if (currentTable != null && tableRow != null)
  2376. {
  2377. graph.selectNode(graph.insertRow(currentTable, tableRow.sectionRowIndex + 1));
  2378. }
  2379. }
  2380. catch (e)
  2381. {
  2382. alert(e);
  2383. }
  2384. }, tablePanel),
  2385. this.editorUi.toolbar.addButton('geSprite-deleterow', mxResources.get('deleteRow'),
  2386. function()
  2387. {
  2388. try
  2389. {
  2390. if (currentTable != null && tableRow != null)
  2391. {
  2392. graph.deleteRow(currentTable, tableRow.sectionRowIndex);
  2393. }
  2394. }
  2395. catch (e)
  2396. {
  2397. alert(e);
  2398. }
  2399. }, tablePanel)];
  2400. this.styleButtons(btns);
  2401. btns[2].style.marginRight = '9px';
  2402. var wrapper3 = this.createPanel();
  2403. wrapper3.style.paddingTop = '10px';
  2404. wrapper3.style.paddingBottom = '10px';
  2405. wrapper3.appendChild(this.createTitle(mxResources.get('table')));
  2406. wrapper3.appendChild(tablePanel);
  2407. if (mxClient.IS_QUIRKS)
  2408. {
  2409. mxUtils.br(container);
  2410. wrapper3.style.height = '70';
  2411. }
  2412. var tablePanel2 = stylePanel.cloneNode(false);
  2413. tablePanel2.style.paddingLeft = '0px';
  2414. var btns = [
  2415. this.editorUi.toolbar.addButton('geSprite-strokecolor', mxResources.get('borderColor'),
  2416. mxUtils.bind(this, function()
  2417. {
  2418. if (currentTable != null)
  2419. {
  2420. // Converts rgb(r,g,b) values
  2421. var color = currentTable.style.borderColor.replace(
  2422. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  2423. function($0, $1, $2, $3) {
  2424. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  2425. });
  2426. this.editorUi.pickColor(color, function(newColor)
  2427. {
  2428. if (newColor == null || newColor == mxConstants.NONE)
  2429. {
  2430. currentTable.removeAttribute('border');
  2431. currentTable.style.border = '';
  2432. currentTable.style.borderCollapse = '';
  2433. }
  2434. else
  2435. {
  2436. currentTable.setAttribute('border', '1');
  2437. currentTable.style.border = '1px solid ' + newColor;
  2438. currentTable.style.borderCollapse = 'collapse';
  2439. }
  2440. });
  2441. }
  2442. }), tablePanel2),
  2443. this.editorUi.toolbar.addButton('geSprite-fillcolor', mxResources.get('backgroundColor'),
  2444. mxUtils.bind(this, function()
  2445. {
  2446. // Converts rgb(r,g,b) values
  2447. if (currentTable != null)
  2448. {
  2449. var color = currentTable.style.backgroundColor.replace(
  2450. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  2451. function($0, $1, $2, $3) {
  2452. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  2453. });
  2454. this.editorUi.pickColor(color, function(newColor)
  2455. {
  2456. if (newColor == null || newColor == mxConstants.NONE)
  2457. {
  2458. currentTable.style.backgroundColor = '';
  2459. }
  2460. else
  2461. {
  2462. currentTable.style.backgroundColor = newColor;
  2463. }
  2464. });
  2465. }
  2466. }), tablePanel2),
  2467. this.editorUi.toolbar.addButton('geSprite-fit', mxResources.get('spacing'),
  2468. function()
  2469. {
  2470. if (currentTable != null)
  2471. {
  2472. var value = currentTable.getAttribute('cellPadding') || 0;
  2473. var dlg = new FilenameDialog(ui, value, mxResources.get('apply'), mxUtils.bind(this, function(newValue)
  2474. {
  2475. if (newValue != null && newValue.length > 0)
  2476. {
  2477. currentTable.setAttribute('cellPadding', newValue);
  2478. }
  2479. else
  2480. {
  2481. currentTable.removeAttribute('cellPadding');
  2482. }
  2483. }), mxResources.get('spacing'));
  2484. ui.showDialog(dlg.container, 300, 80, true, true);
  2485. dlg.init();
  2486. }
  2487. }, tablePanel2),
  2488. this.editorUi.toolbar.addButton('geSprite-left', mxResources.get('left'),
  2489. function()
  2490. {
  2491. if (currentTable != null)
  2492. {
  2493. currentTable.setAttribute('align', 'left');
  2494. }
  2495. }, tablePanel2),
  2496. this.editorUi.toolbar.addButton('geSprite-center', mxResources.get('center'),
  2497. function()
  2498. {
  2499. if (currentTable != null)
  2500. {
  2501. currentTable.setAttribute('align', 'center');
  2502. }
  2503. }, tablePanel2),
  2504. this.editorUi.toolbar.addButton('geSprite-right', mxResources.get('right'),
  2505. function()
  2506. {
  2507. if (currentTable != null)
  2508. {
  2509. currentTable.setAttribute('align', 'right');
  2510. }
  2511. }, tablePanel2)];
  2512. this.styleButtons(btns);
  2513. btns[2].style.marginRight = '9px';
  2514. if (mxClient.IS_QUIRKS)
  2515. {
  2516. mxUtils.br(wrapper3);
  2517. mxUtils.br(wrapper3);
  2518. }
  2519. wrapper3.appendChild(tablePanel2);
  2520. container.appendChild(wrapper3);
  2521. tableWrapper = wrapper3;
  2522. }
  2523. function setSelected(elt, selected)
  2524. {
  2525. if (mxClient.IS_IE && (mxClient.IS_QUIRKS || document.documentMode < 10))
  2526. {
  2527. elt.style.filter = (selected) ? 'progid:DXImageTransform.Microsoft.Gradient('+
  2528. 'StartColorStr=\'#c5ecff\', EndColorStr=\'#87d4fb\', GradientType=0)' : '';
  2529. }
  2530. else
  2531. {
  2532. elt.style.backgroundImage = (selected) ? 'linear-gradient(#c5ecff 0px,#87d4fb 100%)' : '';
  2533. }
  2534. };
  2535. var listener = mxUtils.bind(this, function(sender, evt, force)
  2536. {
  2537. ss = this.format.getSelectionState();
  2538. var fontStyle = mxUtils.getValue(ss.style, mxConstants.STYLE_FONTSTYLE, 0);
  2539. setSelected(fontStyleItems[0], (fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD);
  2540. setSelected(fontStyleItems[1], (fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC);
  2541. setSelected(fontStyleItems[2], (fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE);
  2542. fontMenu.firstChild.nodeValue = mxUtils.htmlEntities(mxUtils.getValue(ss.style, mxConstants.STYLE_FONTFAMILY, Menus.prototype.defaultFont));
  2543. setSelected(verticalItem, mxUtils.getValue(ss.style, mxConstants.STYLE_HORIZONTAL, '1') == '0');
  2544. if (force || document.activeElement != input)
  2545. {
  2546. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_FONTSIZE, Menus.prototype.defaultFontSize));
  2547. input.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2548. }
  2549. var align = mxUtils.getValue(ss.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER);
  2550. setSelected(left, align == mxConstants.ALIGN_LEFT);
  2551. setSelected(center, align == mxConstants.ALIGN_CENTER);
  2552. setSelected(right, align == mxConstants.ALIGN_RIGHT);
  2553. var valign = mxUtils.getValue(ss.style, mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE);
  2554. setSelected(top, valign == mxConstants.ALIGN_TOP);
  2555. setSelected(middle, valign == mxConstants.ALIGN_MIDDLE);
  2556. setSelected(bottom, valign == mxConstants.ALIGN_BOTTOM);
  2557. var pos = mxUtils.getValue(ss.style, mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);
  2558. var vpos = mxUtils.getValue(ss.style, mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE);
  2559. if (pos == mxConstants.ALIGN_LEFT && vpos == mxConstants.ALIGN_TOP)
  2560. {
  2561. positionSelect.value = 'topLeft';
  2562. }
  2563. else if (pos == mxConstants.ALIGN_CENTER && vpos == mxConstants.ALIGN_TOP)
  2564. {
  2565. positionSelect.value = 'top';
  2566. }
  2567. else if (pos == mxConstants.ALIGN_RIGHT && vpos == mxConstants.ALIGN_TOP)
  2568. {
  2569. positionSelect.value = 'topRight';
  2570. }
  2571. else if (pos == mxConstants.ALIGN_LEFT && vpos == mxConstants.ALIGN_BOTTOM)
  2572. {
  2573. positionSelect.value = 'bottomLeft';
  2574. }
  2575. else if (pos == mxConstants.ALIGN_CENTER && vpos == mxConstants.ALIGN_BOTTOM)
  2576. {
  2577. positionSelect.value = 'bottom';
  2578. }
  2579. else if (pos == mxConstants.ALIGN_RIGHT && vpos == mxConstants.ALIGN_BOTTOM)
  2580. {
  2581. positionSelect.value = 'bottomRight';
  2582. }
  2583. else if (pos == mxConstants.ALIGN_LEFT)
  2584. {
  2585. positionSelect.value = 'left';
  2586. }
  2587. else if (pos == mxConstants.ALIGN_RIGHT)
  2588. {
  2589. positionSelect.value = 'right';
  2590. }
  2591. else
  2592. {
  2593. positionSelect.value = 'center';
  2594. }
  2595. var dir = mxUtils.getValue(ss.style, mxConstants.STYLE_TEXT_DIRECTION, mxConstants.DEFAULT_TEXT_DIRECTION);
  2596. if (dir == mxConstants.TEXT_DIRECTION_RTL)
  2597. {
  2598. dirSelect.value = 'rightToLeft';
  2599. }
  2600. else if (dir == mxConstants.TEXT_DIRECTION_LTR)
  2601. {
  2602. dirSelect.value = 'leftToRight';
  2603. }
  2604. else if (dir == mxConstants.TEXT_DIRECTION_AUTO)
  2605. {
  2606. dirSelect.value = 'automatic';
  2607. }
  2608. if (force || document.activeElement != globalSpacing)
  2609. {
  2610. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING, 2));
  2611. globalSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2612. }
  2613. if (force || document.activeElement != topSpacing)
  2614. {
  2615. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_TOP, 0));
  2616. topSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2617. }
  2618. if (force || document.activeElement != rightSpacing)
  2619. {
  2620. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_RIGHT, 0));
  2621. rightSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2622. }
  2623. if (force || document.activeElement != bottomSpacing)
  2624. {
  2625. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_BOTTOM, 0));
  2626. bottomSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2627. }
  2628. if (force || document.activeElement != leftSpacing)
  2629. {
  2630. var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_LEFT, 0));
  2631. leftSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  2632. }
  2633. });
  2634. globalUpdate = this.installInputHandler(globalSpacing, mxConstants.STYLE_SPACING, 2, -999, 999, ' pt');
  2635. topUpdate = this.installInputHandler(topSpacing, mxConstants.STYLE_SPACING_TOP, 0, -999, 999, ' pt');
  2636. rightUpdate = this.installInputHandler(rightSpacing, mxConstants.STYLE_SPACING_RIGHT, 0, -999, 999, ' pt');
  2637. bottomUpdate = this.installInputHandler(bottomSpacing, mxConstants.STYLE_SPACING_BOTTOM, 0, -999, 999, ' pt');
  2638. leftUpdate = this.installInputHandler(leftSpacing, mxConstants.STYLE_SPACING_LEFT, 0, -999, 999, ' pt');
  2639. this.addKeyHandler(input, listener);
  2640. this.addKeyHandler(globalSpacing, listener);
  2641. this.addKeyHandler(topSpacing, listener);
  2642. this.addKeyHandler(rightSpacing, listener);
  2643. this.addKeyHandler(bottomSpacing, listener);
  2644. this.addKeyHandler(leftSpacing, listener);
  2645. graph.getModel().addListener(mxEvent.CHANGE, listener);
  2646. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  2647. listener();
  2648. if (graph.cellEditor.isContentEditing())
  2649. {
  2650. var updating = false;
  2651. var updateCssHandler = function()
  2652. {
  2653. if (!updating)
  2654. {
  2655. updating = true;
  2656. window.setTimeout(function()
  2657. {
  2658. var selectedElement = graph.getSelectedElement();
  2659. var node = selectedElement;
  2660. while (node != null && node.nodeType != mxConstants.NODETYPE_ELEMENT)
  2661. {
  2662. node = node.parentNode;
  2663. }
  2664. if (node != null)
  2665. {
  2666. var css = mxUtils.getCurrentStyle(node);
  2667. if (css != null)
  2668. {
  2669. setSelected(fontStyleItems[0], css.fontWeight == 'bold' || graph.getParentByName(node, 'B', graph.cellEditor.textarea) != null);
  2670. setSelected(fontStyleItems[1], css.fontStyle == 'italic' || graph.getParentByName(node, 'I', graph.cellEditor.textarea) != null);
  2671. setSelected(fontStyleItems[2], graph.getParentByName(node, 'U', graph.cellEditor.textarea) != null);
  2672. setSelected(left, css.textAlign == 'left');
  2673. setSelected(center, css.textAlign == 'center');
  2674. setSelected(right, css.textAlign == 'right');
  2675. setSelected(full, css.textAlign == 'justify');
  2676. setSelected(sup, graph.getParentByName(node, 'SUP', graph.cellEditor.textarea) != null);
  2677. setSelected(sub, graph.getParentByName(node, 'SUB', graph.cellEditor.textarea) != null);
  2678. currentTable = graph.getParentByName(node, 'TABLE', graph.cellEditor.textarea);
  2679. tableRow = (currentTable == null) ? null : graph.getParentByName(node, 'TR', currentTable);
  2680. tableCell = (currentTable == null) ? null : graph.getParentByName(node, 'TD', currentTable);
  2681. tableWrapper.style.display = (currentTable != null) ? '' : 'none';
  2682. if (document.activeElement != input)
  2683. {
  2684. if (node.nodeName == 'FONT' && node.getAttribute('size') == '4' &&
  2685. pendingFontSize != null)
  2686. {
  2687. node.removeAttribute('size');
  2688. node.style.fontSize = pendingFontSize + 'px';
  2689. pendingFontSize = null;
  2690. }
  2691. else
  2692. {
  2693. input.value = parseFloat(css.fontSize) + ' pt';
  2694. }
  2695. var tmp = node.style.lineHeight || css.lineHeight;
  2696. var lh = parseFloat(tmp);
  2697. if (tmp.substring(tmp.length - 2) == 'px')
  2698. {
  2699. lh = lh / parseFloat(css.fontSize);
  2700. }
  2701. if (tmp.substring(tmp.length - 1) != '%')
  2702. {
  2703. lh *= 100;
  2704. }
  2705. lineHeightInput.value = lh + ' %';
  2706. }
  2707. // Converts rgb(r,g,b) values
  2708. var color = css.color.replace(
  2709. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  2710. function($0, $1, $2, $3) {
  2711. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  2712. });
  2713. var color2 = css.backgroundColor.replace(
  2714. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  2715. function($0, $1, $2, $3) {
  2716. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  2717. });
  2718. // Updates the color picker for the current font
  2719. if (fontColorApply != null)
  2720. {
  2721. if (color.charAt(0) == '#')
  2722. {
  2723. currentFontColor = color;
  2724. }
  2725. else
  2726. {
  2727. currentFontColor = '#000000';
  2728. }
  2729. fontColorApply(currentFontColor, true);
  2730. }
  2731. if (bgColorApply != null)
  2732. {
  2733. if (color2.charAt(0) == '#')
  2734. {
  2735. currentBgColor = color2;
  2736. }
  2737. else
  2738. {
  2739. currentBgColor = null;
  2740. }
  2741. bgColorApply(currentBgColor, true);
  2742. }
  2743. // Workaround for firstChild is null or not an object
  2744. // in the log which seems to be IE8- only / 29.01.15
  2745. if (fontMenu.firstChild != null)
  2746. {
  2747. // Strips leading and trailing quotes
  2748. var ff = css.fontFamily;
  2749. if (ff.charAt(0) == '\'')
  2750. {
  2751. ff = ff.substring(1);
  2752. }
  2753. if (ff.charAt(ff.length - 1) == '\'')
  2754. {
  2755. ff = ff.substring(0, ff.length - 1);
  2756. }
  2757. fontMenu.firstChild.nodeValue = ff;
  2758. }
  2759. }
  2760. }
  2761. updating = false;
  2762. }, 0);
  2763. }
  2764. };
  2765. mxEvent.addListener(graph.cellEditor.textarea, 'input', updateCssHandler)
  2766. mxEvent.addListener(graph.cellEditor.textarea, 'touchend', updateCssHandler);
  2767. mxEvent.addListener(graph.cellEditor.textarea, 'mouseup', updateCssHandler);
  2768. mxEvent.addListener(graph.cellEditor.textarea, 'keyup', updateCssHandler);
  2769. this.listeners.push({destroy: function()
  2770. {
  2771. // No need to remove listener since textarea is destroyed after edit
  2772. }});
  2773. updateCssHandler();
  2774. }
  2775. return container;
  2776. };
  2777. /**
  2778. * Adds the label menu items to the given menu and parent.
  2779. */
  2780. StyleFormatPanel = function(format, editorUi, container)
  2781. {
  2782. BaseFormatPanel.call(this, format, editorUi, container);
  2783. this.init();
  2784. };
  2785. mxUtils.extend(StyleFormatPanel, BaseFormatPanel);
  2786. /**
  2787. * Adds the label menu items to the given menu and parent.
  2788. */
  2789. StyleFormatPanel.prototype.init = function()
  2790. {
  2791. var ui = this.editorUi;
  2792. var editor = ui.editor;
  2793. var graph = editor.graph;
  2794. var ss = this.format.getSelectionState();
  2795. if (!ss.containsImage || ss.style.shape == 'image')
  2796. {
  2797. this.container.appendChild(this.addFill(this.createPanel()));
  2798. }
  2799. this.container.appendChild(this.addStroke(this.createPanel()));
  2800. var opacityPanel = this.createRelativeOption(mxResources.get('opacity'), mxConstants.STYLE_OPACITY, 41);
  2801. opacityPanel.style.paddingTop = '8px';
  2802. opacityPanel.style.paddingBottom = '8px';
  2803. this.container.appendChild(opacityPanel);
  2804. this.container.appendChild(this.addEffects(this.createPanel()));
  2805. var opsPanel = this.addEditOps(this.createPanel());
  2806. if (opsPanel.firstChild != null)
  2807. {
  2808. mxUtils.br(opsPanel);
  2809. }
  2810. this.container.appendChild(this.addStyleOps(opsPanel));
  2811. };
  2812. /**
  2813. * Adds the label menu items to the given menu and parent.
  2814. */
  2815. StyleFormatPanel.prototype.addEditOps = function(div)
  2816. {
  2817. var ss = this.format.getSelectionState();
  2818. var btn = null;
  2819. if (this.editorUi.editor.graph.getSelectionCount() == 1)
  2820. {
  2821. btn = mxUtils.button(mxResources.get('editStyle'), mxUtils.bind(this, function(evt)
  2822. {
  2823. this.editorUi.actions.get('editStyle').funct();
  2824. }));
  2825. btn.setAttribute('title', mxResources.get('editStyle') + ' (' + this.editorUi.actions.get('editStyle').shortcut + ')');
  2826. btn.style.width = '202px';
  2827. btn.style.marginBottom = '2px';
  2828. div.appendChild(btn);
  2829. }
  2830. if (ss.image)
  2831. {
  2832. var btn2 = mxUtils.button(mxResources.get('editImage'), mxUtils.bind(this, function(evt)
  2833. {
  2834. this.editorUi.actions.get('image').funct();
  2835. }));
  2836. btn2.setAttribute('title', mxResources.get('editImage'));
  2837. btn2.style.marginBottom = '2px';
  2838. if (btn == null)
  2839. {
  2840. btn2.style.width = '202px';
  2841. }
  2842. else
  2843. {
  2844. btn.style.width = '100px';
  2845. btn2.style.width = '100px';
  2846. btn2.style.marginLeft = '2px';
  2847. }
  2848. div.appendChild(btn2);
  2849. }
  2850. return div;
  2851. };
  2852. /**
  2853. * Adds the label menu items to the given menu and parent.
  2854. */
  2855. StyleFormatPanel.prototype.addFill = function(container)
  2856. {
  2857. var ui = this.editorUi;
  2858. var graph = ui.editor.graph;
  2859. var ss = this.format.getSelectionState();
  2860. container.style.paddingTop = '6px';
  2861. container.style.paddingBottom = '6px';
  2862. // Adds gradient direction option
  2863. var gradientSelect = document.createElement('select');
  2864. gradientSelect.style.position = 'absolute';
  2865. gradientSelect.style.marginTop = '-2px';
  2866. gradientSelect.style.right = (mxClient.IS_QUIRKS) ? '52px' : '72px';
  2867. gradientSelect.style.width = '70px';
  2868. // Stops events from bubbling to color option event handler
  2869. mxEvent.addListener(gradientSelect, 'click', function(evt)
  2870. {
  2871. mxEvent.consume(evt);
  2872. });
  2873. var gradientPanel = this.createCellColorOption(mxResources.get('gradient'), mxConstants.STYLE_GRADIENTCOLOR, '#ffffff', function(color)
  2874. {
  2875. if (color == null || color == mxConstants.NONE)
  2876. {
  2877. gradientSelect.style.display = 'none';
  2878. }
  2879. else
  2880. {
  2881. gradientSelect.style.display = '';
  2882. }
  2883. });
  2884. var fillKey = (ss.style.shape == 'image') ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR;
  2885. var fillPanel = this.createCellColorOption(mxResources.get('fill'), fillKey, '#ffffff');
  2886. fillPanel.style.fontWeight = 'bold';
  2887. var tmpColor = mxUtils.getValue(ss.style, fillKey, null);
  2888. gradientPanel.style.display = (tmpColor != null && tmpColor != mxConstants.NONE &&
  2889. ss.fill && ss.style.shape != 'image') ? '' : 'none';
  2890. var directions = [mxConstants.DIRECTION_NORTH, mxConstants.DIRECTION_EAST,
  2891. mxConstants.DIRECTION_SOUTH, mxConstants.DIRECTION_WEST];
  2892. for (var i = 0; i < directions.length; i++)
  2893. {
  2894. var gradientOption = document.createElement('option');
  2895. gradientOption.setAttribute('value', directions[i]);
  2896. mxUtils.write(gradientOption, mxResources.get(directions[i]));
  2897. gradientSelect.appendChild(gradientOption);
  2898. }
  2899. gradientPanel.appendChild(gradientSelect);
  2900. var listener = mxUtils.bind(this, function()
  2901. {
  2902. ss = this.format.getSelectionState();
  2903. var value = mxUtils.getValue(ss.style, mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_SOUTH);
  2904. // Handles empty string which is not allowed as a value
  2905. if (value == '')
  2906. {
  2907. value = mxConstants.DIRECTION_SOUTH;
  2908. }
  2909. gradientSelect.value = value;
  2910. container.style.display = (ss.fill) ? '' : 'none';
  2911. var fillColor = mxUtils.getValue(ss.style, mxConstants.STYLE_FILLCOLOR, null);
  2912. if (!ss.fill || ss.containsImage || fillColor == null || fillColor == mxConstants.NONE)
  2913. {
  2914. gradientPanel.style.display = 'none';
  2915. }
  2916. else
  2917. {
  2918. gradientPanel.style.display = '';
  2919. }
  2920. });
  2921. graph.getModel().addListener(mxEvent.CHANGE, listener);
  2922. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  2923. listener();
  2924. mxEvent.addListener(gradientSelect, 'change', function(evt)
  2925. {
  2926. graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, gradientSelect.value, graph.getSelectionCells());
  2927. mxEvent.consume(evt);
  2928. });
  2929. container.appendChild(fillPanel);
  2930. container.appendChild(gradientPanel);
  2931. if (ss.style.shape == 'swimlane')
  2932. {
  2933. container.appendChild(this.createCellColorOption(mxResources.get('laneColor'), 'swimlaneFillColor', '#ffffff'));
  2934. }
  2935. return container;
  2936. };
  2937. /**
  2938. * Adds the label menu items to the given menu and parent.
  2939. */
  2940. StyleFormatPanel.prototype.addStroke = function(container)
  2941. {
  2942. var ui = this.editorUi;
  2943. var graph = ui.editor.graph;
  2944. var ss = this.format.getSelectionState();
  2945. container.style.paddingTop = '4px';
  2946. container.style.paddingBottom = '4px';
  2947. container.style.whiteSpace = 'normal';
  2948. var colorPanel = document.createElement('div');
  2949. colorPanel.style.fontWeight = 'bold';
  2950. // Adds gradient direction option
  2951. var styleSelect = document.createElement('select');
  2952. styleSelect.style.position = 'absolute';
  2953. styleSelect.style.marginTop = '-2px';
  2954. styleSelect.style.right = '72px';
  2955. styleSelect.style.width = '80px';
  2956. var styles = ['sharp', 'rounded', 'curved'];
  2957. for (var i = 0; i < styles.length; i++)
  2958. {
  2959. var styleOption = document.createElement('option');
  2960. styleOption.setAttribute('value', styles[i]);
  2961. mxUtils.write(styleOption, mxResources.get(styles[i]));
  2962. styleSelect.appendChild(styleOption);
  2963. }
  2964. mxEvent.addListener(styleSelect, 'change', function(evt)
  2965. {
  2966. graph.getModel().beginUpdate();
  2967. try
  2968. {
  2969. var keys = [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED];
  2970. // Default for rounded is 1
  2971. var values = ['0', null];
  2972. if (styleSelect.value == 'rounded')
  2973. {
  2974. values = ['1', null];
  2975. }
  2976. else if (styleSelect.value == 'curved')
  2977. {
  2978. values = [null, '1'];
  2979. }
  2980. for (var i = 0; i < keys.length; i++)
  2981. {
  2982. graph.setCellStyles(keys[i], values[i], graph.getSelectionCells());
  2983. }
  2984. ui.fireEvent(new mxEventObject('styleChanged', 'keys', keys,
  2985. 'values', values, 'cells', graph.getSelectionCells()));
  2986. }
  2987. finally
  2988. {
  2989. graph.getModel().endUpdate();
  2990. }
  2991. mxEvent.consume(evt);
  2992. });
  2993. // Stops events from bubbling to color option event handler
  2994. mxEvent.addListener(styleSelect, 'click', function(evt)
  2995. {
  2996. mxEvent.consume(evt);
  2997. });
  2998. var strokeKey = (ss.style.shape == 'image') ? mxConstants.STYLE_IMAGE_BORDER : mxConstants.STYLE_STROKECOLOR;
  2999. var lineColor = this.createCellColorOption(mxResources.get('line'), strokeKey, '#000000');
  3000. lineColor.appendChild(styleSelect);
  3001. colorPanel.appendChild(lineColor);
  3002. // Used if only edges selected
  3003. var stylePanel = colorPanel.cloneNode(false);
  3004. stylePanel.style.fontWeight = 'normal';
  3005. stylePanel.style.whiteSpace = 'nowrap';
  3006. stylePanel.style.position = 'relative';
  3007. stylePanel.style.paddingLeft = '16px'
  3008. stylePanel.style.marginBottom = '2px';
  3009. stylePanel.style.marginTop = '2px';
  3010. stylePanel.className = 'geToolbarContainer';
  3011. var addItem = mxUtils.bind(this, function(menu, width, cssName, keys, values)
  3012. {
  3013. var item = this.editorUi.menus.styleChange(menu, '', keys, values, 'geIcon', null);
  3014. var pat = document.createElement('div');
  3015. pat.style.width = width + 'px';
  3016. pat.style.height = '1px';
  3017. pat.style.borderBottom = '1px ' + cssName + ' black';
  3018. pat.style.paddingTop = '6px';
  3019. item.firstChild.firstChild.style.padding = '0px 4px 0px 4px';
  3020. item.firstChild.firstChild.style.width = width + 'px';
  3021. item.firstChild.firstChild.appendChild(pat);
  3022. return item;
  3023. });
  3024. var pattern = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu)
  3025. {
  3026. addItem(menu, 75, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid'));
  3027. addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed'));
  3028. addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)');
  3029. addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)');
  3030. addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)');
  3031. }));
  3032. // Used for mixed selection (vertices and edges)
  3033. var altStylePanel = stylePanel.cloneNode(false);
  3034. var edgeShape = this.editorUi.toolbar.addMenuFunctionInContainer(altStylePanel, 'geSprite-connection', mxResources.get('connection'), false, mxUtils.bind(this, function(menu)
  3035. {
  3036. this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], [null, null, null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line'));
  3037. this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['link', null, null, null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link'));
  3038. this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['flexArrow', null, null, null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow'));
  3039. this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['arrow', null, null, null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow'));
  3040. }));
  3041. var altPattern = this.editorUi.toolbar.addMenuFunctionInContainer(altStylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu)
  3042. {
  3043. addItem(menu, 33, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid'));
  3044. addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed'));
  3045. addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)');
  3046. addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)');
  3047. addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)');
  3048. }));
  3049. var stylePanel2 = stylePanel.cloneNode(false);
  3050. // Stroke width
  3051. var input = document.createElement('input');
  3052. input.style.textAlign = 'right';
  3053. input.style.marginTop = '2px';
  3054. input.style.width = '41px';
  3055. input.setAttribute('title', mxResources.get('linewidth'));
  3056. stylePanel.appendChild(input);
  3057. var altInput = input.cloneNode(true);
  3058. altStylePanel.appendChild(altInput);
  3059. function update(evt)
  3060. {
  3061. // Maximum stroke width is 999
  3062. var value = parseInt(input.value);
  3063. value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value));
  3064. if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1))
  3065. {
  3066. graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, graph.getSelectionCells());
  3067. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_STROKEWIDTH],
  3068. 'values', [value], 'cells', graph.getSelectionCells()));
  3069. }
  3070. input.value = value + ' pt';
  3071. mxEvent.consume(evt);
  3072. };
  3073. function altUpdate(evt)
  3074. {
  3075. // Maximum stroke width is 999
  3076. var value = parseInt(altInput.value);
  3077. value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value));
  3078. if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1))
  3079. {
  3080. graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, graph.getSelectionCells());
  3081. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_STROKEWIDTH],
  3082. 'values', [value], 'cells', graph.getSelectionCells()));
  3083. }
  3084. altInput.value = value + ' pt';
  3085. mxEvent.consume(evt);
  3086. };
  3087. var stepper = this.createStepper(input, update, 1, 9);
  3088. stepper.style.display = input.style.display;
  3089. stepper.style.marginTop = '2px';
  3090. stylePanel.appendChild(stepper);
  3091. var altStepper = this.createStepper(altInput, altUpdate, 1, 9);
  3092. altStepper.style.display = altInput.style.display;
  3093. altStepper.style.marginTop = '2px';
  3094. altStylePanel.appendChild(altStepper);
  3095. if (!mxClient.IS_QUIRKS)
  3096. {
  3097. input.style.position = 'absolute';
  3098. input.style.right = '32px';
  3099. input.style.height = '15px';
  3100. stepper.style.right = '20px';
  3101. altInput.style.position = 'absolute';
  3102. altInput.style.right = '32px';
  3103. altInput.style.height = '15px';
  3104. altStepper.style.right = '20px';
  3105. }
  3106. else
  3107. {
  3108. input.style.height = '17px';
  3109. altInput.style.height = '17px';
  3110. }
  3111. mxEvent.addListener(input, 'blur', update);
  3112. mxEvent.addListener(input, 'change', update);
  3113. mxEvent.addListener(altInput, 'blur', altUpdate);
  3114. mxEvent.addListener(altInput, 'change', altUpdate);
  3115. if (mxClient.IS_QUIRKS)
  3116. {
  3117. mxUtils.br(stylePanel2);
  3118. mxUtils.br(stylePanel2);
  3119. }
  3120. var edgeStyle = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-orthogonal', mxResources.get('waypoints'), false, mxUtils.bind(this, function(menu)
  3121. {
  3122. if (ss.style.shape != 'arrow')
  3123. {
  3124. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], [null, null, null], 'geIcon geSprite geSprite-straight', null, true).setAttribute('title', mxResources.get('straight'));
  3125. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', null, null], 'geIcon geSprite geSprite-orthogonal', null, true).setAttribute('title', mxResources.get('orthogonal'));
  3126. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalelbow', null, true).setAttribute('title', mxResources.get('simple'));
  3127. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalelbow', null, true).setAttribute('title', mxResources.get('simple'));
  3128. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
  3129. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
  3130. if (ss.style.shape == 'connector')
  3131. {
  3132. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', '1', null], 'geIcon geSprite geSprite-curved', null, true).setAttribute('title', mxResources.get('curved'));
  3133. }
  3134. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['entityRelationEdgeStyle', null, null], 'geIcon geSprite geSprite-entity', null, true).setAttribute('title', mxResources.get('entityRelation'));
  3135. }
  3136. }));
  3137. var lineStart = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-startclassic', mxResources.get('linestart'), false, mxUtils.bind(this, function(menu)
  3138. {
  3139. if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow')
  3140. {
  3141. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null, false).setAttribute('title', mxResources.get('none'));
  3142. if (ss.style.shape == 'connector')
  3143. {
  3144. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-startclassic', null, false).setAttribute('title', mxResources.get('classic'));
  3145. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], 'geIcon geSprite geSprite-startclassicthin', null, false);
  3146. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OPEN, 0], 'geIcon geSprite geSprite-startopen', null, false).setAttribute('title', mxResources.get('openArrow'));
  3147. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OPEN_THIN, 0], 'geIcon geSprite geSprite-startopenthin', null, false);
  3148. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['openAsync', 0], 'geIcon geSprite geSprite-startopenasync', null, false);
  3149. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-startblock', null, false).setAttribute('title', mxResources.get('block'));
  3150. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK_THIN, 1], 'geIcon geSprite geSprite-startblockthin', null, false);
  3151. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['async', 1], 'geIcon geSprite geSprite-startasync', null, false);
  3152. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-startoval', null, false).setAttribute('title', mxResources.get('oval'));
  3153. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-startdiamond', null, false).setAttribute('title', mxResources.get('diamond'));
  3154. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-startthindiamond', null, false).setAttribute('title', mxResources.get('diamondThin'));
  3155. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-startclassictrans', null, false).setAttribute('title', mxResources.get('classic'));
  3156. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC_THIN, 0], 'geIcon geSprite geSprite-startclassicthintrans', null, false);
  3157. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-startblocktrans', null, false).setAttribute('title', mxResources.get('block'));
  3158. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK_THIN, 0], 'geIcon geSprite geSprite-startblockthintrans', null, false);
  3159. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['async', 0], 'geIcon geSprite geSprite-startasynctrans', null, false);
  3160. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-startovaltrans', null, false).setAttribute('title', mxResources.get('oval'));
  3161. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-startdiamondtrans', null, false).setAttribute('title', mxResources.get('diamond'));
  3162. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-startthindiamondtrans', null, false).setAttribute('title', mxResources.get('diamondThin'));
  3163. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['dash', 0], 'geIcon geSprite geSprite-startdash', null, false);
  3164. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['cross', 0], 'geIcon geSprite geSprite-startcross', null, false);
  3165. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['circlePlus', 0], 'geIcon geSprite geSprite-startcircleplus', null, false);
  3166. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['circle', 1], 'geIcon geSprite geSprite-startcircle', null, false);
  3167. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERone', 0], 'geIcon geSprite geSprite-starterone', null, false);
  3168. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERmandOne', 0], 'geIcon geSprite geSprite-starteronetoone', null, false);
  3169. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERmany', 0], 'geIcon geSprite geSprite-startermany', null, false);
  3170. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERoneToMany', 0], 'geIcon geSprite geSprite-starteronetomany', null, false);
  3171. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERzeroToOne', 1], 'geIcon geSprite geSprite-starteroneopt', null, false);
  3172. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERzeroToMany', 1], 'geIcon geSprite geSprite-startermanyopt', null, false);
  3173. }
  3174. else
  3175. {
  3176. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW], [mxConstants.ARROW_BLOCK], 'geIcon geSprite geSprite-startblocktrans', null, false).setAttribute('title', mxResources.get('block'));
  3177. }
  3178. }
  3179. }));
  3180. var lineEnd = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-endclassic', mxResources.get('lineend'), false, mxUtils.bind(this, function(menu)
  3181. {
  3182. if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow')
  3183. {
  3184. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon geSprite geSprite-noarrow', null, false).setAttribute('title', mxResources.get('none'));
  3185. if (ss.style.shape == 'connector')
  3186. {
  3187. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-endclassic', null, false).setAttribute('title', mxResources.get('classic'));
  3188. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], 'geIcon geSprite geSprite-endclassicthin', null, false);
  3189. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OPEN, 0], 'geIcon geSprite geSprite-endopen', null, false).setAttribute('title', mxResources.get('openArrow'));
  3190. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OPEN_THIN, 0], 'geIcon geSprite geSprite-endopenthin', null, false);
  3191. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['openAsync', 0], 'geIcon geSprite geSprite-endopenasync', null, false);
  3192. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-endblock', null, false).setAttribute('title', mxResources.get('block'));
  3193. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK_THIN, 1], 'geIcon geSprite geSprite-endblockthin', null, false);
  3194. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['async', 1], 'geIcon geSprite geSprite-endasync', null, false);
  3195. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-endoval', null, false).setAttribute('title', mxResources.get('oval'));
  3196. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-enddiamond', null, false).setAttribute('title', mxResources.get('diamond'));
  3197. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-endthindiamond', null, false).setAttribute('title', mxResources.get('diamondThin'));
  3198. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-endclassictrans', null, false).setAttribute('title', mxResources.get('classic'));
  3199. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC_THIN, 0], 'geIcon geSprite geSprite-endclassicthintrans', null, false);
  3200. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-endblocktrans', null, false).setAttribute('title', mxResources.get('block'));
  3201. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK_THIN, 0], 'geIcon geSprite geSprite-endblockthintrans', null, false);
  3202. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['async', 0], 'geIcon geSprite geSprite-endasynctrans', null, false);
  3203. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-endovaltrans', null, false).setAttribute('title', mxResources.get('oval'));
  3204. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-enddiamondtrans', null, false).setAttribute('title', mxResources.get('diamond'));
  3205. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-endthindiamondtrans', null, false).setAttribute('title', mxResources.get('diamondThin'));
  3206. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['dash', 0], 'geIcon geSprite geSprite-enddash', null, false);
  3207. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['cross', 0], 'geIcon geSprite geSprite-endcross', null, false);
  3208. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['circlePlus', 0], 'geIcon geSprite geSprite-endcircleplus', null, false);
  3209. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['circle', 1], 'geIcon geSprite geSprite-endcircle', null, false);
  3210. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERone', 0], 'geIcon geSprite geSprite-enderone', null, false);
  3211. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERmandOne', 0], 'geIcon geSprite geSprite-enderonetoone', null, false);
  3212. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERmany', 0], 'geIcon geSprite geSprite-endermany', null, false);
  3213. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERoneToMany', 0], 'geIcon geSprite geSprite-enderonetomany', null, false);
  3214. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERzeroToOne', 1], 'geIcon geSprite geSprite-enderoneopt', null, false);
  3215. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERzeroToMany', 1], 'geIcon geSprite geSprite-endermanyopt', null, false);
  3216. }
  3217. else
  3218. {
  3219. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW], [mxConstants.ARROW_BLOCK], 'geIcon geSprite geSprite-endblocktrans', null, false).setAttribute('title', mxResources.get('block'));
  3220. }
  3221. }
  3222. }));
  3223. this.addArrow(edgeShape, 8);
  3224. this.addArrow(edgeStyle);
  3225. this.addArrow(lineStart);
  3226. this.addArrow(lineEnd);
  3227. var symbol = this.addArrow(pattern, 9);
  3228. symbol.className = 'geIcon';
  3229. symbol.style.width = '84px';
  3230. var altSymbol = this.addArrow(altPattern, 9);
  3231. altSymbol.className = 'geIcon';
  3232. altSymbol.style.width = '22px';
  3233. var solid = document.createElement('div');
  3234. solid.style.width = '85px';
  3235. solid.style.height = '1px';
  3236. solid.style.borderBottom = '1px solid black';
  3237. solid.style.marginBottom = '9px';
  3238. symbol.appendChild(solid);
  3239. var altSolid = document.createElement('div');
  3240. altSolid.style.width = '23px';
  3241. altSolid.style.height = '1px';
  3242. altSolid.style.borderBottom = '1px solid black';
  3243. altSolid.style.marginBottom = '9px';
  3244. altSymbol.appendChild(altSolid);
  3245. pattern.style.height = '15px';
  3246. altPattern.style.height = '15px';
  3247. edgeShape.style.height = '15px';
  3248. edgeStyle.style.height = '17px';
  3249. lineStart.style.marginLeft = '3px';
  3250. lineStart.style.height = '17px';
  3251. lineEnd.style.marginLeft = '3px';
  3252. lineEnd.style.height = '17px';
  3253. container.appendChild(colorPanel);
  3254. container.appendChild(altStylePanel);
  3255. container.appendChild(stylePanel);
  3256. var arrowPanel = stylePanel.cloneNode(false);
  3257. arrowPanel.style.paddingBottom = '6px';
  3258. arrowPanel.style.paddingTop = '4px';
  3259. arrowPanel.style.fontWeight = 'normal';
  3260. var span = document.createElement('div');
  3261. span.style.position = 'absolute';
  3262. span.style.marginLeft = '3px';
  3263. span.style.marginBottom = '12px';
  3264. span.style.marginTop = '2px';
  3265. span.style.fontWeight = 'normal';
  3266. span.style.width = '76px';
  3267. mxUtils.write(span, mxResources.get('lineend'));
  3268. arrowPanel.appendChild(span);
  3269. var endSpacingUpdate, endSizeUpdate;
  3270. var endSpacing = this.addUnitInput(arrowPanel, 'pt', 74, 33, function()
  3271. {
  3272. endSpacingUpdate.apply(this, arguments);
  3273. });
  3274. var endSize = this.addUnitInput(arrowPanel, 'pt', 20, 33, function()
  3275. {
  3276. endSizeUpdate.apply(this, arguments);
  3277. });
  3278. mxUtils.br(arrowPanel);
  3279. var spacer = document.createElement('div');
  3280. spacer.style.height = '8px';
  3281. arrowPanel.appendChild(spacer);
  3282. span = span.cloneNode(false);
  3283. mxUtils.write(span, mxResources.get('linestart'));
  3284. arrowPanel.appendChild(span);
  3285. var startSpacingUpdate, startSizeUpdate;
  3286. var startSpacing = this.addUnitInput(arrowPanel, 'pt', 74, 33, function()
  3287. {
  3288. startSpacingUpdate.apply(this, arguments);
  3289. });
  3290. var startSize = this.addUnitInput(arrowPanel, 'pt', 20, 33, function()
  3291. {
  3292. startSizeUpdate.apply(this, arguments);
  3293. });
  3294. mxUtils.br(arrowPanel);
  3295. this.addLabel(arrowPanel, mxResources.get('spacing'), 74, 50);
  3296. this.addLabel(arrowPanel, mxResources.get('size'), 20, 50);
  3297. mxUtils.br(arrowPanel);
  3298. var perimeterPanel = colorPanel.cloneNode(false);
  3299. perimeterPanel.style.fontWeight = 'normal';
  3300. perimeterPanel.style.position = 'relative';
  3301. perimeterPanel.style.paddingLeft = '16px'
  3302. perimeterPanel.style.marginBottom = '2px';
  3303. perimeterPanel.style.marginTop = '6px';
  3304. perimeterPanel.style.borderWidth = '0px';
  3305. perimeterPanel.style.paddingBottom = '18px';
  3306. var span = document.createElement('div');
  3307. span.style.position = 'absolute';
  3308. span.style.marginLeft = '3px';
  3309. span.style.marginBottom = '12px';
  3310. span.style.marginTop = '1px';
  3311. span.style.fontWeight = 'normal';
  3312. span.style.width = '120px';
  3313. mxUtils.write(span, mxResources.get('perimeter'));
  3314. perimeterPanel.appendChild(span);
  3315. var perimeterUpdate;
  3316. var perimeterSpacing = this.addUnitInput(perimeterPanel, 'pt', 20, 41, function()
  3317. {
  3318. perimeterUpdate.apply(this, arguments);
  3319. });
  3320. if (ss.edges.length == graph.getSelectionCount())
  3321. {
  3322. container.appendChild(stylePanel2);
  3323. if (mxClient.IS_QUIRKS)
  3324. {
  3325. mxUtils.br(container);
  3326. mxUtils.br(container);
  3327. }
  3328. container.appendChild(arrowPanel);
  3329. }
  3330. else if (ss.vertices.length == graph.getSelectionCount())
  3331. {
  3332. if (mxClient.IS_QUIRKS)
  3333. {
  3334. mxUtils.br(container);
  3335. }
  3336. container.appendChild(perimeterPanel);
  3337. }
  3338. var listener = mxUtils.bind(this, function(sender, evt, force)
  3339. {
  3340. ss = this.format.getSelectionState();
  3341. var color = mxUtils.getValue(ss.style, strokeKey, null);
  3342. if (force || document.activeElement != input)
  3343. {
  3344. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1));
  3345. input.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3346. }
  3347. if (force || document.activeElement != altInput)
  3348. {
  3349. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1));
  3350. altInput.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3351. }
  3352. styleSelect.style.visibility = (ss.style.shape == 'connector') ? '' : 'hidden';
  3353. if (mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == '1')
  3354. {
  3355. styleSelect.value = 'curved';
  3356. }
  3357. else if (mxUtils.getValue(ss.style, mxConstants.STYLE_ROUNDED, null) == '1')
  3358. {
  3359. styleSelect.value = 'rounded';
  3360. }
  3361. if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASHED, null) == '1')
  3362. {
  3363. if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, null) == null)
  3364. {
  3365. solid.style.borderBottom = '1px dashed black';
  3366. }
  3367. else
  3368. {
  3369. solid.style.borderBottom = '1px dotted black';
  3370. }
  3371. }
  3372. else
  3373. {
  3374. solid.style.borderBottom = '1px solid black';
  3375. }
  3376. altSolid.style.borderBottom = solid.style.borderBottom;
  3377. // Updates toolbar icon for edge style
  3378. var edgeStyleDiv = edgeStyle.getElementsByTagName('div')[0];
  3379. var es = mxUtils.getValue(ss.style, mxConstants.STYLE_EDGE, null);
  3380. if (mxUtils.getValue(ss.style, mxConstants.STYLE_NOEDGESTYLE, null) == '1')
  3381. {
  3382. es = null;
  3383. }
  3384. if (es == 'orthogonalEdgeStyle' && mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == '1')
  3385. {
  3386. edgeStyleDiv.className = 'geSprite geSprite-curved';
  3387. }
  3388. else if (es == 'straight' || es == 'none' || es == null)
  3389. {
  3390. edgeStyleDiv.className = 'geSprite geSprite-straight';
  3391. }
  3392. else if (es == 'entityRelationEdgeStyle')
  3393. {
  3394. edgeStyleDiv.className = 'geSprite geSprite-entity';
  3395. }
  3396. else if (es == 'elbowEdgeStyle')
  3397. {
  3398. edgeStyleDiv.className = 'geSprite ' + ((mxUtils.getValue(ss.style,
  3399. mxConstants.STYLE_ELBOW, null) == 'vertical') ?
  3400. 'geSprite-verticalelbow' : 'geSprite-horizontalelbow');
  3401. }
  3402. else if (es == 'isometricEdgeStyle')
  3403. {
  3404. edgeStyleDiv.className = 'geSprite ' + ((mxUtils.getValue(ss.style,
  3405. mxConstants.STYLE_ELBOW, null) == 'vertical') ?
  3406. 'geSprite-verticalisometric' : 'geSprite-horizontalisometric');
  3407. }
  3408. else
  3409. {
  3410. edgeStyleDiv.className = 'geSprite geSprite-orthogonal';
  3411. }
  3412. // Updates icon for edge shape
  3413. var edgeShapeDiv = edgeShape.getElementsByTagName('div')[0];
  3414. if (ss.style.shape == 'link')
  3415. {
  3416. edgeShapeDiv.className = 'geSprite geSprite-linkedge';
  3417. }
  3418. else if (ss.style.shape == 'flexArrow')
  3419. {
  3420. edgeShapeDiv.className = 'geSprite geSprite-arrow';
  3421. }
  3422. else if (ss.style.shape == 'arrow')
  3423. {
  3424. edgeShapeDiv.className = 'geSprite geSprite-simplearrow';
  3425. }
  3426. else
  3427. {
  3428. edgeShapeDiv.className = 'geSprite geSprite-connection';
  3429. }
  3430. if (ss.edges.length == graph.getSelectionCount())
  3431. {
  3432. altStylePanel.style.display = '';
  3433. stylePanel.style.display = 'none';
  3434. }
  3435. else
  3436. {
  3437. altStylePanel.style.display = 'none';
  3438. stylePanel.style.display = '';
  3439. }
  3440. function updateArrow(marker, fill, elt, prefix)
  3441. {
  3442. var markerDiv = elt.getElementsByTagName('div')[0];
  3443. markerDiv.className = ui.getCssClassForMarker(prefix, ss.style.shape, marker, fill);
  3444. return markerDiv;
  3445. };
  3446. var sourceDiv = updateArrow(mxUtils.getValue(ss.style, mxConstants.STYLE_STARTARROW, null),
  3447. mxUtils.getValue(ss.style, 'startFill', '1'), lineStart, 'start');
  3448. var targetDiv = updateArrow(mxUtils.getValue(ss.style, mxConstants.STYLE_ENDARROW, null),
  3449. mxUtils.getValue(ss.style, 'endFill', '1'), lineEnd, 'end');
  3450. // Special cases for markers
  3451. if (ss.style.shape == 'arrow')
  3452. {
  3453. sourceDiv.className = 'geSprite geSprite-noarrow';
  3454. targetDiv.className = 'geSprite geSprite-endblocktrans';
  3455. }
  3456. else if (ss.style.shape == 'link')
  3457. {
  3458. sourceDiv.className = 'geSprite geSprite-noarrow';
  3459. targetDiv.className = 'geSprite geSprite-noarrow';
  3460. }
  3461. mxUtils.setOpacity(edgeStyle, (ss.style.shape == 'arrow') ? 30 : 100);
  3462. if (ss.style.shape != 'connector' && ss.style.shape != 'flexArrow')
  3463. {
  3464. mxUtils.setOpacity(lineStart, 30);
  3465. mxUtils.setOpacity(lineEnd, 30);
  3466. }
  3467. else
  3468. {
  3469. mxUtils.setOpacity(lineStart, 100);
  3470. mxUtils.setOpacity(lineEnd, 100);
  3471. }
  3472. if (force || document.activeElement != startSize)
  3473. {
  3474. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE));
  3475. startSize.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3476. }
  3477. if (force || document.activeElement != startSpacing)
  3478. {
  3479. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_SOURCE_PERIMETER_SPACING, 0));
  3480. startSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3481. }
  3482. if (force || document.activeElement != endSize)
  3483. {
  3484. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE));
  3485. endSize.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3486. }
  3487. if (force || document.activeElement != startSpacing)
  3488. {
  3489. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_TARGET_PERIMETER_SPACING, 0));
  3490. endSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3491. }
  3492. if (force || document.activeElement != perimeterSpacing)
  3493. {
  3494. var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_PERIMETER_SPACING, 0));
  3495. perimeterSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt';
  3496. }
  3497. });
  3498. startSizeUpdate = this.installInputHandler(startSize, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE, 0, 999, ' pt');
  3499. startSpacingUpdate = this.installInputHandler(startSpacing, mxConstants.STYLE_SOURCE_PERIMETER_SPACING, 0, -999, 999, ' pt');
  3500. endSizeUpdate = this.installInputHandler(endSize, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE, 0, 999, ' pt');
  3501. endSpacingUpdate = this.installInputHandler(endSpacing, mxConstants.STYLE_TARGET_PERIMETER_SPACING, 0, -999, 999, ' pt');
  3502. perimeterUpdate = this.installInputHandler(perimeterSpacing, mxConstants.STYLE_PERIMETER_SPACING, 0, 0, 999, ' pt');
  3503. this.addKeyHandler(input, listener);
  3504. this.addKeyHandler(startSize, listener);
  3505. this.addKeyHandler(startSpacing, listener);
  3506. this.addKeyHandler(endSize, listener);
  3507. this.addKeyHandler(endSpacing, listener);
  3508. this.addKeyHandler(perimeterSpacing, listener);
  3509. graph.getModel().addListener(mxEvent.CHANGE, listener);
  3510. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  3511. listener();
  3512. return container;
  3513. };
  3514. /**
  3515. * Adds the label menu items to the given menu and parent.
  3516. */
  3517. StyleFormatPanel.prototype.addEffects = function(div)
  3518. {
  3519. var ui = this.editorUi;
  3520. var editor = ui.editor;
  3521. var graph = editor.graph;
  3522. var ss = this.format.getSelectionState();
  3523. div.style.paddingTop = '0px';
  3524. div.style.paddingBottom = '2px';
  3525. var table = document.createElement('table');
  3526. if (mxClient.IS_QUIRKS)
  3527. {
  3528. table.style.fontSize = '1em';
  3529. }
  3530. table.style.width = '100%';
  3531. table.style.fontWeight = 'bold';
  3532. table.style.paddingRight = '20px';
  3533. var tbody = document.createElement('tbody');
  3534. var row = document.createElement('tr');
  3535. row.style.padding = '0px';
  3536. var left = document.createElement('td');
  3537. left.style.padding = '0px';
  3538. left.style.width = '50%';
  3539. left.setAttribute('valign', 'top');
  3540. var right = left.cloneNode(true);
  3541. right.style.paddingLeft = '8px';
  3542. row.appendChild(left);
  3543. row.appendChild(right);
  3544. tbody.appendChild(row);
  3545. table.appendChild(tbody);
  3546. div.appendChild(table);
  3547. var current = left;
  3548. var count = 0;
  3549. var addOption = mxUtils.bind(this, function(label, key, defaultValue)
  3550. {
  3551. var opt = this.createCellOption(label, key, defaultValue);
  3552. opt.style.width = '100%';
  3553. current.appendChild(opt);
  3554. current = (current == left) ? right : left;
  3555. count++;
  3556. });
  3557. var listener = mxUtils.bind(this, function(sender, evt, force)
  3558. {
  3559. ss = this.format.getSelectionState();
  3560. left.innerHTML = '';
  3561. right.innerHTML = '';
  3562. current = left;
  3563. if (ss.rounded)
  3564. {
  3565. addOption(mxResources.get('rounded'), mxConstants.STYLE_ROUNDED, 0);
  3566. }
  3567. if (ss.style.shape == 'swimlane')
  3568. {
  3569. addOption(mxResources.get('divider'), 'swimlaneLine', 1);
  3570. }
  3571. if (!ss.containsImage)
  3572. {
  3573. addOption(mxResources.get('shadow'), mxConstants.STYLE_SHADOW, 0);
  3574. }
  3575. if (ss.glass)
  3576. {
  3577. addOption(mxResources.get('glass'), mxConstants.STYLE_GLASS, 0);
  3578. }
  3579. if (ss.comic)
  3580. {
  3581. addOption(mxResources.get('comic'), 'comic', 0);
  3582. }
  3583. if (count == 0)
  3584. {
  3585. div.style.display = 'none';
  3586. }
  3587. });
  3588. graph.getModel().addListener(mxEvent.CHANGE, listener);
  3589. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  3590. listener();
  3591. return div;
  3592. }
  3593. /**
  3594. * Adds the label menu items to the given menu and parent.
  3595. */
  3596. StyleFormatPanel.prototype.addStyleOps = function(div)
  3597. {
  3598. div.style.paddingTop = '10px';
  3599. div.style.paddingBottom = '10px';
  3600. var btn = mxUtils.button(mxResources.get('setAsDefaultStyle'), mxUtils.bind(this, function(evt)
  3601. {
  3602. this.editorUi.actions.get('setAsDefaultStyle').funct();
  3603. }));
  3604. btn.setAttribute('title', mxResources.get('setAsDefaultStyle') + ' (' + this.editorUi.actions.get('setAsDefaultStyle').shortcut + ')');
  3605. btn.style.width = '202px';
  3606. div.appendChild(btn);
  3607. return div;
  3608. };
  3609. /**
  3610. * Adds the label menu items to the given menu and parent.
  3611. */
  3612. DiagramFormatPanel = function(format, editorUi, container)
  3613. {
  3614. BaseFormatPanel.call(this, format, editorUi, container);
  3615. this.init();
  3616. };
  3617. mxUtils.extend(DiagramFormatPanel, BaseFormatPanel);
  3618. /**
  3619. * Specifies if the background image option should be shown. Default is true.
  3620. */
  3621. DiagramFormatPanel.prototype.showBackgroundImageOption = true;
  3622. /**
  3623. * Adds the label menu items to the given menu and parent.
  3624. */
  3625. DiagramFormatPanel.prototype.init = function()
  3626. {
  3627. var ui = this.editorUi;
  3628. var editor = ui.editor;
  3629. var graph = editor.graph;
  3630. this.container.appendChild(this.addView(this.createPanel()));
  3631. if (graph.isEnabled())
  3632. {
  3633. this.container.appendChild(this.addOptions(this.createPanel()));
  3634. this.container.appendChild(this.addPaperSize(this.createPanel()));
  3635. this.container.appendChild(this.addStyleOps(this.createPanel()));
  3636. }
  3637. };
  3638. /**
  3639. * Adds the label menu items to the given menu and parent.
  3640. */
  3641. DiagramFormatPanel.prototype.addView = function(div)
  3642. {
  3643. var ui = this.editorUi;
  3644. var editor = ui.editor;
  3645. var graph = editor.graph;
  3646. div.appendChild(this.createTitle(mxResources.get('view')));
  3647. // Grid
  3648. this.addGridOption(div);
  3649. if (graph.isEnabled())
  3650. {
  3651. // Guides
  3652. div.appendChild(this.createOption(mxResources.get('guides'), function()
  3653. {
  3654. return graph.graphHandler.guidesEnabled;
  3655. }, function(checked)
  3656. {
  3657. ui.actions.get('guides').funct();
  3658. },
  3659. {
  3660. install: function(apply)
  3661. {
  3662. this.listener = function()
  3663. {
  3664. apply(graph.graphHandler.guidesEnabled);
  3665. };
  3666. ui.addListener('guidesEnabledChanged', this.listener);
  3667. },
  3668. destroy: function()
  3669. {
  3670. ui.removeListener(this.listener);
  3671. }
  3672. }));
  3673. // Page View
  3674. div.appendChild(this.createOption(mxResources.get('pageView'), function()
  3675. {
  3676. return graph.pageVisible;
  3677. }, function(checked)
  3678. {
  3679. ui.actions.get('pageView').funct();
  3680. },
  3681. {
  3682. install: function(apply)
  3683. {
  3684. this.listener = function()
  3685. {
  3686. apply(graph.pageVisible);
  3687. };
  3688. ui.addListener('pageViewChanged', this.listener);
  3689. },
  3690. destroy: function()
  3691. {
  3692. ui.removeListener(this.listener);
  3693. }
  3694. }));
  3695. // Background
  3696. var bg = this.createColorOption(mxResources.get('background'), function()
  3697. {
  3698. return graph.background;
  3699. }, function(color)
  3700. {
  3701. ui.setBackgroundColor(color);
  3702. }, '#ffffff',
  3703. {
  3704. install: function(apply)
  3705. {
  3706. this.listener = function()
  3707. {
  3708. apply(graph.background);
  3709. };
  3710. ui.addListener('backgroundColorChanged', this.listener);
  3711. },
  3712. destroy: function()
  3713. {
  3714. ui.removeListener(this.listener);
  3715. }
  3716. });
  3717. if (this.showBackgroundImageOption)
  3718. {
  3719. var btn = mxUtils.button(mxResources.get('image'), function(evt)
  3720. {
  3721. ui.showBackgroundImageDialog();
  3722. mxEvent.consume(evt);
  3723. })
  3724. btn.style.position = 'absolute';
  3725. btn.className = 'geColorBtn';
  3726. btn.style.marginTop = '-4px';
  3727. btn.style.paddingBottom = (document.documentMode == 11 || mxClient.IS_MT) ? '0px' : '2px';
  3728. btn.style.height = '22px';
  3729. btn.style.right = (mxClient.IS_QUIRKS) ? '52px' : '72px';
  3730. btn.style.width = '56px';
  3731. bg.appendChild(btn);
  3732. }
  3733. div.appendChild(bg);
  3734. }
  3735. return div;
  3736. };
  3737. /**
  3738. * Adds the label menu items to the given menu and parent.
  3739. */
  3740. DiagramFormatPanel.prototype.addOptions = function(div)
  3741. {
  3742. var ui = this.editorUi;
  3743. var editor = ui.editor;
  3744. var graph = editor.graph;
  3745. div.appendChild(this.createTitle(mxResources.get('options')));
  3746. if (graph.isEnabled())
  3747. {
  3748. // Connection arrows
  3749. div.appendChild(this.createOption(mxResources.get('connectionArrows'), function()
  3750. {
  3751. return graph.connectionArrowsEnabled;
  3752. }, function(checked)
  3753. {
  3754. ui.actions.get('connectionArrows').funct();
  3755. },
  3756. {
  3757. install: function(apply)
  3758. {
  3759. this.listener = function()
  3760. {
  3761. apply(graph.connectionArrowsEnabled);
  3762. };
  3763. ui.addListener('connectionArrowsChanged', this.listener);
  3764. },
  3765. destroy: function()
  3766. {
  3767. ui.removeListener(this.listener);
  3768. }
  3769. }));
  3770. // Connection points
  3771. div.appendChild(this.createOption(mxResources.get('connectionPoints'), function()
  3772. {
  3773. return graph.connectionHandler.isEnabled();
  3774. }, function(checked)
  3775. {
  3776. ui.actions.get('connectionPoints').funct();
  3777. },
  3778. {
  3779. install: function(apply)
  3780. {
  3781. this.listener = function()
  3782. {
  3783. apply(graph.connectionHandler.isEnabled());
  3784. };
  3785. ui.addListener('connectionPointsChanged', this.listener);
  3786. },
  3787. destroy: function()
  3788. {
  3789. ui.removeListener(this.listener);
  3790. }
  3791. }));
  3792. }
  3793. return div;
  3794. };
  3795. /**
  3796. *
  3797. */
  3798. DiagramFormatPanel.prototype.addGridOption = function(container)
  3799. {
  3800. var ui = this.editorUi;
  3801. var graph = ui.editor.graph;
  3802. var input = document.createElement('input');
  3803. input.style.position = 'absolute';
  3804. input.style.textAlign = 'right';
  3805. input.style.width = '38px';
  3806. input.value = graph.getGridSize() + ' pt';
  3807. var stepper = this.createStepper(input, update);
  3808. input.style.display = (graph.isGridEnabled()) ? '' : 'none';
  3809. stepper.style.display = input.style.display;
  3810. mxEvent.addListener(input, 'keydown', function(e)
  3811. {
  3812. if (e.keyCode == 13)
  3813. {
  3814. graph.container.focus();
  3815. mxEvent.consume(e);
  3816. }
  3817. else if (e.keyCode == 27)
  3818. {
  3819. input.value = graph.getGridSize();
  3820. graph.container.focus();
  3821. mxEvent.consume(e);
  3822. }
  3823. });
  3824. function update(evt)
  3825. {
  3826. var value = parseInt(input.value);
  3827. value = Math.max(1, (isNaN(value)) ? 10 : value);
  3828. if (value != graph.getGridSize())
  3829. {
  3830. graph.setGridSize(value)
  3831. }
  3832. input.value = value + ' pt';
  3833. mxEvent.consume(evt);
  3834. };
  3835. mxEvent.addListener(input, 'blur', update);
  3836. mxEvent.addListener(input, 'change', update);
  3837. if (mxClient.IS_SVG)
  3838. {
  3839. input.style.marginTop = '-2px';
  3840. input.style.right = '84px';
  3841. stepper.style.marginTop = '-16px';
  3842. stepper.style.right = '72px';
  3843. var panel = this.createColorOption(mxResources.get('grid'), function()
  3844. {
  3845. var color = graph.view.gridColor;
  3846. return (graph.isGridEnabled()) ? color : null;
  3847. }, function(color)
  3848. {
  3849. if (color == mxConstants.NONE)
  3850. {
  3851. graph.setGridEnabled(false);
  3852. ui.fireEvent(new mxEventObject('gridEnabledChanged'));
  3853. }
  3854. else
  3855. {
  3856. graph.setGridEnabled(true);
  3857. ui.setGridColor(color);
  3858. }
  3859. input.style.display = (graph.isGridEnabled()) ? '' : 'none';
  3860. stepper.style.display = input.style.display;
  3861. }, '#e0e0e0',
  3862. {
  3863. install: function(apply)
  3864. {
  3865. this.listener = function()
  3866. {
  3867. apply((graph.isGridEnabled()) ? graph.view.gridColor : null);
  3868. };
  3869. ui.addListener('gridColorChanged', this.listener);
  3870. ui.addListener('gridEnabledChanged', this.listener);
  3871. },
  3872. destroy: function()
  3873. {
  3874. ui.removeListener(this.listener);
  3875. }
  3876. });
  3877. panel.appendChild(input);
  3878. panel.appendChild(stepper);
  3879. container.appendChild(panel);
  3880. }
  3881. else
  3882. {
  3883. input.style.marginTop = '2px';
  3884. input.style.right = '32px';
  3885. stepper.style.marginTop = '2px';
  3886. stepper.style.right = '20px';
  3887. container.appendChild(input);
  3888. container.appendChild(stepper);
  3889. container.appendChild(this.createOption(mxResources.get('grid'), function()
  3890. {
  3891. return graph.isGridEnabled();
  3892. }, function(checked)
  3893. {
  3894. graph.setGridEnabled(checked);
  3895. if (graph.isGridEnabled())
  3896. {
  3897. graph.view.gridColor = '#e0e0e0';
  3898. }
  3899. ui.fireEvent(new mxEventObject('gridEnabledChanged'));
  3900. },
  3901. {
  3902. install: function(apply)
  3903. {
  3904. this.listener = function()
  3905. {
  3906. input.style.display = (graph.isGridEnabled()) ? '' : 'none';
  3907. stepper.style.display = input.style.display;
  3908. apply(graph.isGridEnabled());
  3909. };
  3910. ui.addListener('gridEnabledChanged', this.listener);
  3911. },
  3912. destroy: function()
  3913. {
  3914. ui.removeListener(this.listener);
  3915. }
  3916. }));
  3917. }
  3918. };
  3919. /**
  3920. * Adds the label menu items to the given menu and parent.
  3921. */
  3922. DiagramFormatPanel.prototype.addDocumentProperties = function(div)
  3923. {
  3924. // Hook for subclassers
  3925. var ui = this.editorUi;
  3926. var editor = ui.editor;
  3927. var graph = editor.graph;
  3928. div.appendChild(this.createTitle(mxResources.get('options')));
  3929. return div;
  3930. };
  3931. /**
  3932. * Adds the label menu items to the given menu and parent.
  3933. */
  3934. DiagramFormatPanel.prototype.addPaperSize = function(div)
  3935. {
  3936. var ui = this.editorUi;
  3937. var editor = ui.editor;
  3938. var graph = editor.graph;
  3939. div.appendChild(this.createTitle(mxResources.get('paperSize')));
  3940. var accessor = PageSetupDialog.addPageFormatPanel(div, 'formatpanel', graph.pageFormat, function(pageFormat)
  3941. {
  3942. if (graph.pageFormat == null || graph.pageFormat.width != pageFormat.width || graph.pageFormat.height != pageFormat.height)
  3943. {
  3944. ui.setPageFormat(pageFormat);
  3945. }
  3946. });
  3947. this.addKeyHandler(accessor.widthInput, function()
  3948. {
  3949. console.log('here', graph.pageFormat);
  3950. accessor.set(graph.pageFormat);
  3951. });
  3952. - this.addKeyHandler(accessor.heightInput, function()
  3953. {
  3954. accessor.set(graph.pageFormat);
  3955. });
  3956. var listener = function()
  3957. {
  3958. accessor.set(graph.pageFormat);
  3959. };
  3960. ui.addListener('pageFormatChanged', listener);
  3961. this.listeners.push({destroy: function() { ui.removeListener(listener); }});
  3962. graph.getModel().addListener(mxEvent.CHANGE, listener);
  3963. this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }});
  3964. return div;
  3965. };
  3966. /**
  3967. * Adds the label menu items to the given menu and parent.
  3968. */
  3969. DiagramFormatPanel.prototype.addStyleOps = function(div)
  3970. {
  3971. var btn = mxUtils.button(mxResources.get('editData'), mxUtils.bind(this, function(evt)
  3972. {
  3973. this.editorUi.actions.get('editData').funct();
  3974. }));
  3975. btn.setAttribute('title', mxResources.get('editData') + ' (' + this.editorUi.actions.get('editData').shortcut + ')');
  3976. btn.style.width = '202px';
  3977. btn.style.marginBottom = '2px';
  3978. div.appendChild(btn);
  3979. mxUtils.br(div);
  3980. btn = mxUtils.button(mxResources.get('clearDefaultStyle'), mxUtils.bind(this, function(evt)
  3981. {
  3982. this.editorUi.actions.get('clearDefaultStyle').funct();
  3983. }));
  3984. btn.setAttribute('title', mxResources.get('clearDefaultStyle') + ' (' + this.editorUi.actions.get('clearDefaultStyle').shortcut + ')');
  3985. btn.style.width = '202px';
  3986. div.appendChild(btn);
  3987. return div;
  3988. };
  3989. /**
  3990. * Adds the label menu items to the given menu and parent.
  3991. */
  3992. DiagramFormatPanel.prototype.destroy = function()
  3993. {
  3994. BaseFormatPanel.prototype.destroy.apply(this, arguments);
  3995. if (this.gridEnabledListener)
  3996. {
  3997. this.editorUi.removeListener(this.gridEnabledListener);
  3998. this.gridEnabledListener = null;
  3999. }
  4000. };