• 基于Web实现网络拓扑图


    想想好像好久没用写博客了! 由于最近想跳槽了(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="测试网闸[内端]&#xa;通讯:192.168.0.199 &#xa;业务: 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', 'gateWayVPN', '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>&lt;&lt;Interface&gt;&gt;</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('&lt;&lt;component&gt;&gt;<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;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群!
  • 相关阅读:
    TweenMax 前台脚本库
    如何使用CSS Sprites技术进行图片合并
    QQ群开放接口
    使用 Hexo 生成一套静态博客网页
    把表插入数据库
    WCF
    SOA
    登录验证
    登录菜单权限验证
    GetJsonByDataTable
  • 原文地址:https://www.cnblogs.com/visec479/p/4360052.html
Copyright © 2020-2023  润新知