想想好像好久没用写博客了! 由于最近想跳槽了(ps:尽管公司挽留,提出一些异与往常的挽留“制度”,But确实已经死心了) ,发现前一段时间一些做Hadoop,和Spark同事时常来请教网络拓扑图的有关问题,由于当时确实比较忙,没时间帮着一起分析,表示歉意!
先前整理过份简单的Demo 但是不详细 基于Web实现在线绘画拓扑图[GraphEditor]
首先呢这里是要详述的几个要点:(我用图是直接显示了~) (当然这套UI模块是后期改动的~重点不在这里) [备案:后续使用文档]
显示拓扑图

其次呢是一些后期加上去的代码,我想既然用了网络拓扑图,后期的可塑性应该是很强的,部分都是后续需求加上去的!
言归正传,看完一些简单的流程图,我想都大概知道他的基本用途,和后期的塑造价值
一些简单的用途比如:做大数据Hadoop,Spark是的个个服务器之间的关系,以及关系流程图的描述; 大型企业的负载集群管理的关系以及流程图,安全管理,OA企业人士管理.....多事不可缺少的素材!
主要JQ代码模块:
上面的一些常量是一些属性!
用于绑定一些菜单信息
编辑保存
(主要文件:mxClient.js , Editor.js ,Graph.js,Shapes.js,EditorUi.js,Actions.js,Menus.js,Sidebar.js, Toolbar.js,Dialogs.js,jscolor.js )
核心文件代码如下:
EditorUi.js
1 /**
2 *$id:Action 。JS,V 2015-3-23
3 *$author Dana丶Li$
4 */
5 /**
6 * 构建了一种新的图形编辑器
7 * 编辑管理 实现方法管理
8 */
9 EditorUi = function(editor, container)
10 {
11 this.editor = editor || new Editor();
12 this.container = container || document.body;
13 var graph = editor.graph;
14 //禁用滚动条
15 this.container.style.overflow = \'hidden\';
16
17 var textEditing = mxUtils.bind(this, function(evt)
18 {
19 if (evt == null)
20 {
21 evt = window.event;
22 }
23
24 if (this.isSelectionAllowed(evt))
25 {
26 return true;
27 }
28
29 return graph.isEditing() || this.dialog != null;
30 });
31
32 //禁用文本选择而不是编辑没有对话框可见
33 if (this.container == document.body)
34 {
35 document.onselectstart = textEditing;
36 document.onmousedown = textEditing;
37 }
38
39 //使用内置的上下文菜单编辑时
40 if (mxClient.IS_IE && document.documentMode != 9)
41 {
42 mxEvent.addListener(this.container, \'contextmenu\', textEditing);
43 }
44 else
45 {
46 this.container.oncontextmenu = textEditing;
47 }
48
49 //图像预fetches子菜单
50 new Image().src = mxPopupMenu.prototype.submenuImage;
51
52 //预取连接图像
53 if (mxConnectionHandler.prototype.connectImage != null)
54 {
55 new Image().src = mxConnectionHandler.prototype.connectImage.src;
56 }
57
58 //创建用户界面
59 this.actions = new Actions(this);
60 this.menus = new Menus(this);
61 this.createDivs();
62 this.refresh();
63 this.createUi();
64
65 //contains the given the inside main图审小组
66 graph.init(this.diagramContainer);
67 graph.refresh();
68
69 //使容器的滚动条和设置光标样式
70 graph.container.setAttribute(\'tabindex\', \'0\');
71 graph.container.style.overflow = (touchStyle) ? \'hidden\' : \'auto\';
72 graph.container.style.cursor = \'default\';
73 graph.container.style.backgroundImage = \'url(\' + IMAGE_PATH + \'/grid.gif)\';
74 graph.container.focus();
75
76 //保持图形容器集中在鼠标按下
77 var graphFireMouseEvent = graph.fireMouseEvent;
78 graph.fireMouseEvent = function(evtName, me, sender)
79 {
80 if (evtName == mxEvent.MOUSE_DOWN)
81 {
82 this.container.focus();
83 }
84
85 graphFireMouseEvent.apply(this, arguments);
86 };
87
88 //在鼠标经过时自动扩展配置
89 graph.panningHandler.autoExpand = true;
90
91 //对上下文菜单
92 graph.panningHandler.factoryMethod = mxUtils.bind(this, function(menu, cell, evt)
93 {
94 this.menus.createPopupMenu(menu, cell, evt);
95 });
96
97 //初始化轮廓
98 editor.outline.init(this.outlineContainer);
99
100 //隐藏菜单
101 var md = (mxClient.IS_TOUCH) ? \'touchstart\' : \'mousedown\';
102 mxEvent.addListener(document, md, mxUtils.bind(this, function(evt)
103 {
104 graph.panningHandler.hideMenu();
105 }));
106
107 //增加了手势操作(缩放)
108 if (mxClient.IS_TOUCH)
109 {
110 mxEvent.addListener(graph.container, \'gesturechange\',
111 mxUtils.bind(this, function(evt)
112 {
113 graph.view.getDrawPane().setAttribute(\'transform\', \'scale(\' + evt.scale + \')\');
114 graph.view.getOverlayPane().style.visibility = \'hidden\';
115 })
116 );
117
118 mxEvent.addListener(graph.container, \'gestureend\',
119 mxUtils.bind(this, function(evt)
120 {
121 graph.view.getDrawPane().removeAttribute(\'transform\');
122 graph.zoomToCenter = true;
123 graph.zoom(evt.scale);
124 graph.view.getOverlayPane().style.visibility = \'visible\';
125 })
126 );
127 }
128
129 // Create handler for key events
130 var keyHandler = this.createKeyHandler(editor);
131
132 // Getter for key handler
133 this.getKeyHandler = function()
134 {
135 return keyHandler;
136 };
137
138 // Shows dialog if changes are lost
139 window.onbeforeunload = function()
140 {
141 if (editor.modified)
142 {
143 //return mxResources.get(\'allChangesLost\');
144 }
145 };
146
147 // Updates the editor UI after the window has been resized
148 mxEvent.addListener(window, \'resize\', mxUtils.bind(this, function()
149 {
150 this.refresh();
151 graph.sizeDidChange();
152 this.editor.outline.update(false);
153 this.editor.outline.outline.sizeDidChange();
154 }));
155
156 // Updates action and menu states
157 this.init();
158 this.open();
159 };
160
161 /**
162 * Specifies the size of the split bar.
163 */
164 EditorUi.prototype.splitSize = (mxClient.IS_TOUCH) ? 16 : 8;
165
166 /**
167 * Specifies the height of the menubar. Default is 34.
168 */
169 EditorUi.prototype.menubarHeight = 34;
170
171 /**
172 * Specifies the height of the toolbar. Default is 46.
173 */
174 EditorUi.prototype.toolbarHeight = 46;
175
176 /**
177 * Specifies the height of the footer. Default is 28.
178 */
179 EditorUi.prototype.footerHeight = 28;
180
181 /**
182 * Specifies the position of the horizontal split bar. Default is 190.
183 */
184 EditorUi.prototype.hsplitPosition = 190;
185
186 /**
187 * Specifies the position of the vertical split bar. Default is 190.
188 */
189 EditorUi.prototype.vsplitPosition = 190;
190
191 /**
192 * Installs the listeners to update the action states.
193 */
194 EditorUi.prototype.init = function()
195 {
196 // Updates action states
197 this.addUndoListener();
198 this.addSelectionListener();
199
200 // Overrides clipboard to update paste action state
201 var paste = this.actions.get(\'paste\');
202
203 var updatePaste = function()
204 {
205 paste.setEnabled(!mxClipboard.isEmpty());
206 };
207
208 var mxClipboardCut = mxClipboard.cut;
209 mxClipboard.cut = function()
210 {
211 mxClipboardCut.apply(this, arguments);
212 updatePaste();
213 };
214
215 var mxClipboardCopy = mxClipboard.copy;
216 mxClipboard.copy = function()
217 {
218 mxClipboardCopy.apply(this, arguments);
219 updatePaste();
220 };
221 };
222
223 /**
224 * Hook for allowing selection and context menu for certain events.
225 */
226 EditorUi.prototype.isSelectionAllowed = function(evt)
227 {
228 return false;
229 };
230
231 /**
232 * Opens the current diagram via the window.opener if one exists.
233 */
234 EditorUi.prototype.open = function()
235 {
236 // Cross-domain window access is not allowed in FF, so if we
237 // were opened from another domain then this will fail.
238 try
239 {
240 if (window.opener != null && window.opener.openFile != null)
241 {
242 window.opener.openFile.setConsumer(mxUtils.bind(this, function(xml, filename)
243 {
244 try
245 {
246 var doc = mxUtils.parseXml(xml);
247 this.editor.setGraphXml(doc.documentElement);
248 this.editor.modified = false;
249 this.editor.undoManager.clear();
250
251 if (filename != null)
252 {
253 this.editor.filename = filename;
254 }
255 }
256 catch (e)
257 {
258 mxUtils.alert(mxResources.get(\'invalidOrMissingFile\') + \': \' + e.message);
259 }
260 }));
261 }
262 }
263 catch(e)
264 {
265 // ignore
266 }
267 };
268
269 /**
270 * 在给定的文件名保存当前图。
271 */
272 EditorUi.prototype.save = function()
273 {
274 var xml = mxUtils.getXml(this.editor.getGraphXml());
275 //火狐浏览器
276 //if (navigator.userAgent.indexOf(\'Firefox\') >= 0){
277 //}
278 xml="<mxGraphModel grid=\"0\" guides=\"1\" tooltips=\"1\" connect=\"1\" fold=\"1\" page=\"0\" pageScale=\"1\" pageWidth=\"826\" pageHeight=\"1169\">"+xml+"</mxGraphModel>"
279
280 //将xml代码保存至服务器文件
281 $.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"xml":xml,"type":"set"},function(text){
282 if(text=="0"){
283 alert("保存失败!");
284 }
285 });
286 };
287
288 /**
289 * 返回一个拷贝没有状态这个编辑器的URL。
290 */
291 EditorUi.prototype.getUrl = function(pathname)
292 {
293 var href = (pathname != null) ? pathname : window.location.pathname;
294 var parms = (pathname.indexOf(\'?\') > 0) ? 1 : 0;
295
296 // Removes template URL parameter for new blank diagram
297 for (var key in urlParams)
298 {
299 if (parms == 0)
300 {
301 href += \'?\';
302 }
303 else
304 {
305 href += \'&\';
306 }
307
308 href += key + \'=\' + urlParams[key];
309 parms++;
310 }
311
312 return href;
313 };
314
315 /**
316 * 更新的撤销/重做项的状态。
317 */
318 EditorUi.prototype.addUndoListener = function()
319 {
320 var undo = this.actions.get(\'undo\');
321 var redo = this.actions.get(\'redo\');
322
323 var undoMgr = this.editor.undoManager;
324
325 var undoListener = function()
326 {
327 undo.setEnabled(undoMgr.canUndo());
328 redo.setEnabled(undoMgr.canRedo());
329 };
330
331 undoMgr.addListener(mxEvent.ADD, undoListener);
332 undoMgr.addListener(mxEvent.UNDO, undoListener);
333 undoMgr.addListener(mxEvent.REDO, undoListener);
334 undoMgr.addListener(mxEvent.CLEAR, undoListener);
335
336 // Updates the button states once
337 undoListener();
338 };
339
340 /**
341 * Updates the states of the given toolbar items based on the selection.
342 */
343 EditorUi.prototype.addSelectionListener = function()
344 {
345 var selectionListener = mxUtils.bind(this, function()
346 {
347 var graph = this.editor.graph;
348 var selected = !graph.isSelectionEmpty();
349 var vertexSelected = false;
350 var edgeSelected = false;
351
352 var cells = graph.getSelectionCells();
353
354 if (cells != null)
355 {
356 for (var i = 0; i < cells.length; i++)
357 {
358 var cell = cells[i];
359
360 if (graph.getModel().isEdge(cell))
361 {
362 edgeSelected = true;
363 }
364
365 if (graph.getModel().isVertex(cell))
366 {
367 vertexSelected = true;
368 }
369
370 if (edgeSelected && vertexSelected)
371 {
372 break;
373 }
374 }
375 }
376
377 // 更新动作状态
378 var actions = [\'cut\', \'copy\', \'delete\', \'duplicate\', \'bold\', \'italic\', \'style\', \'fillColor\',
379 \'gradientColor\', \'underline\', \'fontColor\', \'strokeColor\', \'backgroundColor\',
380 \'borderColor\', \'toFront\', \'toBack\', \'dashed\', \'rounded\', \'shadow\', \'rotate\',
381 \'autosize\'];
382
383 for (var i = 0; i < actions.length; i++)
384 {
385 this.actions.get(actions[i]).setEnabled(selected);
386 }
387
388 this.actions.get(\'rotation\').setEnabled(vertexSelected);
389 this.actions.get(\'group\').setEnabled(graph.getSelectionCount() > 1);
390 this.actions.get(\'ungroup\').setEnabled(graph.getSelectionCount() == 1 &&
391 graph.getModel().getChildCount(graph.getSelectionCell()) > 0);
392 var oneVertexSelected = vertexSelected && graph.getSelectionCount() == 1;
393 this.actions.get(\'removeFromGroup\').setEnabled(oneVertexSelected &&
394 graph.getModel().isVertex(graph.getModel().getParent(graph.getSelectionCell())));
395
396 //更新菜单状态
397 var menus = [\'fontFamily\', \'fontSize\', \'alignment\', \'position\', \'text\', \'format\',
398 \'arrange\', \'linewidth\', \'spacing\', \'gradient\'];
399
400 for (var i = 0; i < menus.length; i++)
401 {
402 this.menus.get(menus[i]).setEnabled(selected);
403 }
404
405 menus = [\'line\', \'lineend\', \'linestart\'];
406
407 for (var i = 0; i < menus.length; i++)
408 {
409 this.menus.get(menus[i]).setEnabled(edgeSelected);
410 }
411
412 this.actions.get(\'setAsDefaultEdge\').setEnabled(edgeSelected);
413
414 this.menus.get(\'align\').setEnabled(graph.getSelectionCount() > 1);
415 this.menus.get(\'direction\').setEnabled(vertexSelected || (edgeSelected &&
416 graph.isLoop(graph.view.getState(graph.getSelectionCell()))));
417 this.menus.get(\'navigation\').setEnabled(graph.foldingEnabled && ((graph.view.currentRoot != null) ||
418 (graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell()))));
419 this.actions.get(\'home\').setEnabled(graph.view.currentRoot != null);
420 this.actions.get(\'exitGroup\').setEnabled(graph.view.currentRoot != null);
421 var groupEnabled = graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell());
422 this.actions.get(\'enterGroup\').setEnabled(groupEnabled);
423 this.actions.get(\'expand\').setEnabled(groupEnabled);
424 this.actions.get(\'collapse\').setEnabled(groupEnabled);
425 this.actions.get(\'editLink\').setEnabled(graph.getSelectionCount() == 1);
426 this.actions.get(\'openLink\').setEnabled(graph.getSelectionCount() == 1 &&
427 graph.getLinkForCell(graph.getSelectionCell()) != null);
428 });
429
430 this.editor.graph.getSelectionModel().addListener(mxEvent.CHANGE, selectionListener);
431 selectionListener();
432 };
433
434 /**
435 * Refreshes the viewport.
436 */
437 EditorUi.prototype.refresh = function()
438 {
439 var quirks = mxClient.IS_IE && (document.documentMode == null || document.documentMode == 5);
440 var w = this.container.clientWidth;
441 var h = this.container.clientHeight;
442
443 if (this.container == document.body)
444 {
445 w = document.body.clientWidth || document.documentElement.clientWidth;
446 h = (quirks) ? document.body.clientHeight || document.documentElement.clientHeight : document.documentElement.clientHeight;
447 }
448
449 var effHsplitPosition = Math.max(0, Math.min(this.hsplitPosition, w - this.splitSize - 20));
450 var effVsplitPosition = Math.max(0, Math.min(this.vsplitPosition, h - this.menubarHeight - this.toolbarHeight - this.footerHeight - this.splitSize - 1));
451
452 this.menubarContainer.style.height = this.menubarHeight + \'px\';
453 this.toolbarContainer.style.top = this.menubarHeight + \'px\';
454 this.toolbarContainer.style.height = this.toolbarHeight + \'px\';
455 this.sidebarContainer.style.top = (this.menubarHeight + this.toolbarHeight) + \'px\';
456 this.sidebarContainer.style.width = effHsplitPosition + \'px\';
457 this.outlineContainer.style.width = effHsplitPosition + \'px\';
458 this.outlineContainer.style.height = effVsplitPosition + \'px\';
459 this.outlineContainer.style.bottom = this.footerHeight + \'px\';
460 this.diagramContainer.style.left = (effHsplitPosition + this.splitSize) + \'px\';
461 this.diagramContainer.style.top = this.sidebarContainer.style.top;
462 this.footerContainer.style.height = this.footerHeight + \'px\';
463 this.hsplit.style.top = this.sidebarContainer.style.top;
464 this.hsplit.style.bottom = this.outlineContainer.style.bottom;
465 this.hsplit.style.left = effHsplitPosition + \'px\';
466 this.vsplit.style.width = this.sidebarContainer.style.width;
467 this.vsplit.style.bottom = (effVsplitPosition + this.footerHeight) + \'px\';
468
469 if (quirks)
470 {
471 this.menubarContainer.style.width = w + \'px\';
472 this.toolbarContainer.style.width = this.menubarContainer.style.width;
473 var sidebarHeight = (h - effVsplitPosition - this.splitSize - this.footerHeight - this.menubarHeight - this.toolbarHeight);
474 this.sidebarContainer.style.height = sidebarHeight + \'px\';
475 this.diagramContainer.style.width = (w - effHsplitPosition - this.splitSize) + \'px\';
476 var diagramHeight = (h - this.footerHeight - this.menubarHeight - this.toolbarHeight);
477 this.diagramContainer.style.height = diagramHeight + \'px\';
478 this.footerContainer.style.width = this.menubarContainer.style.width;
479 this.hsplit.style.height = diagramHeight + \'px\';
480 }
481 else
482 {
483 this.sidebarContainer.style.bottom = (effVsplitPosition + this.splitSize + this.footerHeight) + \'px\';
484 this.diagramContainer.style.bottom = this.outlineContainer.style.bottom;
485 }
486 };
487
488 /**
489 * Creates the required containers.
490 */
491 EditorUi.prototype.createDivs = function()
492 {
493 this.menubarContainer = this.createDiv(\'geMenubarContainer\');
494 this.toolbarContainer = this.createDiv(\'geToolbarContainer\');
495 this.sidebarContainer = this.createDiv(\'geSidebarContainer\');
496 this.outlineContainer = this.createDiv(\'geOutlineContainer\');
497 this.diagramContainer = this.createDiv(\'geDiagramContainer\');
498 this.footerContainer = this.createDiv(\'geFooterContainer\');
499 this.hsplit = this.createDiv(\'geHsplit\');
500 this.vsplit = this.createDiv(\'geVsplit\');
501
502 // Sets static style for containers
503 this.menubarContainer.style.top = \'0px\';
504 this.menubarContainer.style.left = \'0px\';
505 this.menubarContainer.style.right = \'0px\';
506 this.toolbarContainer.style.left = \'0px\';
507 this.toolbarContainer.style.right = \'0px\';
508 this.sidebarContainer.style.left = \'0px\';
509 this.outlineContainer.style.left = \'0px\';
510 this.diagramContainer.style.right = \'0px\';
511 this.footerContainer.style.left = \'0px\';
512 this.footerContainer.style.right = \'0px\';
513 this.footerContainer.style.bottom = \'0px\';
514 this.vsplit.style.left = \'0px\';
515 this.vsplit.style.height = this.splitSize + \'px\';
516 this.hsplit.style.width = this.splitSize + \'px\';
517 };
518
519 /**
520 * Creates the required containers.
521 */
522 EditorUi.prototype.createUi = function()
523 {
524 // Creates menubar
525 this.menubar = this.menus.createMenubar(this.createDiv(\'geMenubar\'));
526 this.menubarContainer.appendChild(this.menubar.container);
527
528 // Creates toolbar
529 this.toolbar = this.createToolbar(this.createDiv(\'geToolbar\'));
530 this.toolbarContainer.appendChild(this.toolbar.container);
531
532 // Creates the sidebar
533 this.sidebar = this.createSidebar(this.sidebarContainer);
534
535 // Creates the footer
536 this.footerContainer.appendChild(this.createFooter());
537
538 // Adds status bar in menubar
539 this.statusContainer = this.createStatusContainer();
540
541 // Connects the status bar to the editor status
542 this.editor.addListener(\'statusChanged\', mxUtils.bind(this, function()
543 {
544 this.setStatusText(this.editor.getStatus());
545 }));
546
547 this.setStatusText(this.editor.getStatus());
548 this.menubar.container.appendChild(this.statusContainer);
549
550 // Inserts into DOM
551 this.container.appendChild(this.menubarContainer);
552 this.container.appendChild(this.toolbarContainer);
553 this.container.appendChild(this.sidebarContainer);
554 this.container.appendChild(this.outlineContainer);
555 this.container.appendChild(this.diagramContainer);
556 this.container.appendChild(this.footerContainer);
557 this.container.appendChild(this.hsplit);
558 this.container.appendChild(this.vsplit);
559
560 // HSplit
561 this.addSplitHandler(this.hsplit, true, 0, mxUtils.bind(this, function(value)
562 {
563 this.hsplitPosition = value;
564 this.refresh();
565 this.editor.graph.sizeDidChange();
566 this.editor.outline.update(false);
567 this.editor.outline.outline.sizeDidChange();
568 }));
569
570 // VSplit
571 this.addSplitHandler(this.vsplit, false, this.footerHeight, mxUtils.bind(this, function(value)
572 {
573 this.vsplitPosition = value;
574 this.refresh();
575 this.editor.outline.update(false);
576 this.editor.outline.outline.sizeDidChange();
577 }));
578 };
579
580 /**
581 * Creates a new toolbar for the given container.
582 */
583 EditorUi.prototype.createStatusContainer = function()
584 {
585 var container = document.createElement(\'a\');
586 container.className = \'geItem geStatus\';
587
588 return container;
589 };
590
591 /**
592 * Creates a new toolbar for the given container.
593 */
594 EditorUi.prototype.setStatusText = function(value)
595 {
596 this.statusContainer.innerHTML = value;
597 };
598
599 /**
600 * Creates a new toolbar for the given container.
601 */
602 EditorUi.prototype.createToolbar = function(container)
603 {
604 return new Toolbar(this, container);
605 };
606
607 /**
608 * Creates a new sidebar for the given container.
609 */
610 EditorUi.prototype.createSidebar = function(container)
611 {
612 return new Sidebar(this, container);
613 };
614
615 /**
616 * Creates and returns a new footer.
617 */
618 EditorUi.prototype.createFooter = function()
619 {
620 return this.createDiv(\'geFooter\');
621 };
622
623 /**
624 * Creates the actual toolbar for the toolbar container.
625 */
626 EditorUi.prototype.createDiv = function(classname)
627 {
628 var elt = document.createElement(\'div\');
629 elt.className = classname;
630
631 return elt;
632 };
633
634 /**
635 * Updates the states of the given undo/redo items.
636 */
637 EditorUi.prototype.addSplitHandler = function(elt, horizontal, dx, onChange)
638 {
639 var start = null;
640 var initial = null;
641
642 function getValue()
643 {
644 return parseInt(((horizontal) ? elt.style.left : elt.style.bottom));
645 }
646
647 var md = (mxClient.IS_TOUCH) ? \'touchstart\' : \'mousedown\';
648 var mm = (mxClient.IS_TOUCH) ? \'touchmove\' : \'mousemove\';
649 var mu = (mxClient.IS_TOUCH) ? \'touchend\' : \'mouseup\';
650
651 mxEvent.addListener(elt, md, function(evt)
652 {
653 start = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
654 initial = getValue();
655 mxEvent.consume(evt);
656 });
657
658 function moveHandler(evt)
659 {
660 if (start != null)
661 {
662 var pt = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
663 onChange(Math.max(0, initial + ((horizontal) ? (pt.x - start.x) : (start.y - pt.y)) - dx));
664 mxEvent.consume(evt);
665 }
666 }
667
668 mxEvent.addListener(document, mm, moveHandler);
669
670 mxEvent.addListener(document, mu, function(evt)
671 {
672 moveHandler(evt);
673 start = null;
674 initial = null;
675 });
676 };
677
678 /**
679 * Displays a print dialog.
680 */
681 EditorUi.prototype.showDialog = function(elt, w, h, modal, closable, onClose)
682 {
683 this.hideDialog();
684 this.dialog = new Dialog(this, elt, w, (mxClient.IS_VML) ? h - 12 : h, modal, closable, onClose);
685 };
686
687 /**
688 * Displays a print dialog.
689 */
690 EditorUi.prototype.hideDialog = function()
691 {
692 if (this.dialog != null)
693 {
694 this.dialog.close();
695 this.dialog = null;
696 this.editor.graph.container.focus();
697 }
698 };
699
700 /**
701 * Adds the label menu items to the given menu and parent.
702 */
703 EditorUi.prototype.openFile = function()
704 {
705 // Closes dialog after open
706 window.openFile = new OpenFile(mxUtils.bind(this, function()
707 {
708 this.hideDialog();
709 }));
710
711 // Removes openFile if dialog is closed
712 this.showDialog(new OpenDialog(this).container, 300, 180, true, true, function()
713 {
714 window.openFile = null;
715 });
716 };
717
718 /**
719 * Adds the label menu items to the given menu and parent.
720 */
721 EditorUi.prototype.saveFile = function(forceDialog)
722 {
723 if (!forceDialog && this.editor.filename != null)
724 {
725 this.save(this.editor.getOrCreateFilename());
726 }
727 else
728 {
729 this.showDialog(new SaveDialog(this).container, 300, 100, true, true);
730 }
731 };
732
733 /**
734 * Executes the given layout.
735 */
736 EditorUi.prototype.executeLayout = function(layout, animate, ignoreChildCount)
737 {
738 var graph = this.editor.graph;
739 var cell = graph.getSelectionCell();
740
741 graph.getModel().beginUpdate();
742 try
743 {
744 layout.execute(graph.getDefaultParent(), cell);
745 }
746 catch (e)
747 {
748 throw e;
749 }
750 finally
751 {
752 // Animates the changes in the graph model except
753 // for Camino, where animation is too slow
754 if (animate && navigator.userAgent.indexOf(\'Camino\') < 0)
755 {
756 // New API for animating graph layout results asynchronously
757 var morph = new mxMorphing(graph);
758 morph.addListener(mxEvent.DONE, mxUtils.bind(this, function()
759 {
760 graph.getModel().endUpdate();
761 }));
762
763 morph.startAnimation();
764 }
765 else
766 {
767 graph.getModel().endUpdate();
768 }
769 }
770 };
771
772 /**
773 * Creates the keyboard event handler for the current graph and history.
774 */
775 EditorUi.prototype.createKeyHandler = function(editor)
776 {
777 var graph = this.editor.graph;
778 var keyHandler = new mxKeyHandler(graph);
779
780 // Routes command-key to control-key on Mac
781 keyHandler.isControlDown = function(evt)
782 {
783 return mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey);
784 };
785
786 // Helper function to move cells with the cursor keys
787 function nudge(keyCode)
788 {
789 if (!graph.isSelectionEmpty())
790 {
791 var dx = 0;
792 var dy = 0;
793
794 if (keyCode == 37)
795 {
796 dx = -1;
797 }
798 else if (keyCode == 38)
799 {
800 dy = -1;
801 }
802 else if (keyCode == 39)
803 {
804 dx = 1;
805 }
806 else if (keyCode == 40)
807 {
808 dy = 1;
809 }
810
811 graph.moveCells(graph.getSelectionCells(), dx, dy);
812 graph.scrollCellVisible(graph.getSelectionCell());
813 }
814 };
815
816 // Binds keystrokes to actions
817 var bindAction = mxUtils.bind(this, function(code, control, key, shift)
818 {
819 var action = this.actions.get(key);
820
821 if (action != null)
822 {
823 var f = function()
824 {
825 if (action.enabled)
826 {
827 action.funct();
828 }
829 };
830
831 if (control)
832 {
833 if (shift)
834 {
835 keyHandler.bindControlShiftKey(code, f);
836 }
837 else
838 {
839 keyHandler.bindControlKey(code, f);
840 }
841 }
842 else
843 {
844 if (shift)
845 {
846 keyHandler.bindShiftKey(code, f);
847 }
848 else
849 {
850 keyHandler.bindKey(code, f);
851 }
852 }
853 }
854 });
855
856 var ui = this;
857 var keyHandleEscape = keyHandler.escape;
858 keyHandler.escape = function(evt)
859 {
860 ui.hideDialog();
861 keyHandleEscape.apply(this, arguments);
862 };
863
864 // Ignores enter keystroke. Remove this line if you want the
865 // enter keystroke to stop editing.
866 keyHandler.enter = function() {};
867 keyHandler.bindKey(8, function() { graph.foldCells(true); }); // Backspace
868 keyHandler.bindKey(13, function() { graph.foldCells(false); }); // Enter
869 keyHandler.bindKey(33, function() { graph.exitGroup(); }); // Page Up
870 keyHandler.bindKey(34, function() { graph.enterGroup(); }); // Page Down
871 keyHandler.bindKey(36, function() { graph.home(); }); // Home
872 keyHandler.bindKey(35, function() { graph.refresh(); }); // End
873 keyHandler.bindKey(37, function() { nudge(37); }); // Left arrow
874 keyHandler.bindKey(38, function() { nudge(38); }); // Up arrow
875 keyHandler.bindKey(39, function() { nudge(39); }); // Right arrow
876 keyHandler.bindKey(40, function() { nudge(40); }); // Down arrow
877 keyHandler.bindKey(113, function() { graph.startEditingAtCell(); });
878 bindAction(46, false, \'delete\'); // Delete
879 bindAction(82, true, \'rotate\'); // Ctrl+R
880 bindAction(83, true, \'save\'); // Ctrl+S
881 bindAction(83, true, \'saveAs\', true); // Ctrl+Shift+S
882 bindAction(107, false, \'zoomIn\'); // Add
883 bindAction(109, false, \'zoomOut\'); // Subtract
884 bindAction(65, true, \'selectAll\'); // Ctrl+A
885 bindAction(86, true, \'selectVertices\', true); // Ctrl+Shift+V
886 bindAction(69, true, \'selectEdges\', true); // Ctrl+Shift+E
887 bindAction(69, true, \'export\'); // Ctrl+Shift+E
888 bindAction(66, true, \'toBack\'); // Ctrl+B
889 bindAction(70, true, \'toFront\'); // Ctrl+F
890 bindAction(68, true, \'duplicate\'); // Ctrl+D
891 bindAction(90, true, \'undo\'); // Ctrl+Z
892 bindAction(89, true, \'redo\'); // Ctrl+Y
893 bindAction(88, true, \'cut\'); // Ctrl+X
894 bindAction(67, true, \'copy\'); // Ctrl+C
895 bindAction(81, true, \'connect\'); // Ctrl+Q
896 bindAction(86, true, \'paste\'); // Ctrl+V
897 bindAction(71, true, \'group\'); // Ctrl+G
898 bindAction(71, true, \'grid\', true); // Ctrl+Shift+G
899 bindAction(85, true, \'ungroup\'); // Ctrl+U
900 bindAction(112, false, \'about\'); // F1
901
902 return keyHandler;
903 };
View Code
这里是图形化操作以后保存拓扑对于的Xml文件,便于再次访问,或者查看的时候加载原信息!
如操作功能:
对应的通过上面EditorUi.js文件中EditorUi.prototype.save = function()控制,我是通过一个Servlet来保存XML文件
1 package com.visec.systemConfig;
2 import java.io.BufferedReader;
3 import java.io.File;
4 import java.io.FileReader;
5 import java.io.IOException;
6 import java.io.PrintWriter;
7 import java.io.RandomAccessFile;
8 import javax.servlet.ServletException;
9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 /**
13 * <p>Title: 网络拓扑图保存</p>
14 * <p>Description: 将网络拓扑图保存至对应的xml文件中 以及 读取网络拓扑图对应的xml文件</p>
15 * <p>Copyright: Copyright (c) 2015</p>
16 * <p>Company: XXX科技</p>
17 * @author 李尚志
18 * @version 3.0
19 */
20 public class SaveToXmlServlet extends HttpServlet {
21 private static final long serialVersionUID = 1L;
22 public void doGet(HttpServletRequest request, HttpServletResponse response)
23 throws ServletException, IOException {
24 doPost(request,response);
25 }
26 public void doPost(HttpServletRequest request, HttpServletResponse response)
27 throws ServletException, IOException {
28 response.setContentType("text/html;charset=utf-8");
29 response.setCharacterEncoding("utf-8");
30 request.setCharacterEncoding("utf-8");
31 String type = request.getParameter("type");
32 String tp = request.getParameter("tp");
33 StringBuffer result = new StringBuffer("");
34 String xmlPath=new String("");
35 String strPath = this.getClass().getResource("/").toString();
36 xmlPath = ("qsy".equals(tp))?"network_map/network_qsy.xml":("dzj".equals(tp))?"network_map/network_dzj.xml":("zdw".equals(tp))?"network_map/network_zdw.xml":"network_map/network_sp.xml";
37 String osName = System.getProperties().getProperty("os.name");
38 if(osName.toLowerCase().indexOf("windows")>-1){
39 strPath=strPath.substring(6)+xmlPath;
40 }else{
41 strPath=strPath.substring(5)+xmlPath;
42 }
43 File file = new File(strPath);
44 if(file.isFile()){//判断该路径是否为一个文件
45 if("set".equals(type.toLowerCase())){//文件保存
46 String xml = request.getParameter("xml");
47 if(xml==null||"".equals(xml)){
48 result.append("0");
49 }else{
50 RandomAccessFile randomAccessFile = new RandomAccessFile(strPath, "rw");
51 randomAccessFile.seek(0);
52 randomAccessFile.setLength(0);
53 randomAccessFile.write(xml.getBytes());
54 randomAccessFile.close();
55 result.append("1");
56 }
57 }else if("get".equals(type.toLowerCase())){//获取文件信息
58 //开始读取
59 BufferedReader reader = new BufferedReader(new FileReader(new File(strPath)));
60 String tempString = null;
61 // 一次读入一行,直到读入null为文件结束
62 while ((tempString = reader.readLine()) != null){
63 result.append(tempString);
64 }
65 reader.close();
66 }
67 }else{
68 System.out.println(strPath+" 找不到!");
69 result.append("0");
70 }
71 PrintWriter out = response.getWriter();
72 out.write(result.toString());
73 out.flush();
74 out.close();
75 }
76
77 }
View Code
当我们再次访问编辑页面时,即要加载先前对应的XML文件
主要文件( Actions.js和上述Servlet中get方法)
Servlet在此处省略(上述中已提供源码)
Actions.js源码
1 /**
2 *$id:Action 。JS,V 2015-3-23
3 *$author Dana丶Li$
4 */
5 /**
6 *结构对于给定的UI操作的对象。
7 *编辑函数方法管理
8 */
9 function Actions(editorUi)
10 {
11 this.editorUi = editorUi;
12 this.actions = new Object();
13 this.init();
14 };
15 /**
16 * 添加默认的函数
17 */
18 Actions.prototype.init = function()
19 {
20 var ui = this.editorUi;
21 var editor = ui.editor;
22 var graph = editor.graph;
23 graph.cellsMovable=!0; //设置不可移动
24 graph.cellsDisconnectable=!0; //设置边不可编辑
25 graph.cellsResizable=!0; //设置不可改变大小
26 $.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"type":"get"},function(text){
27 if(text=="0"){
28 alert("拓扑图XML文件加载失败!");
29 }else{
30 //保存拓扑图XML模板文件
31 //example:
32 //<mxGraphModel grid="0" guides="1" tooltips="1" connect="1" fold="1" page="0" pageScale="1" pageWidth="826" pageHeight="1169">
33 // <root>
34 // <mxCell id="0"/>
35 // <mxCell id="1" parent="0"/>
36 // <mxCell id="2" value="测试网闸[内端]
通讯:192.168.0.199 
业务: 192.168.1.199" style="image;image=stencils/clipart/pic3.png" vertex="1" remark="142588842925033" parent="1">
37 // <mxGeometry x="236" y="139" width="80" height="80" as="geometry"/>
38 // </mxCell>
39 // </root>
40 //</mxGraphModel>
41 var xml = text;
42 var doc = mxUtils.parseXml(xml);
43 var model = new mxGraphModel();
44 var codec = new mxCodec(doc);
45 codec.decode(doc.documentElement, model);
46 var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
47 graph.setSelectionCells(editor.graph.importCells(children));
48 }
49 });
50
51 //文件操作
52 this.addAction(\'new\', function() { window.open(ui.getUrl());});
53 this.addAction(\'open\', function()
54 {
55 window.openNew = true;
56 window.openKey = \'open\';
57 ui.openFile();
58 });
59
60 this.addAction(\'import\', function()
61 {
62 window.openNew = false;
63 window.openKey = \'import\';
64
65 //关闭对话框后打开
66 window.openFile = new OpenFile(mxUtils.bind(this, function()
67 {
68 ui.hideDialog();
69 }));
70
71 window.openFile.setConsumer(mxUtils.bind(this, function(xml, filename)
72 {
73 try
74 {
75 var doc = mxUtils.parseXml(xml);
76 var model = new mxGraphModel();
77 var codec = new mxCodec(doc);
78 codec.decode(doc.documentElement, model);
79
80 var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
81 editor.graph.setSelectionCells(editor.graph.importCells(children));
82 }
83 catch (e)
84 {
85 mxUtils.alert(mxResources.get(\'invalidOrMissingFile\') + \': \' + e.message);
86 }
87 }));
88
89 //如果删除打开文件对话框关闭
90 ui.showDialog(new OpenDialog(this).container, 300, 180, true, true, function()
91 {
92 window.openFile = null;
93 });
94 });
95 this.addAction(\'save\', function() { ui.save(); }, null, null, \'Ctrl+S\');
96
97 //this.addAction(\'saveAs\', function() { ui.saveFile(true); }, null, null, \'Ctrl+Shift-S\');
98 //this.addAction(\'export\', function() { ui.showDialog(new ExportDialog(ui).container, 300, 200, true, true); }, null, null, \'Ctrl+E\');
99 //this.put(\'editFile\', new Action(mxResources.get(\'edit\'), mxUtils.bind(this, function()
100 //{
101 //this.editorUi.showDialog(new EditFileDialog(ui).container, 620, 420, true, true);
102 //})));
103 this.addAction(\'pageSetup\', function() { ui.showDialog(new PageSetupDialog(ui).container, 300, 200, true, true); });
104
105 //打印
106 this.addAction(\'print\', function() { ui.showDialog(new PrintDialog(ui).container, 300, 200, true, true); }, null, \'sprite-print\', \'Ctrl+P\');
107
108 this.addAction(\'preview\', function() { mxUtils.show(graph, null, 10, 10); });
109
110 //编辑操作
111 this.addAction(\'undo\', function() { editor.undoManager.undo(); }, null, \'sprite-undo\', \'Ctrl+Z\');
112 this.addAction(\'redo\', function() { editor.undoManager.redo(); }, null, \'sprite-redo\', \'Ctrl+Y\');
113 this.addAction(\'cut\', function() { mxClipboard.cut(graph); }, null, \'sprite-cut\', \'Ctrl+X\');
114 this.addAction(\'copy\', function() { mxClipboard.copy(graph); }, null, \'sprite-copy\', \'Ctrl+C\');
115 this.addAction(\'paste\', function() { mxClipboard.paste(graph); }, false, \'sprite-paste\', \'Ctrl+V\');
116 this.addAction(\'delete\', function() { graph.removeCells(); }, null, null, \'Delete\');
117 this.addAction(\'duplicate\', function()
118 {
119 var s = graph.gridSize;
120 graph.setSelectionCells(graph.moveCells(graph.getSelectionCells(), s, s, true));
121 }, null, null, \'Ctrl+D\');
122 this.addAction(\'selectVertices\', function() { graph.selectVertices(); }, null, null, \'Ctrl+Shift+V\');
123 this.addAction(\'selectEdges\', function() { graph.selectEdges(); }, null, null, \'Ctrl+Shift+E\');
124 this.addAction(\'selectAll\', function() { graph.selectAll(); }, null, null, \'Ctrl+A\');
125
126 //导航行动
127 this.addAction(\'home\', function() { graph.home(); }, null, null, \'Home\');
128 this.addAction(\'exitGroup\', function() { graph.exitGroup(); }, null, null, \'Page Up\');
129 this.addAction(\'enterGroup\', function() { graph.enterGroup(); }, null, null, \'Page Down\');
130 this.addAction(\'expand\', function() { graph.foldCells(false); }, null, null, \'Enter\');
131 this.addAction(\'collapse\', function() { graph.foldCells(true); }, null, null, \'Backspace\');
132
133 //安排行动
134 this.addAction(\'toFront\', function() { graph.orderCells(false); }, null, null, \'Ctrl+F\');
135 this.addAction(\'toBack\', function() { graph.orderCells(true); }, null, null, \'Ctrl+B\');
136 this.addAction(\'group\', function() { graph.setSelectionCell(graph.groupCells(null, 0)); }, null, null, \'Ctrl+G\');
137 this.addAction(\'ungroup\', function() { graph.setSelectionCells(graph.ungroupCells()); }, null, null, \'Ctrl+U\');
138 this.addAction(\'removeFromGroup\', function() { graph.removeCellsFromParent(); });
139 this.addAction(\'editLink\', function()
140 {
141 var cell = graph.getSelectionCell();
142 var link = graph.getLinkForCell(cell);
143
144 if (link == null)
145 {
146 link = \'\';
147 }
148
149 link = mxUtils.prompt(mxResources.get(\'enterValue\'), link);
150
151 if (link != null)
152 {
153 graph.setLinkForCell(cell, link);
154 }
155 });
156 this.addAction(\'openLink\', function()
157 {
158 var cell = graph.getSelectionCell();
159 var link = graph.getLinkForCell(cell);
160
161 if (link != null)
162 {
163 window.open(link);
164 }
165 });
166 this.addAction(\'autosize\', function()
167 {
168 var cells = graph.getSelectionCells();
169
170 if (cells != null)
171 {
172 graph.getModel().beginUpdate();
173 try
174 {
175 for (var i = 0; i < cells.length; i++)
176 {
177 var cell = cells[i];
178
179 if (graph.getModel().getChildCount(cell))
180 {
181 graph.updateGroupBounds([cell], 20);
182 }
183 else
184 {
185 graph.updateCellSize(cell);
186 }
187 }
188 }
189 finally
190 {
191 graph.getModel().endUpdate();
192 }
193 }
194 });
195 this.addAction(\'rotation\', function()
196 {
197 var value = \'0\';
198 var state = graph.getView().getState(graph.getSelectionCell());
199
200 if (state != null)
201 {
202 value = state.style[mxConstants.STYLE_ROTATION] || value;
203 }
204
205 value = mxUtils.prompt(mxResources.get(\'enterValue\') + \' (\' +
206 mxResources.get(\'rotation\') + \' 0-360)\', value);
207
208 if (value != null)
209 {
210 graph.setCellStyles(mxConstants.STYLE_ROTATION, value);
211 }
212 });
213 this.addAction(\'rotate\', function()
214 {
215 var cells = graph.getSelectionCells();
216
217 if (cells != null)
218 {
219 graph.getModel().beginUpdate();
220 try
221 {
222 for (var i = 0; i < cells.length; i++)
223 {
224 var cell = cells[i];
225
226 if (graph.getModel().isVertex(cell) && graph.getModel().getChildCount(cell) == 0)
227 {
228 var geo = graph.getCellGeometry(cell);
229
230 if (geo != null)
231 {
232 //旋转的几何尺寸及位置
233 geo = geo.clone();
234 geo.x += geo.width / 2 - geo.height / 2;
235 geo.y += geo.height / 2 - geo.width / 2;
236 var tmp = geo.width;
237 geo.width = geo.height;
238 geo.height = tmp;
239 graph.getModel().setGeometry(cell, geo);
240
241 //方向和进展90度读
242 var state = graph.view.getState(cell);
243
244 if (state != null)
245 {
246 var dir = state.style[mxConstants.STYLE_DIRECTION] || \'east\'/*default*/;
247
248 if (dir == \'east\')
249 {
250 dir = \'south\';
251 }
252 else if (dir == \'south\')
253 {
254 dir = \'west\';
255 }
256 else if (dir == \'west\')
257 {
258 dir = \'north\';
259 }
260 else if (dir == \'north\')
261 {
262 dir = \'east\';
263 }
264
265 graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);
266 }
267 }
268 }
269 }
270 }
271 finally
272 {
273 graph.getModel().endUpdate();
274 }
275 }
276 }, null, null, \'Ctrl+R\');
277
278 //视图的操作
279 this.addAction(\'actualSize\', function()
280 {
281 graph.zoomTo(1);
282 });
283 this.addAction(\'zoomIn\', function() { graph.zoomIn(); }, null, null, \'Add\');
284 this.addAction(\'zoomOut\', function() { graph.zoomOut(); }, null, null, \'Subtract\');
285 this.addAction(\'fitWindow\', function() { graph.fit(); });
286
287 this.addAction(\'fitPage\', mxUtils.bind(this, function()
288 {
289 if (!graph.pageVisible)
290 {
291 this.get(\'pageView\').funct();
292 }
293
294 var fmt = graph.pageFormat;
295 var ps = graph.pageScale;
296 var cw = graph.container.clientWidth - 20;
297 var ch = graph.container.clientHeight - 20;
298
299 var scale = Math.floor(100 * Math.min(cw / fmt.width / ps, ch / fmt.height / ps)) / 100;
300 graph.zoomTo(scale);
301
302 graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
303 graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
304 }));
305 this.addAction(\'fitPageWidth\', mxUtils.bind(this, function()
306 {
307 if (!graph.pageVisible)
308 {
309 this.get(\'pageView\').funct();
310 }
311
312 var fmt = graph.pageFormat;
313 var ps = graph.pageScale;
314 var cw = graph.container.clientWidth - 20;
315
316 var scale = Math.floor(100 * cw / fmt.width / ps) / 100;
317 graph.zoomTo(scale);
318
319 graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
320 graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
321 }));
322 this.put(\'customZoom\', new Action(mxResources.get(\'custom\'), function()
323 {
324 var value = mxUtils.prompt(mxResources.get(\'enterValue\') + \' (%)\', parseInt(graph.getView().getScale() * 100));
325
326 if (value != null && value.length > 0 && !isNaN(parseInt(value)))
327 {
328 graph.zoomTo(parseInt(value) / 100);
329 }
330 }));
331
332 //选择行动
333 var action = null;
334 action = this.addAction(\'grid\', function()
335 {
336 graph.setGridEnabled(!graph.isGridEnabled());
337 editor.updateGraphComponents();
338 }, null, null, \'Ctrl+Shift+G\');
339 action.setToggleAction(true);
340 action.setSelectedCallback(function() { return graph.isGridEnabled(); });
341 action = this.addAction(\'guides\', function() { graph.graphHandler.guidesEnabled = !graph.graphHandler.guidesEnabled; });
342 action.setToggleAction(true);
343 action.setSelectedCallback(function() { return graph.graphHandler.guidesEnabled; });
344 action = this.addAction(\'tooltips\', function()
345 {
346 graph.tooltipHandler.setEnabled(!graph.tooltipHandler.isEnabled());
347 });
348 action.setToggleAction(true);
349 action.setSelectedCallback(function() { return graph.tooltipHandler.isEnabled(); });
350 action = this.addAction(\'navigation\', function()
351 {
352 graph.foldingEnabled = !graph.foldingEnabled;
353 graph.view.revalidate();
354 });
355 action.setToggleAction(true);
356 action.setSelectedCallback(function() { return graph.foldingEnabled; });
357 action = this.addAction(\'scrollbars\', function()
358 {
359 graph.scrollbars = !graph.scrollbars;
360 editor.updateGraphComponents();
361
362 if (!graph.scrollbars)
363 {
364 var t = graph.view.translate;
365 graph.view.setTranslate(t.x - graph.container.scrollLeft / graph.view.scale, t.y - graph.container.scrollTop / graph.view.scale);
366 graph.container.scrollLeft = 0;
367 graph.container.scrollTop = 0;
368 graph.sizeDidChange();
369 }
370 else
371 {
372 var dx = graph.view.translate.x;
373 var dy = graph.view.translate.y;
374
375 graph.view.translate.x = 0;
376 graph.view.translate.y = 0;
377 graph.sizeDidChange();
378 graph.container.scrollLeft -= Math.round(dx * graph.view.scale);
379 graph.container.scrollTop -= Math.round(dy * graph.view.scale);
380 }
381 }, !mxClient.IS_TOUCH);
382 action.setToggleAction(true);
383 action.setSelectedCallback(function() { return graph.container.style.overflow == \'auto\'; });
384 action = this.addAction(\'pageView\', mxUtils.bind(this, function()
385 {
386 graph.pageVisible = !graph.pageVisible;
387 graph.pageBreaksVisible = graph.pageVisible;
388 graph.preferPageSize = graph.pageBreaksVisible;
389 graph.view.validate();
390 graph.sizeDidChange();
391
392 editor.updateGraphComponents();
393 editor.outline.update();
394
395 if (mxUtils.hasScrollbars(graph.container))
396 {
397 if (graph.pageVisible)
398 {
399 graph.container.scrollLeft -= 20;
400 graph.container.scrollTop -= 20;
401 }
402 else
403 {
404 graph.container.scrollLeft += 20;
405 graph.container.scrollTop += 20;
406 }
407 }
408 }));
409 action.setToggleAction(true);
410 action.setSelectedCallback(function() { return graph.pageVisible; });
411 this.put(\'pageBackgroundColor\', new Action(mxResources.get(\'backgroundColor\'), function()
412 {
413 var apply = function(color)
414 {
415 graph.background = color;
416 editor.updateGraphComponents();
417 };
418
419 var cd = new ColorDialog(ui, graph.background || \'none\', apply);
420 ui.showDialog(cd.container, 220, 360, true, false);
421
422 if (!mxClient.IS_TOUCH)
423 {
424 cd.colorInput.focus();
425 }
426 }));
427 action = this.addAction(\'connect\', function()
428 {
429 graph.setConnectable(!graph.connectionHandler.isEnabled());
430 }, null, null, \'Ctrl+Q\');
431 action.setToggleAction(true);
432 action.setSelectedCallback(function() { return graph.connectionHandler.isEnabled(); });
433
434 //帮助行为
435 this.addAction(\'help\', function()
436 {
437 var ext = \'\';
438
439 if (mxResources.isLanguageSupported(mxClient.language))
440 {
441 ext = \'_\' + mxClient.language;
442 }
443
444 window.open(RESOURCES_PATH + \'/help\' + ext + \'.html\');
445 });
446 this.put(\'about\', new Action(mxResources.get(\'about\') + \' Graph Editor\', function()
447 {
448 ui.showDialog(new AboutDialog(ui).container, 320, 280, true, true);
449 }, null, null, \'F1\'));
450
451 //字体风格的动作
452 var toggleFontStyle = mxUtils.bind(this, function(key, style)
453 {
454 this.addAction(key, function()
455 {
456 graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, style);
457 });
458 });
459
460 toggleFontStyle(\'bold\', mxConstants.FONT_BOLD);
461 toggleFontStyle(\'italic\', mxConstants.FONT_ITALIC);
462 toggleFontStyle(\'underline\', mxConstants.FONT_UNDERLINE);
463
464 //颜色动作
465 this.addAction(\'fontColor\', function() { ui.menus.pickColor(mxConstants.STYLE_FONTCOLOR); });
466 this.addAction(\'strokeColor\', function() { ui.menus.pickColor(mxConstants.STYLE_STROKECOLOR); });
467 this.addAction(\'fillColor\', function() { ui.menus.pickColor(mxConstants.STYLE_FILLCOLOR); });
468 this.addAction(\'gradientColor\', function() { ui.menus.pickColor(mxConstants.STYLE_GRADIENTCOLOR); });
469 this.addAction(\'backgroundColor\', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR); });
470 this.addAction(\'borderColor\', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BORDERCOLOR); });
471
472 //格式的行为
473 this.addAction(\'shadow\', function() { graph.toggleCellStyles(mxConstants.STYLE_SHADOW); });
474 this.addAction(\'dashed\', function() { graph.toggleCellStyles(mxConstants.STYLE_DASHED); });
475 this.addAction(\'rounded\', function() { graph.toggleCellStyles(mxConstants.STYLE_ROUNDED); });
476 this.addAction(\'style\', function()
477 {
478 var cells = graph.getSelectionCells();
479
480 if (cells != null && cells.length > 0)
481 {
482 var model = graph.getModel();
483 var style = mxUtils.prompt(mxResources.get(\'enterValue\')+ \' (\' + mxResources.get(\'style\') + \')\',
484 model.getStyle(cells[0]) || \'\');
485
486 if (style != null)
487 {
488 graph.setCellStyle(style, cells);
489 }
490 }
491 });
492 this.addAction(\'setAsDefaultEdge\', function()
493 {
494 var cell = graph.getSelectionCell();
495
496 if (cell != null && graph.getModel().isEdge(cell))
497 {
498 //采取快照的细胞在调用的时刻
499 var proto = graph.getModel().cloneCells([cell])[0];
500
501 //删除输入/ exitxy风格
502 var style = proto.getStyle();
503 style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_X, \'\');
504 style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_Y, \'\');
505 style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_X, \'\');
506 style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_Y, \'\');
507 proto.setStyle(style);
508
509 //使用边缘模板连接预览
510 graph.connectionHandler.createEdgeState = function(me)
511 {
512 return graph.view.createState(proto);
513 };
514
515 //创建新的连接边缘模板
516 graph.connectionHandler.factoryMethod = function()
517 {
518 return graph.cloneCells([proto])[0];
519 };
520 }
521 });
522 this.addAction(\'image\', function()
523 {
524 function updateImage(value, w, h)
525 {
526 var select = null;
527 var cells = graph.getSelectionCells();
528
529 graph.getModel().beginUpdate();
530 try
531 {
532 //没有选中单元格
533 if (cells.length == 0)
534 {
535 var gs = graph.getGridSize();
536 cells = [graph.insertVertex(graph.getDefaultParent(), null, \'\', gs, gs, w, h)];
537 select = cells;
538 }
539
540 graph.setCellStyles(mxConstants.STYLE_IMAGE, value, cells);
541 graph.setCellStyles(mxConstants.STYLE_SHAPE, \'image\', cells);
542
543 if (graph.getSelectionCount() == 1)
544 {
545 if (w != null && h != null)
546 {
547 var cell = cells[0];
548 var geo = graph.getModel().getGeometry(cell);
549
550 if (geo != null)
551 {
552 geo = geo.clone();
553 geo.width = w;
554 geo.height = h;
555 graph.getModel().setGeometry(cell, geo);
556 }
557 }
558 }
559 }
560 finally
561 {
562 graph.getModel().endUpdate();
563 }
564
565 if (select != null)
566 {
567 graph.setSelectionCells(select);
568 graph.scrollCellToVisible(select[0]);
569 }
570 };
571
572 var value = \'\';
573 var state = graph.getView().getState(graph.getSelectionCell());
574
575 if (state != null)
576 {
577 value = state.style[mxConstants.STYLE_IMAGE] || value;
578 }
579
580 value = mxUtils.prompt(mxResources.get(\'enterValue\') + \' (\' + mxResources.get(\'url\') + \')\', value);
581
582 if (value != null)
583 {
584 if (value.length > 0)
585 {
586 var img = new Image();
587
588 img.onload = function()
589 {
590 updateImage(value, img.width, img.height);
591 };
592 img.onerror = function()
593 {
594 mxUtils.alert(mxResources.get(\'fileNotFound\'));
595 };
596 img.src = value;
597 }
598 }
599 });
600 };
601
602 /**
603 * 寄存器的作用在给定的名称.
604 */
605 Actions.prototype.addAction = function(key, funct, enabled, iconCls, shortcut)
606 {
607 return this.put(key, new Action(mxResources.get(key), funct, enabled, iconCls, shortcut));
608 };
609
610 /**
611 * 寄存器的作用在给定的名称。
612 */
613 Actions.prototype.put = function(name, action)
614 {
615 this.actions[name] = action;
616
617 return action;
618 };
619
620 /**
621 * 返回给定名称或空如果没有这样的行动存在的动作。
622 */
623 Actions.prototype.get = function(name)
624 {
625 return this.actions[name];
626 };
627
628 /**
629 * 对于给定的参数的一种新的活动构造。
630 */
631 function Action(label, funct, enabled, iconCls, shortcut)
632 {
633 mxEventSource.call(this);
634 this.label = label;
635 this.funct = funct;
636 this.enabled = (enabled != null) ? enabled : true;
637 this.iconCls = iconCls;
638 this.shortcut = shortcut;
639 };
640
641 //行动继承mxeventsource
642 mxUtils.extend(Action, mxEventSource);
643
644
645 Action.prototype.setEnabled = function(value)
646 {
647 if (this.enabled != value)
648 {
649 this.enabled = value;
650 this.fireEvent(new mxEventObject(\'stateChanged\'));
651 }
652 };
653
654 /**
655 *套动作启用状态statechanged事件。
656 */
657 Action.prototype.setToggleAction = function(value)
658 {
659 this.toggleAction = value;
660 };
661
662 /**
663 *套动作启用状态statechanged事件。
664 */
665 Action.prototype.setSelectedCallback = function(funct)
666 {
667 this.selectedCallback = funct;
668 };
669
670 /**
671 * 套动作启用状态statechanged事件。
672 */
673 Action.prototype.isSelected = function()
674 {
675 return this.selectedCallback();
676 };
View Code
工具栏~Sidebar.js
如:图标A区 ,图标B区的控制
源码:
1 /**
2 *$id:Action 。JS,V 2015-3-23
3 *$author Dana丶Li$
4 */
5 /**
6 * Construcs a new sidebar for the given editor.
7 */
8 function Sidebar(editorUi, container)
9 {
10 this.editorUi = editorUi;
11 this.container = container;
12 this.palettes = new Object();
13 this.showTooltips = true;
14 this.graph = new Graph(document.createElement(\'div\'), null, null, this.editorUi.editor.graph.getStylesheet());
15 this.graph.foldingEnabled = false;
16 this.graph.autoScroll = false;
17 this.graph.setTooltips(false);
18 this.graph.setConnectable(false);
19 this.graph.resetViewOnRootChange = false;
20 this.graph.view.setTranslate(this.thumbBorder, this.thumbBorder);
21 this.graph.setEnabled(false);
22
23 // Workaround for VML rendering in IE8 standards mode where the container must be in the DOM
24 // so that VML references can be restored via document.getElementById in mxShape.init.
25 if (document.documentMode == 8)
26 {
27 document.body.appendChild(this.graph.container);
28 }
29
30 // Workaround for no rendering in 0 coordinate in FF 10
31 if (this.shiftThumbs)
32 {
33 this.graph.view.canvas.setAttribute(\'transform\', \'translate(1, 1)\');
34 }
35
36 if (!mxClient.IS_TOUCH)
37 {
38 mxEvent.addListener(document, \'mouseup\', mxUtils.bind(this, function()
39 {
40 this.showTooltips = true;
41 }));
42
43 // Enables tooltips after scroll
44 mxEvent.addListener(container, \'scroll\', mxUtils.bind(this, function()
45 {
46 this.showTooltips = true;
47 }));
48
49 mxEvent.addListener(document, \'mousedown\', mxUtils.bind(this, function()
50 {
51 this.showTooltips = false;
52 this.hideTooltip();
53 }));
54
55 mxEvent.addListener(document, \'mousemove\', mxUtils.bind(this, function(evt)
56 {
57 var src = mxEvent.getSource(evt);
58
59 while (src != null)
60 {
61 if (src == this.currentElt)
62 {
63 return;
64 }
65
66 src = src.parentNode;
67 }
68
69 this.hideTooltip();
70 }));
71
72 // Handles mouse leaving the window
73 mxEvent.addListener(document, \'mouseout\', mxUtils.bind(this, function(evt)
74 {
75 if (evt.toElement == null && evt.relatedTarget == null)
76 {
77 this.hideTooltip();
78 }
79 }));
80 }
81
82 this.init();
83
84 //图像预fetches提示
85 new Image().src = IMAGE_PATH + \'/tooltip.png\';
86 };
87
88 /**
89 * 将所有工具栏的侧边栏。
90 */
91 Sidebar.prototype.init = function()
92 {
93 var dir = STENCIL_PATH;
94
95 //this.addGeneralPalette(true);
96 //this.addUmlPalette(true);
97 //this.addBpmnPalette(dir, false);
98 //this.addStencilPalette(\'flowchart\', \'Flowchart\', dir + \'/flowchart.xml\',\';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2\');
99 //this.addStencilPalette(\'basic\', mxResources.get(\'basic\'), dir + \'/basic.xml\',\';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2\');
100 //this.addStencilPalette(\'arrows\', mxResources.get(\'arrows\'), dir + \'/arrows.xml\',\';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2\');
101
102 this.addImagePalette(\'clipart\', mxResources.get(\'clipart\'), dir + \'/clipart/\', \'_128x128.png\',
103 [ \'colud\', \'Firewall_02\', \'Server_Tower\', \'serverDB\', \'serverAuth\',
104 \'serverPrint\', \'serverEmail\', \'serverDisk\', \'Router_Icon\', \'routerFirewall\', \'route1\', \'atm\', \'police\',
105 \'accessServer\',\'SIP\', \'sipProxy\', \'ITP\', \'CA\', \'3U\', \'ipv6Route\',
106 \'3layer\', \'pbx\', \'IDS\', \'actionCheck\', \'gateWay***\', \'server1\',\'server2\',\'normalServer\',\'IPSAN\',\'H3Cswitch\']);
107
108 this.addImagePalette(\'clipartB\', mxResources.get(\'clipartB\'), dir + \'/clipart/\', \'.png\',
109 [ \'pic1\',\'pic2\',\'pic3\',\'pic4\',\'pic5\',\'pic6\',\'pic7\',\'pic8\',\'pic9\',\'pic10\',\'pic11\',\'pic12\',\'pic13\',\'pic14\',\'pic15\']);
110
111 };
112
113 /**
114 * 指定工具提示应该是可见的。默认的是真的。
115 */
116 Sidebar.prototype.enableTooltips = !mxClient.IS_TOUCH;
117
118 /**
119 * 将缩略图1像素。
120 */
121 Sidebar.prototype.shiftThumbs = mxClient.IS_SVG || document.documentMode == 8;
122
123 /**
124 * 指定工具提示的延迟。默认是16像素。
125 */
126 Sidebar.prototype.tooltipBorder = 16;
127
128 /**
129 * 指定工具提示的延迟。默认是2像素。
130 */
131 Sidebar.prototype.thumbBorder = 2;
132
133 /**
134 * Specifies the delay for the tooltip. Default is 300 ms.
135 */
136 Sidebar.prototype.tooltipDelay = 300;
137
138 /**
139 * Specifies if edges should be used as templates if clicked. Default is true.
140 */
141 Sidebar.prototype.installEdges = true;
142
143 /**
144 * Specifies the URL of the gear image.
145 */
146 Sidebar.prototype.gearImage = STENCIL_PATH + \'/clipart/Gear_128x128.png\';
147
148 /**
149 * Specifies the width of the thumbnails.
150 */
151 Sidebar.prototype.thumbWidth = 26;
152
153 /**
154 * Specifies the height of the thumbnails.
155 */
156 Sidebar.prototype.thumbHeight = 26;
157
158 /**
159 * Adds all palettes to the sidebar.
160 */
161 Sidebar.prototype.showTooltip = function(elt, cells)
162 {
163 if (this.enableTooltips && this.showTooltips)
164 {
165 if (this.currentElt != elt)
166 {
167 if (this.thread != null)
168 {
169 window.clearTimeout(this.thread);
170 this.thread = null;
171 }
172
173 var show = mxUtils.bind(this, function()
174 {
175 // Workaround for off-screen text rendering in IE
176 var old = mxText.prototype.getTableSize;
177
178 if (this.graph.dialect != mxConstants.DIALECT_SVG)
179 {
180 mxText.prototype.getTableSize = function(table)
181 {
182 var oldParent = table.parentNode;
183
184 document.body.appendChild(table);
185 var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
186 oldParent.appendChild(table);
187
188 return size;
189 };
190 }
191
192 // Lazy creation of the DOM nodes and graph instance
193 if (this.tooltip == null)
194 {
195 this.tooltip = document.createElement(\'div\');
196 this.tooltip.className = \'geSidebarTooltip\';
197 document.body.appendChild(this.tooltip);
198
199 this.graph2 = new Graph(this.tooltip, null, null, this.editorUi.editor.graph.getStylesheet());
200 this.graph2.view.setTranslate(this.tooltipBorder, this.tooltipBorder);
201 this.graph2.resetViewOnRootChange = false;
202 this.graph2.foldingEnabled = false;
203 this.graph2.autoScroll = false;
204 this.graph2.setTooltips(false);
205 this.graph2.setConnectable(false);
206 this.graph2.setEnabled(false);
207
208 this.tooltipImage = mxUtils.createImage(IMAGE_PATH + \'/tooltip.png\');
209 this.tooltipImage.style.position = \'absolute\';
210 this.tooltipImage.style.width = \'14px\';
211 this.tooltipImage.style.height = \'27px\';
212
213 document.body.appendChild(this.tooltipImage);
214 }
215
216 this.graph2.model.clear();
217 this.graph2.addCells(cells);
218
219 var bounds = this.graph2.getGraphBounds();
220 var width = bounds.x + bounds.width + this.tooltipBorder;
221 var height = bounds.y + bounds.height + this.tooltipBorder;
222
223 if (mxClient.IS_QUIRKS)
224 {
225 width += 4;
226 height += 4;
227 }
228
229 this.tooltip.style.display = \'block\';
230 this.tooltip.style.overflow = \'visible\';
231 this.tooltipImage.style.visibility = \'visible\';
232 this.tooltip.style.width = width + \'px\';
233 this.tooltip.style.height = height + \'px\';
234
235 var left = this.container.clientWidth + this.editorUi.splitSize + 3;
236 var top = Math.max(0, (this.container.offsetTop + elt.offsetTop - this.container.scrollTop - height / 2 + 16));
237
238 // Workaround for ignored position CSS style in IE9
239 // (changes to relative without the following line)
240 this.tooltip.style.position = \'absolute\';
241 this.tooltip.style.left = left + \'px\';
242 this.tooltip.style.top = top + \'px\';
243 this.tooltipImage.style.left = (left - 13) + \'px\';
244 this.tooltipImage.style.top = (top + height / 2 - 13) + \'px\';
245
246 mxText.prototype.getTableSize = old;
247 });
248
249 if (this.tooltip != null && this.tooltip.style.display != \'none\')
250 {
251 show();
252 }
253 else
254 {
255 this.thread = window.setTimeout(show, this.tooltipDelay);
256 }
257
258 this.currentElt = elt;
259 }
260 }
261 };
262
263 /**
264 * Hides the current tooltip.
265 */
266 Sidebar.prototype.hideTooltip = function()
267 {
268 if (this.thread != null)
269 {
270 window.clearTimeout(this.thread);
271 this.thread = null;
272 }
273
274 if (this.tooltip != null)
275 {
276 this.tooltip.style.display = \'none\';
277 this.tooltipImage.style.visibility = \'hidden\';
278 this.currentElt = null;
279 }
280 };
281
282 /**
283 * Adds the general palette to the sidebar.
284 */
285 Sidebar.prototype.addGeneralPalette = function(expand)
286 {
287 this.addPalette(\'general\', mxResources.get(\'general\'), expand || true, mxUtils.bind(this, function(content)
288 {
289 content.appendChild(this.createVertexTemplate(\'swimlane\', 200, 200, \'Container\'));
290 content.appendChild(this.createVertexTemplate(\'swimlane;horizontal=0\', 200, 200, \'Pool\'));
291 content.appendChild(this.createVertexTemplate(\'text\', 40, 26, \'Text\'));
292 content.appendChild(this.createVertexTemplate(\'icon;image=\' + this.gearImage, 60, 60, \'Image\'));
293 content.appendChild(this.createVertexTemplate(\'label;image=\' + this.gearImage, 140, 60, \'Label\'));
294 content.appendChild(this.createVertexTemplate(null, 120, 60));
295 content.appendChild(this.createVertexTemplate(\'rounded=1\', 120, 60));
296 content.appendChild(this.createVertexTemplate(\'ellipse\', 80, 80));
297 content.appendChild(this.createVertexTemplate(\'ellipse;shape=doubleEllipse\', 80, 80));
298 content.appendChild(this.createVertexTemplate(\'triangle\', 60, 80));
299 content.appendChild(this.createVertexTemplate(\'rhombus\', 80, 80));
300 content.appendChild(this.createVertexTemplate(\'shape=hexagon\', 120, 80));
301 content.appendChild(this.createVertexTemplate(\'shape=actor;verticalLabelPosition=bottom;verticalAlign=top\', 40, 60));
302 content.appendChild(this.createVertexTemplate(\'ellipse;shape=cloud\', 120, 80));
303 content.appendChild(this.createVertexTemplate(\'shape=cylinder\', 60, 80));
304 content.appendChild(this.createVertexTemplate(\'line\', 160, 10));
305 content.appendChild(this.createVertexTemplate(\'line;direction=south\', 10, 160));
306 content.appendChild(this.createVertexTemplate(\'shape=xor\', 60, 80));
307 content.appendChild(this.createVertexTemplate(\'shape=or\', 60, 80));
308 content.appendChild(this.createVertexTemplate(\'shape=step\', 120, 80));
309 content.appendChild(this.createVertexTemplate(\'shape=tape\', 120, 100));
310 content.appendChild(this.createVertexTemplate(\'shape=cube\', 120, 80));
311 content.appendChild(this.createVertexTemplate(\'shape=note\', 80, 100));
312 content.appendChild(this.createVertexTemplate(\'shape=folder\', 120, 120));
313 content.appendChild(this.createVertexTemplate(\'shape=card\', 60, 80));
314 content.appendChild(this.createVertexTemplate(\'shape=plus\', 20, 20));
315
316 content.appendChild(this.createEdgeTemplate(\'edgeStyle=none;endArrow=none;\', 100, 100));
317 content.appendChild(this.createEdgeTemplate(\'edgeStyle=none\', 100, 100));
318 content.appendChild(this.createEdgeTemplate(\'edgeStyle=elbowEdgeStyle;elbow=horizontal\', 100, 100));
319 content.appendChild(this.createEdgeTemplate(\'edgeStyle=elbowEdgeStyle;elbow=vertical\', 100, 100));
320 content.appendChild(this.createEdgeTemplate(\'edgeStyle=entityRelationEdgeStyle\', 100, 100));
321 content.appendChild(this.createEdgeTemplate(\'edgeStyle=segmentEdgeStyle\', 100, 100));
322 content.appendChild(this.createEdgeTemplate(\'edgeStyle=orthogonalEdgeStyle\', 100, 100));
323 content.appendChild(this.createEdgeTemplate(\'shape=link\', 100, 100));
324 content.appendChild(this.createEdgeTemplate(\'arrow\', 100, 100));
325 }));
326 };
327
328 /**
329 * Adds the general palette to the sidebar.
330 */
331 Sidebar.prototype.addUmlPalette = function(expand)
332 {
333 this.addPalette(\'uml\', \'UML\', expand || false, mxUtils.bind(this, function(content)
334 {
335 content.appendChild(this.createVertexTemplate(\'\', 110, 50, \'Object\'));
336
337 var classCell = new mxCell(\'<p style="margin:0px;margin-top:4px;text-align:center;">\' +
338 \'<b>Class</b></p>\' +
339 \'<hr/><div style="height:2px;"></div><hr/>\', new mxGeometry(0, 0, 140, 60),
340 \'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1\');
341 classCell.vertex = true;
342 content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60));
343
344 var classCell = new mxCell(\'<p style="margin:0px;margin-top:4px;text-align:center;">\' +
345 \'<b>Class</b></p>\' +
346 \'<hr/><p style="margin:0px;margin-left:4px;">+ field: Type</p><hr/>\' +
347 \'<p style="margin:0px;margin-left:4px;">+ method(): Type</p>\', new mxGeometry(0, 0, 160, 90),
348 \'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1\');
349 classCell.vertex = true;
350 content.appendChild(this.createVertexTemplateFromCells([classCell], 160, 90));
351
352 var classCell = new mxCell(\'<p style="margin:0px;margin-top:4px;text-align:center;">\' +
353 \'<i><<Interface>></i><br/><b>Interface</b></p>\' +
354 \'<hr/><p style="margin:0px;margin-left:4px;">+ field1: Type<br/>\' +
355 \'+ field2: Type</p>\' +
356 \'<hr/><p style="margin:0px;margin-left:4px;">\' +
357 \'+ method1(Type): Type<br/>\' +
358 \'+ method2(Type, Type): Type</p>\', new mxGeometry(0, 0, 190, 140),
359 \'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1\');
360 classCell.vertex = true;
361 content.appendChild(this.createVertexTemplateFromCells([classCell], 190, 140));
362
363 var classCell = new mxCell(\'Module\', new mxGeometry(0, 0, 120, 60),
364 \'shape=component;align=left;spacingLeft=36\');
365 classCell.vertex = true;
366
367 content.appendChild(this.createVertexTemplateFromCells([classCell], 120, 60));
368
369 var classCell = new mxCell(\'<<component>><br/><b>Component</b>\', new mxGeometry(0, 0, 180, 90),
370 \'overflow=fill;html=1\');
371 classCell.vertex = true;
372 var classCell1 = new mxCell(\'\', new mxGeometry(1, 0, 20, 20), \'shape=component;jettyWidth=8;jettyHeight=4;\');
373 classCell1.vertex = true;
374 classCell1.connectable = false;
375 classCell1.geometry.relative = true;
376 classCell1.geometry.offset = new mxPoint(-30, 10);
377 classCell.insert(classCell1);
378
379 content.appendChild(this.createVertexTemplateFromCells([classCell], 180, 90));
380
381 var classCell = new mxCell(\'<p style="margin:0px;margin-top:6px;text-align:center;"><b>Component</b></p>\' +
382 \'<hr/><p style="margin:0px;margin-left:8px;">+ Attribute1: Type<br/>+ Attribute2: Type</p>\', new mxGeometry(0, 0, 180, 90),
383 \'verticalAlign=top;align=left;overflow=fill;html=1\');
384 classCell.vertex = true;
385 var classCell1 = new mxCell(\'\', new mxGeometry(1, 0, 20, 20), \'shape=component;jettyWidth=8;jettyHeight=4;\');
386 classCell1.vertex = true;
387 classCell1.connectable = false;
388 classCell1.geometry.relative = true;
389 classCell1.geometry.offset = new mxPoint(-23, 3);
390 classCell.insert(classCell1);
391
392 content.appendChild(this.createVertexTemplateFromCells([classCell], 180, 90));
393
394 content.appendChild(this.createVertexTemplate(\'shape=lollipop;direction=south;\', 30, 10));
395
396 var cardCell = new mxCell(\'Block\', new mxGeometry(0, 0, 180, 120),
397 \'verticalAlign=top;align=left;spacingTop=8;spacingLeft=2;spacingRight=12;shape=cube;size=10;direction=south;fontStyle=4;\');
398 cardCell.vertex = true;
399 content.appendChild(this.createVertexTemplateFromCells([cardCell], 180, 120));
400
401 content.appendChild(this.createVertexTemplate(\'shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;\', 70, 50,
402 \'package\'));
403
404 var classCell = new mxCell(\'<p style="margin:0px;margin-top:4px;text-align:center;text-decoration:underline;">\' +
405 \'<b>Object:Type</b></p><hr/>\' +
406 \'<p style="margin:0px;margin-left:8px;">field1 = value1<br/>field2 = value2<br>field3 = value3</p>\',
407 new mxGeometry(0, 0, 160, 90),
408 \'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1\');
409 classCell.vertex = true;
410 content.appendChild(this.createVertexTemplateFromCells([classCell], 160, 90));
411
412 var tableCell = new mxCell(\'<table cellpadding="5" style="font-size:9pt;border:none;border-collapse:collapse;width:100%;">\' +
413 \'<tr><td colspan="2" style="border:1px solid gray;background:#e4e4e4;">Tablename</td></tr>\' +
414 \'<tr><td style="border:1px solid gray;">PK</td><td style="border:1px solid gray;">uniqueId</td></tr>\' +
415 \'<tr><td style="border:1px solid gray;">FK1</td><td style="border:1px solid gray;">foreignKey</td></tr>\' +
416 \'<tr><td style="border:1px solid gray;"></td><td style="border:1px solid gray;">fieldname</td></tr>\' +
417 \'</table>\', new mxGeometry(0, 0, 180, 99), \'verticalAlign=top;align=left;overflow=fill;html=1\');
418 tableCell.vertex = true;
419 content.appendChild(this.createVertexTemplateFromCells([tableCell], 180, 99));
420
421 content.appendChild(this.createVertexTemplate(\'shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top\', 40, 80, \'Actor\'));
422 content.appendChild(this.createVertexTemplate(\'ellipse\', 140, 70, \'Use Case\'));
423
424 var cardCell = new mxCell(\'\', new mxGeometry(0, 0, 30, 30),
425 \'ellipse;shape=startState;fillColor=#000000;strokeColor=#ff0000;\');
426 cardCell.vertex = true;
427
428 var assoc2 = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;\');
429 assoc2.geometry.setTerminalPoint(new mxPoint(15, 70), false);
430 assoc2.edge = true;
431
432 cardCell.insertEdge(assoc2, true);
433
434 content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 30, 30));
435
436 var cardCell = new mxCell(\'Activity\', new mxGeometry(0, 0, 120, 40),
437 \'rounded=1;arcSize=40;fillColor=#ffffc0;strokeColor=#ff0000;\');
438 cardCell.vertex = true;
439
440 var assoc2 = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;\');
441 assoc2.geometry.setTerminalPoint(new mxPoint(60, 80), false);
442 assoc2.edge = true;
443
444 cardCell.insertEdge(assoc2, true);
445
446 content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 120, 40));
447
448 var cardCell = new mxCell(\'<div style="margin-top:8px;"><b>Composite State</b><hr/>Subtitle</div>\', new mxGeometry(0, 0, 160, 60),
449 \'rounded=1;arcSize=40;overflow=fill;html=1;verticalAlign=top;fillColor=#ffffc0;strokeColor=#ff0000;\');
450 cardCell.vertex = true;
451
452 var assoc2 = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;\');
453 assoc2.geometry.setTerminalPoint(new mxPoint(80, 100), false);
454 assoc2.edge = true;
455
456 cardCell.insertEdge(assoc2, true);
457
458 content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 160, 60));
459
460 var cardCell = new mxCell(\'Condition\', new mxGeometry(0, 0, 80, 40),
461 \'rhombus;fillColor=#ffffc0;strokeColor=#ff0000;\');
462 cardCell.vertex = true;
463
464 var assoc1 = new mxCell(\'no\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;align=left;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;\');
465 assoc1.geometry.setTerminalPoint(new mxPoint(120, 20), false);
466 assoc1.geometry.relative = true;
467 assoc1.geometry.x = -1;
468 assoc1.edge = true;
469
470 cardCell.insertEdge(assoc1, true);
471
472 var assoc2 = new mxCell(\'yes\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;align=left;verticalAlign=top;endArrow=open;endSize=8;strokeColor=#ff0000;\');
473 assoc2.geometry.setTerminalPoint(new mxPoint(40, 80), false);
474 assoc2.geometry.relative = true;
475 assoc2.geometry.x = -1;
476 assoc2.edge = true;
477
478 cardCell.insertEdge(assoc2, true);
479
480 content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc1, assoc2], 80, 40));
481
482 var cardCell = new mxCell(\'\', new mxGeometry(0, 0, 200, 10),
483 \'shape=line;strokeWidth=6;strokeColor=#ff0000;\');
484 cardCell.vertex = true;
485
486 var assoc2 = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;\');
487 assoc2.geometry.setTerminalPoint(new mxPoint(100, 50), false);
488 assoc2.edge = true;
489
490 cardCell.insertEdge(assoc2, true);
491
492 content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 200, 10));
493
494 content.appendChild(this.createVertexTemplate(\'ellipse;shape=endState;fillColor=#000000;strokeColor=#ff0000\', 30, 30));
495
496 var classCell1 = new mxCell(\':Object\', new mxGeometry(0, 0, 100, 50));
497 classCell1.vertex = true;
498
499 var classCell2 = new mxCell(\'\', new mxGeometry(40, 50, 20, 240), \'shape=line;direction=north;dashed=1\');
500 classCell2.vertex = true;
501
502 content.appendChild(this.createVertexTemplateFromCells([classCell1, classCell2], 100, 290));
503
504 var classCell1 = new mxCell(\'\', new mxGeometry(100, 0, 20, 70));
505 classCell1.vertex = true;
506
507 var assoc1 = new mxCell(\'invoke\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;endArrow=block;\');
508 assoc1.geometry.setTerminalPoint(new mxPoint(0, 0), true);
509 assoc1.edge = true;
510
511 classCell1.insertEdge(assoc1, false);
512
513 content.appendChild(this.createVertexTemplateFromCells([classCell1, assoc1], 120, 70));
514
515 var classCell1 = new mxCell(\'\', new mxGeometry(100, 0, 20, 70));
516 classCell1.vertex = true;
517
518 var assoc1 = new mxCell(\'invoke\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;endArrow=block;\');
519 assoc1.geometry.setTerminalPoint(new mxPoint(0, 0), true);
520 assoc1.edge = true;
521
522 classCell1.insertEdge(assoc1, false);
523
524 var assoc2 = new mxCell(\'return\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;dashed=1;endArrow=open;endSize=8;\');
525 assoc2.geometry.setTerminalPoint(new mxPoint(0, 70), false);
526 assoc2.edge = true;
527
528 classCell1.insertEdge(assoc2, true);
529
530 var assoc3 = new mxCell(\'invoke\', new mxGeometry(0, 0, 0, 0), \'edgeStyle=elbowEdgeStyle;elbow=vertical;align=left;endArrow=open;\');
531 assoc3.edge = true;
532
533 classCell1.insertEdge(assoc3, true);
534 classCell1.insertEdge(assoc3, false);
535
536 content.appendChild(this.createVertexTemplateFromCells([classCell1, assoc1, assoc2, assoc3], 120, 70));
537
538 var assoc = new mxCell(\'name\', new mxGeometry(0, 0, 0, 0), \'endArrow=block;endFill=1;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=top;\');
539 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
540 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
541 assoc.geometry.relative = true;
542 assoc.geometry.x = -1;
543 assoc.edge = true;
544
545 var sourceLabel = new mxCell(\'1\', new mxGeometry(-1, 0, 0, 0), \'resizable=0;align=left;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10\');
546 sourceLabel.geometry.relative = true;
547 sourceLabel.setConnectable(false);
548 sourceLabel.vertex = true;
549 assoc.insert(sourceLabel);
550
551 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
552
553 var assoc = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'endArrow=none;edgeStyle=orthogonalEdgeStyle;\');
554 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
555 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
556 assoc.edge = true;
557
558 var sourceLabel = new mxCell(\'parent\', new mxGeometry(-1, 0, 0, 0), \'resizable=0;align=left;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10\');
559 sourceLabel.geometry.relative = true;
560 sourceLabel.setConnectable(false);
561 sourceLabel.vertex = true;
562 assoc.insert(sourceLabel);
563
564 var targetLabel = new mxCell(\'child\', new mxGeometry(1, 0, 0, 0), \'resizable=0;align=right;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10\');
565 targetLabel.geometry.relative = true;
566 targetLabel.setConnectable(false);
567 targetLabel.vertex = true;
568 assoc.insert(targetLabel);
569
570 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
571
572 var assoc = new mxCell(\'1\', new mxGeometry(0, 0, 0, 0), \'endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;\');
573 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
574 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
575 assoc.geometry.relative = true;
576 assoc.geometry.x = -1;
577 assoc.edge = true;
578
579 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
580
581 var assoc = new mxCell(\'Relation\', new mxGeometry(0, 0, 0, 0), \'endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;\');
582 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
583 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
584 assoc.edge = true;
585
586 var sourceLabel = new mxCell(\'0..n\', new mxGeometry(-1, 0, 0, 0), \'resizable=0;align=left;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10\');
587 sourceLabel.geometry.relative = true;
588 sourceLabel.setConnectable(false);
589 sourceLabel.vertex = true;
590 assoc.insert(sourceLabel);
591
592 var targetLabel = new mxCell(\'1\', new mxGeometry(1, 0, 0, 0), \'resizable=0;align=right;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10\');
593 targetLabel.geometry.relative = true;
594 targetLabel.setConnectable(false);
595 targetLabel.vertex = true;
596 assoc.insert(targetLabel);
597
598 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
599
600 var assoc = new mxCell(\'Use\', new mxGeometry(0, 0, 0, 0), \'endArrow=open;endSize=12;dashed=1\');
601 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
602 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
603 assoc.edge = true;
604
605 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
606
607 var assoc = new mxCell(\'Extends\', new mxGeometry(0, 0, 0, 0), \'endArrow=block;endSize=16;endFill=0;dashed=1\');
608 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
609 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
610 assoc.edge = true;
611
612 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
613
614 var assoc = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'endArrow=block;startArrow=block;endFill=1;startFill=1\');
615 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
616 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
617 assoc.edge = true;
618
619 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
620 }));
621 };
622
623 /**
624 * Adds the BPMN library to the sidebar.
625 */
626 Sidebar.prototype.addBpmnPalette = function(dir, expand)
627 {
628 this.addStencilPalette(\'bpmn\', \'BPMN\', dir + \'/bpmn.xml\',
629 \';fillColor=#ffffff;strokeColor=#000000;perimeter=ellipsePerimeter;\',
630 [\'Cancel\', \'Error\', \'Link\', \'Message\', \'Compensation\', \'Multiple\', \'Rule\', \'Timer\'],
631 function(content)
632 {
633 content.appendChild(this.createVertexTemplate(\'swimlane;horizontal=0;\', 300, 160, \'Pool\'));
634
635 var classCell = new mxCell(\'Process\', new mxGeometry(0, 0, 140, 60),
636 \'rounded=1\');
637 classCell.vertex = true;
638 var classCell1 = new mxCell(\'\', new mxGeometry(1, 1, 30, 30), \'shape=mxgraph.bpmn.timer_start;perimeter=ellipsePerimeter;\');
639 classCell1.vertex = true;
640 classCell1.geometry.relative = true;
641 classCell1.geometry.offset = new mxPoint(-40, -15);
642 classCell.insert(classCell1);
643
644 content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60));
645
646 var classCell = new mxCell(\'Process\', new mxGeometry(0, 0, 140, 60),
647 \'rounded=1\');
648 classCell.vertex = true;
649 var classCell1 = new mxCell(\'\', new mxGeometry(0.5, 1, 12, 12), \'shape=plus\');
650 classCell1.vertex = true;
651 classCell1.connectable = false;
652 classCell1.geometry.relative = true;
653 classCell1.geometry.offset = new mxPoint(-6, -12);
654 classCell.insert(classCell1);
655
656 content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60));
657
658 var classCell = new mxCell(\'Process\', new mxGeometry(0, 0, 140, 60),
659 \'rounded=1\');
660 classCell.vertex = true;
661 var classCell1 = new mxCell(\'\', new mxGeometry(0, 0, 20, 14), \'shape=message\');
662 classCell1.vertex = true;
663 classCell1.connectable = false;
664 classCell1.geometry.relative = true;
665 classCell1.geometry.offset = new mxPoint(5, 5);
666 classCell.insert(classCell1);
667
668 content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60));
669
670 var classCell = new mxCell(\'\', new mxGeometry(0, 0, 60, 40), \'shape=message\');
671 classCell.vertex = true;
672
673 content.appendChild(this.createEdgeTemplateFromCells([classCell], 60, 40));
674
675 var assoc = new mxCell(\'Sequence\', new mxGeometry(0, 0, 0, 0), \'endArrow=block;endFill=1;endSize=6\');
676 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
677 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
678 assoc.edge = true;
679
680 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
681
682 var assoc = new mxCell(\'Default\', new mxGeometry(0, 0, 0, 0), \'startArrow=dash;startSize=8;endArrow=block;endFill=1;endSize=6\');
683 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
684 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
685 assoc.edge = true;
686
687 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
688
689 var assoc = new mxCell(\'Conditional\', new mxGeometry(0, 0, 0, 0), \'startArrow=diamondThin;startFill=0;startSize=14;endArrow=block;endFill=1;endSize=6\');
690 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
691 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
692 assoc.edge = true;
693
694 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
695
696 var assoc = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'startArrow=oval;startFill=0;startSize=7;endArrow=block;endFill=0;endSize=10;dashed=1\');
697 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
698 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
699 assoc.edge = true;
700
701 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
702
703 var assoc = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'startArrow=oval;startFill=0;startSize=7;endArrow=block;endFill=0;endSize=10;dashed=1\');
704 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
705 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
706 assoc.edge = true;
707
708 var sourceLabel = new mxCell(\'\', new mxGeometry(0, 0, 20, 14), \'shape=message\');
709 sourceLabel.geometry.relative = true;
710 sourceLabel.setConnectable(false);
711 sourceLabel.vertex = true;
712 sourceLabel.geometry.offset = new mxPoint(-10, -7);
713 assoc.insert(sourceLabel);
714
715 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
716
717 var assoc = new mxCell(\'\', new mxGeometry(0, 0, 0, 0), \'shape=link\');
718 assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
719 assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
720 assoc.edge = true;
721
722 content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
723 }, 0.5);
724 };
725
726 /**
727 * Creates and returns the given title element.
728 */
729 Sidebar.prototype.createTitle = function(label)
730 {
731 var elt = document.createElement(\'a\');
732 elt.setAttribute(\'href\', \'javascript:void(0);\');
733 elt.className = \'geTitle\';
734 mxUtils.write(elt, label);
735
736 return elt;
737 };
738
739 /**
740 * Creates a thumbnail for the given cells.
741 */
742 Sidebar.prototype.createThumb = function(cells, width, height, parent)
743 {
744 // Workaround for off-screen text rendering in IE
745 var old = mxText.prototype.getTableSize;
746
747 if (this.graph.dialect != mxConstants.DIALECT_SVG)
748 {
749 mxText.prototype.getTableSize = function(table)
750 {
751 var oldParent = table.parentNode;
752
753 document.body.appendChild(table);
754 var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
755 oldParent.appendChild(table);
756
757 return size;
758 };
759 }
760
761 var prev = mxImageShape.prototype.preserveImageAspect;
762 mxImageShape.prototype.preserveImageAspect = false;
763
764 this.graph.view.rendering = false;
765 this.graph.view.setScale(1);
766 this.graph.addCells(cells);
767 var bounds = this.graph.getGraphBounds();
768
769 var corr = (this.shiftThumbs) ? this.thumbBorder + 1 : this.thumbBorder;
770 var s = Math.min((width - 1) / (bounds.x + bounds.width + corr),
771 (height - 1) / (bounds.y + bounds.height + corr));
772 this.graph.view.setScale(s);
773 this.graph.view.rendering = true;
774 this.graph.refresh();
775 mxImageShape.prototype.preserveImageAspect = prev;
776
777 bounds = this.graph.getGraphBounds();
778 var dx = Math.max(0, Math.floor((width - bounds.width) / 2));
779 var dy = Math.max(0, Math.floor((height - bounds.height) / 2));
780
781 var node = null;
782
783 // For supporting HTML labels in IE9 standards mode the container is cloned instead
784 if (this.graph.dialect == mxConstants.DIALECT_SVG && !mxClient.IS_IE)
785 {
786 node = this.graph.view.getCanvas().ownerSVGElement.cloneNode(true);
787 }
788 // Workaround for VML rendering in IE8 standards mode
789 else if (document.documentMode == 8)
790 {
791 node = this.graph.container.cloneNode(false);
792 node.innerHTML = this.graph.container.innerHTML;
793 }
794 else
795 {
796 node = this.graph.container.cloneNode(true);
797 }
798
799 this.graph.getModel().clear();
800
801 // Outer dimension is (32, 32)
802 var dd = (this.shiftThumbs) ? 2 : 3;
803 node.style.position = \'relative\';
804 node.style.overflow = \'visible\';
805 node.style.cursor = \'pointer\';
806 node.style.left = (dx + dd) + \'px\';
807 node.style.top = (dy + dd) + \'px\';
808 node.style.width = width + \'px\';
809 node.style.height = height + \'px\';
810
811 parent.appendChild(node);
812 mxText.prototype.getTableSize = old;
813 };
814
815 /**
816 * Creates and returns a new palette item for the given image.
817 */
818 Sidebar.prototype.createItem = function(cells)
819 {
820 var elt = document.createElement(\'a\');
821 elt.setAttribute(\'href\', \'javascript:void(0);\');
822 elt.className = \'geItem\';
823
824 // Blocks default click action
825 mxEvent.addListener(elt, \'click\', function(evt)
826 {
827 mxEvent.consume(evt);
828 });
829
830 this.createThumb(cells, this.thumbWidth, this.thumbHeight, elt);
831
832 return elt;
833 };
834
835 /**
836 * Creates a drop handler for inserting the given cells.
837 */
838 Sidebar.prototype.createDropHandler = function(cells, allowSplit)
839 {
840 return function(graph, evt, target, x, y)
841 {
842 cells = graph.getImportableCells(cells);
843
844 if (cells.length > 0)
845 {
846 var validDropTarget = (target != null) ?
847 graph.isValidDropTarget(target, cells, evt) : false;
848 var select = null;
849
850 if (target != null && !validDropTarget)
851 {
852 target = null;
853 }
854
855 // Splits the target edge or inserts into target group
856 if (allowSplit && graph.isSplitEnabled() && graph.isSplitTarget(target, cells, evt))
857 {
858 graph.splitEdge(target, cells, null, x, y);
859 select = cells;
860 }
861 else if (cells.length > 0)
862 {
863 select = graph.importCells(cells, x, y, target);
864 }
865
866 if (select != null && select.length > 0)
867 {
868 graph.scrollCellToVisible(select[0]);
869 graph.setSelectionCells(select);
870 }
871 }
872 };
873 };
874
875 /**
876 * Creates and returns a preview element for the given width and height.
877 */
878 Sidebar.prototype.createDragPreview = function(width, height)
879 {
880 var elt = document.createElement(\'div\');
881 elt.style.border = \'1px dashed black\';
882 elt.style.width = width + \'px\';
883 elt.style.height = height + \'px\';
884
885 return elt;
886 };
887
888 /**
889 * Creates a drag source for the given element.
890 */
891 Sidebar.prototype.createDragSource = function(elt, dropHandler, preview)
892 {
893 var dragSource = mxUtils.makeDraggable(elt, this.editorUi.editor.graph, dropHandler,
894 preview, 0, 0, this.editorUi.editor.graph.autoscroll, true, true);
895
896 // Allows drop into cell only if target is a valid root
897 dragSource.getDropTarget = function(graph, x, y)
898 {
899 var target = mxDragSource.prototype.getDropTarget.apply(this, arguments);
900
901 if (!graph.isValidRoot(target))
902 {
903 target = null;
904 }
905
906 return target;
907 };
908
909 return dragSource;
910 };
911
912 /**
913 * Adds a handler for inserting the cell with a single click.
914 */
915 Sidebar.prototype.addClickHandler = function(elt, ds)
916 {
917 var graph = this.editorUi.editor.graph;
918 var first = null;
919
920 var md = (mxClient.IS_TOUCH) ? \'touchstart\' : \'mousedown\';
921 mxEvent.addListener(elt, md, function(evt)
922 {
923 first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
924 });
925
926 var oldMouseUp = ds.mouseUp;
927 ds.mouseUp = function(evt)
928 {
929 if (!mxEvent.isPopupTrigger(evt) && this.currentGraph == null && first != null)
930 {
931 var tol = graph.tolerance;
932
933 if (Math.abs(first.x - mxEvent.getClientX(evt)) <= tol &&
934 Math.abs(first.y - mxEvent.getClientY(evt)) <= tol)
935 {
936 var gs = graph.getGridSize();
937 ds.drop(graph, evt, null, gs, gs);
938 }
939 }
940
941 oldMouseUp.apply(this, arguments);
942 first = null;
943 };
944 };
945
946 /**
947 * Creates a drop handler for inserting the given cells.
948 */
949 Sidebar.prototype.createVertexTemplate = function(style, width, height, value)
950 {
951 var cells = [new mxCell((value != null) ? value : \'\', new mxGeometry(0, 0, width, height), style)];
952 cells[0].vertex = true;
953
954 return this.createVertexTemplateFromCells(cells, width, height);
955 };
956
957 /**
958 * Creates a drop handler for inserting the given cells.
959 */
960 Sidebar.prototype.createVertexTemplateFromCells = function(cells, width, height)
961 {
962 var elt = this.createItem(cells);
963 var ds = this.createDragSource(elt, this.createDropHandler(cells, true), this.createDragPreview(width, height));
964 this.addClickHandler(elt, ds);
965
966 // Uses guides for vertices only if enabled in graph
967 ds.isGuidesEnabled = mxUtils.bind(this, function()
968 {
969 return this.editorUi.editor.graph.graphHandler.guidesEnabled;
970 });
971
972 // Shows a tooltip with the rendered cell
973 if (!touchStyle)
974 {
975 mxEvent.addListener(elt, \'mousemove\', mxUtils.bind(this, function(evt)
976 {
977 this.showTooltip(elt, cells);
978 }));
979 }
980
981 return elt;
982 };
983
984 /**
985 * Creates a drop handler for inserting the given cells.
986 */
987 Sidebar.prototype.createEdgeTemplate = function(style, width, height, value)
988 {
989 var cells = [new mxCell((value != null) ? value : \'\', new mxGeometry(0, 0, width, height), style)];
990 cells[0].geometry.setTerminalPoint(new mxPoint(0, height), true);
991 cells[0].geometry.setTerminalPoint(new mxPoint(width, 0), false);
992 cells[0].edge = true;
993
994 return this.createEdgeTemplateFromCells(cells, width, height);
995 };
996
997 /**
998 * Creates a drop handler for inserting the given cells.
999 */
1000 Sidebar.prototype.createEdgeTemplateFromCells = function(cells, width, height)
1001 {
1002 var elt = this.createItem(cells);
1003 this.createDragSource(elt, this.createDropHandler(cells, false), this.createDragPreview(width, height));
1004
1005 // Installs the default edge
1006 var graph = this.editorUi.editor.graph;
1007 mxEvent.addListener(elt, \'click\', mxUtils.bind(this, function(evt)
1008 {
1009 if (this.installEdges)
1010 {
1011 // Uses edge template for connect preview
1012 graph.connectionHandler.createEdgeState = function(me)
1013 {
1014 return graph.view.createState(cells[0]);
1015 };
1016
1017 // Creates new connections from edge template
1018 graph.connectionHandler.factoryMethod = function()
1019 {
1020 return graph.cloneCells([cells[0]])[0];
1021 };
1022 }
1023
1024 // Highlights the entry for 200ms
1025 elt.style.backgroundColor = \'#ffffff\';
1026
1027 window.setTimeout(function()
1028 {
1029 elt.style.backgroundColor = \'\';
1030 }, 200);
1031
1032 mxEvent.consume(evt);
1033 }));
1034
1035 // Shows a tooltip with the rendered cell
1036 if (!touchStyle)
1037 {
1038 mxEvent.addListener(elt, \'mousemove\', mxUtils.bind(this, function(evt)
1039 {
1040 this.showTooltip(elt, cells);
1041 }));
1042 }
1043
1044 return elt;
1045 };
1046
1047 /**
1048 * Adds the given palette.
1049 */
1050 Sidebar.prototype.addPalette = function(id, title, expanded, onInit)
1051 {
1052 var elt = this.createTitle(title);
1053 this.container.appendChild(elt);
1054
1055 var div = document.createElement(\'div\');
1056 div.className = \'geSidebar\';
1057
1058 if (expanded)
1059 {
1060 onInit(div);
1061 onInit = null;
1062 }
1063 else
1064 {
1065 div.style.display = \'none\';
1066 }
1067
1068 this.addFoldingHandler(elt, div, onInit);
1069
1070 var outer = document.createElement(\'div\');
1071 outer.appendChild(div);
1072 this.container.appendChild(outer);
1073
1074 // Keeps references to the DOM nodes
1075 if (id != null)
1076 {
1077 this.palettes[id] = [elt, outer];
1078 }
1079 };
1080
1081 /**
1082 * Create the given title element.
1083 */
1084 Sidebar.prototype.addFoldingHandler = function(title, content, funct)
1085 {
1086 var initialized = false;
1087
1088 title.style.backgroundImage = (content.style.display == \'none\') ?
1089 \'url(\' + IMAGE_PATH + \'/collapsed.gif)\' : \'url(\' + IMAGE_PATH + \'/expanded.gif)\';
1090 title.style.backgroundRepeat = \'no-repeat\';
1091 title.style.backgroundPosition = \'100% 50%\';
1092
1093 mxEvent.addListener(title, \'click\', function(evt)
1094 {
1095 if (content.style.display == \'none\')
1096 {
1097 if (!initialized)
1098 {
1099 initialized = true;
1100
1101 if (funct != null)
1102 {
1103 funct(content);
1104 }
1105 }
1106
1107 title.style.backgroundImage = \'url(\' + IMAGE_PATH + \'/expanded.gif)\';
1108 content.style.display = \'block\';
1109 }
1110 else
1111 {
1112 title.style.backgroundImage = \'url(\' + IMAGE_PATH + \'/collapsed.gif)\';
1113 content.style.display = \'none\';
1114 }
1115
1116 mxEvent.consume(evt);
1117 });
1118 };
1119
1120 /**
1121 * Removes the palette for the given ID.
1122 */
1123 Sidebar.prototype.removePalette = function(id)
1124 {
1125 var elts = this.palettes[id];
1126
1127 if (elts != null)
1128 {
1129 this.palettes[id] = null;
1130
1131 for (var i = 0; i < elts.length; i++)
1132 {
1133 this.container.removeChild(elts[i]);
1134 }
1135
1136 return true;
1137 }
1138
1139 return false;
1140 };
1141
1142 /**
1143 * Adds the given image palette.
1144 */
1145 Sidebar.prototype.addImagePalette = function(id, title, prefix, postfix, items)
1146 {
1147 this.addPalette(id, title, true, mxUtils.bind(this, function(content)
1148 {
1149 for (var i = 0; i < items.length; i++)
1150 {
1151 var icon = prefix + items[i] + postfix;
1152 content.appendChild(this.createVertexTemplate(\'image;image=\' + icon, 80, 80, \'\'));
1153 }
1154 }));
1155 };
1156
1157 /**
1158 * Adds the given stencil palette.
1159 */
1160 Sidebar.prototype.addStencilPalette = function(id, title, stencilFile, style, ignore, onInit, scale)
1161 {
1162 scale = (scale != null) ? scale : 1;
1163
1164 this.addPalette(id, title, false, mxUtils.bind(this, function(content)
1165 {
1166 if (style == null)
1167 {
1168 style = \'\';
1169 }
1170
1171 if (onInit != null)
1172 {
1173 onInit.call(this, content);
1174 }
1175
1176 mxStencilRegistry.loadStencilSet(stencilFile, mxUtils.bind(this, function(packageName, stencilName, displayName, w, h)
1177 {
1178 if (ignore == null || mxUtils.indexOf(ignore, stencilName) < 0)
1179 {
1180 content.appendChild(this.createVertexTemplate(\'shape=\' + packageName + stencilName.toLowerCase() + style,
1181 Math.round(w * scale), Math.round(h * scale), \'\'));
1182 }
1183 }), true);
1184 }));
1185 };
View Code
对应于配置属性文件的参数变量:
右键菜单绑定设备,设置线宽
文档比较乱! 也有点赶~
欢迎加入一起讨论,后期的开发与研讨,还有一些瓶颈没有解决....
Demo下载地址:点击下载
本文基于署名 2.5 ***许可协议发布,欢迎转载,演绎或用于商业目的,但是必须且在文章页面明显位置给出原文链接Dana、Li(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请留言或加Q群!