Minimal.js 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830
  1. /**
  2. * Code for the minimal UI theme.
  3. */
  4. EditorUi.initMinimalTheme = function()
  5. {
  6. // Disabled in lightbox and chromeless mode
  7. if (urlParams['lightbox'] == '1' || urlParams['chrome'] == '0' || typeof window.Format === 'undefined' || typeof window.Menus === 'undefined')
  8. {
  9. window.uiTheme = null;
  10. return;
  11. }
  12. var iw = 0;
  13. try
  14. {
  15. iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  16. }
  17. catch (e)
  18. {
  19. // ignore
  20. }
  21. /**
  22. *
  23. */
  24. var WrapperWindow = function(editorUi, title, x, y, w, h, fn)
  25. {
  26. var graph = editorUi.editor.graph;
  27. var div = document.createElement('div');
  28. div.className = 'geSidebarContainer';
  29. div.style.position = 'absolute';
  30. div.style.width = '100%';
  31. div.style.height = '100%';
  32. div.style.border = '1px solid whiteSmoke';
  33. div.style.overflowX = 'hidden';
  34. div.style.overflowY = 'auto';
  35. fn(div);
  36. this.window = new mxWindow(title, div, x, y, w, h, true, true);
  37. this.window.destroyOnClose = false;
  38. this.window.setMaximizable(false);
  39. this.window.setResizable(true);
  40. this.window.setClosable(true);
  41. this.window.setVisible(true);
  42. this.window.setLocation = function(x, y)
  43. {
  44. var iiw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  45. var ih = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
  46. x = Math.max(0, Math.min(x, iiw - this.table.clientWidth));
  47. y = Math.max(0, Math.min(y, ih - this.table.clientHeight -
  48. ((urlParams['sketch'] == '1') ? 3 : 48)));
  49. if (this.getX() != x || this.getY() != y)
  50. {
  51. mxWindow.prototype.setLocation.apply(this, arguments);
  52. }
  53. };
  54. // Workaround for text selection starting in Safari
  55. // when dragging shapes outside of window
  56. if (mxClient.IS_SF)
  57. {
  58. this.window.div.onselectstart = mxUtils.bind(this, function(evt)
  59. {
  60. if (evt == null)
  61. {
  62. evt = window.event;
  63. }
  64. return (evt != null && editorUi.isSelectionAllowed(evt));
  65. });
  66. }
  67. };
  68. function toggleFormat(ui, visible)
  69. {
  70. var graph = ui.editor.graph;
  71. graph.popupMenuHandler.hideMenu();
  72. if (ui.formatWindow == null)
  73. {
  74. ui.formatWindow = new WrapperWindow(ui, mxResources.get('format'),
  75. (urlParams['sketch'] == '1') ? Math.max(10, ui.diagramContainer.clientWidth - 241) :
  76. Math.max(10, ui.diagramContainer.clientWidth - 248),
  77. EditorUi.isElectronApp && urlParams['sketch'] == '1'? 80 : 60,
  78. 240, Math.min(566, graph.container.clientHeight - 10), function(container)
  79. {
  80. var format = ui.createFormat(container);
  81. format.init();
  82. ui.addListener('darkModeChanged', mxUtils.bind(this, function()
  83. {
  84. format.refresh();
  85. }));
  86. return format;
  87. });
  88. ui.formatWindow.window.minimumSize = new mxRectangle(0, 0, 240, 80);
  89. ui.formatWindow.window.setVisible(true);
  90. }
  91. else
  92. {
  93. ui.formatWindow.window.setVisible((visible != null) ?
  94. visible : !ui.formatWindow.window.isVisible());
  95. }
  96. if (ui.formatWindow.window.isVisible() && urlParams['sketch'] != '1')
  97. {
  98. ui.formatWindow.window.fit();
  99. }
  100. };
  101. function toggleShapes(ui, visible)
  102. {
  103. var graph = ui.editor.graph;
  104. graph.popupMenuHandler.hideMenu();
  105. var rect = new mxRectangle();
  106. if (ui.sidebarWindow == null)
  107. {
  108. var w = Math.min(graph.container.clientWidth - 10, 218);
  109. ui.sidebarWindow = new WrapperWindow(ui, mxResources.get('shapes'), 10,
  110. (urlParams['sketch'] == '1' && urlParams['embedInline'] != '1') ? 15 : 56,
  111. w - 6, Math.min(650, graph.container.clientHeight - 30),
  112. function(container)
  113. {
  114. var div = document.createElement('div');
  115. div.style.cssText = 'position:absolute;left:0;right:0;border-top:1px solid lightgray;' +
  116. 'height:24px;bottom:31px;text-align:center;cursor:pointer;padding:6px 0 0 0;';
  117. div.className = 'geTitle';
  118. var span = document.createElement('span');
  119. span.style.fontSize = '18px';
  120. span.style.marginRight = '5px';
  121. span.innerHTML = '+';
  122. div.appendChild(span);
  123. mxUtils.write(div, mxResources.get('moreShapes'));
  124. container.appendChild(div);
  125. mxEvent.addListener(div, 'click', function()
  126. {
  127. ui.actions.get('shapes').funct();
  128. });
  129. var menuObj = new Menubar(ui, container);
  130. function addMenu(id, label)
  131. {
  132. var menu = ui.menus.get(id);
  133. var elt = menuObj.addMenu(label, mxUtils.bind(this, function()
  134. {
  135. // Allows extensions of menu.functid
  136. menu.funct.apply(this, arguments);
  137. }));
  138. elt.style.cssText = 'position:absolute;border-top:1px solid lightgray;width:50%;' +
  139. 'height:24px;bottom:0px;text-align:center;cursor:pointer;padding:6px 0 0 0;cusor:pointer;';
  140. elt.className = 'geTitle';
  141. container.appendChild(elt);
  142. return elt;
  143. }
  144. if (Editor.enableCustomLibraries && (urlParams['embed'] != '1' || urlParams['libraries'] == '1'))
  145. {
  146. // Defined in native apps together with openLibrary
  147. if (ui.actions.get('newLibrary') != null)
  148. {
  149. var div = document.createElement('div');
  150. div.style.cssText = 'position:absolute;left:0px;width:50%;border-top:1px solid lightgray;' +
  151. 'height:30px;bottom:0px;text-align:center;cursor:pointer;padding:0px;';
  152. div.className = 'geTitle';
  153. var span = document.createElement('span');
  154. span.style.cssText = 'position:relative;top:6px;';
  155. mxUtils.write(span, mxResources.get('newLibrary'));
  156. div.appendChild(span);
  157. container.appendChild(div);
  158. mxEvent.addListener(div, 'click', ui.actions.get('newLibrary').funct);
  159. var div = document.createElement('div');
  160. div.style.cssText = 'position:absolute;left:50%;width:50%;border-top:1px solid lightgray;' +
  161. 'height:30px;bottom:0px;text-align:center;cursor:pointer;padding:0px;border-left: 1px solid lightgray;';
  162. div.className = 'geTitle';
  163. var span = document.createElement('span');
  164. span.style.cssText = 'position:relative;top:6px;';
  165. mxUtils.write(span, mxResources.get('openLibrary'));
  166. div.appendChild(span);
  167. container.appendChild(div);
  168. mxEvent.addListener(div, 'click', ui.actions.get('openLibrary').funct);
  169. }
  170. else
  171. {
  172. var elt = addMenu('newLibrary', mxResources.get('newLibrary'));
  173. elt.style.boxSizing = 'border-box';
  174. elt.style.paddingRight = '6px';
  175. elt.style.paddingLeft = '6px';
  176. elt.style.height = '32px';
  177. elt.style.left = '0';
  178. var elt = addMenu('openLibraryFrom', mxResources.get('openLibraryFrom'));
  179. elt.style.borderLeft = '1px solid lightgray';
  180. elt.style.boxSizing = 'border-box';
  181. elt.style.paddingRight = '6px';
  182. elt.style.paddingLeft = '6px';
  183. elt.style.height = '32px';
  184. elt.style.left = '50%';
  185. }
  186. }
  187. else
  188. {
  189. div.style.bottom = '0';
  190. }
  191. container.appendChild(ui.sidebar.container);
  192. container.style.overflow = 'hidden';
  193. return container;
  194. });
  195. ui.sidebarWindow.window.minimumSize = new mxRectangle(0, 0, 90, 90);
  196. ui.sidebarWindow.window.setVisible(true);
  197. ui.getLocalData('sidebar', function(value)
  198. {
  199. ui.sidebar.showEntries(value, null, true);
  200. });
  201. ui.restoreLibraries();
  202. }
  203. else
  204. {
  205. ui.sidebarWindow.window.setVisible((visible != null) ?
  206. visible : !ui.sidebarWindow.window.isVisible());
  207. }
  208. if (ui.sidebarWindow.window.isVisible())
  209. {
  210. ui.sidebarWindow.window.fit();
  211. }
  212. };
  213. // Changes colors for some UI elements
  214. var fill = '#29b6f2';
  215. var stroke = '#ffffff';
  216. Editor.checkmarkImage = Graph.createSvgImage(22, 18, '<path transform="translate(4 0)" d="M7.181,15.007a1,1,0,0,1-.793-0.391L3.222,10.5A1,1,0,1,1,4.808,9.274L7.132,12.3l6.044-8.86A1,1,0,1,1,14.83,4.569l-6.823,10a1,1,0,0,1-.8.437H7.181Z" fill="' + fill + '"/>').src;
  217. mxWindow.prototype.closeImage = Graph.createSvgImage(18, 10, '<path d="M 5 1 L 13 9 M 13 1 L 5 9" stroke="#C0C0C0" stroke-width="2"/>').src;
  218. mxWindow.prototype.minimizeImage = Graph.createSvgImage(14, 10, '<path d="M 3 7 L 7 3 L 11 7" stroke="#C0C0C0" stroke-width="2" fill="none"/>').src;
  219. mxWindow.prototype.normalizeImage = Graph.createSvgImage(14, 10, '<path d="M 3 3 L 7 7 L 11 3" stroke="#C0C0C0" stroke-width="2" fill="none"/>').src;
  220. mxConstraintHandler.prototype.pointImage = Graph.createSvgImage(5, 5,
  221. '<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke-width="2" style="stroke-opacity:0.4" stroke="#ffffff"/>' +
  222. '<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke="' + fill + '"/>');
  223. mxOutline.prototype.sizerImage = null;
  224. mxConstants.VERTEX_SELECTION_COLOR = '#C0C0C0';
  225. mxConstants.EDGE_SELECTION_COLOR = '#C0C0C0';
  226. mxConstants.CONNECT_HANDLE_FILLCOLOR = '#cee7ff';
  227. mxConstants.DEFAULT_VALID_COLOR = fill;
  228. mxConstants.GUIDE_COLOR = '#C0C0C0';
  229. mxConstants.HIGHLIGHT_STROKEWIDTH = 5;
  230. mxConstants.HIGHLIGHT_OPACITY = 35;
  231. mxConstants.OUTLINE_COLOR = '#29b6f2';
  232. mxConstants.OUTLINE_HANDLE_FILLCOLOR = '#29b6f2';
  233. mxConstants.OUTLINE_HANDLE_STROKECOLOR = '#fff';
  234. Graph.prototype.svgShadowColor = '#3D4574';
  235. Graph.prototype.svgShadowOpacity = '0.4';
  236. Graph.prototype.svgShadowSize = '0.6';
  237. Graph.prototype.svgShadowBlur = '1.2';
  238. Format.inactiveTabBackgroundColor = '#f0f0f0';
  239. mxGraphHandler.prototype.previewColor = '#C0C0C0';
  240. mxRubberband.prototype.defaultOpacity = 50;
  241. HoverIcons.prototype.inactiveOpacity = 25;
  242. Format.prototype.showCloseButton = false;
  243. EditorUi.prototype.closableScratchpad = false;
  244. EditorUi.prototype.toolbarHeight = (urlParams['sketch'] == '1') ? 1 : 46;
  245. EditorUi.prototype.footerHeight = 0;
  246. Graph.prototype.editAfterInsert = urlParams['sketch'] != '1' &&
  247. !mxClient.IS_IOS && !mxClient.IS_ANDROID;
  248. /**
  249. * Dynamic change of dark mode.
  250. */
  251. EditorUi.prototype.setDarkMode = function(value)
  252. {
  253. if (this.spinner.spin(document.body, mxResources.get('working') + '...'))
  254. {
  255. window.setTimeout(mxUtils.bind(this, function()
  256. {
  257. this.spinner.stop();
  258. this.doSetDarkMode(value);
  259. // Persist setting
  260. if (urlParams['dark'] == null)
  261. {
  262. mxSettings.settings.darkMode = value;
  263. mxSettings.save();
  264. }
  265. this.fireEvent(new mxEventObject('darkModeChanged'));
  266. }), 0);
  267. }
  268. };
  269. /**
  270. * Links to dark.css
  271. */
  272. var darkStyle = document.createElement('link');
  273. darkStyle.setAttribute('rel', 'stylesheet');
  274. darkStyle.setAttribute('href', STYLE_PATH + '/dark.css');
  275. darkStyle.setAttribute('charset', 'UTF-8');
  276. darkStyle.setAttribute('type', 'text/css');
  277. /**
  278. * Dynamic change of dark mode.
  279. */
  280. EditorUi.prototype.doSetDarkMode = function(value)
  281. {
  282. if (Editor.darkMode != value)
  283. {
  284. var graph = this.editor.graph;
  285. Editor.darkMode = value;
  286. // Sets instance vars and graph stylesheet
  287. this.spinner.opts.color = Editor.isDarkMode() ? '#c0c0c0' : '#000';
  288. this.setGridColor(Editor.isDarkMode() ? graph.view.defaultDarkGridColor : graph.view.defaultGridColor);
  289. graph.defaultPageBackgroundColor = (urlParams['embedInline'] == '1') ? 'transparent' :
  290. Editor.isDarkMode() ? Editor.darkColor : '#ffffff';
  291. graph.defaultPageBorderColor = Editor.isDarkMode() ? '#505759' : '#ffffff';
  292. graph.shapeBackgroundColor = Editor.isDarkMode() ? Editor.darkColor : '#ffffff';
  293. graph.shapeForegroundColor = Editor.isDarkMode() ? Editor.lightColor : '#000000';
  294. graph.defaultThemeName = Editor.isDarkMode() ? 'darkTheme' : 'default-style2';
  295. graph.graphHandler.previewColor = Editor.isDarkMode() ? '#cccccc' : 'black';
  296. document.body.style.backgroundColor = (urlParams['embedInline'] == '1') ? 'transparent' :
  297. (Editor.isDarkMode() ? Editor.darkColor : '#ffffff');
  298. graph.loadStylesheet();
  299. // Destroys windows with code for dark mode
  300. if (this.actions.layersWindow != null)
  301. {
  302. var wasVisible = this.actions.layersWindow.window.isVisible();
  303. this.actions.layersWindow.window.setVisible(false);
  304. this.actions.layersWindow.destroy();
  305. this.actions.layersWindow = null;
  306. if (wasVisible)
  307. {
  308. window.setTimeout(this.actions.get('layers').funct, 0);
  309. }
  310. }
  311. if (this.menus.commentsWindow != null)
  312. {
  313. this.menus.commentsWindow.window.setVisible(false);
  314. this.menus.commentsWindow.destroy();
  315. this.menus.commentsWindow = null;
  316. }
  317. if (this.ruler != null)
  318. {
  319. this.ruler.updateStyle();
  320. }
  321. // Sets global vars
  322. Graph.prototype.defaultPageBackgroundColor = graph.defaultPageBackgroundColor;
  323. Graph.prototype.defaultPageBorderColor = graph.defaultPageBorderColor;
  324. Graph.prototype.shapeBackgroundColor = graph.shapeBackgroundColor;
  325. Graph.prototype.shapeForegroundColor = graph.shapeForegroundColor;
  326. Graph.prototype.defaultThemeName = graph.defaultThemeName;
  327. StyleFormatPanel.prototype.defaultStrokeColor = Editor.isDarkMode() ? '#cccccc' : 'black';
  328. BaseFormatPanel.prototype.buttonBackgroundColor = Editor.isDarkMode() ? Editor.darkColor : 'white';
  329. Format.inactiveTabBackgroundColor = Editor.isDarkMode() ? 'black' : '#f0f0f0';
  330. Dialog.backdropColor = Editor.isDarkMode() ? Editor.darkColor : 'white';
  331. mxConstants.DROP_TARGET_COLOR = Editor.isDarkMode() ? '#00ff00' : '#0000FF';
  332. Editor.helpImage = (Editor.isDarkMode() && mxClient.IS_SVG) ?
  333. Editor.darkHelpImage : Editor.lightHelpImage;
  334. Editor.checkmarkImage = (Editor.isDarkMode() && mxClient.IS_SVG) ?
  335. Editor.darkCheckmarkImage : Editor.lightCheckmarkImage;
  336. // Updates CSS
  337. styleElt.innerHTML = Editor.createMinimalCss();
  338. // Adds or removes link to CSS
  339. if (Editor.darkMode)
  340. {
  341. if (darkStyle.parentNode == null)
  342. {
  343. var head = document.getElementsByTagName('head')[0];
  344. head.appendChild(darkStyle);
  345. }
  346. }
  347. else if (darkStyle.parentNode != null)
  348. {
  349. darkStyle.parentNode.removeChild(darkStyle);
  350. }
  351. }
  352. };
  353. /**
  354. * Dynamic change of dark mode.
  355. */
  356. Editor.createMinimalCss = function()
  357. {
  358. return '* { -webkit-font-smoothing: antialiased; }' +
  359. 'html body td.mxWindowTitle > div > img { padding: 8px 4px; }' +
  360. // Dark mode styles
  361. (Editor.isDarkMode() ?
  362. 'html body td.mxWindowTitle > div > img { margin: -4px; }' +
  363. 'html body .geToolbarContainer .geMenuItem, html body .geToolbarContainer .geToolbarButton, ' +
  364. 'html body .geMenubarContainer .geMenuItem .geMenuItem, html body .geMenubarContainer a.geMenuItem,' +
  365. 'html body .geMenubarContainer .geToolbarButton { filter: invert(1); }' +
  366. 'html body div.geToolbarContainer a.geInverted { filter: none; }' +
  367. 'html body .geMenubarContainer .geMenuItem .geMenuItem, html body .geMenubarContainer a.geMenuItem { color: #353535; }' +
  368. 'html > body > div > .geToolbarContainer { border: 1px solid #c0c0c0 !important; box-shadow: none !important; }' +
  369. 'html > body.geEditor > div > a.geItem { background-color: #2a2a2a; color: #cccccc; border-color: #505759; }' +
  370. 'html body .geTabContainer, html body .geTabContainer div, html body .geMenubarContainer { border-color: #505759 !important; }' +
  371. 'html body .mxCellEditor { color: #f0f0f0; }'
  372. :
  373. // Non-dark mode styles
  374. 'html body div.geToolbarContainer a.geInverted { filter: invert(1); }' +
  375. 'html body.geEditor .geTabContainer div { border-color: #e5e5e5 !important; }'
  376. ) +
  377. // End of custom styles
  378. 'html > body > div > a.geItem { background-color: #ffffff; color: #707070; border-top: 1px solid lightgray; border-left: 1px solid lightgray; }' +
  379. 'html body .geMenubarContainer { border-bottom:1px solid lightgray;background-color:#ffffff; }' +
  380. 'html body .mxWindow button.geBtn { font-size:12px !important; margin-left: 0; }' +
  381. 'html body table.mxWindow td.mxWindowPane div.mxWindowPane *:not(svg *) { font-size:9pt; }' +
  382. 'table.mxWindow * :not(svg *) { font-size:13px; }' +
  383. 'html body .mxWindow { z-index: 3; }' +
  384. 'html body div.diagramContainer button, html body button.geBtn { font-size:14px; font-weight:700; border-radius: 5px; }' +
  385. 'html body button.geBtn:active { opacity: 0.6; }' +
  386. 'html body a.geMenuItem { opacity: 0.75; cursor: pointer; user-select: none; }' +
  387. 'html body a.geMenuItem[disabled] { opacity: 0.2; }' +
  388. 'html body a.geMenuItem[disabled]:active { opacity: 0.2; }' +
  389. 'html body div.geActivePage { opacity: 0.7; }' +
  390. 'html body a.geMenuItem:active { opacity: 0.2; }' +
  391. 'html body .geToolbarButton { opacity: 0.3; }' +
  392. 'html body .geToolbarButton:active { opacity: 0.15; }' +
  393. 'html body .geStatus:active { opacity: 0.5; }' +
  394. 'html body .geStatus { padding-top:3px !important; }' +
  395. 'html body .geMenubarContainer .geStatus { margin-top: 0px !important; }' +
  396. 'html table.mxPopupMenu tr.mxPopupMenuItemHover:active { opacity: 0.7; }' +
  397. 'html body .geDialog input, html body .geToolbarContainer input, html body .mxWindow input {padding: 2px; display: inline-block; }' +
  398. 'html body .mxWindow input[type="checkbox"] {padding: 0px; }' +
  399. 'div.geDialog { border-radius: 5px; }' +
  400. 'html body div.geDialog button.geBigButton { color: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + ' !important; border: none !important; }' +
  401. '.mxWindow button, .geDialog select, .mxWindow select { display:inline-block; }' +
  402. 'html body .mxWindow .geColorBtn, html body .geDialog .geColorBtn { background: none; }' +
  403. 'html body div.diagramContainer button, html body .mxWindow button, html body .geDialog button { min-width: 0px; border-radius: 5px; color: ' + (Editor.isDarkMode() ? '#cccccc' : '#353535') + ' !important; border-style: solid; border-width: 1px; border-color: rgb(216, 216, 216); }' +
  404. 'html body div.diagramContainer button:hover, html body .mxWindow button:hover, html body .geDialog button:hover { border-color: rgb(177, 177, 177); }' +
  405. 'html body div.diagramContainer button:active, html body .mxWindow button:active, html body .geDialog button:active { opacity: 0.6; }' +
  406. 'div.diagramContainer button.geBtn, .mxWindow button.geBtn, .geDialog button.geBtn { min-width:72px; font-weight: 600; background: none; }' +
  407. 'div.diagramContainer button.gePrimaryBtn, .mxWindow button.gePrimaryBtn, .geDialog button.gePrimaryBtn, html body .gePrimaryBtn { background: #29b6f2; color: #fff !important; border: none; box-shadow: none; }' +
  408. 'html body .gePrimaryBtn:hover { background: #29b6f2; border: none; box-shadow: inherit; }' +
  409. 'html body button.gePrimaryBtn:hover { background: #29b6f2; border: none; }' +
  410. '.geBtn button { min-width:72px !important; }' +
  411. 'div.geToolbarContainer a.geButton { margin:0px; padding: 0 2px 4px 2px; } ' +
  412. 'html body div.geToolbarContainer a.geColorBtn { margin: 2px; } ' +
  413. 'html body .mxWindow td.mxWindowPane input, html body .mxWindow td.mxWindowPane select, html body .mxWindow td.mxWindowPane textarea, html body .mxWindow td.mxWindowPane radio { padding: 0px; box-sizing: border-box; }' +
  414. '.geDialog, .mxWindow td.mxWindowPane *, div.geSprite, td.mxWindowTitle, .geDiagramContainer { box-sizing:content-box; }' +
  415. '.mxWindow div button.geStyleButton { box-sizing: border-box; }' +
  416. 'table.mxWindow td.mxWindowPane button.geColorBtn { padding:0px; box-sizing: border-box; }' +
  417. 'td.mxWindowPane .geSidebarContainer button { padding:2px; box-sizing: border-box; }' +
  418. 'html body .geMenuItem { font-size:14px; text-decoration: none; font-weight: normal; padding: 6px 10px 6px 10px; border: none; border-radius: 5px; color: #353535; box-shadow: inset 0 0 0 1px rgba(0,0,0,.11), inset 0 -1px 0 0 rgba(0,0,0,.08), 0 1px 2px 0 rgba(0,0,0,.04); }' +
  419. // Styling for Minimal
  420. '.geTabContainer { border-bottom:1px solid lightgray; border-top:1px solid lightgray; background: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + ' !important; }' +
  421. '.geToolbarContainer { background: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + '; }' +
  422. 'div.geSidebarContainer { background-color: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + '; }' +
  423. 'div.geSidebarContainer .geTitle { background-color: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fdfdfd') + '; }' +
  424. 'div.mxWindow td.mxWindowPane button { background-image: none; float: none; }' +
  425. 'td.mxWindowTitle { height: 22px !important; background: none !important; font-size: 13px !important; text-align:center !important; border-bottom:1px solid lightgray; }' +
  426. 'div.mxWindow, div.mxWindowTitle { background-image: none !important; background-color:' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + ' !important; }' +
  427. 'div.mxWindow { border-radius:5px; box-shadow: 0px 0px 2px #C0C0C0 !important;}' +
  428. 'div.mxWindow *:not(svg *) { font-family: inherit !important; }' +
  429. // Minimal Style UI
  430. 'html div.geVerticalHandle { position:absolute;bottom:0px;left:50%;cursor:row-resize;width:11px;height:11px;background:white;margin-bottom:-6px; margin-left:-6px; border: none; border-radius: 6px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.11), inset 0 -1px 0 0 rgba(0,0,0,.08), 0 1px 2px 0 rgba(0,0,0,.04); }' +
  431. 'html div.geInactivePage { background: ' + (Editor.isDarkMode() ? Editor.darkColor : 'rgb(249, 249, 249)') + ' !important; color: #A0A0A0 !important; } ' +
  432. 'html div.geActivePage { background: ' + (Editor.isDarkMode() ? Editor.darkColor : '#fff') + ' !important; ' + (Editor.isDarkMode() ? '' : 'color: #353535 !important; } ') +
  433. 'html div.mxRubberband { border:1px solid; border-color: #29b6f2 !important; background:rgba(41,182,242,0.4) !important; } ' +
  434. 'html body div.mxPopupMenu { border-radius:5px; border:1px solid #c0c0c0; padding:5px 0 5px 0; box-shadow: 0px 4px 17px -4px rgba(96,96,96,1); } ' +
  435. 'html table.mxPopupMenu td.mxPopupMenuItem { color: ' + (Editor.isDarkMode() ? '#cccccc' : '#353535') + '; font-size: 14px; padding-top: 4px; padding-bottom: 4px; }' +
  436. 'html table.mxPopupMenu tr.mxPopupMenuItemHover { background-color: ' + (Editor.isDarkMode() ? '#000000' : '#29b6f2') + '; }' +
  437. 'html tr.mxPopupMenuItemHover td.mxPopupMenuItem, html tr.mxPopupMenuItemHover td.mxPopupMenuItem span { color: ' + (Editor.isDarkMode() ? '#cccccc' : '#ffffff') + ' !important; }' +
  438. 'html tr.mxPopupMenuItem, html td.mxPopupMenuItem { transition-property: none !important; }' +
  439. 'html table.mxPopupMenu hr { height: 2px; background-color: rgba(0,0,0,.07); margin: 5px 0; }' +
  440. 'html body td.mxWindowTitle { padding-right: 14px; }' +
  441. 'html td.mxWindowTitle div { top: 0px !important; }' +
  442. // Fixes checkbox and radio size on iOS
  443. ((mxClient.IS_IOS) ? 'html input[type=checkbox], html input[type=radio] { height:12px; }' : '') +
  444. ((urlParams['sketch'] == '1') ? 'a.geStatus > div { overflow: hidden; text-overflow: ellipsis; max-width: 100%; }' : '');
  445. };
  446. var styleElt = document.createElement('style')
  447. styleElt.type = 'text/css';
  448. styleElt.innerHTML = Editor.createMinimalCss();
  449. document.getElementsByTagName('head')[0].appendChild(styleElt);
  450. /**
  451. * Sets the XML node for the current diagram.
  452. */
  453. Editor.prototype.isChromelessView = function()
  454. {
  455. return false;
  456. };
  457. /**
  458. * Sets the XML node for the current diagram.
  459. */
  460. Graph.prototype.isLightboxView = function()
  461. {
  462. return false;
  463. };
  464. // Overridden to ignore tabContainer height for diagramContainer
  465. var editorUiUpdateTabContainer = EditorUi.prototype.updateTabContainer;
  466. EditorUi.prototype.updateTabContainer = function()
  467. {
  468. if (this.tabContainer != null)
  469. {
  470. // Makes room for view zoom menu
  471. this.tabContainer.style.right = '70px';
  472. this.diagramContainer.style.bottom = (urlParams['sketch'] == '1') ?
  473. '0px' : this.tabContainerHeight + 'px';
  474. }
  475. editorUiUpdateTabContainer.apply(this, arguments);
  476. };
  477. // Overridden to update save menu state
  478. /**
  479. * Updates action states depending on the selection.
  480. */
  481. var editorUiUpdateActionStates = EditorUi.prototype.updateActionStates;
  482. EditorUi.prototype.updateActionStates = function()
  483. {
  484. editorUiUpdateActionStates.apply(this, arguments);
  485. this.menus.get('save').setEnabled(this.getCurrentFile() != null || urlParams['embed'] == '1');
  486. };
  487. // Hides keyboard shortcuts in menus
  488. var menusAddShortcut = Menus.prototype.addShortcut;
  489. Menus.prototype.addShortcut = function(item, action)
  490. {
  491. if (action.shortcut != null && iw < 900 && !mxClient.IS_IOS)
  492. {
  493. var td = item.firstChild.nextSibling;
  494. td.setAttribute('title', action.shortcut);
  495. }
  496. else
  497. {
  498. menusAddShortcut.apply(this, arguments);
  499. }
  500. };
  501. var appUpdateUserElement = App.prototype.updateUserElement;
  502. App.prototype.updateUserElement = function()
  503. {
  504. appUpdateUserElement.apply(this, arguments);
  505. if (this.userElement != null)
  506. {
  507. var elt = this.userElement;
  508. elt.style.cssText = 'position:relative;margin-right:4px;cursor:pointer;display:' + elt.style.display;
  509. elt.className = 'geToolbarButton';
  510. elt.innerHTML = '';
  511. elt.style.backgroundImage = 'url(' + Editor.userImage + ')';
  512. elt.style.backgroundPosition = 'center center';
  513. elt.style.backgroundRepeat = 'no-repeat';
  514. elt.style.backgroundSize = '24px 24px';
  515. elt.style.height = '24px';
  516. elt.style.width = '24px';
  517. elt.style.cssFloat = 'right';
  518. elt.setAttribute('title', mxResources.get('changeUser'));
  519. if (elt.style.display != 'none')
  520. {
  521. elt.style.display = 'inline-block';
  522. }
  523. }
  524. };
  525. var appUpdateButtonContainer = App.prototype.updateButtonContainer;
  526. App.prototype.updateButtonContainer = function()
  527. {
  528. appUpdateButtonContainer.apply(this, arguments);
  529. if (this.shareButton != null)
  530. {
  531. var elt = this.shareButton;
  532. elt.style.cssText = 'display:inline-block;position:relative;box-sizing:border-box;margin-right:4px;cursor:pointer;';
  533. elt.className = 'geToolbarButton';
  534. elt.innerHTML = '';
  535. elt.style.backgroundImage = 'url(' + Editor.shareImage + ')';
  536. elt.style.backgroundPosition = 'center center';
  537. elt.style.backgroundRepeat = 'no-repeat';
  538. elt.style.backgroundSize = '24px 24px';
  539. elt.style.height = '24px';
  540. elt.style.width = '24px';
  541. // Share button hidden via CSS to enable notifications button
  542. if (urlParams['sketch'] == '1')
  543. {
  544. this.shareButton.style.display = 'none';
  545. }
  546. }
  547. if (this.buttonContainer != null)
  548. {
  549. this.buttonContainer.style.marginTop = '-2px';
  550. this.buttonContainer.style.paddingTop = '4px';
  551. }
  552. };
  553. EditorUi.prototype.addEmbedButtons = function()
  554. {
  555. if (this.buttonContainer != null && urlParams['embedInline'] != '1')
  556. {
  557. var div = document.createElement('div');
  558. div.style.display = 'inline-block';
  559. div.style.position = 'relative';
  560. div.style.marginTop = '6px';
  561. div.style.marginRight = '4px';
  562. var button = document.createElement('a');
  563. button.className = 'geMenuItem gePrimaryBtn';
  564. button.style.marginLeft = '8px';
  565. button.style.padding = '6px';
  566. if (urlParams['noSaveBtn'] == '1')
  567. {
  568. if (urlParams['saveAndExit'] != '0')
  569. {
  570. var saveAndExitTitle = urlParams['publishClose'] == '1' ? mxResources.get('publish') : mxResources.get('saveAndExit');
  571. mxUtils.write(button, saveAndExitTitle);
  572. button.setAttribute('title', saveAndExitTitle);
  573. mxEvent.addListener(button, 'click', mxUtils.bind(this, function()
  574. {
  575. this.actions.get('saveAndExit').funct();
  576. }));
  577. div.appendChild(button);
  578. }
  579. }
  580. else
  581. {
  582. mxUtils.write(button, mxResources.get('save'));
  583. button.setAttribute('title', mxResources.get('save') + ' (' + Editor.ctrlKey + '+S)');
  584. mxEvent.addListener(button, 'click', mxUtils.bind(this, function()
  585. {
  586. this.actions.get('save').funct();
  587. }));
  588. div.appendChild(button);
  589. if (urlParams['saveAndExit'] == '1')
  590. {
  591. button = document.createElement('a');
  592. mxUtils.write(button, mxResources.get('saveAndExit'));
  593. button.setAttribute('title', mxResources.get('saveAndExit'));
  594. button.className = 'geMenuItem';
  595. button.style.marginLeft = '6px';
  596. button.style.padding = '6px';
  597. mxEvent.addListener(button, 'click', mxUtils.bind(this, function()
  598. {
  599. this.actions.get('saveAndExit').funct();
  600. }));
  601. div.appendChild(button);
  602. }
  603. }
  604. if (urlParams['noExitBtn'] != '1')
  605. {
  606. button = document.createElement('a');
  607. var exitTitle = urlParams['publishClose'] == '1' ? mxResources.get('close') : mxResources.get('exit');
  608. mxUtils.write(button, exitTitle);
  609. button.setAttribute('title', exitTitle);
  610. button.className = 'geMenuItem';
  611. button.style.marginLeft = '6px';
  612. button.style.padding = '6px';
  613. mxEvent.addListener(button, 'click', mxUtils.bind(this, function()
  614. {
  615. this.actions.get('exit').funct();
  616. }));
  617. div.appendChild(button);
  618. }
  619. this.buttonContainer.appendChild(div);
  620. this.buttonContainer.style.top = '6px';
  621. this.editor.fireEvent(new mxEventObject('statusChanged'));
  622. }
  623. };
  624. // Fixes sidebar tooltips (previews)
  625. var sidebarGetTooltipOffset = Sidebar.prototype.getTooltipOffset;
  626. Sidebar.prototype.getTooltipOffset = function(elt, bounds)
  627. {
  628. if (this.editorUi.sidebarWindow == null ||
  629. mxUtils.isAncestorNode(this.editorUi.picker, elt))
  630. {
  631. var off = mxUtils.getOffset(this.editorUi.picker);
  632. off.x += this.editorUi.picker.offsetWidth + 4;
  633. off.y += elt.offsetTop - bounds.height / 2 + 16;
  634. return off;
  635. }
  636. else
  637. {
  638. var result = sidebarGetTooltipOffset.apply(this, arguments);
  639. var off = mxUtils.getOffset(this.editorUi.sidebarWindow.window.div);
  640. result.x += off.x - 16;
  641. result.y += off.y;
  642. return result;
  643. }
  644. };
  645. // Adds context menu items
  646. var menuCreatePopupMenu = Menus.prototype.createPopupMenu;
  647. Menus.prototype.createPopupMenu = function(menu, cell, evt)
  648. {
  649. var graph = this.editorUi.editor.graph;
  650. menu.smartSeparators = true;
  651. menuCreatePopupMenu.apply(this, arguments);
  652. if (urlParams['sketch'] == '1')
  653. {
  654. if (graph.isEnabled())
  655. {
  656. menu.addSeparator();
  657. if (graph.getSelectionCount() == 1)
  658. {
  659. this.addMenuItems(menu, ['-', 'lockUnlock'], null, evt);
  660. }
  661. }
  662. }
  663. else
  664. {
  665. if (graph.getSelectionCount() == 1)
  666. {
  667. if (graph.isCellFoldable(graph.getSelectionCell()))
  668. {
  669. this.addMenuItems(menu, (graph.isCellCollapsed(cell)) ? ['expand'] : ['collapse'], null, evt);
  670. }
  671. this.addMenuItems(menu, ['collapsible', '-', 'lockUnlock', 'enterGroup'], null, evt);
  672. menu.addSeparator();
  673. this.addSubmenu('layout', menu);
  674. }
  675. else if (graph.isSelectionEmpty() && graph.isEnabled())
  676. {
  677. menu.addSeparator();
  678. this.addMenuItems(menu, ['editData'], null, evt);
  679. menu.addSeparator();
  680. this.addSubmenu('layout', menu);
  681. this.addSubmenu('insert', menu);
  682. this.addMenuItems(menu, ['-', 'exitGroup'], null, evt);
  683. }
  684. else if (graph.isEnabled())
  685. {
  686. this.addMenuItems(menu, ['-', 'lockUnlock'], null, evt);
  687. }
  688. }
  689. if (graph.isEnabled() && graph.isSelectionEmpty())
  690. {
  691. this.addMenuItems(menu, ['-', 'fullscreen']);
  692. if (urlParams['embedInline'] != '1' && (Editor.isDarkMode() ||
  693. (!mxClient.IS_IE && !mxClient.IS_IE11)))
  694. {
  695. this.addMenuItems(menu, ['toggleDarkMode']);
  696. }
  697. }
  698. };
  699. // Adds copy as image after paste for empty selection
  700. var menuAddPopupMenuEditItems = Menus.prototype.addPopupMenuEditItems;
  701. /**
  702. * Creates the keyboard event handler for the current graph and history.
  703. */
  704. Menus.prototype.addPopupMenuEditItems = function(menu, cell, evt)
  705. {
  706. menuAddPopupMenuEditItems.apply(this, arguments);
  707. if (this.editorUi.editor.graph.isSelectionEmpty())
  708. {
  709. this.addMenuItems(menu, ['copyAsImage'], null, evt);
  710. }
  711. };
  712. // Overridden to toggle window instead
  713. EditorUi.prototype.toggleFormatPanel = function(visible)
  714. {
  715. if (this.formatWindow != null)
  716. {
  717. this.formatWindow.window.setVisible((visible != null) ?
  718. visible : !this.formatWindow.window.isVisible());
  719. }
  720. else
  721. {
  722. toggleFormat(this);
  723. }
  724. };
  725. DiagramFormatPanel.prototype.isMathOptionVisible = function()
  726. {
  727. return true;
  728. };
  729. // Initializes the user interface
  730. var editorUiDestroy = EditorUi.prototype.destroy;
  731. EditorUi.prototype.destroy = function()
  732. {
  733. if (this.sidebarWindow != null)
  734. {
  735. this.sidebarWindow.window.setVisible(false);
  736. this.sidebarWindow.window.destroy();
  737. this.sidebarWindow = null;
  738. }
  739. if (this.formatWindow != null)
  740. {
  741. this.formatWindow.window.setVisible(false);
  742. this.formatWindow.window.destroy();
  743. this.formatWindow = null;
  744. }
  745. if (this.actions.outlineWindow != null)
  746. {
  747. this.actions.outlineWindow.window.setVisible(false);
  748. this.actions.outlineWindow.window.destroy();
  749. this.actions.outlineWindow = null;
  750. }
  751. if (this.actions.layersWindow != null)
  752. {
  753. this.actions.layersWindow.window.setVisible(false);
  754. this.actions.layersWindow.destroy();
  755. this.actions.layersWindow = null;
  756. }
  757. if (this.menus.tagsWindow != null)
  758. {
  759. this.menus.tagsWindow.window.setVisible(false);
  760. this.menus.tagsWindow.window.destroy();
  761. this.menus.tagsWindow = null;
  762. }
  763. if (this.menus.findWindow != null)
  764. {
  765. this.menus.findWindow.window.setVisible(false);
  766. this.menus.findWindow.window.destroy();
  767. this.menus.findWindow = null;
  768. }
  769. if (this.menus.findReplaceWindow != null)
  770. {
  771. this.menus.findReplaceWindow.window.setVisible(false);
  772. this.menus.findReplaceWindow.window.destroy();
  773. this.menus.findReplaceWindow = null;
  774. }
  775. editorUiDestroy.apply(this, arguments);
  776. };
  777. // Hides windows when a file is closed
  778. var editorUiSetGraphEnabled = EditorUi.prototype.setGraphEnabled;
  779. EditorUi.prototype.setGraphEnabled = function(enabled)
  780. {
  781. editorUiSetGraphEnabled.apply(this, arguments);
  782. if (!enabled)
  783. {
  784. if (this.sidebarWindow != null)
  785. {
  786. this.sidebarWindow.window.setVisible(false);
  787. }
  788. if (this.formatWindow != null)
  789. {
  790. this.formatWindow.window.setVisible(false);
  791. }
  792. }
  793. else
  794. {
  795. var iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  796. if (iw >= 1000 && this.sidebarWindow != null && urlParams['sketch'] != '1')
  797. {
  798. this.sidebarWindow.window.setVisible(true);
  799. }
  800. if (this.formatWindow != null && (iw >= 1000 || urlParams['sketch'] == '1'))
  801. {
  802. this.formatWindow.window.setVisible(true);
  803. }
  804. }
  805. };
  806. // Disables centering of graph after iframe resize
  807. EditorUi.prototype.chromelessWindowResize = function() {};
  808. // Adds actions and menus
  809. var menusInit = Menus.prototype.init;
  810. Menus.prototype.init = function()
  811. {
  812. menusInit.apply(this, arguments);
  813. var ui = this.editorUi;
  814. var graph = ui.editor.graph;
  815. ui.actions.get('editDiagram').label = mxResources.get('formatXml') + '...';
  816. ui.actions.get('createShape').label = mxResources.get('shape') + '...';
  817. ui.actions.get('outline').label = mxResources.get('outline') + '...';
  818. ui.actions.get('layers').label = mxResources.get('layers') + '...';
  819. ui.actions.get('tags').label = mxResources.get('tags') + '...';
  820. ui.actions.get('forkme').visible = urlParams['sketch'] != '1';
  821. ui.actions.get('downloadDesktop').visible = urlParams['sketch'] != '1';
  822. var toggleDarkModeAction = ui.actions.put('toggleDarkMode', new Action(mxResources.get('dark'), function(e)
  823. {
  824. ui.setDarkMode(!Editor.darkMode);
  825. }));
  826. toggleDarkModeAction.setToggleAction(true);
  827. toggleDarkModeAction.setSelectedCallback(function() { return Editor.isDarkMode(); });
  828. var toggleSketchModeAction = ui.actions.put('toggleSketchMode', new Action(mxResources.get('sketch'), function(e)
  829. {
  830. ui.setSketchMode(!Editor.sketchMode);
  831. }));
  832. toggleSketchModeAction.setToggleAction(true);
  833. toggleSketchModeAction.setSelectedCallback(function() { return Editor.sketchMode; });
  834. var togglePagesAction = ui.actions.put('togglePagesVisible', new Action(mxResources.get('pages'), function(e)
  835. {
  836. ui.setPagesVisible(!Editor.pagesVisible);
  837. }));
  838. togglePagesAction.setToggleAction(true);
  839. togglePagesAction.setSelectedCallback(function() { return Editor.pagesVisible; });
  840. ui.actions.put('importCsv', new Action(mxResources.get('csv') + '...', function()
  841. {
  842. graph.popupMenuHandler.hideMenu();
  843. ui.showImportCsvDialog();
  844. }));
  845. ui.actions.put('importText', new Action(mxResources.get('text') + '...', function()
  846. {
  847. var dlg = new ParseDialog(ui, 'Insert from Text');
  848. ui.showDialog(dlg.container, 620, 420, true, false);
  849. dlg.init();
  850. }));
  851. ui.actions.put('formatSql', new Action(mxResources.get('formatSql') + '...', function()
  852. {
  853. var dlg = new ParseDialog(ui, 'Insert from Text', 'formatSql');
  854. ui.showDialog(dlg.container, 620, 420, true, false);
  855. dlg.init();
  856. }));
  857. ui.actions.put('toggleShapes', new Action(mxResources.get((urlParams['sketch'] == '1') ?
  858. 'moreShapes' : 'shapes') + '...', function()
  859. {
  860. toggleShapes(ui);
  861. }, null, null, Editor.ctrlKey + '+Shift+K'));
  862. var action = ui.actions.put('toggleFormat', new Action(mxResources.get('format') + '...', function()
  863. {
  864. toggleFormat(ui);
  865. }));
  866. action.shortcut = ui.actions.get('formatPanel').shortcut;
  867. if (EditorUi.enablePlantUml && !ui.isOffline())
  868. {
  869. ui.actions.put('plantUml', new Action(mxResources.get('plantUml') + '...', function()
  870. {
  871. var dlg = new ParseDialog(ui, mxResources.get('plantUml') + '...', 'plantUml');
  872. ui.showDialog(dlg.container, 620, 420, true, false);
  873. dlg.init();
  874. }));
  875. }
  876. ui.actions.put('mermaid', new Action(mxResources.get('mermaid') + '...', function()
  877. {
  878. var dlg = new ParseDialog(ui, mxResources.get('mermaid') + '...', 'mermaid');
  879. ui.showDialog(dlg.container, 620, 420, true, false);
  880. dlg.init();
  881. }));
  882. // Adds submenu for edit items
  883. var addPopupMenuCellEditItems = this.addPopupMenuCellEditItems;
  884. this.put('editCell', new Menu(mxUtils.bind(this, function(menu, parent)
  885. {
  886. var graph = this.editorUi.editor.graph;
  887. var cell = graph.getSelectionCell();
  888. addPopupMenuCellEditItems.call(this, menu, cell, null, parent);
  889. this.addMenuItems(menu, ['editTooltip'], parent);
  890. if (graph.model.isVertex(cell))
  891. {
  892. this.addMenuItems(menu, ['editGeometry'], parent);
  893. }
  894. this.addMenuItems(menu, ['-', 'edit'], parent);
  895. })));
  896. this.addPopupMenuCellEditItems = function(menu, cell, evt, parent)
  897. {
  898. // LATER: Pass-through for evt from context menu to submenu item
  899. menu.addSeparator();
  900. this.addSubmenu('editCell', menu, parent, mxResources.get('edit'));
  901. };
  902. this.put('diagram', new Menu(mxUtils.bind(this, function(menu, parent)
  903. {
  904. var file = ui.getCurrentFile();
  905. ui.menus.addSubmenu('extras', menu, parent, mxResources.get('preferences'));
  906. menu.addSeparator(parent);
  907. if (mxClient.IS_CHROMEAPP || EditorUi.isElectronApp)
  908. {
  909. ui.menus.addMenuItems(menu, ['new', 'open', '-', 'synchronize',
  910. '-', 'save', 'saveAs', '-'], parent);
  911. }
  912. else if (urlParams['embed'] == '1')
  913. {
  914. if (urlParams['noSaveBtn'] != '1' &&
  915. urlParams['embedInline'] != '1')
  916. {
  917. ui.menus.addMenuItems(menu, ['-', 'save'], parent);
  918. }
  919. if (urlParams['saveAndExit'] == '1' ||
  920. (urlParams['noSaveBtn'] == '1' &&
  921. urlParams['saveAndExit'] != '0'))
  922. {
  923. ui.menus.addMenuItems(menu, ['saveAndExit'], parent);
  924. }
  925. menu.addSeparator(parent);
  926. }
  927. else if (ui.mode == App.MODE_ATLAS)
  928. {
  929. ui.menus.addMenuItems(menu, ['save', 'synchronize', '-'], parent);
  930. }
  931. else if (urlParams['noFileMenu'] != '1')
  932. {
  933. ui.menus.addMenuItems(menu, ['new'], parent);
  934. ui.menus.addSubmenu('openFrom', menu, parent);
  935. if (isLocalStorage)
  936. {
  937. this.addSubmenu('openRecent', menu, parent);
  938. }
  939. if (urlParams['sketch'] != '1')
  940. {
  941. menu.addSeparator(parent);
  942. if (file != null && file.constructor == DriveFile)
  943. {
  944. ui.menus.addMenuItems(menu, ['share'], parent);
  945. }
  946. if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp &&
  947. file != null && file.constructor != LocalFile)
  948. {
  949. ui.menus.addMenuItems(menu, ['synchronize'], parent);
  950. }
  951. }
  952. menu.addSeparator(parent);
  953. ui.menus.addSubmenu('save', menu, parent);
  954. }
  955. ui.menus.addSubmenu('exportAs', menu, parent);
  956. if (mxClient.IS_CHROMEAPP || EditorUi.isElectronApp)
  957. {
  958. ui.menus.addMenuItems(menu, ['import'], parent);
  959. }
  960. else if (urlParams['noFileMenu'] != '1')
  961. {
  962. ui.menus.addSubmenu('importFrom', menu, parent);
  963. }
  964. if (urlParams['sketch'] != '1')
  965. {
  966. ui.menus.addMenuItems(menu, ['-', 'outline'], parent);
  967. if (ui.commentsSupported())
  968. {
  969. ui.menus.addMenuItems(menu, ['comments'], parent);
  970. }
  971. }
  972. ui.menus.addMenuItems(menu, ['-', 'findReplace', 'layers', 'tags'], parent);
  973. ui.menus.addMenuItems(menu, ['-', 'pageSetup', 'pageScale'], parent);
  974. // Cannot use print in standalone mode on iOS as we cannot open new windows
  975. if (urlParams['noFileMenu'] != '1' && (!mxClient.IS_IOS || !navigator.standalone))
  976. {
  977. ui.menus.addMenuItems(menu, ['print'], parent);
  978. }
  979. if (file != null && ui.fileNode != null && urlParams['embedInline'] != '1')
  980. {
  981. var filename = (file.getTitle() != null) ?
  982. file.getTitle() : ui.defaultFilename;
  983. if (!/(\.html)$/i.test(filename) &&
  984. !/(\.svg)$/i.test(filename))
  985. {
  986. this.addMenuItems(menu, ['-', 'properties']);
  987. }
  988. }
  989. menu.addSeparator(parent);
  990. ui.menus.addSubmenu('help', menu, parent);
  991. if (urlParams['embed'] == '1')
  992. {
  993. if (urlParams['noExitBtn'] != '1')
  994. {
  995. ui.menus.addMenuItems(menu, ['-', 'exit'], parent);
  996. }
  997. }
  998. else if (urlParams['noFileMenu'] != '1')
  999. {
  1000. ui.menus.addMenuItems(menu, ['-', 'close']);
  1001. }
  1002. })));
  1003. this.put('save', new Menu(mxUtils.bind(this, function(menu, parent)
  1004. {
  1005. var file = ui.getCurrentFile();
  1006. if (file != null && file.constructor == DriveFile)
  1007. {
  1008. ui.menus.addMenuItems(menu, ['save', 'makeCopy', '-', 'rename', 'moveToFolder'], parent);
  1009. }
  1010. else
  1011. {
  1012. ui.menus.addMenuItems(menu, ['save', 'saveAs', '-', 'rename'], parent);
  1013. if (ui.isOfflineApp())
  1014. {
  1015. if (navigator.onLine && urlParams['stealth'] != '1' && urlParams['lockdown'] != '1')
  1016. {
  1017. this.addMenuItems(menu, ['upload'], parent);
  1018. }
  1019. }
  1020. else
  1021. {
  1022. ui.menus.addMenuItems(menu, ['makeCopy'], parent);
  1023. }
  1024. }
  1025. if (urlParams['sketch'] == '1' && !mxClient.IS_CHROMEAPP &&
  1026. !EditorUi.isElectronApp && file != null &&
  1027. file.constructor != LocalFile)
  1028. {
  1029. ui.menus.addMenuItems(menu, ['-', 'synchronize'], parent);
  1030. }
  1031. ui.menus.addMenuItems(menu, ['-', 'autosave'], parent);
  1032. if (file != null && file.isRevisionHistorySupported())
  1033. {
  1034. ui.menus.addMenuItems(menu, ['-', 'revisionHistory'], parent);
  1035. }
  1036. })));
  1037. // Augments the existing export menu
  1038. var exportAsMenu = this.get('exportAs');
  1039. this.put('exportAs', new Menu(mxUtils.bind(this, function(menu, parent)
  1040. {
  1041. exportAsMenu.funct(menu, parent);
  1042. if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp)
  1043. {
  1044. // Publish menu contains only one element by default...
  1045. //ui.menus.addSubmenu('publish', menu, parent);
  1046. ui.menus.addMenuItems(menu, ['publishLink'], parent);
  1047. }
  1048. if (ui.mode != App.MODE_ATLAS && urlParams['extAuth'] != '1')
  1049. {
  1050. menu.addSeparator(parent);
  1051. ui.menus.addSubmenu('embed', menu, parent);
  1052. }
  1053. })));
  1054. var langMenu = this.get('language');
  1055. this.put('table', new Menu(mxUtils.bind(this, function(menu, parent)
  1056. {
  1057. ui.menus.addInsertTableCellItem(menu, parent);
  1058. })));
  1059. // Adds XML option to import menu
  1060. var importMenu = this.get('importFrom');
  1061. this.put('importFrom', new Menu(mxUtils.bind(this, function(menu, parent)
  1062. {
  1063. importMenu.funct(menu, parent);
  1064. this.addMenuItems(menu, ['editDiagram'], parent);
  1065. if (urlParams['sketch'] == '1')
  1066. {
  1067. menu.addSeparator(parent);
  1068. menu.addItem(mxResources.get('csv') + '...', null, function()
  1069. {
  1070. ui.showImportCsvDialog();
  1071. }, parent, null, mxUtils.bind(graph, graph.isEnabled));
  1072. ui.addInsertMenuItems(menu, parent, ['formatSql', '-',
  1073. 'fromText', 'plantUml', 'mermaid']);
  1074. }
  1075. })));
  1076. // Extras menu is labelled preferences but keeps ID for extensions
  1077. this.put('extras', new Menu(mxUtils.bind(this, function(menu, parent)
  1078. {
  1079. if (urlParams['embed'] != '1' && urlParams['extAuth'] != '1')
  1080. {
  1081. ui.menus.addSubmenu('theme', menu, parent);
  1082. }
  1083. if (langMenu != null)
  1084. {
  1085. ui.menus.addSubmenu('language', menu, parent);
  1086. }
  1087. ui.menus.addSubmenu('units', menu, parent);
  1088. menu.addSeparator(parent);
  1089. ui.menus.addMenuItems(menu, ['scrollbars', 'tooltips', 'ruler', '-', 'copyConnect', 'collapseExpand', '-'], parent);
  1090. if (urlParams['sketch'] == '1')
  1091. {
  1092. this.addMenuItems(menu, ['toggleSketchMode'], parent);
  1093. }
  1094. if (urlParams['embedInline'] != '1')
  1095. {
  1096. if (Editor.isDarkMode() || (!mxClient.IS_IE && !mxClient.IS_IE11))
  1097. {
  1098. this.addMenuItems(menu, ['toggleDarkMode'], parent);
  1099. }
  1100. if (urlParams['embed'] != '1' && (isLocalStorage || mxClient.IS_CHROMEAPP))
  1101. {
  1102. ui.menus.addMenuItems(menu, ['-', 'showStartScreen', 'search', 'scratchpad'], parent);
  1103. }
  1104. if (urlParams['sketch'] == '1' && urlParams['pages'] == null)
  1105. {
  1106. this.addMenuItems(menu, ['togglePagesVisible'], parent);
  1107. }
  1108. }
  1109. menu.addSeparator(parent);
  1110. ui.menus.addMenuItem(menu, 'configuration', parent);
  1111. if (!ui.isOfflineApp() && isLocalStorage)
  1112. {
  1113. ui.menus.addMenuItem(menu, 'plugins', parent);
  1114. }
  1115. this.addMenuItems(menu, ['-', 'fullscreen'], parent);
  1116. // Adds trailing separator in case new plugin entries are added
  1117. menu.addSeparator(parent);
  1118. })));
  1119. this.put('insertAdvanced', new Menu(mxUtils.bind(this, function(menu, parent)
  1120. {
  1121. ui.menus.addMenuItems(menu, ['importText', 'plantUml', 'mermaid', '-', 'formatSql', 'importCsv', '-', 'createShape', 'editDiagram'], parent);
  1122. })));
  1123. (mxUtils.bind(this, function()
  1124. {
  1125. var insertMenu = this.get('insert');
  1126. var insertMenuFunct = insertMenu.funct;
  1127. insertMenu.funct = function(menu, parent)
  1128. {
  1129. if (urlParams['sketch'] == '1')
  1130. {
  1131. ui.menus.addMenuItems(menu, ['insertFreehand'], parent);
  1132. if (ui.insertTemplateEnabled && !ui.isOffline())
  1133. {
  1134. ui.menus.addMenuItems(menu, ['insertTemplate'], parent);
  1135. }
  1136. }
  1137. else
  1138. {
  1139. insertMenuFunct.apply(this, arguments);
  1140. ui.menus.addSubmenu('table', menu, parent);
  1141. menu.addSeparator(parent);
  1142. }
  1143. ui.menus.addMenuItems(menu, ['-', 'toggleShapes'], parent);
  1144. };
  1145. }))();
  1146. var methods = ['horizontalFlow', 'verticalFlow', '-', 'horizontalTree', 'verticalTree',
  1147. 'radialTree', '-', 'organic', 'circle'];
  1148. var addInsertItem = function(menu, parent, title, method)
  1149. {
  1150. menu.addItem(title, null, mxUtils.bind(this, function()
  1151. {
  1152. var dlg = new CreateGraphDialog(ui, title, method);
  1153. ui.showDialog(dlg.container, 620, 420, true, false);
  1154. // Executed after dialog is added to dom
  1155. dlg.init();
  1156. }), parent);
  1157. };
  1158. this.put('insertLayout', new Menu(mxUtils.bind(this, function(menu, parent)
  1159. {
  1160. for (var i = 0; i < methods.length; i++)
  1161. {
  1162. if (methods[i] == '-')
  1163. {
  1164. menu.addSeparator(parent);
  1165. }
  1166. else
  1167. {
  1168. addInsertItem(menu, parent, mxResources.get(methods[i]) + '...', methods[i]);
  1169. }
  1170. }
  1171. })));
  1172. };
  1173. // Installs the format toolbar
  1174. EditorUi.prototype.installFormatToolbar = function(container)
  1175. {
  1176. var graph = this.editor.graph;
  1177. var div = document.createElement('div');
  1178. div.style.cssText = 'position:absolute;top:10px;z-index:1;border-radius:4px;' +
  1179. 'box-shadow:0px 0px 3px 1px #d1d1d1;padding:6px;white-space:nowrap;background-color:#fff;' +
  1180. 'transform:translate(-50%, 0);left:50%;';
  1181. graph.getSelectionModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function(sender, evt)
  1182. {
  1183. if (graph.getSelectionCount() > 0)
  1184. {
  1185. container.appendChild(div);
  1186. div.innerHTML = 'Selected: ' + graph.getSelectionCount();
  1187. }
  1188. else if (div.parentNode != null)
  1189. {
  1190. div.parentNode.removeChild(div);
  1191. }
  1192. }));
  1193. };
  1194. var formatWindowInitialized = false;
  1195. EditorUi.prototype.initFormatWindow = function()
  1196. {
  1197. if (!formatWindowInitialized)
  1198. {
  1199. formatWindowInitialized = true;
  1200. this.formatWindow.window.setClosable(false);
  1201. var toggleMinimized = this.formatWindow.window.toggleMinimized;
  1202. this.formatWindow.window.toggleMinimized = function()
  1203. {
  1204. toggleMinimized.apply(this, arguments);
  1205. if (this.minimized)
  1206. {
  1207. this.div.style.width = '90px';
  1208. this.table.style.width = '90px';
  1209. this.div.style.left = parseInt(this.div.style.left) + 150 + 'px';
  1210. }
  1211. else
  1212. {
  1213. this.div.style.width = '240px';
  1214. this.table.style.width = '240px';
  1215. this.div.style.left = Math.max(0, parseInt(this.div.style.left) - 150) + 'px';
  1216. }
  1217. this.fit();
  1218. };
  1219. mxEvent.addListener(this.formatWindow.window.title, 'dblclick', mxUtils.bind(this, function(evt)
  1220. {
  1221. if (mxEvent.getSource(evt) == this.formatWindow.window.title)
  1222. {
  1223. this.formatWindow.window.toggleMinimized();
  1224. }
  1225. }));
  1226. }
  1227. };
  1228. // Initializes the user interface
  1229. var editorUiInit = EditorUi.prototype.init;
  1230. EditorUi.prototype.init = function()
  1231. {
  1232. editorUiInit.apply(this, arguments);
  1233. if (urlParams['embedInline'] != '1')
  1234. {
  1235. this.doSetDarkMode((urlParams['dark'] != null) ?
  1236. urlParams['dark'] == 1 && !mxClient.IS_IE &&
  1237. !mxClient.IS_IE11 : ((mxSettings.settings.darkMode != null) ?
  1238. mxSettings.settings.darkMode : (window.matchMedia &&
  1239. window.matchMedia('(prefers-color-scheme: dark)').matches)));
  1240. }
  1241. var div = document.createElement('div');
  1242. div.style.cssText = 'position:absolute;left:0px;right:0px;top:0px;overflow-y:auto;overflow-x:hidden;';
  1243. div.style.bottom = (urlParams['embed'] != '1' || urlParams['libraries'] == '1') ? '63px' : '32px';
  1244. this.sidebar = this.createSidebar(div);
  1245. if (urlParams['sketch'] == '1')
  1246. {
  1247. this.toggleScratchpad();
  1248. }
  1249. if ((urlParams['sketch'] != '1' && iw >= 1000) || urlParams['clibs'] != null ||
  1250. urlParams['libs'] != null || urlParams['search-shapes'] != null)
  1251. {
  1252. toggleShapes(this, true);
  1253. if (this.sidebar != null && urlParams['search-shapes'] != null && this.sidebar.searchShapes != null)
  1254. {
  1255. this.sidebar.searchShapes(urlParams['search-shapes']);
  1256. this.sidebar.showEntries('search');
  1257. }
  1258. }
  1259. // Overrides mxWindow.fit to allow for embedViewport
  1260. var ui = this;
  1261. mxWindow.prototype.fit = function()
  1262. {
  1263. if (!Editor.inlineFullscreen && ui.embedViewport != null)
  1264. {
  1265. var left = parseInt(this.div.offsetLeft);
  1266. var width = parseInt(this.div.offsetWidth);
  1267. var right = ui.embedViewport.x + ui.embedViewport.width;
  1268. this.div.style.left = Math.max(ui.embedViewport.x, Math.min(left, right - width)) + 'px';
  1269. var top = parseInt(this.div.offsetTop);
  1270. var height = parseInt(this.div.offsetHeight);
  1271. var bottom = ui.embedViewport.y + ui.embedViewport.height;
  1272. this.div.style.top = Math.max(ui.embedViewport.y, Math.min(top, bottom - height)) + 'px';
  1273. }
  1274. else
  1275. {
  1276. mxUtils.fit(this.div);
  1277. }
  1278. };
  1279. // Overrides insert ellipse shortcut
  1280. this.keyHandler.bindAction(75, true, 'toggleShapes', true); // Ctrl+Shift+K
  1281. if (urlParams['sketch'] == '1' || iw >= 1000)
  1282. {
  1283. if (urlParams['embedInline'] != '1')
  1284. {
  1285. toggleFormat(this, true);
  1286. if (urlParams['sketch'] == '1')
  1287. {
  1288. this.initFormatWindow();
  1289. this.formatWindow.window.toggleMinimized();
  1290. }
  1291. }
  1292. }
  1293. // Needed for creating elements in Format panel
  1294. var ui = this;
  1295. var graph = ui.editor.graph;
  1296. ui.toolbar = this.createToolbar(ui.createDiv('geToolbar'));
  1297. ui.defaultLibraryName = mxResources.get('untitledLibrary');
  1298. var menubar = document.createElement('div');
  1299. menubar.className = 'geMenubarContainer';
  1300. var before = null;
  1301. var menuObj = new Menubar(ui, menubar);
  1302. function addMenu(id, small, img)
  1303. {
  1304. var menu = ui.menus.get(id);
  1305. var elt = menuObj.addMenu(mxResources.get(id), mxUtils.bind(this, function()
  1306. {
  1307. // Allows extensions of menu.functid
  1308. menu.funct.apply(this, arguments);
  1309. }), before);
  1310. elt.className = (urlParams['sketch'] == '1') ? 'geToolbarButton' : 'geMenuItem';
  1311. elt.style.display = 'inline-block';
  1312. elt.style.boxSizing = 'border-box';
  1313. elt.style.top = '6px';
  1314. elt.style.marginRight = '6px';
  1315. elt.style.height = '30px';
  1316. elt.style.paddingTop = '6px';
  1317. elt.style.paddingBottom = '6px';
  1318. elt.style.cursor = 'pointer';
  1319. elt.setAttribute('title', mxResources.get(id));
  1320. ui.menus.menuCreated(menu, elt, 'geMenuItem');
  1321. if (img != null)
  1322. {
  1323. elt.style.backgroundImage = 'url(' + img + ')';
  1324. elt.style.backgroundPosition = 'center center';
  1325. elt.style.backgroundRepeat = 'no-repeat';
  1326. elt.style.backgroundSize = '24px 24px';
  1327. elt.style.width = '34px';
  1328. elt.innerHTML = '';
  1329. }
  1330. else if (!small)
  1331. {
  1332. elt.style.backgroundImage = 'url(' + mxWindow.prototype.normalizeImage + ')';
  1333. elt.style.backgroundPosition = 'right 6px center';
  1334. elt.style.backgroundRepeat = 'no-repeat';
  1335. elt.style.paddingRight = '22px';
  1336. }
  1337. return elt;
  1338. };
  1339. function addMenuItem(label, fn, small, tooltip, action, img)
  1340. {
  1341. var btn = document.createElement('a');
  1342. btn.className = (urlParams['sketch'] == '1') ? 'geToolbarButton' : 'geMenuItem';
  1343. btn.style.display = 'inline-block';
  1344. btn.style.boxSizing = 'border-box';
  1345. btn.style.height = '30px';
  1346. btn.style.padding = '6px';
  1347. btn.style.position = 'relative';
  1348. btn.style.verticalAlign = 'top';
  1349. btn.style.top = '0px';
  1350. if (urlParams['sketch'] == '1')
  1351. {
  1352. btn.style.borderStyle = 'none';
  1353. btn.style.boxShadow = 'none';
  1354. btn.style.padding = '6px';
  1355. btn.style.margin = '0px';
  1356. }
  1357. if (ui.statusContainer != null)
  1358. {
  1359. menubar.insertBefore(btn, ui.statusContainer);
  1360. }
  1361. else
  1362. {
  1363. menubar.appendChild(btn);
  1364. }
  1365. if (img != null)
  1366. {
  1367. btn.style.backgroundImage = 'url(' + img + ')';
  1368. btn.style.backgroundPosition = 'center center';
  1369. btn.style.backgroundRepeat = 'no-repeat';
  1370. btn.style.backgroundSize = '24px 24px';
  1371. btn.style.width = '34px';
  1372. }
  1373. else
  1374. {
  1375. mxUtils.write(btn, label);
  1376. }
  1377. // Prevents focus
  1378. mxEvent.addListener(btn, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
  1379. mxUtils.bind(this, function(evt)
  1380. {
  1381. evt.preventDefault();
  1382. }));
  1383. mxEvent.addListener(btn, 'click', function(evt)
  1384. {
  1385. if (btn.getAttribute('disabled') != 'disabled')
  1386. {
  1387. fn(evt);
  1388. }
  1389. mxEvent.consume(evt);
  1390. });
  1391. if (small == null)
  1392. {
  1393. btn.style.marginRight = '4px';
  1394. }
  1395. if (tooltip != null)
  1396. {
  1397. btn.setAttribute('title', tooltip);
  1398. }
  1399. if (action != null)
  1400. {
  1401. function updateState()
  1402. {
  1403. if (action.isEnabled())
  1404. {
  1405. btn.removeAttribute('disabled');
  1406. btn.style.cursor = 'pointer';
  1407. }
  1408. else
  1409. {
  1410. btn.setAttribute('disabled', 'disabled');
  1411. btn.style.cursor = 'default';
  1412. }
  1413. };
  1414. action.addListener('stateChanged', updateState);
  1415. graph.addListener('enabledChanged', updateState);
  1416. updateState();
  1417. }
  1418. return btn;
  1419. };
  1420. function createGroup(btns, op, container)
  1421. {
  1422. var btnGroup = document.createElement('div');
  1423. btnGroup.className = 'geMenuItem';
  1424. btnGroup.style.display = 'inline-block';
  1425. btnGroup.style.verticalAlign = 'top';
  1426. btnGroup.style.marginRight = '6px';
  1427. btnGroup.style.padding = '0 4px 0 4px';
  1428. btnGroup.style.height = '30px';
  1429. btnGroup.style.position = 'relative';
  1430. btnGroup.style.top = '0px';
  1431. if (urlParams['sketch'] == '1')
  1432. {
  1433. btnGroup.style.boxShadow = 'none';
  1434. }
  1435. for (var i = 0; i < btns.length; i++)
  1436. {
  1437. if (btns[i] != null)
  1438. {
  1439. if (urlParams['sketch'] == '1')
  1440. {
  1441. btns[i].style.padding = '10px 8px';
  1442. btns[i].style.width = '30px';
  1443. }
  1444. btns[i].style.margin = '0px';
  1445. btns[i].style.boxShadow = 'none';
  1446. btnGroup.appendChild(btns[i]);
  1447. }
  1448. }
  1449. if (op != null)
  1450. {
  1451. mxUtils.setOpacity(btnGroup, op);
  1452. }
  1453. if (ui.statusContainer != null && urlParams['sketch'] != '1')
  1454. {
  1455. menubar.insertBefore(btnGroup, ui.statusContainer);
  1456. }
  1457. else
  1458. {
  1459. menubar.appendChild(btnGroup);
  1460. }
  1461. return btnGroup;
  1462. };
  1463. ui.statusContainer = ui.createStatusContainer();
  1464. ui.statusContainer.style.position = 'relative';
  1465. ui.statusContainer.style.maxWidth = '';
  1466. ui.statusContainer.style.marginTop = '7px';
  1467. ui.statusContainer.style.marginLeft = '6px';
  1468. ui.statusContainer.style.color = 'gray';
  1469. ui.statusContainer.style.cursor = 'default';
  1470. function updateTitle()
  1471. {
  1472. var file = ui.getCurrentFile();
  1473. if (file != null && file.getTitle() != null)
  1474. {
  1475. var mode = file.getMode();
  1476. if (mode == 'google')
  1477. {
  1478. mode = 'googleDrive';
  1479. }
  1480. else if (mode == 'github')
  1481. {
  1482. mode = 'gitHub';
  1483. }
  1484. else if (mode == 'gitlab')
  1485. {
  1486. mode = 'gitLab';
  1487. }
  1488. else if (mode == 'onedrive')
  1489. {
  1490. mode = 'oneDrive';
  1491. }
  1492. mode = mxResources.get(mode);
  1493. menubar.setAttribute('title', file.getTitle() + ((mode != null) ? ' (' + mode + ')' : ''));
  1494. }
  1495. else
  1496. {
  1497. menubar.removeAttribute('title');
  1498. }
  1499. };
  1500. // Hides popup menus
  1501. var uiHideCurrentMenu = ui.hideCurrentMenu;
  1502. ui.hideCurrentMenu = function()
  1503. {
  1504. uiHideCurrentMenu.apply(this, arguments);
  1505. this.editor.graph.popupMenuHandler.hideMenu();
  1506. };
  1507. // Connects the status bar to the editor status
  1508. var uiDescriptorChanged = ui.descriptorChanged;
  1509. ui.descriptorChanged = function()
  1510. {
  1511. uiDescriptorChanged.apply(this, arguments);
  1512. updateTitle();
  1513. };
  1514. ui.setStatusText(ui.editor.getStatus());
  1515. menubar.appendChild(ui.statusContainer);
  1516. ui.buttonContainer = document.createElement('div');
  1517. ui.buttonContainer.style.cssText = 'position:absolute;right:0px;padding-right:34px;top:10px;' +
  1518. 'white-space:nowrap;padding-top:2px;background-color:inherit;';
  1519. menubar.appendChild(ui.buttonContainer);
  1520. // Container for the user element
  1521. ui.menubarContainer = ui.buttonContainer;
  1522. ui.tabContainer = document.createElement('div');
  1523. ui.tabContainer.className = 'geTabContainer';
  1524. ui.tabContainer.style.cssText = 'position:absolute;left:0px;right:0px;bottom:0px;height:30px;white-space:nowrap;' +
  1525. 'margin-bottom:-2px;visibility:hidden;';
  1526. var previousParent = ui.diagramContainer.parentNode;
  1527. var wrapper = document.createElement('div');
  1528. wrapper.style.cssText = 'position:absolute;top:0px;left:0px;right:0px;bottom:0px;overflow:hidden;';
  1529. ui.diagramContainer.style.top = (urlParams['sketch'] == '1') ? '0px' : '47px';
  1530. //Create draggable titlebar
  1531. if (EditorUi.isElectronApp && urlParams['sketch'] == '1')
  1532. {
  1533. wrapper.style.top = '20px';
  1534. ui.titlebar = document.createElement('div');
  1535. ui.titlebar.style.cssText = 'position:absolute;top:0px;left:0px;right:0px;height:20px;overflow:hidden;box-shadow: 0px 0px 2px #c0c0c0;';
  1536. var title = document.createElement('div');
  1537. title.style.cssText = 'max-width: calc(100% - 100px);text-overflow: ellipsis;user-select:none;height:20px;margin: 2px 10px;font-size: 12px;white-space: nowrap;overflow: hidden;';
  1538. ui.titlebar.appendChild(title);
  1539. previousParent.appendChild(ui.titlebar);
  1540. }
  1541. var viewZoomMenu = ui.menus.get('viewZoom');
  1542. var insertImage = (urlParams['sketch'] != '1') ? Editor.plusImage : Editor.shapesImage;
  1543. var footer = (urlParams['sketch'] == '1') ? document.createElement('div') : null;
  1544. var picker = (urlParams['sketch'] == '1') ? document.createElement('div') : null;
  1545. var toolbar = (urlParams['sketch'] == '1') ? document.createElement('div') : null;
  1546. var refreshSidebar = mxUtils.bind(this, function()
  1547. {
  1548. if (this.sidebar != null)
  1549. {
  1550. this.sidebar.graph.stylesheet.styles =
  1551. mxUtils.clone(graph.stylesheet.styles);
  1552. this.sidebar.container.innerHTML = '';
  1553. this.sidebar.palettes = new Object();
  1554. this.sidebar.init();
  1555. if (urlParams['sketch'] == '1')
  1556. {
  1557. this.scratchpad = null;
  1558. this.toggleScratchpad();
  1559. }
  1560. }
  1561. graph.refresh();
  1562. graph.view.validateBackground();
  1563. });
  1564. ui.addListener('darkModeChanged', refreshSidebar);
  1565. ui.addListener('sketchModeChanged', refreshSidebar);
  1566. var inlineSizeChanged = mxUtils.bind(this, function()
  1567. {
  1568. if (Editor.inlineFullscreen)
  1569. {
  1570. toolbar.style.left = '10px';
  1571. toolbar.style.top = '10px';
  1572. picker.style.left = '10px';
  1573. picker.style.top = '60px';
  1574. footer.style.top = '10px';
  1575. footer.style.right = '12px';
  1576. footer.style.left = '';
  1577. ui.diagramContainer.setAttribute('data-bounds', ui.diagramContainer.style.top + ' ' +
  1578. ui.diagramContainer.style.left + ' ' + ui.diagramContainer.style.width + ' ' +
  1579. ui.diagramContainer.style.height);
  1580. ui.diagramContainer.style.top = '0px';
  1581. ui.diagramContainer.style.left = '0px';
  1582. ui.diagramContainer.style.bottom = '0px';
  1583. ui.diagramContainer.style.right = '0px';
  1584. ui.diagramContainer.style.width = '';
  1585. ui.diagramContainer.style.height = '';
  1586. }
  1587. else
  1588. {
  1589. var bounds = ui.diagramContainer.getAttribute('data-bounds');
  1590. if (bounds != null)
  1591. {
  1592. ui.diagramContainer.style.background = 'transparent';
  1593. ui.diagramContainer.removeAttribute('data-bounds');
  1594. var gb = graph.getGraphBounds();
  1595. var tokens = bounds.split(' ');
  1596. ui.diagramContainer.style.top = tokens[0];
  1597. ui.diagramContainer.style.left = tokens[1];
  1598. ui.diagramContainer.style.width = (gb.width + 50) + 'px';
  1599. ui.diagramContainer.style.height = (gb.height + 46) + 'px';
  1600. ui.diagramContainer.style.bottom = '';
  1601. ui.diagramContainer.style.right = '';
  1602. var parent = window.opener || window.parent;
  1603. parent.postMessage(JSON.stringify({
  1604. event: 'resize',
  1605. rect: ui.diagramContainer.getBoundingClientRect()
  1606. }), '*');
  1607. ui.refresh();
  1608. }
  1609. toolbar.style.left = ui.diagramContainer.offsetLeft + 'px';
  1610. toolbar.style.top = (ui.diagramContainer.offsetTop -
  1611. toolbar.offsetHeight - 4) + 'px';
  1612. picker.style.display = '';
  1613. picker.style.left = (ui.diagramContainer.offsetLeft -
  1614. picker.offsetWidth - 4) + 'px';
  1615. picker.style.top = ui.diagramContainer.offsetTop + 'px';
  1616. footer.style.left = (ui.diagramContainer.offsetLeft +
  1617. ui.diagramContainer.offsetWidth -
  1618. footer.offsetWidth) + 'px';
  1619. footer.style.top = toolbar.style.top;
  1620. footer.style.right = '';
  1621. ui.bottomResizer.style.left = (ui.diagramContainer.offsetLeft +
  1622. (ui.diagramContainer.offsetWidth -
  1623. ui.bottomResizer.offsetWidth) / 2) + 'px';
  1624. ui.bottomResizer.style.top = (ui.diagramContainer.offsetTop +
  1625. ui.diagramContainer.offsetHeight -
  1626. ui.bottomResizer.offsetHeight / 2 - 1) + 'px';
  1627. ui.rightResizer.style.left = (ui.diagramContainer.offsetLeft +
  1628. ui.diagramContainer.offsetWidth -
  1629. ui.rightResizer.offsetWidth / 2 - 1) + 'px';
  1630. ui.rightResizer.style.top = (ui.diagramContainer.offsetTop +
  1631. (ui.diagramContainer.offsetHeight -
  1632. ui.bottomResizer.offsetHeight) / 2) + 'px';
  1633. }
  1634. ui.bottomResizer.style.visibility = (Editor.inlineFullscreen) ? 'hidden' : '';
  1635. ui.rightResizer.style.visibility = ui.bottomResizer.style.visibility;
  1636. menubar.style.display = 'none';
  1637. toolbar.style.visibility = '';
  1638. footer.style.visibility = '';
  1639. });
  1640. var inlineFullscreenChanged = mxUtils.bind(this, function()
  1641. {
  1642. fullscreenElt.style.backgroundImage = 'url(' + ((!Editor.inlineFullscreen) ?
  1643. Editor.fullscreenImage : Editor.fullscreenExitImage) + ')';
  1644. this.diagramContainer.style.background = (Editor.inlineFullscreen) ?
  1645. (Editor.isDarkMode() ? Editor.darkColor : '#ffffff') : 'transparent';
  1646. inlineSizeChanged();
  1647. });
  1648. var editInlineStart = mxUtils.bind(this, function()
  1649. {
  1650. inlineFullscreenChanged();
  1651. toggleFormat(ui, true);
  1652. ui.initFormatWindow();
  1653. var r = this.diagramContainer.getBoundingClientRect();
  1654. this.formatWindow.window.setLocation(r.x + r.width + 4, r.y);
  1655. });
  1656. ui.addListener('inlineFullscreenChanged', inlineFullscreenChanged);
  1657. ui.addListener('editInlineStart', editInlineStart);
  1658. if (urlParams['embedInline'] == '1')
  1659. {
  1660. ui.addListener('darkModeChanged', editInlineStart);
  1661. }
  1662. ui.addListener('editInlineStop', mxUtils.bind(this, function(evt)
  1663. {
  1664. ui.diagramContainer.style.width = '10px';
  1665. ui.diagramContainer.style.height = '10px';
  1666. ui.diagramContainer.style.border = '';
  1667. ui.bottomResizer.style.visibility = 'hidden';
  1668. ui.rightResizer.style.visibility = 'hidden';
  1669. toolbar.style.visibility = 'hidden';
  1670. footer.style.visibility = 'hidden';
  1671. picker.style.display = 'none';
  1672. }));
  1673. // Stops panning while freehand is active
  1674. if (Graph.touchStyle)
  1675. {
  1676. graph.panningHandler.isPanningTrigger = function(me)
  1677. {
  1678. var evt = me.getEvent();
  1679. return (me.getState() == null && (!mxEvent.isMouseEvent(evt) &&
  1680. !graph.freehand.isDrawing())) ||
  1681. (mxEvent.isPopupTrigger(evt) && (me.getState() == null ||
  1682. mxEvent.isControlDown(evt) || mxEvent.isShiftDown(evt)));
  1683. };
  1684. }
  1685. // Hides hover icons if freehand is active
  1686. if (ui.hoverIcons != null)
  1687. {
  1688. var hoverIconsUpdate = ui.hoverIcons.update;
  1689. ui.hoverIcons.update = function()
  1690. {
  1691. if (!graph.freehand.isDrawing())
  1692. {
  1693. hoverIconsUpdate.apply(this, arguments);
  1694. }
  1695. };
  1696. }
  1697. // Removes sketch style from freehand shapes
  1698. if (graph.freehand != null)
  1699. {
  1700. var freehandCreateStyle = graph.freehand.createStyle;
  1701. graph.freehand.createStyle = function(stencil)
  1702. {
  1703. return freehandCreateStyle.apply(this, arguments) + 'sketch=0;';
  1704. };
  1705. }
  1706. if (urlParams['sketch'] == '1')
  1707. {
  1708. picker.className = 'geToolbarContainer';
  1709. footer.className = 'geToolbarContainer';
  1710. toolbar.className = 'geToolbarContainer';
  1711. menubar.className = 'geToolbarContainer';
  1712. ui.picker = picker;
  1713. var statusVisible = false;
  1714. mxEvent.addListener(menubar, 'mouseenter', function()
  1715. {
  1716. ui.statusContainer.style.display = 'inline-block';
  1717. });
  1718. mxEvent.addListener(menubar, 'mouseleave', function()
  1719. {
  1720. if (!statusVisible)
  1721. {
  1722. ui.statusContainer.style.display = 'none';
  1723. }
  1724. });
  1725. var setNotificationTitle = mxUtils.bind(this, function(title)
  1726. {
  1727. if (ui.notificationBtn != null)
  1728. {
  1729. if (title != null)
  1730. {
  1731. ui.notificationBtn.setAttribute('title', title);
  1732. }
  1733. else
  1734. {
  1735. ui.notificationBtn.removeAttribute('title');
  1736. }
  1737. }
  1738. });
  1739. // Connects the status bar to the editor status and
  1740. // moves status to bell icon tooltip for trivial messages
  1741. if (urlParams['embed'] != '1')
  1742. {
  1743. menubar.style.visibility = (menubar.clientWidth < 14) ? 'hidden' : '';
  1744. ui.editor.addListener('statusChanged', mxUtils.bind(this, function()
  1745. {
  1746. ui.setStatusText(ui.editor.getStatus());
  1747. if (ui.statusContainer.children.length == 0 ||
  1748. (ui.statusContainer.children.length == 1 &&
  1749. typeof ui.statusContainer.firstChild.getAttribute === 'function' &&
  1750. ui.statusContainer.firstChild.getAttribute('class') == null))
  1751. {
  1752. var title = (ui.statusContainer.firstChild != null &&
  1753. typeof ui.statusContainer.firstChild.getAttribute === 'function') ?
  1754. ui.statusContainer.firstChild.getAttribute('title') :
  1755. ui.editor.getStatus();
  1756. setNotificationTitle(title);
  1757. var file = ui.getCurrentFile();
  1758. var key = (file != null) ? file.savingStatusKey : DrawioFile.prototype.savingStatusKey;
  1759. if (title == mxResources.get(key) + '...')
  1760. {
  1761. ui.statusContainer.innerHTML = '<img title="' + mxUtils.htmlEntities(
  1762. mxResources.get(key)) + '...' + '"src="' + Editor.tailSpin + '">';
  1763. ui.statusContainer.style.display = 'inline-block';
  1764. statusVisible = true;
  1765. }
  1766. else if (ui.buttonContainer.clientWidth > 6)
  1767. {
  1768. ui.statusContainer.style.display = 'none';
  1769. statusVisible = false;
  1770. }
  1771. }
  1772. else
  1773. {
  1774. ui.statusContainer.style.display = 'inline-block';
  1775. setNotificationTitle(null);
  1776. statusVisible = true;
  1777. }
  1778. menubar.style.visibility = (menubar.clientWidth > 12) ? '' : 'hidden';
  1779. }));
  1780. }
  1781. else
  1782. {
  1783. ui.editor.addListener('statusChanged', mxUtils.bind(this, function()
  1784. {
  1785. menubar.style.visibility = (menubar.clientWidth > 16) ? '' : 'hidden';
  1786. }));
  1787. }
  1788. elt = addMenu('diagram', null, Editor.menuImage);
  1789. elt.style.boxShadow = 'none';
  1790. elt.style.padding = '6px';
  1791. elt.style.margin = '0px';
  1792. toolbar.appendChild(elt);
  1793. mxEvent.disableContextMenu(elt);
  1794. mxEvent.addGestureListeners(elt, mxUtils.bind(this, function(evt)
  1795. {
  1796. if (mxEvent.isShiftDown(evt) || mxEvent.isAltDown(evt) ||
  1797. mxEvent.isMetaDown(evt) || mxEvent.isControlDown(evt) ||
  1798. mxEvent.isPopupTrigger(evt))
  1799. {
  1800. this.appIconClicked(evt);
  1801. }
  1802. }), null, null);
  1803. ui.statusContainer.style.position = '';
  1804. ui.statusContainer.style.display = 'none';
  1805. ui.statusContainer.style.margin = '0px';
  1806. ui.statusContainer.style.padding = '6px 0px';
  1807. ui.statusContainer.style.maxWidth = Math.min(iw - 240, 280) + 'px';
  1808. ui.statusContainer.style.display = 'inline-block';
  1809. ui.statusContainer.style.textOverflow = 'ellipsis';
  1810. ui.buttonContainer.style.position = '';
  1811. ui.buttonContainer.style.paddingRight = '0px';
  1812. ui.buttonContainer.style.display = 'inline-block';
  1813. var foldImg = document.createElement('a');
  1814. foldImg.style.padding = '0px';
  1815. foldImg.style.boxShadow = 'none';
  1816. foldImg.className = 'geMenuItem';
  1817. foldImg.style.display = 'inline-block';
  1818. foldImg.style.width = '40px';
  1819. foldImg.style.height = '12px';
  1820. foldImg.style.marginBottom = '-2px';
  1821. foldImg.style.backgroundImage = 'url(' + mxWindow.prototype.normalizeImage + ')';
  1822. foldImg.style.backgroundPosition = 'top center';
  1823. foldImg.style.backgroundRepeat = 'no-repeat';
  1824. foldImg.setAttribute('title', 'Minimize'/*TODO:mxResources.get('minimize')*/);
  1825. var collapsed = false;
  1826. var initPicker = mxUtils.bind(this, function()
  1827. {
  1828. picker.innerHTML = '';
  1829. if (!collapsed)
  1830. {
  1831. function addElt(elt, title, cursor)
  1832. {
  1833. if (title != null)
  1834. {
  1835. elt.setAttribute('title', title);
  1836. }
  1837. elt.style.cursor = (cursor != null) ? cursor : 'default';
  1838. elt.style.margin = '2px 0px';
  1839. picker.appendChild(elt);
  1840. mxUtils.br(picker);
  1841. return elt;
  1842. };
  1843. // Append sidebar elements
  1844. addElt(ui.sidebar.createVertexTemplate('text;strokeColor=none;fillColor=none;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;',
  1845. 60, 30, 'Text', mxResources.get('text'), true, false, null, true, true), mxResources.get('text') +
  1846. ' (' + Editor.ctrlKey + '+Shift+X' + ')');
  1847. addElt(ui.sidebar.createVertexTemplate('shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;' +
  1848. 'fontColor=#000000;darkOpacity=0.05;fillColor=#FFF9B2;strokeColor=none;fillStyle=solid;' +
  1849. 'direction=west;gradientDirection=north;gradientColor=#FFF2A1;shadow=1;size=20;pointerEvents=1;',
  1850. 140, 160, '', mxResources.get('note'), true, false, null, true), mxResources.get('note'));
  1851. addElt(ui.sidebar.createVertexTemplate('rounded=0;whiteSpace=wrap;html=1;', 160, 80,
  1852. '', mxResources.get('rectangle'), true, false, null, true), mxResources.get('rectangle') +
  1853. ' (' + Editor.ctrlKey + '+K' + ')');
  1854. addElt(ui.sidebar.createVertexTemplate('ellipse;whiteSpace=wrap;html=1;', 160, 100,
  1855. '', mxResources.get('ellipse'), true, false, null, true), mxResources.get('ellipse'));
  1856. (function()
  1857. {
  1858. var edgeStyle = 'edgeStyle=none;orthogonalLoop=1;jettySize=auto;html=1;';
  1859. var cell = new mxCell('', new mxGeometry(0, 0, graph.defaultEdgeLength, 0), edgeStyle);
  1860. cell.geometry.setTerminalPoint(new mxPoint(0, 0), true);
  1861. cell.geometry.setTerminalPoint(new mxPoint(cell.geometry.width, 0), false);
  1862. cell.geometry.points = [];
  1863. cell.geometry.relative = true;
  1864. cell.edge = true;
  1865. addElt(ui.sidebar.createEdgeTemplateFromCells([cell],
  1866. cell.geometry.width, cell.geometry.height,
  1867. mxResources.get('line'), true, null, true, false),
  1868. mxResources.get('line'));
  1869. cell = cell.clone();
  1870. cell.style = edgeStyle + 'shape=flexArrow;rounded=1;startSize=8;endSize=8;';
  1871. cell.geometry.width = graph.defaultEdgeLength + 20;
  1872. cell.geometry.setTerminalPoint(new mxPoint(0, 20), true);
  1873. cell.geometry.setTerminalPoint(new mxPoint(cell.geometry.width, 20), false);
  1874. var elt = addElt(ui.sidebar.createEdgeTemplateFromCells([cell],
  1875. cell.geometry.width, 40, mxResources.get('arrow'),
  1876. true, null, true, false), mxResources.get('arrow'));
  1877. elt.style.borderBottom = '1px solid ' + (Editor.isDarkMode() ? '#505050' : 'lightgray');
  1878. elt.style.paddingBottom = '14px';
  1879. elt.style.marginBottom = '14px';
  1880. })();
  1881. function addAction(action, label, image)
  1882. {
  1883. var elt = addMenuItem('', action.funct, null, label, action, image);
  1884. elt.style.width = '40px';
  1885. elt.style.opacity = '0.7';
  1886. return addElt(elt, null, 'pointer');
  1887. };
  1888. addAction(ui.actions.get('insertFreehand'), mxResources.get('freehand'), Editor.freehandImage);
  1889. var toggleShapesAction = ui.actions.get('toggleShapes');
  1890. addAction(toggleShapesAction, mxResources.get('shapes') + ' (' + toggleShapesAction.shortcut + ')', insertImage);
  1891. elt = addMenu('table', null, Editor.tableImage);
  1892. elt.style.boxShadow = 'none';
  1893. elt.style.opacity = '0.7';
  1894. elt.style.padding = '6px';
  1895. elt.style.margin = '0px';
  1896. elt.style.width = '37px';
  1897. addElt(elt, null, 'pointer');
  1898. addAction(ui.actions.get('insertTemplate'), mxResources.get('template'), Editor.templateImage);
  1899. }
  1900. if (urlParams['embedInline'] != '1')
  1901. {
  1902. picker.appendChild(foldImg);
  1903. }
  1904. });
  1905. mxEvent.addListener(foldImg, 'click', mxUtils.bind(this, function()
  1906. {
  1907. if (collapsed)
  1908. {
  1909. mxUtils.setPrefixedStyle(picker.style, 'transform', 'translate(0, -50%)');
  1910. picker.style.padding = '8px 6px 4px';
  1911. picker.style.top = '50%';
  1912. picker.style.bottom = '';
  1913. picker.style.height = '';
  1914. foldImg.style.backgroundImage = 'url(' + mxWindow.prototype.normalizeImage + ')';
  1915. foldImg.style.width = '40px';
  1916. foldImg.style.height = '12px';
  1917. foldImg.setAttribute('title', 'Minimize'/*TODO:mxResources.get('minimize')*/);
  1918. collapsed = false;
  1919. initPicker();
  1920. }
  1921. else
  1922. {
  1923. picker.innerHTML = '';
  1924. picker.appendChild(foldImg);
  1925. mxUtils.setPrefixedStyle(picker.style, 'transform', 'translate(0, 0)');
  1926. picker.style.top = '';
  1927. picker.style.bottom = '12px';
  1928. picker.style.padding = '0px';
  1929. picker.style.height = '24px';
  1930. foldImg.style.height = '24px';
  1931. foldImg.style.backgroundImage = 'url(' + Editor.plusImage + ')';
  1932. foldImg.setAttribute('title', mxResources.get('insert'));
  1933. foldImg.style.width = '24px';
  1934. collapsed = true;
  1935. }
  1936. }));
  1937. initPicker();
  1938. ui.addListener('darkModeChanged', initPicker);
  1939. ui.addListener('sketchModeChanged', initPicker);
  1940. }
  1941. else
  1942. {
  1943. // Connects the status bar to the editor status
  1944. ui.editor.addListener('statusChanged', mxUtils.bind(this, function()
  1945. {
  1946. ui.setStatusText(ui.editor.getStatus());
  1947. }));
  1948. }
  1949. if (viewZoomMenu != null)
  1950. {
  1951. var fitFunction = function(evt)
  1952. {
  1953. graph.popupMenuHandler.hideMenu();
  1954. if (mxEvent.isAltDown(evt))
  1955. {
  1956. ui.actions.get('customZoom').funct();
  1957. }
  1958. else
  1959. {
  1960. ui.actions.get('smartFit').funct();
  1961. }
  1962. };
  1963. var zoomInAction = ui.actions.get('zoomIn');
  1964. var zoomOutAction = ui.actions.get('zoomOut');
  1965. var resetViewAction = ui.actions.get('resetView');
  1966. var fullscreenAction = ui.actions.get('fullscreen');
  1967. var toggleDarkAction = ui.actions.get('toggleDarkMode');
  1968. var undoAction = ui.actions.get('undo');
  1969. var redoAction = ui.actions.get('redo');
  1970. var undoElt = addMenuItem('', undoAction.funct, null, mxResources.get('undo') + ' (' + undoAction.shortcut + ')', undoAction, Editor.undoImage);
  1971. var redoElt = addMenuItem('', redoAction.funct, null, mxResources.get('redo') + ' (' + redoAction.shortcut + ')', redoAction, Editor.redoImage);
  1972. var fullscreenElt = addMenuItem('', fullscreenAction.funct, null, mxResources.get('fullscreen'), fullscreenAction, Editor.fullscreenImage);
  1973. if (footer != null)
  1974. {
  1975. fullscreenElt.parentNode.removeChild(fullscreenElt);
  1976. var deleteAction = ui.actions.get('delete');
  1977. var deleteElt = addMenuItem('', deleteAction.funct, null, mxResources.get('delete'), deleteAction, Editor.trashImage);
  1978. deleteElt.style.opacity = '0.1';
  1979. toolbar.appendChild(deleteElt);
  1980. deleteAction.addListener('stateChanged', function()
  1981. {
  1982. deleteElt.style.opacity = (deleteAction.enabled) ? '' : '0.1';
  1983. });
  1984. var undoListener = function()
  1985. {
  1986. undoElt.style.display = (ui.editor.undoManager.history.length > 0 ||
  1987. graph.isEditing()) ? 'inline-block' : 'none';
  1988. redoElt.style.display = undoElt.style.display;
  1989. undoElt.style.opacity = (undoAction.enabled) ? '' : '0.1';
  1990. redoElt.style.opacity = (redoAction.enabled) ? '' : '0.1';
  1991. };
  1992. toolbar.appendChild(undoElt);
  1993. toolbar.appendChild(redoElt);
  1994. undoAction.addListener('stateChanged', undoListener);
  1995. redoAction.addListener('stateChanged', undoListener);
  1996. undoListener();
  1997. if (urlParams['layers'] != null)
  1998. {
  1999. var layersAction = ui.actions.get('layers');
  2000. var layersElt = addMenuItem('', layersAction.funct, null, mxResources.get('layers'), layersAction, Editor.layersImage);
  2001. layersElt.style.opacity = '0.4';
  2002. footer.appendChild(layersElt);
  2003. }
  2004. if (urlParams['tags'] != null)
  2005. {
  2006. var tagsAction = ui.actions.get('tags');
  2007. var tagsElt = addMenuItem('', tagsAction.funct, null, mxResources.get('tags'), tagsAction, Editor.tagsImage);
  2008. tagsElt.style.opacity = '0.4';
  2009. footer.appendChild(tagsElt);
  2010. }
  2011. var outlineAction = ui.actions.get('outline');
  2012. var outlineElt = addMenuItem('', outlineAction.funct, null, mxResources.get('outline'), outlineAction, Editor.outlineImage);
  2013. footer.appendChild(outlineElt);
  2014. var zoomOutElt = addMenuItem('', zoomOutAction.funct, true, mxResources.get('zoomOut') +
  2015. ' (' + Editor.ctrlKey + ' -/Alt+Mousewheel)', zoomOutAction, Editor.zoomOutImage);
  2016. footer.appendChild(zoomOutElt);
  2017. var elt = document.createElement('div');
  2018. elt.innerHTML = '100%';
  2019. elt.setAttribute('title', mxResources.get('fitWindow') + '/' + mxResources.get('resetView') + ' (Enter)');
  2020. elt.style.display = 'inline-block';
  2021. elt.style.cursor = 'pointer';
  2022. elt.style.textAlign = 'center';
  2023. elt.style.whiteSpace = 'nowrap';
  2024. elt.style.paddingRight = '10px';
  2025. elt.style.textDecoration = 'none';
  2026. elt.style.verticalAlign = 'top';
  2027. elt.style.padding = '6px 0';
  2028. elt.style.fontSize = '14px';
  2029. elt.style.width = '40px';
  2030. elt.style.opacity = '0.4';
  2031. footer.appendChild(elt);
  2032. mxEvent.addListener(elt, 'click', fitFunction);
  2033. var zoomInElt = addMenuItem('', zoomInAction.funct, true, mxResources.get('zoomIn') +
  2034. ' (' + Editor.ctrlKey + ' +/Alt+Mousewheel)', zoomInAction, Editor.zoomInImage);
  2035. footer.appendChild(zoomInElt);
  2036. if (urlParams['embedInline'] == '1')
  2037. {
  2038. footer.appendChild(fullscreenElt);
  2039. var exitAction = ui.actions.get('exit');
  2040. footer.appendChild(addMenuItem('', exitAction.funct, null, mxResources.get('exit'), exitAction, Editor.closeImage));
  2041. }
  2042. var pageMenu = this.createPageMenuTab(false);
  2043. pageMenu.style.display = 'none';
  2044. pageMenu.style.position = '';
  2045. pageMenu.style.marginLeft = '';
  2046. pageMenu.style.top = '';
  2047. pageMenu.style.left = '';
  2048. pageMenu.style.height = '100%';
  2049. pageMenu.style.lineHeight = '';
  2050. pageMenu.style.borderStyle = 'none';
  2051. pageMenu.style.padding = '3px 0';
  2052. pageMenu.style.margin = '0px';
  2053. pageMenu.style.background = '';
  2054. pageMenu.style.border = '';
  2055. pageMenu.style.boxShadow = 'none';
  2056. pageMenu.style.verticalAlign = 'top';
  2057. pageMenu.firstChild.style.height = '100%';
  2058. pageMenu.firstChild.style.opacity = '0.6';
  2059. pageMenu.firstChild.style.margin = '0px';
  2060. footer.appendChild(pageMenu);
  2061. function pagesVisibleChanged()
  2062. {
  2063. pageMenu.style.display = ui.pages != null &&
  2064. (urlParams['pages'] == '1' || ui.pages.length > 1 ||
  2065. Editor.pagesVisible) ? 'inline-block' : 'none';
  2066. };
  2067. // Page menu only visible for multiple pages
  2068. ui.addListener('fileDescriptorChanged', pagesVisibleChanged);
  2069. ui.addListener('pagesVisibleChanged', pagesVisibleChanged);
  2070. pagesVisibleChanged();
  2071. ui.tabContainer.style.visibility = 'hidden';
  2072. menubar.style.cssText = 'position:absolute;right:12px;top:10px;height:30px;z-index:1;border-radius:4px;' +
  2073. 'box-shadow:0px 0px 3px 1px #d1d1d1;padding:6px 0px 6px 6px;border-bottom:1px solid lightgray;' +
  2074. 'text-align:right;white-space:nowrap;overflow:hidden;user-select:none;';
  2075. toolbar.style.cssText = 'position:absolute;left:10px;top:10px;height:30px;z-index:1;border-radius:4px;' +
  2076. 'box-shadow:0px 0px 3px 1px #d1d1d1;padding:6px;border-bottom:1px solid lightgray;' +
  2077. 'text-align:right;white-space:nowrap;overflow:hidden;user-select:none;';
  2078. footer.style.cssText = 'position:absolute;right:12px;bottom:12px;height:28px;z-index:1;border-radius:4px;' +
  2079. 'box-shadow:0px 0px 3px 1px #d1d1d1;padding:8px;white-space:nowrap;user-select:none;';
  2080. wrapper.appendChild(toolbar);
  2081. wrapper.appendChild(footer);
  2082. picker.style.cssText = 'position:absolute;left:10px;z-index:1;border-radius:4px;' +
  2083. 'box-shadow:0px 0px 3px 1px #d1d1d1;padding:8px 6px 4px 6px;white-space:nowrap;' +
  2084. 'transform:translate(0, -50%);top:50%;user-select:none;';
  2085. wrapper.appendChild(picker);
  2086. window.setTimeout(function()
  2087. {
  2088. mxUtils.setPrefixedStyle(picker.style, 'transition', 'transform .3s ease-out');
  2089. }, 0);
  2090. if (urlParams['format-toolbar'] == '1')
  2091. {
  2092. this.installFormatToolbar(wrapper);
  2093. }
  2094. }
  2095. else
  2096. {
  2097. var fitElt = addMenuItem('', fitFunction, true, mxResources.get('fit') + ' (' + Editor.ctrlKey + '+H)', resetViewAction, Editor.zoomFitImage);
  2098. menubar.style.cssText = 'position:absolute;left:0px;right:0px;top:0px;height:30px;padding:8px;' +
  2099. 'text-align:left;white-space:nowrap;';
  2100. this.tabContainer.style.right = '70px';
  2101. var elt = menuObj.addMenu('100%', viewZoomMenu.funct);
  2102. elt.setAttribute('title', mxResources.get('zoom') + ' (Alt+Mousewheel)');
  2103. elt.style.whiteSpace = 'nowrap';
  2104. elt.style.paddingRight = '10px';
  2105. elt.style.textDecoration = 'none';
  2106. elt.style.textDecoration = 'none';
  2107. elt.style.overflow = 'hidden';
  2108. elt.style.visibility = 'hidden';
  2109. elt.style.textAlign = 'center';
  2110. elt.style.cursor = 'pointer';
  2111. elt.style.height = (parseInt(ui.tabContainerHeight) - 1) + 'px';
  2112. elt.style.lineHeight = (parseInt(ui.tabContainerHeight) + 1) + 'px';
  2113. elt.style.position = 'absolute';
  2114. elt.style.display = 'block';
  2115. elt.style.fontSize = '12px';
  2116. elt.style.width = '59px';
  2117. elt.style.right = '0px';
  2118. elt.style.bottom = '0px';
  2119. elt.style.backgroundImage = 'url(' + mxWindow.prototype.minimizeImage + ')';
  2120. elt.style.backgroundPosition = 'right 6px center';
  2121. elt.style.backgroundRepeat = 'no-repeat';
  2122. wrapper.appendChild(elt);
  2123. }
  2124. // Updates the label if the scale changes
  2125. (function(elt)
  2126. {
  2127. var updateZoom = mxUtils.bind(this, function()
  2128. {
  2129. elt.innerHTML = Math.round(ui.editor.graph.view.scale * 100) + '%';
  2130. });
  2131. ui.editor.graph.view.addListener(mxEvent.EVENT_SCALE, updateZoom);
  2132. ui.editor.addListener('resetGraphView', updateZoom);
  2133. ui.editor.addListener('pageSelected', updateZoom);
  2134. })(elt);
  2135. // Augments setGraphEnabled to update visible state
  2136. var uiSetGraphEnabled = ui.setGraphEnabled;
  2137. ui.setGraphEnabled = function()
  2138. {
  2139. uiSetGraphEnabled.apply(this, arguments);
  2140. if (this.tabContainer != null)
  2141. {
  2142. elt.style.visibility = this.tabContainer.style.visibility;
  2143. this.diagramContainer.style.bottom = (this.tabContainer.style.visibility != 'hidden' &&
  2144. footer == null) ? this.tabContainerHeight + 'px' : '0px';
  2145. }
  2146. };
  2147. }
  2148. wrapper.appendChild(menubar);
  2149. wrapper.appendChild(ui.diagramContainer);
  2150. previousParent.appendChild(wrapper);
  2151. ui.updateTabContainer();
  2152. if (footer == null)
  2153. {
  2154. wrapper.appendChild(ui.tabContainer);
  2155. }
  2156. var langMenuElt = null;
  2157. function refreshMenu()
  2158. {
  2159. if (urlParams['sketch'] == '1')
  2160. {
  2161. if (urlParams['embedInline'] != '1')
  2162. {
  2163. toolbar.style.left = (picker.offsetTop - picker.offsetHeight / 2 < 58) ? '70px' : '10px';
  2164. }
  2165. }
  2166. else
  2167. {
  2168. // Removes all existing menu items
  2169. var node = menubar.firstChild;
  2170. while (node != null)
  2171. {
  2172. var temp = node.nextSibling;
  2173. if (node.className == 'geMenuItem' || node.className == 'geItem')
  2174. {
  2175. node.parentNode.removeChild(node);
  2176. }
  2177. node = temp;
  2178. }
  2179. before = menubar.firstChild;
  2180. iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  2181. var small = iw < 1000 || urlParams['sketch'] == '1';
  2182. var appElt = null;
  2183. if (!small)
  2184. {
  2185. appElt = addMenu('diagram');
  2186. }
  2187. var temp = (small) ? addMenu('diagram', null, Editor.drawLogoImage) : null;
  2188. if (temp != null)
  2189. {
  2190. appElt = temp;
  2191. }
  2192. createGroup([appElt, addMenuItem(mxResources.get('shapes'), ui.actions.get('toggleShapes').funct, null,
  2193. mxResources.get('shapes'), ui.actions.get('image'), (small) ? Editor.shapesImage : null),
  2194. addMenuItem(mxResources.get('format'), ui.actions.get('toggleFormat').funct, null,
  2195. mxResources.get('format') + ' (' + ui.actions.get('formatPanel').shortcut + ')', ui.actions.get('image'),
  2196. (small) ? Editor.formatImage : null)],
  2197. (small) ? 60 : null);
  2198. var elt = addMenu('insert', true, (small) ? insertImage : null);
  2199. createGroup([elt, addMenuItem(mxResources.get('delete'), ui.actions.get('delete').funct,
  2200. null, mxResources.get('delete'), ui.actions.get('delete'),
  2201. (small) ? Editor.trashImage : null)], (small) ? 60 : null);
  2202. if (iw >= 411)
  2203. {
  2204. createGroup([undoElt, redoElt], 60);
  2205. if (iw >= 520)
  2206. {
  2207. createGroup([fitElt,
  2208. (iw >= 640) ? addMenuItem('', zoomInAction.funct, true, mxResources.get('zoomIn') + ' (' + Editor.ctrlKey + ' +)',
  2209. zoomInAction, Editor.zoomInImage) : null,
  2210. (iw >= 640) ? addMenuItem('', zoomOutAction.funct, true, mxResources.get('zoomOut') + ' (' + Editor.ctrlKey + ' -)',
  2211. zoomOutAction, Editor.zoomOutImage) : null], 60);
  2212. }
  2213. }
  2214. }
  2215. if (appElt != null)
  2216. {
  2217. mxEvent.disableContextMenu(appElt);
  2218. mxEvent.addGestureListeners(appElt, mxUtils.bind(this, function(evt)
  2219. {
  2220. if (mxEvent.isShiftDown(evt) || mxEvent.isAltDown(evt) ||
  2221. mxEvent.isMetaDown(evt) || mxEvent.isControlDown(evt) ||
  2222. mxEvent.isPopupTrigger(evt))
  2223. {
  2224. ui.appIconClicked(evt);
  2225. }
  2226. }), null, null);
  2227. }
  2228. var langMenu = ui.menus.get('language');
  2229. if (langMenu != null && !mxClient.IS_CHROMEAPP &&
  2230. !EditorUi.isElectronApp && iw >= 600 &&
  2231. urlParams['sketch'] != '1')
  2232. {
  2233. if (langMenuElt == null)
  2234. {
  2235. var elt = menuObj.addMenu('', langMenu.funct);
  2236. elt.setAttribute('title', mxResources.get('language'));
  2237. elt.className = 'geToolbarButton';
  2238. elt.style.backgroundImage = 'url(' + Editor.globeImage + ')';
  2239. elt.style.backgroundPosition = 'center center';
  2240. elt.style.backgroundRepeat = 'no-repeat';
  2241. elt.style.backgroundSize = '24px 24px';
  2242. elt.style.position = 'absolute';
  2243. elt.style.height = '24px';
  2244. elt.style.width = '24px';
  2245. elt.style.zIndex = '1';
  2246. elt.style.right = '8px';
  2247. elt.style.cursor = 'pointer';
  2248. elt.style.top = (urlParams['embed'] == '1') ? '12px' : '11px';
  2249. menubar.appendChild(elt);
  2250. langMenuElt = elt;
  2251. }
  2252. ui.buttonContainer.style.paddingRight = '34px';
  2253. }
  2254. else
  2255. {
  2256. ui.buttonContainer.style.paddingRight = '4px';
  2257. if (langMenuElt != null)
  2258. {
  2259. langMenuElt.parentNode.removeChild(langMenuElt);
  2260. langMenuElt = null;
  2261. }
  2262. }
  2263. };
  2264. refreshMenu();
  2265. mxEvent.addListener(window, 'resize', function()
  2266. {
  2267. refreshMenu();
  2268. if (ui.sidebarWindow != null)
  2269. {
  2270. ui.sidebarWindow.window.fit();
  2271. }
  2272. if (ui.formatWindow != null)
  2273. {
  2274. ui.formatWindow.window.fit();
  2275. }
  2276. if (ui.actions.outlineWindow != null)
  2277. {
  2278. ui.actions.outlineWindow.window.fit();
  2279. }
  2280. if (ui.actions.layersWindow != null)
  2281. {
  2282. ui.actions.layersWindow.window.fit();
  2283. }
  2284. if (ui.menus.tagsWindow != null)
  2285. {
  2286. ui.menus.tagsWindow.window.fit();
  2287. }
  2288. if (ui.menus.findWindow != null)
  2289. {
  2290. ui.menus.findWindow.window.fit();
  2291. }
  2292. if (ui.menus.findReplaceWindow != null)
  2293. {
  2294. ui.menus.findReplaceWindow.window.fit();
  2295. }
  2296. });
  2297. if (urlParams['embedInline'] == '1')
  2298. {
  2299. document.body.style.cursor = 'text';
  2300. picker.style.transform = '';
  2301. mxEvent.addGestureListeners(ui.diagramContainer.parentNode, function(evt)
  2302. {
  2303. if (mxEvent.getSource(evt) ==
  2304. ui.diagramContainer.parentNode)
  2305. {
  2306. ui.embedExitPoint = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
  2307. ui.sendEmbeddedSvgExport();
  2308. }
  2309. });
  2310. var div = document.createElement('div');
  2311. div.style.position = 'absolute';
  2312. div.style.width = '10px';
  2313. div.style.height = '10px';
  2314. div.style.borderRadius = '5px';
  2315. div.style.border = '1px solid gray';
  2316. div.style.background = '#ffffff';
  2317. div.style.cursor = 'row-resize';
  2318. ui.diagramContainer.parentNode.appendChild(div);
  2319. ui.bottomResizer = div;
  2320. var x0 = null;
  2321. var y0 = null;
  2322. var w0 = null;
  2323. var h0 = null;
  2324. mxEvent.addGestureListeners(div, function(evt)
  2325. {
  2326. h0 = parseInt(ui.diagramContainer.style.height);
  2327. y0 = mxEvent.getClientY(evt);
  2328. graph.popupMenuHandler.hideMenu();
  2329. mxEvent.consume(evt);
  2330. });
  2331. div = div.cloneNode(false);
  2332. div.style.cursor = 'col-resize';
  2333. ui.diagramContainer.parentNode.appendChild(div);
  2334. ui.rightResizer = div;
  2335. mxEvent.addGestureListeners(div, function(evt)
  2336. {
  2337. w0 = parseInt(ui.diagramContainer.style.width);
  2338. x0 = mxEvent.getClientX(evt);
  2339. graph.popupMenuHandler.hideMenu();
  2340. mxEvent.consume(evt);
  2341. });
  2342. mxEvent.addGestureListeners(document.body, null, function(evt)
  2343. {
  2344. var changed = false;
  2345. if (x0 != null)
  2346. {
  2347. ui.diagramContainer.style.width = Math.max(20,
  2348. w0 + mxEvent.getClientX(evt) - x0) + 'px';
  2349. changed = true;
  2350. }
  2351. if (y0 != null)
  2352. {
  2353. ui.diagramContainer.style.height = Math.max(20,
  2354. h0 + mxEvent.getClientY(evt) - y0) + 'px';
  2355. changed = true;
  2356. }
  2357. if (changed)
  2358. {
  2359. var parent = window.opener || window.parent;
  2360. parent.postMessage(JSON.stringify({
  2361. event: 'resize',
  2362. fullscreen: Editor.inlineFullscreen,
  2363. rect: ui.diagramContainer.getBoundingClientRect()
  2364. }), '*');
  2365. inlineSizeChanged();
  2366. ui.refresh();
  2367. }
  2368. }, function(evt)
  2369. {
  2370. if (x0 != null || y0 != null)
  2371. {
  2372. mxEvent.consume(evt);
  2373. }
  2374. x0 = null;
  2375. y0 = null;
  2376. });
  2377. this.diagramContainer.style.borderRadius = '4px';
  2378. document.body.style.backgroundColor = 'transparent';
  2379. ui.bottomResizer.style.visibility = 'hidden';
  2380. ui.rightResizer.style.visibility = 'hidden';
  2381. toolbar.style.visibility = 'hidden';
  2382. footer.style.visibility = 'hidden';
  2383. picker.style.display = 'none';
  2384. }
  2385. if (urlParams['prefetchFonts'] == '1')
  2386. {
  2387. ui.editor.loadFonts();
  2388. }
  2389. };
  2390. };
  2391. (function()
  2392. {
  2393. var initialized = false;
  2394. // ChromeApp has async local storage
  2395. if (uiTheme == 'min' && !initialized && !mxClient.IS_CHROMEAPP)
  2396. {
  2397. EditorUi.initMinimalTheme();
  2398. initialized = true;
  2399. }
  2400. var uiInitTheme = EditorUi.initTheme;
  2401. // For async startup like chromeos
  2402. EditorUi.initTheme = function()
  2403. {
  2404. uiInitTheme.apply(this, arguments);
  2405. if (uiTheme == 'min' && !initialized)
  2406. {
  2407. this.initMinimalTheme();
  2408. initialized = true;
  2409. }
  2410. };
  2411. })();