Toolbar.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. /**
  2. * Copyright (c) 2006-2012, JGraph Ltd
  3. */
  4. /**
  5. * Construcs a new toolbar for the given editor.
  6. */
  7. function Toolbar(editorUi, container)
  8. {
  9. this.editorUi = editorUi;
  10. this.container = container;
  11. this.staticElements = [];
  12. this.init();
  13. // Global handler to hide the current menu
  14. this.gestureHandler = mxUtils.bind(this, function(evt)
  15. {
  16. if (this.editorUi.currentMenu != null && mxEvent.getSource(evt) != this.editorUi.currentMenu.div)
  17. {
  18. this.hideMenu();
  19. }
  20. });
  21. mxEvent.addGestureListeners(document, this.gestureHandler);
  22. };
  23. /**
  24. * Image for the dropdown arrow.
  25. */
  26. Toolbar.prototype.dropdownImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/dropdown.gif' : 'data:image/gif;base64,R0lGODlhDQANAIABAHt7e////yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCREM1NkJFMjE0NEMxMUU1ODk1Q0M5MjQ0MTA4QjNDMSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCREM1NkJFMzE0NEMxMUU1ODk1Q0M5MjQ0MTA4QjNDMSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQzOUMzMjZCMTQ0QjExRTU4OTVDQzkyNDQxMDhCM0MxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkQzOUMzMjZDMTQ0QjExRTU4OTVDQzkyNDQxMDhCM0MxIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEAQAAAQAsAAAAAA0ADQAAAhGMj6nL3QAjVHIu6azbvPtWAAA7';
  27. /**
  28. * Image element for the dropdown arrow.
  29. */
  30. Toolbar.prototype.dropdownImageHtml = '<img border="0" style="position:absolute;right:4px;top:' +
  31. ((!EditorUi.compactUi) ? 8 : 6) + 'px;" src="' + Toolbar.prototype.dropdownImage + '" valign="middle"/>';
  32. /**
  33. * Defines the background for selected buttons.
  34. */
  35. Toolbar.prototype.selectedBackground = '#d0d0d0';
  36. /**
  37. * Defines the background for selected buttons.
  38. */
  39. Toolbar.prototype.unselectedBackground = 'none';
  40. /**
  41. * Array that contains the DOM nodes that should never be removed.
  42. */
  43. Toolbar.prototype.staticElements = null;
  44. /**
  45. * Adds the toolbar elements.
  46. */
  47. Toolbar.prototype.init = function()
  48. {
  49. var sw = screen.width;
  50. // Takes into account initial compact mode
  51. sw -= (screen.height > 740) ? 56 : 0;
  52. if (sw >= 700)
  53. {
  54. var formatMenu = this.addMenu('', mxResources.get('view') + ' (' + mxResources.get('panTooltip') + ')', true, 'viewPanels', null, true);
  55. this.addDropDownArrow(formatMenu, 'geSprite-formatpanel', 38, 50, -4, -3, 36, -8);
  56. this.addSeparator();
  57. }
  58. var viewMenu = this.addMenu('', mxResources.get('zoom') + ' (Alt+Mousewheel)', true, 'viewZoom', null, true);
  59. viewMenu.showDisabled = true;
  60. viewMenu.style.whiteSpace = 'nowrap';
  61. viewMenu.style.position = 'relative';
  62. viewMenu.style.overflow = 'hidden';
  63. if (EditorUi.compactUi)
  64. {
  65. viewMenu.style.width = (mxClient.IS_QUIRKS) ? '58px' : '50px';
  66. }
  67. else
  68. {
  69. viewMenu.style.width = (mxClient.IS_QUIRKS) ? '62px' : '36px';
  70. }
  71. if (sw >= 420)
  72. {
  73. this.addSeparator();
  74. var elts = this.addItems(['zoomIn', 'zoomOut']);
  75. elts[0].setAttribute('title', mxResources.get('zoomIn') + ' (' + this.editorUi.actions.get('zoomIn').shortcut + ')');
  76. elts[1].setAttribute('title', mxResources.get('zoomOut') + ' (' + this.editorUi.actions.get('zoomOut').shortcut + ')');
  77. }
  78. // Updates the label if the scale changes
  79. this.updateZoom = mxUtils.bind(this, function()
  80. {
  81. viewMenu.innerHTML = Math.round(this.editorUi.editor.graph.view.scale * 100) + '%' +
  82. this.dropdownImageHtml;
  83. if (EditorUi.compactUi)
  84. {
  85. viewMenu.getElementsByTagName('img')[0].style.right = '1px';
  86. viewMenu.getElementsByTagName('img')[0].style.top = '5px';
  87. }
  88. });
  89. this.editorUi.editor.graph.view.addListener(mxEvent.EVENT_SCALE, this.updateZoom);
  90. this.editorUi.editor.addListener('resetGraphView', this.updateZoom);
  91. var elts = this.addItems(['-', 'undo', 'redo']);
  92. elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
  93. elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');
  94. if (sw >= 320)
  95. {
  96. var elts = this.addItems(['-', 'delete']);
  97. elts[1].setAttribute('title', mxResources.get('delete') + ' (' + this.editorUi.actions.get('delete').shortcut + ')');
  98. }
  99. if (sw >= 550)
  100. {
  101. this.addItems(['-', 'toFront', 'toBack']);
  102. }
  103. if (sw >= 740)
  104. {
  105. this.addItems(['-', 'fillColor']);
  106. if (sw >= 780)
  107. {
  108. this.addItems(['strokeColor']);
  109. if (sw >= 820)
  110. {
  111. this.addItems(['shadow']);
  112. }
  113. }
  114. }
  115. if (sw >= 400)
  116. {
  117. this.addSeparator();
  118. if (sw >= 440)
  119. {
  120. this.edgeShapeMenu = this.addMenuFunction('', mxResources.get('connection'), false, mxUtils.bind(this, function(menu)
  121. {
  122. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], [null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line'));
  123. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['link', null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link'));
  124. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['flexArrow', null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow'));
  125. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['arrow', null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow'));
  126. }));
  127. this.addDropDownArrow(this.edgeShapeMenu, 'geSprite-connection', 44, 50, 0, 0, 22, -4);
  128. }
  129. this.edgeStyleMenu = this.addMenuFunction('geSprite-orthogonal', mxResources.get('waypoints'), false, mxUtils.bind(this, function(menu)
  130. {
  131. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], [null, null, null], 'geIcon geSprite geSprite-straight', null, true).setAttribute('title', mxResources.get('straight'));
  132. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', null, null], 'geIcon geSprite geSprite-orthogonal', null, true).setAttribute('title', mxResources.get('orthogonal'));
  133. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalelbow', null, true).setAttribute('title', mxResources.get('simple'));
  134. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalelbow', null, true).setAttribute('title', mxResources.get('simple'));
  135. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
  136. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalisometric', null, true).setAttribute('title', mxResources.get('isometric'));
  137. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', '1', null], 'geIcon geSprite geSprite-curved', null, true).setAttribute('title', mxResources.get('curved'));
  138. this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['entityRelationEdgeStyle', null, null], 'geIcon geSprite geSprite-entity', null, true).setAttribute('title', mxResources.get('entityRelation'));
  139. }));
  140. this.addDropDownArrow(this.edgeStyleMenu, 'geSprite-orthogonal', 44, 50, 0, 0, 22, -4);
  141. }
  142. this.addSeparator();
  143. var insertMenu = this.addMenu('', mxResources.get('insert') + ' (' + mxResources.get('doubleClickTooltip') + ')', true, 'insert', null, true);
  144. this.addDropDownArrow(insertMenu, 'geSprite-plus', 38, 48, -4, -3, 36, -8);
  145. if (urlParams['dev'] == '1')
  146. {
  147. this.addSeparator();
  148. // KNOWN: All table stuff does not work with undo/redo
  149. // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
  150. // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
  151. var elt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu)
  152. {
  153. var graph = this.editorUi.editor.graph;
  154. var cell = graph.getSelectionCell();
  155. if (!graph.isTableCell(cell) && !graph.isTableRow(cell) && !graph.isTable(cell))
  156. {
  157. this.editorUi.menus.addInsertTableItem(menu, mxUtils.bind(this, function(evt, rows, cols)
  158. {
  159. var table = (mxEvent.isShiftDown(evt)) ? graph.createCrossFunctionalSwimlane(rows, cols) :
  160. graph.createTable(rows, cols);
  161. var pt = (mxEvent.isAltDown(evt)) ? graph.getFreeInsertPoint() :
  162. graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry([table], true));
  163. var select = graph.importCells([table], pt.x, pt.y);
  164. if (select != null && select.length > 0)
  165. {
  166. graph.scrollCellToVisible(select[0]);
  167. graph.setSelectionCells(select);
  168. }
  169. }));
  170. }
  171. else
  172. {
  173. elt = menu.addItem('', null, mxUtils.bind(this, function()
  174. {
  175. try
  176. {
  177. graph.insertTableColumn(cell, true);
  178. }
  179. catch (e)
  180. {
  181. this.editorUi.handleError(e);
  182. }
  183. }), null, 'geIcon geSprite geSprite-insertcolumnbefore');
  184. elt.setAttribute('title', mxResources.get('insertColumnBefore'));
  185. elt = menu.addItem('', null, mxUtils.bind(this, function()
  186. {
  187. try
  188. {
  189. graph.insertTableColumn(cell, false);
  190. }
  191. catch (e)
  192. {
  193. this.editorUi.handleError(e);
  194. }
  195. }), null, 'geIcon geSprite geSprite-insertcolumnafter');
  196. elt.setAttribute('title', mxResources.get('insertColumnAfter'));
  197. elt = menu.addItem('Delete column', null, mxUtils.bind(this, function()
  198. {
  199. if (cell != null)
  200. {
  201. try
  202. {
  203. graph.deleteTableColumn(cell);
  204. }
  205. catch (e)
  206. {
  207. this.editorUi.handleError(e);
  208. }
  209. }
  210. }), null, 'geIcon geSprite geSprite-deletecolumn');
  211. elt.setAttribute('title', mxResources.get('deleteColumn'));
  212. elt = menu.addItem('', null, mxUtils.bind(this, function()
  213. {
  214. try
  215. {
  216. graph.insertTableRow(cell, true);
  217. }
  218. catch (e)
  219. {
  220. this.editorUi.handleError(e);
  221. }
  222. }), null, 'geIcon geSprite geSprite-insertrowbefore');
  223. elt.setAttribute('title', mxResources.get('insertRowBefore'));
  224. elt = menu.addItem('', null, mxUtils.bind(this, function()
  225. {
  226. try
  227. {
  228. graph.insertTableRow(cell, false);
  229. }
  230. catch (e)
  231. {
  232. this.editorUi.handleError(e);
  233. }
  234. }), null, 'geIcon geSprite geSprite-insertrowafter');
  235. elt.setAttribute('title', mxResources.get('insertRowAfter'));
  236. elt = menu.addItem('', null, mxUtils.bind(this, function()
  237. {
  238. try
  239. {
  240. graph.deleteTableRow(cell);
  241. }
  242. catch (e)
  243. {
  244. this.editorUi.handleError(e);
  245. }
  246. }), null, 'geIcon geSprite geSprite-deleterow');
  247. elt.setAttribute('title', mxResources.get('deleteRow'));
  248. }
  249. }));
  250. elt.style.position = 'relative';
  251. elt.style.whiteSpace = 'nowrap';
  252. elt.style.overflow = 'hidden';
  253. elt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  254. elt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
  255. // Fix for item size in kennedy theme
  256. if (EditorUi.compactUi)
  257. {
  258. elt.getElementsByTagName('img')[0].style.left = '22px';
  259. elt.getElementsByTagName('img')[0].style.top = '5px';
  260. }
  261. }
  262. };
  263. /**
  264. * Adds the toolbar elements.
  265. */
  266. Toolbar.prototype.addDropDownArrow = function(menu, sprite, width, atlasWidth, left, top, atlasDelta, atlasLeft)
  267. {
  268. atlasDelta = (atlasDelta != null) ? atlasDelta : 32;
  269. left = (EditorUi.compactUi) ? left : atlasLeft;
  270. menu.style.whiteSpace = 'nowrap';
  271. menu.style.overflow = 'hidden';
  272. menu.style.position = 'relative';
  273. menu.innerHTML = '<div class="geSprite ' + sprite + '" style="margin-left:' + left + 'px;margin-top:' + top + 'px;"></div>' +
  274. this.dropdownImageHtml;
  275. menu.style.width = (mxClient.IS_QUIRKS) ? atlasWidth + 'px' : (atlasWidth - atlasDelta) + 'px';
  276. if (mxClient.IS_QUIRKS)
  277. {
  278. menu.style.height = (EditorUi.compactUi) ? '24px' : '26px';
  279. }
  280. // Fix for item size in kennedy theme
  281. if (EditorUi.compactUi)
  282. {
  283. menu.getElementsByTagName('img')[0].style.left = '24px';
  284. menu.getElementsByTagName('img')[0].style.top = '5px';
  285. menu.style.width = (mxClient.IS_QUIRKS) ? width + 'px' : (width - 10) + 'px';
  286. }
  287. };
  288. /**
  289. * Sets the current font name.
  290. */
  291. Toolbar.prototype.setFontName = function(value)
  292. {
  293. if (this.fontMenu != null)
  294. {
  295. this.fontMenu.innerHTML = '<div style="width:60px;overflow:hidden;display:inline-block;">' +
  296. mxUtils.htmlEntities(value) + '</div>' + this.dropdownImageHtml;
  297. }
  298. };
  299. /**
  300. * Sets the current font name.
  301. */
  302. Toolbar.prototype.setFontSize = function(value)
  303. {
  304. if (this.sizeMenu != null)
  305. {
  306. this.sizeMenu.innerHTML = '<div style="width:24px;overflow:hidden;display:inline-block;">' +
  307. value + '</div>' + this.dropdownImageHtml;
  308. }
  309. };
  310. /**
  311. * Hides the current menu.
  312. */
  313. Toolbar.prototype.createTextToolbar = function()
  314. {
  315. var graph = this.editorUi.editor.graph;
  316. var styleElt = this.addMenu('', mxResources.get('style'), true, 'formatBlock');
  317. styleElt.style.position = 'relative';
  318. styleElt.style.whiteSpace = 'nowrap';
  319. styleElt.style.overflow = 'hidden';
  320. styleElt.innerHTML = mxResources.get('style') + this.dropdownImageHtml;
  321. if (EditorUi.compactUi)
  322. {
  323. styleElt.style.paddingRight = '18px';
  324. styleElt.getElementsByTagName('img')[0].style.right = '1px';
  325. styleElt.getElementsByTagName('img')[0].style.top = '5px';
  326. }
  327. this.addSeparator();
  328. this.fontMenu = this.addMenu('', mxResources.get('fontFamily'), true, 'fontFamily');
  329. this.fontMenu.style.position = 'relative';
  330. this.fontMenu.style.whiteSpace = 'nowrap';
  331. this.fontMenu.style.overflow = 'hidden';
  332. this.fontMenu.style.width = (mxClient.IS_QUIRKS) ? '80px' : '60px';
  333. this.setFontName(Menus.prototype.defaultFont);
  334. if (EditorUi.compactUi)
  335. {
  336. this.fontMenu.style.paddingRight = '18px';
  337. this.fontMenu.getElementsByTagName('img')[0].style.right = '1px';
  338. this.fontMenu.getElementsByTagName('img')[0].style.top = '5px';
  339. }
  340. this.addSeparator();
  341. this.sizeMenu = this.addMenu(Menus.prototype.defaultFontSize, mxResources.get('fontSize'), true, 'fontSize');
  342. this.sizeMenu.style.position = 'relative';
  343. this.sizeMenu.style.whiteSpace = 'nowrap';
  344. this.sizeMenu.style.overflow = 'hidden';
  345. this.sizeMenu.style.width = (mxClient.IS_QUIRKS) ? '44px' : '24px';
  346. this.setFontSize(Menus.prototype.defaultFontSize);
  347. if (EditorUi.compactUi)
  348. {
  349. this.sizeMenu.style.paddingRight = '18px';
  350. this.sizeMenu.getElementsByTagName('img')[0].style.right = '1px';
  351. this.sizeMenu.getElementsByTagName('img')[0].style.top = '5px';
  352. }
  353. var elts = this.addItems(['-', 'undo', 'redo','-', 'bold', 'italic', 'underline']);
  354. elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
  355. elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');
  356. elts[4].setAttribute('title', mxResources.get('bold') + ' (' + this.editorUi.actions.get('bold').shortcut + ')');
  357. elts[5].setAttribute('title', mxResources.get('italic') + ' (' + this.editorUi.actions.get('italic').shortcut + ')');
  358. elts[6].setAttribute('title', mxResources.get('underline') + ' (' + this.editorUi.actions.get('underline').shortcut + ')');
  359. // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
  360. // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
  361. var alignMenu = this.addMenuFunction('', mxResources.get('align'), false, mxUtils.bind(this, function(menu)
  362. {
  363. elt = menu.addItem('', null, mxUtils.bind(this, function(evt)
  364. {
  365. graph.cellEditor.alignText(mxConstants.ALIGN_LEFT, evt);
  366. }), null, 'geIcon geSprite geSprite-left');
  367. elt.setAttribute('title', mxResources.get('left'));
  368. elt = menu.addItem('', null, mxUtils.bind(this, function(evt)
  369. {
  370. graph.cellEditor.alignText(mxConstants.ALIGN_CENTER, evt);
  371. }), null, 'geIcon geSprite geSprite-center');
  372. elt.setAttribute('title', mxResources.get('center'));
  373. elt = menu.addItem('', null, mxUtils.bind(this, function(evt)
  374. {
  375. graph.cellEditor.alignText(mxConstants.ALIGN_RIGHT, evt);
  376. }), null, 'geIcon geSprite geSprite-right');
  377. elt.setAttribute('title', mxResources.get('right'));
  378. elt = menu.addItem('', null, mxUtils.bind(this, function()
  379. {
  380. document.execCommand('justifyfull', false, null);
  381. }), null, 'geIcon geSprite geSprite-justifyfull');
  382. elt.setAttribute('title', mxResources.get('justifyfull'));
  383. elt = menu.addItem('', null, mxUtils.bind(this, function()
  384. {
  385. document.execCommand('insertorderedlist', false, null);
  386. }), null, 'geIcon geSprite geSprite-orderedlist');
  387. elt.setAttribute('title', mxResources.get('numberedList'));
  388. elt = menu.addItem('', null, mxUtils.bind(this, function()
  389. {
  390. document.execCommand('insertunorderedlist', false, null);
  391. }), null, 'geIcon geSprite geSprite-unorderedlist');
  392. elt.setAttribute('title', mxResources.get('bulletedList'));
  393. elt = menu.addItem('', null, mxUtils.bind(this, function()
  394. {
  395. document.execCommand('outdent', false, null);
  396. }), null, 'geIcon geSprite geSprite-outdent');
  397. elt.setAttribute('title', mxResources.get('decreaseIndent'));
  398. elt = menu.addItem('', null, mxUtils.bind(this, function()
  399. {
  400. document.execCommand('indent', false, null);
  401. }), null, 'geIcon geSprite geSprite-indent');
  402. elt.setAttribute('title', mxResources.get('increaseIndent'));
  403. }));
  404. alignMenu.style.position = 'relative';
  405. alignMenu.style.whiteSpace = 'nowrap';
  406. alignMenu.style.overflow = 'hidden';
  407. alignMenu.innerHTML = '<div class="geSprite geSprite-left" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  408. alignMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
  409. if (EditorUi.compactUi)
  410. {
  411. alignMenu.getElementsByTagName('img')[0].style.left = '22px';
  412. alignMenu.getElementsByTagName('img')[0].style.top = '5px';
  413. }
  414. var formatMenu = this.addMenuFunction('', mxResources.get('format'), false, mxUtils.bind(this, function(menu)
  415. {
  416. elt = menu.addItem('', null, this.editorUi.actions.get('subscript').funct,
  417. null, 'geIcon geSprite geSprite-subscript');
  418. elt.setAttribute('title', mxResources.get('subscript') + ' (' + Editor.ctrlKey + '+,)');
  419. elt = menu.addItem('', null, this.editorUi.actions.get('superscript').funct,
  420. null, 'geIcon geSprite geSprite-superscript');
  421. elt.setAttribute('title', mxResources.get('superscript') + ' (' + Editor.ctrlKey + '+.)');
  422. // KNOWN: IE+FF don't return keyboard focus after color dialog (calling focus doesn't help)
  423. elt = menu.addItem('', null, this.editorUi.actions.get('fontColor').funct,
  424. null, 'geIcon geSprite geSprite-fontcolor');
  425. elt.setAttribute('title', mxResources.get('fontColor'));
  426. elt = menu.addItem('', null, this.editorUi.actions.get('backgroundColor').funct,
  427. null, 'geIcon geSprite geSprite-fontbackground');
  428. elt.setAttribute('title', mxResources.get('backgroundColor'));
  429. elt = menu.addItem('', null, mxUtils.bind(this, function()
  430. {
  431. document.execCommand('removeformat', false, null);
  432. }), null, 'geIcon geSprite geSprite-removeformat');
  433. elt.setAttribute('title', mxResources.get('removeFormat'));
  434. }));
  435. formatMenu.style.position = 'relative';
  436. formatMenu.style.whiteSpace = 'nowrap';
  437. formatMenu.style.overflow = 'hidden';
  438. formatMenu.innerHTML = '<div class="geSprite geSprite-dots" style="margin-left:-2px;"></div>' +
  439. this.dropdownImageHtml;
  440. formatMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
  441. if (EditorUi.compactUi)
  442. {
  443. formatMenu.getElementsByTagName('img')[0].style.left = '22px';
  444. formatMenu.getElementsByTagName('img')[0].style.top = '5px';
  445. }
  446. this.addSeparator();
  447. this.addButton('geIcon geSprite geSprite-code', mxResources.get('html'), function()
  448. {
  449. graph.cellEditor.toggleViewMode();
  450. if (graph.cellEditor.textarea.innerHTML.length > 0 && (graph.cellEditor.textarea.innerHTML != '&nbsp;' || !graph.cellEditor.clearOnChange))
  451. {
  452. window.setTimeout(function()
  453. {
  454. document.execCommand('selectAll', false, null);
  455. });
  456. }
  457. });
  458. this.addSeparator();
  459. // FIXME: Uses geButton here and geLabel in main menu
  460. var insertMenu = this.addMenuFunction('', mxResources.get('insert'), true, mxUtils.bind(this, function(menu)
  461. {
  462. menu.addItem(mxResources.get('insertLink'), null, mxUtils.bind(this, function()
  463. {
  464. this.editorUi.actions.get('link').funct();
  465. }));
  466. menu.addItem(mxResources.get('insertImage'), null, mxUtils.bind(this, function()
  467. {
  468. this.editorUi.actions.get('image').funct();
  469. }));
  470. menu.addItem(mxResources.get('insertHorizontalRule'), null, mxUtils.bind(this, function()
  471. {
  472. document.execCommand('inserthorizontalrule', false, null);
  473. }));
  474. }));
  475. insertMenu.style.whiteSpace = 'nowrap';
  476. insertMenu.style.overflow = 'hidden';
  477. insertMenu.style.position = 'relative';
  478. insertMenu.innerHTML = '<div class="geSprite geSprite-plus" style="margin-left:-4px;margin-top:-3px;"></div>' +
  479. this.dropdownImageHtml;
  480. insertMenu.style.width = (mxClient.IS_QUIRKS) ? '36px' : '16px';
  481. // Fix for item size in kennedy theme
  482. if (EditorUi.compactUi)
  483. {
  484. insertMenu.getElementsByTagName('img')[0].style.left = '24px';
  485. insertMenu.getElementsByTagName('img')[0].style.top = '5px';
  486. insertMenu.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
  487. }
  488. this.addSeparator();
  489. // KNOWN: All table stuff does not work with undo/redo
  490. // KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
  491. // to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
  492. var elt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu)
  493. {
  494. var elt = graph.getSelectedElement();
  495. var cell = graph.getParentByNames(elt, ['TD', 'TH'], graph.cellEditor.text2);
  496. var row = graph.getParentByName(elt, 'TR', graph.cellEditor.text2);
  497. if (row == null)
  498. {
  499. function createTable(rows, cols)
  500. {
  501. var html = ['<table>'];
  502. for (var i = 0; i < rows; i++)
  503. {
  504. html.push('<tr>');
  505. for (var j = 0; j < cols; j++)
  506. {
  507. html.push('<td><br></td>');
  508. }
  509. html.push('</tr>');
  510. }
  511. html.push('</table>');
  512. return html.join('');
  513. };
  514. this.editorUi.menus.addInsertTableItem(menu);
  515. }
  516. else
  517. {
  518. var table = graph.getParentByName(row, 'TABLE', graph.cellEditor.text2);
  519. elt = menu.addItem('', null, mxUtils.bind(this, function()
  520. {
  521. try
  522. {
  523. graph.selectNode(graph.insertColumn(table, (cell != null) ? cell.cellIndex : 0));
  524. }
  525. catch (e)
  526. {
  527. this.editorUi.handleError(e);
  528. }
  529. }), null, 'geIcon geSprite geSprite-insertcolumnbefore');
  530. elt.setAttribute('title', mxResources.get('insertColumnBefore'));
  531. elt = menu.addItem('', null, mxUtils.bind(this, function()
  532. {
  533. try
  534. {
  535. graph.selectNode(graph.insertColumn(table, (cell != null) ? cell.cellIndex + 1 : -1));
  536. }
  537. catch (e)
  538. {
  539. this.editorUi.handleError(e);
  540. }
  541. }), null, 'geIcon geSprite geSprite-insertcolumnafter');
  542. elt.setAttribute('title', mxResources.get('insertColumnAfter'));
  543. elt = menu.addItem('Delete column', null, mxUtils.bind(this, function()
  544. {
  545. if (cell != null)
  546. {
  547. try
  548. {
  549. graph.deleteColumn(table, cell.cellIndex);
  550. }
  551. catch (e)
  552. {
  553. this.editorUi.handleError(e);
  554. }
  555. }
  556. }), null, 'geIcon geSprite geSprite-deletecolumn');
  557. elt.setAttribute('title', mxResources.get('deleteColumn'));
  558. elt = menu.addItem('', null, mxUtils.bind(this, function()
  559. {
  560. try
  561. {
  562. graph.selectNode(graph.insertRow(table, row.sectionRowIndex));
  563. }
  564. catch (e)
  565. {
  566. this.editorUi.handleError(e);
  567. }
  568. }), null, 'geIcon geSprite geSprite-insertrowbefore');
  569. elt.setAttribute('title', mxResources.get('insertRowBefore'));
  570. elt = menu.addItem('', null, mxUtils.bind(this, function()
  571. {
  572. try
  573. {
  574. graph.selectNode(graph.insertRow(table, row.sectionRowIndex + 1));
  575. }
  576. catch (e)
  577. {
  578. this.editorUi.handleError(e);
  579. }
  580. }), null, 'geIcon geSprite geSprite-insertrowafter');
  581. elt.setAttribute('title', mxResources.get('insertRowAfter'));
  582. elt = menu.addItem('', null, mxUtils.bind(this, function()
  583. {
  584. try
  585. {
  586. graph.deleteRow(table, row.sectionRowIndex);
  587. }
  588. catch (e)
  589. {
  590. this.editorUi.handleError(e);
  591. }
  592. }), null, 'geIcon geSprite geSprite-deleterow');
  593. elt.setAttribute('title', mxResources.get('deleteRow'));
  594. elt = menu.addItem('', null, mxUtils.bind(this, function()
  595. {
  596. // Converts rgb(r,g,b) values
  597. var color = table.style.borderColor.replace(
  598. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  599. function($0, $1, $2, $3) {
  600. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  601. });
  602. this.editorUi.pickColor(color, function(newColor)
  603. {
  604. if (newColor == null || newColor == mxConstants.NONE)
  605. {
  606. table.removeAttribute('border');
  607. table.style.border = '';
  608. table.style.borderCollapse = '';
  609. }
  610. else
  611. {
  612. table.setAttribute('border', '1');
  613. table.style.border = '1px solid ' + newColor;
  614. table.style.borderCollapse = 'collapse';
  615. }
  616. });
  617. }), null, 'geIcon geSprite geSprite-strokecolor');
  618. elt.setAttribute('title', mxResources.get('borderColor'));
  619. elt = menu.addItem('', null, mxUtils.bind(this, function()
  620. {
  621. // Converts rgb(r,g,b) values
  622. var color = table.style.backgroundColor.replace(
  623. /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  624. function($0, $1, $2, $3) {
  625. return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2);
  626. });
  627. this.editorUi.pickColor(color, function(newColor)
  628. {
  629. if (newColor == null || newColor == mxConstants.NONE)
  630. {
  631. table.style.backgroundColor = '';
  632. }
  633. else
  634. {
  635. table.style.backgroundColor = newColor;
  636. }
  637. });
  638. }), null, 'geIcon geSprite geSprite-fillcolor');
  639. elt.setAttribute('title', mxResources.get('backgroundColor'));
  640. elt = menu.addItem('', null, mxUtils.bind(this, function()
  641. {
  642. var value = table.getAttribute('cellPadding') || 0;
  643. var dlg = new FilenameDialog(this.editorUi, value, mxResources.get('apply'), mxUtils.bind(this, function(newValue)
  644. {
  645. if (newValue != null && newValue.length > 0)
  646. {
  647. table.setAttribute('cellPadding', newValue);
  648. }
  649. else
  650. {
  651. table.removeAttribute('cellPadding');
  652. }
  653. }), mxResources.get('spacing'));
  654. this.editorUi.showDialog(dlg.container, 300, 80, true, true);
  655. dlg.init();
  656. }), null, 'geIcon geSprite geSprite-fit');
  657. elt.setAttribute('title', mxResources.get('spacing'));
  658. elt = menu.addItem('', null, mxUtils.bind(this, function()
  659. {
  660. table.setAttribute('align', 'left');
  661. }), null, 'geIcon geSprite geSprite-left');
  662. elt.setAttribute('title', mxResources.get('left'));
  663. elt = menu.addItem('', null, mxUtils.bind(this, function()
  664. {
  665. table.setAttribute('align', 'center');
  666. }), null, 'geIcon geSprite geSprite-center');
  667. elt.setAttribute('title', mxResources.get('center'));
  668. elt = menu.addItem('', null, mxUtils.bind(this, function()
  669. {
  670. table.setAttribute('align', 'right');
  671. }), null, 'geIcon geSprite geSprite-right');
  672. elt.setAttribute('title', mxResources.get('right'));
  673. }
  674. }));
  675. elt.style.position = 'relative';
  676. elt.style.whiteSpace = 'nowrap';
  677. elt.style.overflow = 'hidden';
  678. elt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
  679. elt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
  680. // Fix for item size in kennedy theme
  681. if (EditorUi.compactUi)
  682. {
  683. elt.getElementsByTagName('img')[0].style.left = '22px';
  684. elt.getElementsByTagName('img')[0].style.top = '5px';
  685. }
  686. };
  687. /**
  688. * Hides the current menu.
  689. */
  690. Toolbar.prototype.hideMenu = function()
  691. {
  692. this.editorUi.hideCurrentMenu();
  693. };
  694. /**
  695. * Adds a label to the toolbar.
  696. */
  697. Toolbar.prototype.addMenu = function(label, tooltip, showLabels, name, c, showAll, ignoreState)
  698. {
  699. var menu = this.editorUi.menus.get(name);
  700. var elt = this.addMenuFunction(label, tooltip, showLabels, function()
  701. {
  702. menu.funct.apply(menu, arguments);
  703. }, c, showAll);
  704. if (!ignoreState)
  705. {
  706. menu.addListener('stateChanged', function()
  707. {
  708. elt.setEnabled(menu.enabled);
  709. });
  710. }
  711. return elt;
  712. };
  713. /**
  714. * Adds a label to the toolbar.
  715. */
  716. Toolbar.prototype.addMenuFunction = function(label, tooltip, showLabels, funct, c, showAll)
  717. {
  718. return this.addMenuFunctionInContainer((c != null) ? c : this.container, label, tooltip, showLabels, funct, showAll);
  719. };
  720. /**
  721. * Adds a label to the toolbar.
  722. */
  723. Toolbar.prototype.addMenuFunctionInContainer = function(container, label, tooltip, showLabels, funct, showAll)
  724. {
  725. var elt = (showLabels) ? this.createLabel(label) : this.createButton(label);
  726. this.initElement(elt, tooltip);
  727. this.addMenuHandler(elt, showLabels, funct, showAll);
  728. container.appendChild(elt);
  729. return elt;
  730. };
  731. /**
  732. * Adds a separator to the separator.
  733. */
  734. Toolbar.prototype.addSeparator = function(c)
  735. {
  736. c = (c != null) ? c : this.container;
  737. var elt = document.createElement('div');
  738. elt.className = 'geSeparator';
  739. c.appendChild(elt);
  740. return elt;
  741. };
  742. /**
  743. * Adds given action item
  744. */
  745. Toolbar.prototype.addItems = function(keys, c, ignoreDisabled)
  746. {
  747. var items = [];
  748. for (var i = 0; i < keys.length; i++)
  749. {
  750. var key = keys[i];
  751. if (key == '-')
  752. {
  753. items.push(this.addSeparator(c));
  754. }
  755. else
  756. {
  757. items.push(this.addItem('geSprite-' + key.toLowerCase(), key, c, ignoreDisabled));
  758. }
  759. }
  760. return items;
  761. };
  762. /**
  763. * Adds given action item
  764. */
  765. Toolbar.prototype.addItem = function(sprite, key, c, ignoreDisabled)
  766. {
  767. var action = this.editorUi.actions.get(key);
  768. var elt = null;
  769. if (action != null)
  770. {
  771. var tooltip = action.label;
  772. if (action.shortcut != null)
  773. {
  774. tooltip += ' (' + action.shortcut + ')';
  775. }
  776. elt = this.addButton(sprite, tooltip, action.funct, c);
  777. if (!ignoreDisabled)
  778. {
  779. elt.setEnabled(action.enabled);
  780. action.addListener('stateChanged', function()
  781. {
  782. elt.setEnabled(action.enabled);
  783. });
  784. }
  785. }
  786. return elt;
  787. };
  788. /**
  789. * Adds a button to the toolbar.
  790. */
  791. Toolbar.prototype.addButton = function(classname, tooltip, funct, c)
  792. {
  793. var elt = this.createButton(classname);
  794. c = (c != null) ? c : this.container;
  795. this.initElement(elt, tooltip);
  796. this.addClickHandler(elt, funct);
  797. c.appendChild(elt);
  798. return elt;
  799. };
  800. /**
  801. * Initializes the given toolbar element.
  802. */
  803. Toolbar.prototype.initElement = function(elt, tooltip)
  804. {
  805. // Adds tooltip
  806. if (tooltip != null)
  807. {
  808. elt.setAttribute('title', tooltip);
  809. }
  810. this.addEnabledState(elt);
  811. };
  812. /**
  813. * Adds enabled state with setter to DOM node (avoids JS wrapper).
  814. */
  815. Toolbar.prototype.addEnabledState = function(elt)
  816. {
  817. var classname = elt.className;
  818. elt.setEnabled = function(value)
  819. {
  820. elt.enabled = value;
  821. if (value)
  822. {
  823. elt.className = classname;
  824. }
  825. else
  826. {
  827. elt.className = classname + ' mxDisabled';
  828. }
  829. };
  830. elt.setEnabled(true);
  831. };
  832. /**
  833. * Adds enabled state with setter to DOM node (avoids JS wrapper).
  834. */
  835. Toolbar.prototype.addClickHandler = function(elt, funct)
  836. {
  837. if (funct != null)
  838. {
  839. mxEvent.addListener(elt, 'click', function(evt)
  840. {
  841. if (elt.enabled)
  842. {
  843. funct(evt);
  844. }
  845. mxEvent.consume(evt);
  846. });
  847. // Prevents focus
  848. mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
  849. mxUtils.bind(this, function(evt)
  850. {
  851. evt.preventDefault();
  852. }));
  853. }
  854. };
  855. /**
  856. * Creates and returns a new button.
  857. */
  858. Toolbar.prototype.createButton = function(classname)
  859. {
  860. var elt = document.createElement('a');
  861. elt.className = 'geButton';
  862. var inner = document.createElement('div');
  863. if (classname != null)
  864. {
  865. inner.className = 'geSprite ' + classname;
  866. }
  867. elt.appendChild(inner);
  868. return elt;
  869. };
  870. /**
  871. * Creates and returns a new button.
  872. */
  873. Toolbar.prototype.createLabel = function(label, tooltip)
  874. {
  875. var elt = document.createElement('a');
  876. elt.className = 'geLabel';
  877. mxUtils.write(elt, label);
  878. return elt;
  879. };
  880. /**
  881. * Adds a handler for showing a menu in the given element.
  882. */
  883. Toolbar.prototype.addMenuHandler = function(elt, showLabels, funct, showAll)
  884. {
  885. if (funct != null)
  886. {
  887. var graph = this.editorUi.editor.graph;
  888. var menu = null;
  889. var show = true;
  890. mxEvent.addListener(elt, 'click', mxUtils.bind(this, function(evt)
  891. {
  892. if (show && (elt.enabled == null || elt.enabled))
  893. {
  894. graph.popupMenuHandler.hideMenu();
  895. menu = new mxPopupMenu(funct);
  896. menu.div.className += ' geToolbarMenu';
  897. menu.showDisabled = showAll;
  898. menu.labels = showLabels;
  899. menu.autoExpand = true;
  900. var offset = mxUtils.getOffset(elt);
  901. menu.popup(offset.x, offset.y + elt.offsetHeight, null, evt);
  902. this.editorUi.setCurrentMenu(menu, elt);
  903. // Workaround for scrollbar hiding menu items
  904. if (!showLabels && menu.div.scrollHeight > menu.div.clientHeight)
  905. {
  906. menu.div.style.width = '40px';
  907. }
  908. menu.hideMenu = mxUtils.bind(this, function()
  909. {
  910. mxPopupMenu.prototype.hideMenu.apply(menu, arguments);
  911. this.editorUi.resetCurrentMenu();
  912. menu.destroy();
  913. });
  914. // Extends destroy to reset global state
  915. menu.addListener(mxEvent.EVENT_HIDE, mxUtils.bind(this, function()
  916. {
  917. this.currentElt = null;
  918. }));
  919. }
  920. show = true;
  921. mxEvent.consume(evt);
  922. }));
  923. // Hides menu if already showing and prevents focus
  924. mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
  925. mxUtils.bind(this, function(evt)
  926. {
  927. show = this.currentElt != elt;
  928. evt.preventDefault();
  929. }));
  930. }
  931. };
  932. /**
  933. * Adds a handler for showing a menu in the given element.
  934. */
  935. Toolbar.prototype.destroy = function()
  936. {
  937. if (this.gestureHandler != null)
  938. {
  939. mxEvent.removeGestureListeners(document, this.gestureHandler);
  940. this.gestureHandler = null;
  941. }
  942. };