mxRuler.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /**
  2. * Copyright (c) 2017, CTI LOGIC
  3. * Copyright (c) 2006-2017, JGraph Ltd
  4. * Copyright (c) 2006-2017, Gaudenz Alder
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  9. *
  10. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  11. *
  12. * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  15. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  16. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  17. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  18. */
  19. function mxRuler(editorUi, unit, isVertical, isSecondery)
  20. {
  21. var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
  22. window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  23. var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
  24. var RULER_THICKNESS = this.RULER_THICKNESS;
  25. var ruler = this;
  26. this.unit = unit;
  27. var style = (!Editor.isDarkMode()) ? {
  28. bkgClr: '#ffffff',
  29. outBkgClr: '#e8e9ed',
  30. cornerClr: '#fbfbfb',
  31. strokeClr: '#dadce0',
  32. fontClr: '#BBBBBB',
  33. guideClr: '#0000BB'
  34. } : {
  35. bkgClr: '#202020',
  36. outBkgClr: Editor.darkColor,
  37. cornerClr: Editor.darkColor,
  38. strokeClr: '#505759',
  39. fontClr: '#BBBBBB',
  40. guideClr: '#0088cf'
  41. };
  42. //create the container
  43. var container = document.createElement('div');
  44. container.className = 'geRuler';
  45. container.style.position = 'fixed';
  46. function resizeRulerContainer()
  47. {
  48. var diagCont = editorUi.diagramContainer;
  49. container.style.top = (diagCont.offsetTop - RULER_THICKNESS) + 'px';
  50. container.style.left = (diagCont.offsetLeft - RULER_THICKNESS) + 'px';
  51. container.style.width = ((isVertical? 0 : diagCont.offsetWidth) + RULER_THICKNESS) + 'px';
  52. container.style.height = ((isVertical? diagCont.offsetHeight : 0) + RULER_THICKNESS) + 'px';
  53. };
  54. // Hook for dark mode changes
  55. this.updateStyle = mxUtils.bind(this, function()
  56. {
  57. style = (!Editor.isDarkMode()) ? {
  58. outBkgClr: '#e8e9ed',
  59. cornerClr: '#fbfbfb',
  60. strokeClr: '#dadce0',
  61. fontClr: '#BBBBBB',
  62. guideClr: '#0000BB'
  63. } : {
  64. outBkgClr: Editor.darkColor,
  65. cornerClr: Editor.darkColor,
  66. strokeClr: '#505759',
  67. fontClr: '#BBBBBB',
  68. guideClr: '#0088cf'
  69. };
  70. container.style[isVertical? 'borderRight' : 'borderBottom'] = '0.5px solid ' + style.strokeClr;
  71. container.style.borderLeft = '0.5px solid ' + style.strokeClr;
  72. });
  73. this.updateStyle();
  74. editorUi.diagramContainer.appendChild(container);
  75. mxEvent.disableContextMenu(container);
  76. this.editorUiRefresh = editorUi.refresh;
  77. editorUi.refresh = function(minor)
  78. {
  79. ruler.editorUiRefresh.apply(editorUi, arguments);
  80. resizeRulerContainer();
  81. };
  82. resizeRulerContainer();
  83. var canvas = document.createElement('canvas');
  84. //initial sizing which is corrected by the graph size event
  85. canvas.width = container.offsetWidth;
  86. canvas.height = container.offsetHeight;
  87. container.style.overflow = 'hidden';
  88. canvas.style.position = 'relative';
  89. container.appendChild(canvas);
  90. //Disable alpha to improve performance as we don't need it?
  91. var ctx = canvas.getContext('2d');
  92. this.ui = editorUi;
  93. var graph = editorUi.editor.graph;
  94. this.graph = graph;
  95. this.container = container;
  96. this.canvas = canvas;
  97. var drawLine = function (x1, y1, x2, y2, text)
  98. {
  99. //remove all fractions
  100. x1 = Math.round(x1); y1 = Math.round(y1); x2 = Math.round(x2); y2 = Math.round(y2);
  101. //adding the 0.5 is necessary to prevent anti-aliasing from making lines thicker!
  102. ctx.beginPath();
  103. ctx.moveTo(x1 + 0.5, y1 + 0.5);
  104. ctx.lineTo(x2 + 0.5, y2 + 0.5);
  105. ctx.stroke();
  106. if (text)
  107. {
  108. if (isVertical)
  109. {
  110. ctx.save();
  111. ctx.translate(x1, y1);
  112. ctx.rotate(-Math.PI / 2);
  113. ctx.fillText(text, 0, 0);
  114. ctx.restore();
  115. }
  116. else
  117. {
  118. ctx.fillText(text, x1, y1);
  119. }
  120. }
  121. };
  122. var drawRuler = function()
  123. {
  124. ctx.clearRect(0, 0, canvas.width, canvas.height);
  125. ctx.beginPath();
  126. ctx.lineWidth = 0.7;
  127. ctx.strokeStyle = style.strokeClr;
  128. ctx.setLineDash([]);
  129. ctx.font = '9px Arial';
  130. ctx.textAlign = 'center';
  131. var scale = graph.view.scale;
  132. var bgPages = graph.view.getBackgroundPageBounds();
  133. var t = graph.view.translate;
  134. var hasPageView = graph.pageVisible;
  135. //The beginning of the ruler (zero)
  136. var rStart = hasPageView? RULER_THICKNESS + (isVertical? bgPages.y - graph.container.scrollTop : bgPages.x - graph.container.scrollLeft)
  137. : RULER_THICKNESS + (isVertical? t.y * scale - graph.container.scrollTop : t.x * scale - graph.container.scrollLeft);
  138. //handle negative pages
  139. var pageShift = 0;
  140. if (hasPageView)
  141. {
  142. var layout = graph.getPageLayout();
  143. if (isVertical)
  144. {
  145. pageShift = layout.y * graph.pageFormat.height;
  146. }
  147. else
  148. {
  149. pageShift = layout.x * graph.pageFormat.width;
  150. }
  151. }
  152. var tickStep, tickSize, len;
  153. switch(ruler.unit)
  154. {
  155. case mxConstants.POINTS:
  156. len = 10;
  157. tickStep = 10;
  158. tickSize = [3,5,5,5,5,10,5,5,5,5];
  159. break;
  160. case mxConstants.MILLIMETERS:
  161. len = 10;
  162. tickStep = mxConstants.PIXELS_PER_MM;
  163. tickSize = [5,3,3,3,3,6,3,3,3,3];
  164. break;
  165. case mxConstants.METERS:
  166. len = 20;
  167. tickStep = mxConstants.PIXELS_PER_MM;
  168. tickSize = [5,3,3,3,3,6,3,3,3,3,10,3,3,3,3,6,3,3,3,3];
  169. break;
  170. case mxConstants.INCHES:
  171. if (scale <=0.5 || scale >=4)
  172. len = 8;
  173. else
  174. len = 16;
  175. tickStep = mxConstants.PIXELS_PER_INCH / len;
  176. tickSize = [5,3,5,3,7,3,5,3,7,3,5,3,7,3,5,3];
  177. break;
  178. }
  179. //Handle step size and change it with large/small scale
  180. var step = tickStep;
  181. if (scale >= 2)
  182. {
  183. step = tickStep / (Math.floor(scale / 2) * 2);
  184. }
  185. else if (scale <= 0.5)
  186. {
  187. step = tickStep * (Math.floor((1 / scale) / 2) * (ruler.unit == mxConstants.MILLIMETERS? 2 : 1));
  188. }
  189. var lastTick = null;
  190. //End of the ruler (pages end)
  191. var rEnd = hasPageView? Math.min(rStart + (isVertical? bgPages.height: bgPages.width), isVertical? canvas.height : canvas.width) : (isVertical? canvas.height : canvas.width);
  192. if (hasPageView)
  193. {
  194. //Clear the outside page part with a different color
  195. ctx.fillStyle = style.outBkgClr;
  196. if (isVertical)
  197. {
  198. var oh = rStart - RULER_THICKNESS;
  199. if (oh > 0)
  200. {
  201. ctx.fillRect(0, RULER_THICKNESS, RULER_THICKNESS, oh);
  202. }
  203. if (rEnd < canvas.height)
  204. {
  205. ctx.fillRect(0, rEnd, RULER_THICKNESS, canvas.height);
  206. }
  207. }
  208. else
  209. {
  210. var ow = rStart - RULER_THICKNESS;
  211. if (ow > 0)
  212. {
  213. ctx.fillRect(RULER_THICKNESS, 0, ow, RULER_THICKNESS);
  214. }
  215. if (rEnd < canvas.width)
  216. {
  217. ctx.fillRect(rEnd, 0, canvas.width, RULER_THICKNESS);
  218. }
  219. }
  220. }
  221. //Draw ticks
  222. ctx.fillStyle = style.fontClr;
  223. for (var i = hasPageView? rStart : rStart % (step * scale); i <= rEnd; i += step * scale)
  224. {
  225. var current = Math.round((i - rStart) / scale / step);
  226. if (i < RULER_THICKNESS || current == lastTick) //Prevent wasting time in drawing non-visible/duplicate lines
  227. {
  228. continue;
  229. }
  230. lastTick = current;
  231. var text = null;
  232. if (current % len == 0)
  233. {
  234. text = ruler.formatText(pageShift + current * step) + '';
  235. }
  236. if (isVertical)
  237. {
  238. drawLine(RULER_THICKNESS - tickSize[Math.abs(current) % len], i, RULER_THICKNESS, i, text);
  239. }
  240. else
  241. {
  242. drawLine(i, RULER_THICKNESS - tickSize[Math.abs(current) % len], i, RULER_THICKNESS, text);
  243. }
  244. }
  245. //Draw corner rect
  246. ctx.lineWidth = 1;
  247. drawLine(isVertical? 0 : RULER_THICKNESS, isVertical? RULER_THICKNESS : 0, RULER_THICKNESS, RULER_THICKNESS);
  248. ctx.fillStyle = style.cornerClr;
  249. ctx.fillRect(0, 0, RULER_THICKNESS, RULER_THICKNESS);
  250. };
  251. var animationId = -1;
  252. var listenersDrawRuler = function()
  253. {
  254. if (requestAnimationFrame != null)
  255. {
  256. if (cancelAnimationFrame != null)
  257. {
  258. cancelAnimationFrame(animationId);
  259. }
  260. animationId = requestAnimationFrame(drawRuler);
  261. }
  262. else
  263. {
  264. drawRuler();
  265. }
  266. };
  267. var sizeListener = function()
  268. {
  269. var div = graph.container;
  270. if (isVertical)
  271. {
  272. var newH = div.offsetHeight + RULER_THICKNESS;
  273. if (canvas.height != newH)
  274. {
  275. canvas.height = newH;
  276. container.style.height = newH + 'px';
  277. listenersDrawRuler();
  278. }
  279. }
  280. else
  281. {
  282. var newW = div.offsetWidth + RULER_THICKNESS;
  283. if (canvas.width != newW)
  284. {
  285. canvas.width = newW;
  286. container.style.width = newW + 'px';
  287. listenersDrawRuler();
  288. }
  289. }
  290. };
  291. this.drawRuler = listenersDrawRuler;
  292. var efficientSizeListener = debounce(sizeListener, 10);
  293. this.sizeListener = efficientSizeListener;
  294. this.pageListener = function()
  295. {
  296. listenersDrawRuler();
  297. };
  298. var efficientScrollListener = debounce(function()
  299. {
  300. var newScroll = isVertical? graph.container.scrollTop : graph.container.scrollLeft;
  301. if (ruler.lastScroll != newScroll)
  302. {
  303. ruler.lastScroll = newScroll;
  304. listenersDrawRuler();
  305. }
  306. }, 10);
  307. this.scrollListener = efficientScrollListener;
  308. this.unitListener = function(sender, evt)
  309. {
  310. ruler.setUnit(evt.getProperty('unit'));
  311. };
  312. graph.addListener(mxEvent.SIZE, efficientSizeListener);
  313. graph.container.addEventListener('scroll', efficientScrollListener);
  314. graph.view.addListener('unitChanged', this.unitListener);
  315. editorUi.addListener('pageViewChanged', this.pageListener);
  316. editorUi.addListener('pageScaleChanged', this.pageListener);
  317. editorUi.addListener('pageFormatChanged', this.pageListener);
  318. function debounce(func, wait, immediate)
  319. {
  320. if (requestAnimationFrame != null)
  321. {
  322. return func;
  323. }
  324. var timeout;
  325. return function() {
  326. var context = this, args = arguments;
  327. var later = function() {
  328. timeout = null;
  329. if (!immediate) func.apply(context, args);
  330. };
  331. var callNow = immediate && !timeout;
  332. clearTimeout(timeout);
  333. timeout = setTimeout(later, wait);
  334. if (callNow) func.apply(context, args);
  335. };
  336. };
  337. this.setStyle = function(newStyle)
  338. {
  339. style = newStyle;
  340. container.style.background = style.bkgClr;
  341. drawRuler();
  342. }
  343. // Showing guides on cell move
  344. this.origGuideMove = mxGuide.prototype.move;
  345. mxGuide.prototype.move = function (bounds, delta, gridEnabled, clone)
  346. {
  347. var ret = null;
  348. // LATER: Fix repaint for width and height < 5
  349. if ((isVertical && bounds.height > 4) || (!isVertical && bounds.width > 4))
  350. {
  351. if (ruler.guidePart != null)
  352. {
  353. try
  354. {
  355. ctx.putImageData(ruler.guidePart.imgData1, ruler.guidePart.x1, ruler.guidePart.y1);
  356. ctx.putImageData(ruler.guidePart.imgData2, ruler.guidePart.x2, ruler.guidePart.y2);
  357. ctx.putImageData(ruler.guidePart.imgData3, ruler.guidePart.x3, ruler.guidePart.y3);
  358. }
  359. catch (e)
  360. {
  361. // ignore
  362. }
  363. }
  364. ret = ruler.origGuideMove.apply(this, arguments);
  365. try
  366. {
  367. var x1, y1, imgData1, x2, y2, imgData2, x3, y3, imgData3;
  368. ctx.lineWidth = 0.5;
  369. ctx.strokeStyle = style.guideClr;
  370. ctx.setLineDash([2]);
  371. if (isVertical)
  372. {
  373. y1 = bounds.y + ret.y + RULER_THICKNESS - this.graph.container.scrollTop;
  374. x1 = 0;
  375. y2 = y1 + bounds.height / 2;
  376. x2 = RULER_THICKNESS / 2;
  377. y3 = y1 + bounds.height;
  378. x3 = 0;
  379. imgData1 = ctx.getImageData(x1, y1 - 1, RULER_THICKNESS, 3);
  380. drawLine(x1, y1, RULER_THICKNESS, y1);
  381. y1--;
  382. imgData2 = ctx.getImageData(x2, y2 - 1, RULER_THICKNESS, 3);
  383. drawLine(x2, y2, RULER_THICKNESS, y2);
  384. y2--;
  385. imgData3 = ctx.getImageData(x3, y3 - 1, RULER_THICKNESS, 3);
  386. drawLine(x3, y3, RULER_THICKNESS, y3);
  387. y3--;
  388. }
  389. else
  390. {
  391. y1 = 0;
  392. x1 = bounds.x + ret.x + RULER_THICKNESS - this.graph.container.scrollLeft;
  393. y2 = RULER_THICKNESS / 2;
  394. x2 = x1 + bounds.width / 2;
  395. y3 = 0;
  396. x3 = x1 + bounds.width;
  397. imgData1 = ctx.getImageData(x1 - 1, y1, 3, RULER_THICKNESS);
  398. drawLine(x1, y1, x1, RULER_THICKNESS);
  399. x1--;
  400. imgData2 = ctx.getImageData(x2 - 1, y2, 3, RULER_THICKNESS);
  401. drawLine(x2, y2, x2, RULER_THICKNESS);
  402. x2--;
  403. imgData3 = ctx.getImageData(x3 - 1, y3, 3, RULER_THICKNESS);
  404. drawLine(x3, y3, x3, RULER_THICKNESS);
  405. x3--;
  406. }
  407. if (ruler.guidePart == null || ruler.guidePart.x1 != x1 || ruler.guidePart.y1 != y1)
  408. {
  409. ruler.guidePart = {
  410. imgData1: imgData1,
  411. x1: x1,
  412. y1: y1,
  413. imgData2: imgData2,
  414. x2: x2,
  415. y2: y2,
  416. imgData3: imgData3,
  417. x3: x3,
  418. y3: y3
  419. }
  420. }
  421. }
  422. catch (e)
  423. {
  424. // ignore
  425. }
  426. }
  427. else
  428. {
  429. ret = ruler.origGuideMove.apply(this, arguments);
  430. }
  431. return ret;
  432. }
  433. this.origGuideDestroy = mxGuide.prototype.destroy;
  434. mxGuide.prototype.destroy = function()
  435. {
  436. var ret = ruler.origGuideDestroy.apply(this, arguments);
  437. if (ruler.guidePart != null)
  438. {
  439. try
  440. {
  441. ctx.putImageData(ruler.guidePart.imgData1, ruler.guidePart.x1, ruler.guidePart.y1);
  442. ctx.putImageData(ruler.guidePart.imgData2, ruler.guidePart.x2, ruler.guidePart.y2);
  443. ctx.putImageData(ruler.guidePart.imgData3, ruler.guidePart.x3, ruler.guidePart.y3);
  444. ruler.guidePart = null;
  445. }
  446. catch (e)
  447. {
  448. // ignore
  449. }
  450. }
  451. return ret;
  452. };
  453. };
  454. mxRuler.prototype.RULER_THICKNESS = 14;
  455. mxRuler.prototype.unit = mxConstants.POINTS;
  456. mxRuler.prototype.setUnit = function(unit)
  457. {
  458. this.unit = unit;
  459. this.drawRuler();
  460. };
  461. mxRuler.prototype.formatText = function(pixels)
  462. {
  463. switch(this.unit)
  464. {
  465. case mxConstants.POINTS:
  466. return Math.round(pixels);
  467. case mxConstants.MILLIMETERS:
  468. return (pixels / mxConstants.PIXELS_PER_MM).toFixed(1);
  469. case mxConstants.METERS:
  470. return (pixels / (mxConstants.PIXELS_PER_MM * 1000)).toFixed(4);
  471. case mxConstants.INCHES:
  472. return (pixels / mxConstants.PIXELS_PER_INCH).toFixed(2);
  473. }
  474. };
  475. mxRuler.prototype.destroy = function()
  476. {
  477. this.ui.refresh = this.editorUiRefresh;
  478. mxGuide.prototype.move = this.origGuideMove;
  479. mxGuide.prototype.destroy = this.origGuideDestroy;
  480. this.graph.removeListener(this.sizeListener);
  481. this.graph.container.removeEventListener('scroll', this.scrollListener);
  482. this.graph.view.removeListener(this.unitListener);
  483. this.ui.removeListener(this.pageListener);
  484. if (this.container != null)
  485. {
  486. this.container.parentNode.removeChild(this.container);
  487. }
  488. };
  489. function mxDualRuler(editorUi, unit)
  490. {
  491. var rulerOffset = new mxPoint(mxRuler.prototype.RULER_THICKNESS, mxRuler.prototype.RULER_THICKNESS);
  492. this.editorUiGetDiagContOffset = editorUi.getDiagramContainerOffset;
  493. editorUi.getDiagramContainerOffset = function()
  494. {
  495. return rulerOffset;
  496. };
  497. this.editorUiRefresh = editorUi.refresh;
  498. this.ui = editorUi;
  499. this.origGuideMove = mxGuide.prototype.move;
  500. this.origGuideDestroy = mxGuide.prototype.destroy;
  501. this.vRuler = new mxRuler(editorUi, unit, true);
  502. this.hRuler = new mxRuler(editorUi, unit, false, true);
  503. // Adds units context menu
  504. var installMenu = mxUtils.bind(this, function(node)
  505. {
  506. var menuWasVisible = false;
  507. mxEvent.addGestureListeners(node, mxUtils.bind(this, function(evt)
  508. {
  509. menuWasVisible = editorUi.currentMenu != null;
  510. mxEvent.consume(evt);
  511. }), null, mxUtils.bind(this, function(evt)
  512. {
  513. if (editorUi.editor.graph.isEnabled() && !editorUi.editor.graph.isMouseDown &&
  514. (mxEvent.isTouchEvent(evt) || mxEvent.isPopupTrigger(evt)))
  515. {
  516. editorUi.editor.graph.popupMenuHandler.hideMenu();
  517. editorUi.hideCurrentMenu();
  518. if (!mxEvent.isTouchEvent(evt) || !menuWasVisible)
  519. {
  520. var menu = new mxPopupMenu(mxUtils.bind(this, function(menu, parent)
  521. {
  522. editorUi.menus.addMenuItems(menu, ['points', 'inches', 'millimeters', 'meters'], parent);
  523. }));
  524. menu.div.className += ' geMenubarMenu';
  525. menu.smartSeparators = true;
  526. menu.showDisabled = true;
  527. menu.autoExpand = true;
  528. // Disables autoexpand and destroys menu when hidden
  529. menu.hideMenu = mxUtils.bind(this, function()
  530. {
  531. mxPopupMenu.prototype.hideMenu.apply(menu, arguments);
  532. editorUi.resetCurrentMenu();
  533. menu.destroy();
  534. });
  535. var x = mxEvent.getClientX(evt);
  536. var y = mxEvent.getClientY(evt);
  537. menu.popup(x, y, null, evt);
  538. editorUi.setCurrentMenu(menu, node);
  539. }
  540. mxEvent.consume(evt);
  541. }
  542. }));
  543. });
  544. installMenu(this.hRuler.container);
  545. installMenu(this.vRuler.container);
  546. this.vRuler.drawRuler();
  547. this.hRuler.drawRuler();
  548. };
  549. mxDualRuler.prototype.updateStyle = function()
  550. {
  551. this.vRuler.updateStyle();
  552. this.hRuler.updateStyle();
  553. this.vRuler.drawRuler();
  554. this.hRuler.drawRuler();
  555. };
  556. mxDualRuler.prototype.setUnit = function(unit)
  557. {
  558. this.vRuler.setUnit(unit);
  559. this.hRuler.setUnit(unit);
  560. };
  561. mxDualRuler.prototype.setStyle = function(newStyle)
  562. {
  563. this.vRuler.setStyle(newStyle);
  564. this.hRuler.setStyle(newStyle);
  565. }
  566. mxDualRuler.prototype.destroy = function()
  567. {
  568. this.vRuler.destroy();
  569. this.hRuler.destroy();
  570. this.ui.refresh = this.editorUiRefresh;
  571. mxGuide.prototype.move = this.origGuideMove;
  572. mxGuide.prototype.destroy = this.origGuideDestroy;
  573. this.ui.getDiagramContainerOffset = this.editorUiGetDiagContOffset;
  574. };