想想好像好久没用写博客了! 由于最近想跳槽了(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
/**
*$id:Action 。JS,V 2015-3-23
*$author Dana丶Li$
*/
/**
* 构建了一种新的图形编辑器
* 编辑管理 实现方法管理
*/
EditorUi = function(editor, container)
{
this.editor = editor || new Editor();
this.container = container || document.body;
var graph = editor.graph;
//禁用滚动条
this.container.style.overflow = 'hidden'; var textEditing = mxUtils.bind(this, function(evt)
{
if (evt == null)
{
evt = window.event;
} if (this.isSelectionAllowed(evt))
{
return true;
} return graph.isEditing() || this.dialog != null;
}); //禁用文本选择而不是编辑没有对话框可见
if (this.container == document.body)
{
document.onselectstart = textEditing;
document.onmousedown = textEditing;
} //使用内置的上下文菜单编辑时
if (mxClient.IS_IE && document.documentMode != 9)
{
mxEvent.addListener(this.container, 'contextmenu', textEditing);
}
else
{
this.container.oncontextmenu = textEditing;
} //图像预fetches子菜单
new Image().src = mxPopupMenu.prototype.submenuImage; //预取连接图像
if (mxConnectionHandler.prototype.connectImage != null)
{
new Image().src = mxConnectionHandler.prototype.connectImage.src;
} //创建用户界面
this.actions = new Actions(this);
this.menus = new Menus(this);
this.createDivs();
this.refresh();
this.createUi(); //contains the given the inside main图审小组
graph.init(this.diagramContainer);
graph.refresh(); //使容器的滚动条和设置光标样式
graph.container.setAttribute('tabindex', '0');
graph.container.style.overflow = (touchStyle) ? 'hidden' : 'auto';
graph.container.style.cursor = 'default';
graph.container.style.backgroundImage = 'url(' + IMAGE_PATH + '/grid.gif)';
graph.container.focus(); //保持图形容器集中在鼠标按下
var graphFireMouseEvent = graph.fireMouseEvent;
graph.fireMouseEvent = function(evtName, me, sender)
{
if (evtName == mxEvent.MOUSE_DOWN)
{
this.container.focus();
} graphFireMouseEvent.apply(this, arguments);
}; //在鼠标经过时自动扩展配置
graph.panningHandler.autoExpand = true; //对上下文菜单
graph.panningHandler.factoryMethod = mxUtils.bind(this, function(menu, cell, evt)
{
this.menus.createPopupMenu(menu, cell, evt);
}); //初始化轮廓
editor.outline.init(this.outlineContainer); //隐藏菜单
var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
mxEvent.addListener(document, md, mxUtils.bind(this, function(evt)
{
graph.panningHandler.hideMenu();
})); //增加了手势操作(缩放)
if (mxClient.IS_TOUCH)
{
mxEvent.addListener(graph.container, 'gesturechange',
mxUtils.bind(this, function(evt)
{
graph.view.getDrawPane().setAttribute('transform', 'scale(' + evt.scale + ')');
graph.view.getOverlayPane().style.visibility = 'hidden';
})
); mxEvent.addListener(graph.container, 'gestureend',
mxUtils.bind(this, function(evt)
{
graph.view.getDrawPane().removeAttribute('transform');
graph.zoomToCenter = true;
graph.zoom(evt.scale);
graph.view.getOverlayPane().style.visibility = 'visible';
})
);
} // Create handler for key events
var keyHandler = this.createKeyHandler(editor); // Getter for key handler
this.getKeyHandler = function()
{
return keyHandler;
}; // Shows dialog if changes are lost
window.onbeforeunload = function()
{
if (editor.modified)
{
//return mxResources.get('allChangesLost');
}
}; // Updates the editor UI after the window has been resized
mxEvent.addListener(window, 'resize', mxUtils.bind(this, function()
{
this.refresh();
graph.sizeDidChange();
this.editor.outline.update(false);
this.editor.outline.outline.sizeDidChange();
})); // Updates action and menu states
this.init();
this.open();
}; /**
* Specifies the size of the split bar.
*/
EditorUi.prototype.splitSize = (mxClient.IS_TOUCH) ? 16 : 8; /**
* Specifies the height of the menubar. Default is 34.
*/
EditorUi.prototype.menubarHeight = 34; /**
* Specifies the height of the toolbar. Default is 46.
*/
EditorUi.prototype.toolbarHeight = 46; /**
* Specifies the height of the footer. Default is 28.
*/
EditorUi.prototype.footerHeight = 28; /**
* Specifies the position of the horizontal split bar. Default is 190.
*/
EditorUi.prototype.hsplitPosition = 190; /**
* Specifies the position of the vertical split bar. Default is 190.
*/
EditorUi.prototype.vsplitPosition = 190; /**
* Installs the listeners to update the action states.
*/
EditorUi.prototype.init = function()
{
// Updates action states
this.addUndoListener();
this.addSelectionListener(); // Overrides clipboard to update paste action state
var paste = this.actions.get('paste'); var updatePaste = function()
{
paste.setEnabled(!mxClipboard.isEmpty());
}; var mxClipboardCut = mxClipboard.cut;
mxClipboard.cut = function()
{
mxClipboardCut.apply(this, arguments);
updatePaste();
}; var mxClipboardCopy = mxClipboard.copy;
mxClipboard.copy = function()
{
mxClipboardCopy.apply(this, arguments);
updatePaste();
};
}; /**
* Hook for allowing selection and context menu for certain events.
*/
EditorUi.prototype.isSelectionAllowed = function(evt)
{
return false;
}; /**
* Opens the current diagram via the window.opener if one exists.
*/
EditorUi.prototype.open = function()
{
// Cross-domain window access is not allowed in FF, so if we
// were opened from another domain then this will fail.
try
{
if (window.opener != null && window.opener.openFile != null)
{
window.opener.openFile.setConsumer(mxUtils.bind(this, function(xml, filename)
{
try
{
var doc = mxUtils.parseXml(xml);
this.editor.setGraphXml(doc.documentElement);
this.editor.modified = false;
this.editor.undoManager.clear(); if (filename != null)
{
this.editor.filename = filename;
}
}
catch (e)
{
mxUtils.alert(mxResources.get('invalidOrMissingFile') + ': ' + e.message);
}
}));
}
}
catch(e)
{
// ignore
}
}; /**
* 在给定的文件名保存当前图。
*/
EditorUi.prototype.save = function()
{
var xml = mxUtils.getXml(this.editor.getGraphXml());
//火狐浏览器
//if (navigator.userAgent.indexOf('Firefox') >= 0){
//}
xml="<mxGraphModel grid=\"0\" guides=\"1\" tooltips=\"1\" connect=\"1\" fold=\"1\" page=\"0\" pageScale=\"1\" pageWidth=\"826\" pageHeight=\"1169\">"+xml+"</mxGraphModel>" //将xml代码保存至服务器文件
$.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"xml":xml,"type":"set"},function(text){
if(text=="0"){
alert("保存失败!");
}
});
}; /**
* 返回一个拷贝没有状态这个编辑器的URL。
*/
EditorUi.prototype.getUrl = function(pathname)
{
var href = (pathname != null) ? pathname : window.location.pathname;
var parms = (pathname.indexOf('?') > 0) ? 1 : 0; // Removes template URL parameter for new blank diagram
for (var key in urlParams)
{
if (parms == 0)
{
href += '?';
}
else
{
href += '&';
} href += key + '=' + urlParams[key];
parms++;
} return href;
}; /**
* 更新的撤销/重做项的状态。
*/
EditorUi.prototype.addUndoListener = function()
{
var undo = this.actions.get('undo');
var redo = this.actions.get('redo'); var undoMgr = this.editor.undoManager; var undoListener = function()
{
undo.setEnabled(undoMgr.canUndo());
redo.setEnabled(undoMgr.canRedo());
}; undoMgr.addListener(mxEvent.ADD, undoListener);
undoMgr.addListener(mxEvent.UNDO, undoListener);
undoMgr.addListener(mxEvent.REDO, undoListener);
undoMgr.addListener(mxEvent.CLEAR, undoListener); // Updates the button states once
undoListener();
}; /**
* Updates the states of the given toolbar items based on the selection.
*/
EditorUi.prototype.addSelectionListener = function()
{
var selectionListener = mxUtils.bind(this, function()
{
var graph = this.editor.graph;
var selected = !graph.isSelectionEmpty();
var vertexSelected = false;
var edgeSelected = false; var cells = graph.getSelectionCells(); if (cells != null)
{
for (var i = 0; i < cells.length; i++)
{
var cell = cells[i]; if (graph.getModel().isEdge(cell))
{
edgeSelected = true;
} if (graph.getModel().isVertex(cell))
{
vertexSelected = true;
} if (edgeSelected && vertexSelected)
{
break;
}
}
} // 更新动作状态
var actions = ['cut', 'copy', 'delete', 'duplicate', 'bold', 'italic', 'style', 'fillColor',
'gradientColor', 'underline', 'fontColor', 'strokeColor', 'backgroundColor',
'borderColor', 'toFront', 'toBack', 'dashed', 'rounded', 'shadow', 'rotate',
'autosize']; for (var i = 0; i < actions.length; i++)
{
this.actions.get(actions[i]).setEnabled(selected);
} this.actions.get('rotation').setEnabled(vertexSelected);
this.actions.get('group').setEnabled(graph.getSelectionCount() > 1);
this.actions.get('ungroup').setEnabled(graph.getSelectionCount() == 1 &&
graph.getModel().getChildCount(graph.getSelectionCell()) > 0);
var oneVertexSelected = vertexSelected && graph.getSelectionCount() == 1;
this.actions.get('removeFromGroup').setEnabled(oneVertexSelected &&
graph.getModel().isVertex(graph.getModel().getParent(graph.getSelectionCell()))); //更新菜单状态
var menus = ['fontFamily', 'fontSize', 'alignment', 'position', 'text', 'format',
'arrange', 'linewidth', 'spacing', 'gradient']; for (var i = 0; i < menus.length; i++)
{
this.menus.get(menus[i]).setEnabled(selected);
} menus = ['line', 'lineend', 'linestart']; for (var i = 0; i < menus.length; i++)
{
this.menus.get(menus[i]).setEnabled(edgeSelected);
} this.actions.get('setAsDefaultEdge').setEnabled(edgeSelected); this.menus.get('align').setEnabled(graph.getSelectionCount() > 1);
this.menus.get('direction').setEnabled(vertexSelected || (edgeSelected &&
graph.isLoop(graph.view.getState(graph.getSelectionCell()))));
this.menus.get('navigation').setEnabled(graph.foldingEnabled && ((graph.view.currentRoot != null) ||
(graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell()))));
this.actions.get('home').setEnabled(graph.view.currentRoot != null);
this.actions.get('exitGroup').setEnabled(graph.view.currentRoot != null);
var groupEnabled = graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell());
this.actions.get('enterGroup').setEnabled(groupEnabled);
this.actions.get('expand').setEnabled(groupEnabled);
this.actions.get('collapse').setEnabled(groupEnabled);
this.actions.get('editLink').setEnabled(graph.getSelectionCount() == 1);
this.actions.get('openLink').setEnabled(graph.getSelectionCount() == 1 &&
graph.getLinkForCell(graph.getSelectionCell()) != null);
}); this.editor.graph.getSelectionModel().addListener(mxEvent.CHANGE, selectionListener);
selectionListener();
}; /**
* Refreshes the viewport.
*/
EditorUi.prototype.refresh = function()
{
var quirks = mxClient.IS_IE && (document.documentMode == null || document.documentMode == 5);
var w = this.container.clientWidth;
var h = this.container.clientHeight; if (this.container == document.body)
{
w = document.body.clientWidth || document.documentElement.clientWidth;
h = (quirks) ? document.body.clientHeight || document.documentElement.clientHeight : document.documentElement.clientHeight;
} var effHsplitPosition = Math.max(0, Math.min(this.hsplitPosition, w - this.splitSize - 20));
var effVsplitPosition = Math.max(0, Math.min(this.vsplitPosition, h - this.menubarHeight - this.toolbarHeight - this.footerHeight - this.splitSize - 1)); this.menubarContainer.style.height = this.menubarHeight + 'px';
this.toolbarContainer.style.top = this.menubarHeight + 'px';
this.toolbarContainer.style.height = this.toolbarHeight + 'px';
this.sidebarContainer.style.top = (this.menubarHeight + this.toolbarHeight) + 'px';
this.sidebarContainer.style.width = effHsplitPosition + 'px';
this.outlineContainer.style.width = effHsplitPosition + 'px';
this.outlineContainer.style.height = effVsplitPosition + 'px';
this.outlineContainer.style.bottom = this.footerHeight + 'px';
this.diagramContainer.style.left = (effHsplitPosition + this.splitSize) + 'px';
this.diagramContainer.style.top = this.sidebarContainer.style.top;
this.footerContainer.style.height = this.footerHeight + 'px';
this.hsplit.style.top = this.sidebarContainer.style.top;
this.hsplit.style.bottom = this.outlineContainer.style.bottom;
this.hsplit.style.left = effHsplitPosition + 'px';
this.vsplit.style.width = this.sidebarContainer.style.width;
this.vsplit.style.bottom = (effVsplitPosition + this.footerHeight) + 'px'; if (quirks)
{
this.menubarContainer.style.width = w + 'px';
this.toolbarContainer.style.width = this.menubarContainer.style.width;
var sidebarHeight = (h - effVsplitPosition - this.splitSize - this.footerHeight - this.menubarHeight - this.toolbarHeight);
this.sidebarContainer.style.height = sidebarHeight + 'px';
this.diagramContainer.style.width = (w - effHsplitPosition - this.splitSize) + 'px';
var diagramHeight = (h - this.footerHeight - this.menubarHeight - this.toolbarHeight);
this.diagramContainer.style.height = diagramHeight + 'px';
this.footerContainer.style.width = this.menubarContainer.style.width;
this.hsplit.style.height = diagramHeight + 'px';
}
else
{
this.sidebarContainer.style.bottom = (effVsplitPosition + this.splitSize + this.footerHeight) + 'px';
this.diagramContainer.style.bottom = this.outlineContainer.style.bottom;
}
}; /**
* Creates the required containers.
*/
EditorUi.prototype.createDivs = function()
{
this.menubarContainer = this.createDiv('geMenubarContainer');
this.toolbarContainer = this.createDiv('geToolbarContainer');
this.sidebarContainer = this.createDiv('geSidebarContainer');
this.outlineContainer = this.createDiv('geOutlineContainer');
this.diagramContainer = this.createDiv('geDiagramContainer');
this.footerContainer = this.createDiv('geFooterContainer');
this.hsplit = this.createDiv('geHsplit');
this.vsplit = this.createDiv('geVsplit'); // Sets static style for containers
this.menubarContainer.style.top = '0px';
this.menubarContainer.style.left = '0px';
this.menubarContainer.style.right = '0px';
this.toolbarContainer.style.left = '0px';
this.toolbarContainer.style.right = '0px';
this.sidebarContainer.style.left = '0px';
this.outlineContainer.style.left = '0px';
this.diagramContainer.style.right = '0px';
this.footerContainer.style.left = '0px';
this.footerContainer.style.right = '0px';
this.footerContainer.style.bottom = '0px';
this.vsplit.style.left = '0px';
this.vsplit.style.height = this.splitSize + 'px';
this.hsplit.style.width = this.splitSize + 'px';
}; /**
* Creates the required containers.
*/
EditorUi.prototype.createUi = function()
{
// Creates menubar
this.menubar = this.menus.createMenubar(this.createDiv('geMenubar'));
this.menubarContainer.appendChild(this.menubar.container); // Creates toolbar
this.toolbar = this.createToolbar(this.createDiv('geToolbar'));
this.toolbarContainer.appendChild(this.toolbar.container); // Creates the sidebar
this.sidebar = this.createSidebar(this.sidebarContainer); // Creates the footer
this.footerContainer.appendChild(this.createFooter()); // Adds status bar in menubar
this.statusContainer = this.createStatusContainer(); // Connects the status bar to the editor status
this.editor.addListener('statusChanged', mxUtils.bind(this, function()
{
this.setStatusText(this.editor.getStatus());
})); this.setStatusText(this.editor.getStatus());
this.menubar.container.appendChild(this.statusContainer); // Inserts into DOM
this.container.appendChild(this.menubarContainer);
this.container.appendChild(this.toolbarContainer);
this.container.appendChild(this.sidebarContainer);
this.container.appendChild(this.outlineContainer);
this.container.appendChild(this.diagramContainer);
this.container.appendChild(this.footerContainer);
this.container.appendChild(this.hsplit);
this.container.appendChild(this.vsplit); // HSplit
this.addSplitHandler(this.hsplit, true, 0, mxUtils.bind(this, function(value)
{
this.hsplitPosition = value;
this.refresh();
this.editor.graph.sizeDidChange();
this.editor.outline.update(false);
this.editor.outline.outline.sizeDidChange();
})); // VSplit
this.addSplitHandler(this.vsplit, false, this.footerHeight, mxUtils.bind(this, function(value)
{
this.vsplitPosition = value;
this.refresh();
this.editor.outline.update(false);
this.editor.outline.outline.sizeDidChange();
}));
}; /**
* Creates a new toolbar for the given container.
*/
EditorUi.prototype.createStatusContainer = function()
{
var container = document.createElement('a');
container.className = 'geItem geStatus'; return container;
}; /**
* Creates a new toolbar for the given container.
*/
EditorUi.prototype.setStatusText = function(value)
{
this.statusContainer.innerHTML = value;
}; /**
* Creates a new toolbar for the given container.
*/
EditorUi.prototype.createToolbar = function(container)
{
return new Toolbar(this, container);
}; /**
* Creates a new sidebar for the given container.
*/
EditorUi.prototype.createSidebar = function(container)
{
return new Sidebar(this, container);
}; /**
* Creates and returns a new footer.
*/
EditorUi.prototype.createFooter = function()
{
return this.createDiv('geFooter');
}; /**
* Creates the actual toolbar for the toolbar container.
*/
EditorUi.prototype.createDiv = function(classname)
{
var elt = document.createElement('div');
elt.className = classname; return elt;
}; /**
* Updates the states of the given undo/redo items.
*/
EditorUi.prototype.addSplitHandler = function(elt, horizontal, dx, onChange)
{
var start = null;
var initial = null; function getValue()
{
return parseInt(((horizontal) ? elt.style.left : elt.style.bottom));
} var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup'; mxEvent.addListener(elt, md, function(evt)
{
start = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
initial = getValue();
mxEvent.consume(evt);
}); function moveHandler(evt)
{
if (start != null)
{
var pt = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
onChange(Math.max(0, initial + ((horizontal) ? (pt.x - start.x) : (start.y - pt.y)) - dx));
mxEvent.consume(evt);
}
} mxEvent.addListener(document, mm, moveHandler); mxEvent.addListener(document, mu, function(evt)
{
moveHandler(evt);
start = null;
initial = null;
});
}; /**
* Displays a print dialog.
*/
EditorUi.prototype.showDialog = function(elt, w, h, modal, closable, onClose)
{
this.hideDialog();
this.dialog = new Dialog(this, elt, w, (mxClient.IS_VML) ? h - 12 : h, modal, closable, onClose);
}; /**
* Displays a print dialog.
*/
EditorUi.prototype.hideDialog = function()
{
if (this.dialog != null)
{
this.dialog.close();
this.dialog = null;
this.editor.graph.container.focus();
}
}; /**
* Adds the label menu items to the given menu and parent.
*/
EditorUi.prototype.openFile = function()
{
// Closes dialog after open
window.openFile = new OpenFile(mxUtils.bind(this, function()
{
this.hideDialog();
})); // Removes openFile if dialog is closed
this.showDialog(new OpenDialog(this).container, 300, 180, true, true, function()
{
window.openFile = null;
});
}; /**
* Adds the label menu items to the given menu and parent.
*/
EditorUi.prototype.saveFile = function(forceDialog)
{
if (!forceDialog && this.editor.filename != null)
{
this.save(this.editor.getOrCreateFilename());
}
else
{
this.showDialog(new SaveDialog(this).container, 300, 100, true, true);
}
}; /**
* Executes the given layout.
*/
EditorUi.prototype.executeLayout = function(layout, animate, ignoreChildCount)
{
var graph = this.editor.graph;
var cell = graph.getSelectionCell(); graph.getModel().beginUpdate();
try
{
layout.execute(graph.getDefaultParent(), cell);
}
catch (e)
{
throw e;
}
finally
{
// Animates the changes in the graph model except
// for Camino, where animation is too slow
if (animate && navigator.userAgent.indexOf('Camino') < 0)
{
// New API for animating graph layout results asynchronously
var morph = new mxMorphing(graph);
morph.addListener(mxEvent.DONE, mxUtils.bind(this, function()
{
graph.getModel().endUpdate();
})); morph.startAnimation();
}
else
{
graph.getModel().endUpdate();
}
}
}; /**
* Creates the keyboard event handler for the current graph and history.
*/
EditorUi.prototype.createKeyHandler = function(editor)
{
var graph = this.editor.graph;
var keyHandler = new mxKeyHandler(graph); // Routes command-key to control-key on Mac
keyHandler.isControlDown = function(evt)
{
return mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey);
}; // Helper function to move cells with the cursor keys
function nudge(keyCode)
{
if (!graph.isSelectionEmpty())
{
var dx = 0;
var dy = 0; if (keyCode == 37)
{
dx = -1;
}
else if (keyCode == 38)
{
dy = -1;
}
else if (keyCode == 39)
{
dx = 1;
}
else if (keyCode == 40)
{
dy = 1;
} graph.moveCells(graph.getSelectionCells(), dx, dy);
graph.scrollCellVisible(graph.getSelectionCell());
}
}; // Binds keystrokes to actions
var bindAction = mxUtils.bind(this, function(code, control, key, shift)
{
var action = this.actions.get(key); if (action != null)
{
var f = function()
{
if (action.enabled)
{
action.funct();
}
}; if (control)
{
if (shift)
{
keyHandler.bindControlShiftKey(code, f);
}
else
{
keyHandler.bindControlKey(code, f);
}
}
else
{
if (shift)
{
keyHandler.bindShiftKey(code, f);
}
else
{
keyHandler.bindKey(code, f);
}
}
}
}); var ui = this;
var keyHandleEscape = keyHandler.escape;
keyHandler.escape = function(evt)
{
ui.hideDialog();
keyHandleEscape.apply(this, arguments);
}; // Ignores enter keystroke. Remove this line if you want the
// enter keystroke to stop editing.
keyHandler.enter = function() {};
keyHandler.bindKey(8, function() { graph.foldCells(true); }); // Backspace
keyHandler.bindKey(13, function() { graph.foldCells(false); }); // Enter
keyHandler.bindKey(33, function() { graph.exitGroup(); }); // Page Up
keyHandler.bindKey(34, function() { graph.enterGroup(); }); // Page Down
keyHandler.bindKey(36, function() { graph.home(); }); // Home
keyHandler.bindKey(35, function() { graph.refresh(); }); // End
keyHandler.bindKey(37, function() { nudge(37); }); // Left arrow
keyHandler.bindKey(38, function() { nudge(38); }); // Up arrow
keyHandler.bindKey(39, function() { nudge(39); }); // Right arrow
keyHandler.bindKey(40, function() { nudge(40); }); // Down arrow
keyHandler.bindKey(113, function() { graph.startEditingAtCell(); });
bindAction(46, false, 'delete'); // Delete
bindAction(82, true, 'rotate'); // Ctrl+R
bindAction(83, true, 'save'); // Ctrl+S
bindAction(83, true, 'saveAs', true); // Ctrl+Shift+S
bindAction(107, false, 'zoomIn'); // Add
bindAction(109, false, 'zoomOut'); // Subtract
bindAction(65, true, 'selectAll'); // Ctrl+A
bindAction(86, true, 'selectVertices', true); // Ctrl+Shift+V
bindAction(69, true, 'selectEdges', true); // Ctrl+Shift+E
bindAction(69, true, 'export'); // Ctrl+Shift+E
bindAction(66, true, 'toBack'); // Ctrl+B
bindAction(70, true, 'toFront'); // Ctrl+F
bindAction(68, true, 'duplicate'); // Ctrl+D
bindAction(90, true, 'undo'); // Ctrl+Z
bindAction(89, true, 'redo'); // Ctrl+Y
bindAction(88, true, 'cut'); // Ctrl+X
bindAction(67, true, 'copy'); // Ctrl+C
bindAction(81, true, 'connect'); // Ctrl+Q
bindAction(86, true, 'paste'); // Ctrl+V
bindAction(71, true, 'group'); // Ctrl+G
bindAction(71, true, 'grid', true); // Ctrl+Shift+G
bindAction(85, true, 'ungroup'); // Ctrl+U
bindAction(112, false, 'about'); // F1 return keyHandler;
};
这里是图形化操作以后保存拓扑对于的Xml文件,便于再次访问,或者查看的时候加载原信息!
如操作功能:
对应的通过上面EditorUi.js文件中EditorUi.prototype.save = function()控制,我是通过一个Servlet来保存XML文件
package com.visec.systemConfig;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <p>Title: 网络拓扑图保存</p>
* <p>Description: 将网络拓扑图保存至对应的xml文件中 以及 读取网络拓扑图对应的xml文件</p>
* <p>Copyright: Copyright (c) 2015</p>
* <p>Company: XXX科技</p>
* @author 李尚志
* @version 3.0
*/
public class SaveToXmlServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
String type = request.getParameter("type");
String tp = request.getParameter("tp");
StringBuffer result = new StringBuffer("");
String xmlPath=new String("");
String strPath = this.getClass().getResource("/").toString();
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";
String osName = System.getProperties().getProperty("os.name");
if(osName.toLowerCase().indexOf("windows")>-1){
strPath=strPath.substring(6)+xmlPath;
}else{
strPath=strPath.substring(5)+xmlPath;
}
File file = new File(strPath);
if(file.isFile()){//判断该路径是否为一个文件
if("set".equals(type.toLowerCase())){//文件保存
String xml = request.getParameter("xml");
if(xml==null||"".equals(xml)){
result.append("0");
}else{
RandomAccessFile randomAccessFile = new RandomAccessFile(strPath, "rw");
randomAccessFile.seek(0);
randomAccessFile.setLength(0);
randomAccessFile.write(xml.getBytes());
randomAccessFile.close();
result.append("1");
}
}else if("get".equals(type.toLowerCase())){//获取文件信息
//开始读取
BufferedReader reader = new BufferedReader(new FileReader(new File(strPath)));
String tempString = null;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null){
result.append(tempString);
}
reader.close();
}
}else{
System.out.println(strPath+" 找不到!");
result.append("0");
}
PrintWriter out = response.getWriter();
out.write(result.toString());
out.flush();
out.close();
} }
当我们再次访问编辑页面时,即要加载先前对应的XML文件
主要文件( Actions.js和上述Servlet中get方法)
Servlet在此处省略(上述中已提供源码)
Actions.js源码
/**
*$id:Action 。JS,V 2015-3-23
*$author Dana丶Li$
*/
/**
*结构对于给定的UI操作的对象。
*编辑函数方法管理
*/
function Actions(editorUi)
{
this.editorUi = editorUi;
this.actions = new Object();
this.init();
};
/**
* 添加默认的函数
*/
Actions.prototype.init = function()
{
var ui = this.editorUi;
var editor = ui.editor;
var graph = editor.graph;
graph.cellsMovable=!0; //设置不可移动
graph.cellsDisconnectable=!0; //设置边不可编辑
graph.cellsResizable=!0; //设置不可改变大小
$.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"type":"get"},function(text){
if(text=="0"){
alert("拓扑图XML文件加载失败!");
}else{
//保存拓扑图XML模板文件
//example:
//<mxGraphModel grid="0" guides="1" tooltips="1" connect="1" fold="1" page="0" pageScale="1" pageWidth="826" pageHeight="1169">
// <root>
// <mxCell id="0"/>
// <mxCell id="1" parent="0"/>
// <mxCell id="2" value="测试网闸[内端] 通讯:192.168.0.199 业务: 192.168.1.199" style="image;image=stencils/clipart/pic3.png" vertex="1" remark="142588842925033" parent="1">
// <mxGeometry x="236" y="139" width="80" height="80" as="geometry"/>
// </mxCell>
// </root>
//</mxGraphModel>
var xml = text;
var doc = mxUtils.parseXml(xml);
var model = new mxGraphModel();
var codec = new mxCodec(doc);
codec.decode(doc.documentElement, model);
var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
graph.setSelectionCells(editor.graph.importCells(children));
}
}); //文件操作
this.addAction('new', function() { window.open(ui.getUrl());});
this.addAction('open', function()
{
window.openNew = true;
window.openKey = 'open';
ui.openFile();
}); this.addAction('import', function()
{
window.openNew = false;
window.openKey = 'import'; //关闭对话框后打开
window.openFile = new OpenFile(mxUtils.bind(this, function()
{
ui.hideDialog();
})); window.openFile.setConsumer(mxUtils.bind(this, function(xml, filename)
{
try
{
var doc = mxUtils.parseXml(xml);
var model = new mxGraphModel();
var codec = new mxCodec(doc);
codec.decode(doc.documentElement, model); var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
editor.graph.setSelectionCells(editor.graph.importCells(children));
}
catch (e)
{
mxUtils.alert(mxResources.get('invalidOrMissingFile') + ': ' + e.message);
}
})); //如果删除打开文件对话框关闭
ui.showDialog(new OpenDialog(this).container, 300, 180, true, true, function()
{
window.openFile = null;
});
});
this.addAction('save', function() { ui.save(); }, null, null, 'Ctrl+S'); //this.addAction('saveAs', function() { ui.saveFile(true); }, null, null, 'Ctrl+Shift-S');
//this.addAction('export', function() { ui.showDialog(new ExportDialog(ui).container, 300, 200, true, true); }, null, null, 'Ctrl+E');
//this.put('editFile', new Action(mxResources.get('edit'), mxUtils.bind(this, function()
//{
//this.editorUi.showDialog(new EditFileDialog(ui).container, 620, 420, true, true);
//})));
this.addAction('pageSetup', function() { ui.showDialog(new PageSetupDialog(ui).container, 300, 200, true, true); }); //打印
this.addAction('print', function() { ui.showDialog(new PrintDialog(ui).container, 300, 200, true, true); }, null, 'sprite-print', 'Ctrl+P'); this.addAction('preview', function() { mxUtils.show(graph, null, 10, 10); }); //编辑操作
this.addAction('undo', function() { editor.undoManager.undo(); }, null, 'sprite-undo', 'Ctrl+Z');
this.addAction('redo', function() { editor.undoManager.redo(); }, null, 'sprite-redo', 'Ctrl+Y');
this.addAction('cut', function() { mxClipboard.cut(graph); }, null, 'sprite-cut', 'Ctrl+X');
this.addAction('copy', function() { mxClipboard.copy(graph); }, null, 'sprite-copy', 'Ctrl+C');
this.addAction('paste', function() { mxClipboard.paste(graph); }, false, 'sprite-paste', 'Ctrl+V');
this.addAction('delete', function() { graph.removeCells(); }, null, null, 'Delete');
this.addAction('duplicate', function()
{
var s = graph.gridSize;
graph.setSelectionCells(graph.moveCells(graph.getSelectionCells(), s, s, true));
}, null, null, 'Ctrl+D');
this.addAction('selectVertices', function() { graph.selectVertices(); }, null, null, 'Ctrl+Shift+V');
this.addAction('selectEdges', function() { graph.selectEdges(); }, null, null, 'Ctrl+Shift+E');
this.addAction('selectAll', function() { graph.selectAll(); }, null, null, 'Ctrl+A'); //导航行动
this.addAction('home', function() { graph.home(); }, null, null, 'Home');
this.addAction('exitGroup', function() { graph.exitGroup(); }, null, null, 'Page Up');
this.addAction('enterGroup', function() { graph.enterGroup(); }, null, null, 'Page Down');
this.addAction('expand', function() { graph.foldCells(false); }, null, null, 'Enter');
this.addAction('collapse', function() { graph.foldCells(true); }, null, null, 'Backspace'); //安排行动
this.addAction('toFront', function() { graph.orderCells(false); }, null, null, 'Ctrl+F');
this.addAction('toBack', function() { graph.orderCells(true); }, null, null, 'Ctrl+B');
this.addAction('group', function() { graph.setSelectionCell(graph.groupCells(null, 0)); }, null, null, 'Ctrl+G');
this.addAction('ungroup', function() { graph.setSelectionCells(graph.ungroupCells()); }, null, null, 'Ctrl+U');
this.addAction('removeFromGroup', function() { graph.removeCellsFromParent(); });
this.addAction('editLink', function()
{
var cell = graph.getSelectionCell();
var link = graph.getLinkForCell(cell); if (link == null)
{
link = '';
} link = mxUtils.prompt(mxResources.get('enterValue'), link); if (link != null)
{
graph.setLinkForCell(cell, link);
}
});
this.addAction('openLink', function()
{
var cell = graph.getSelectionCell();
var link = graph.getLinkForCell(cell); if (link != null)
{
window.open(link);
}
});
this.addAction('autosize', function()
{
var cells = graph.getSelectionCells(); if (cells != null)
{
graph.getModel().beginUpdate();
try
{
for (var i = 0; i < cells.length; i++)
{
var cell = cells[i]; if (graph.getModel().getChildCount(cell))
{
graph.updateGroupBounds([cell], 20);
}
else
{
graph.updateCellSize(cell);
}
}
}
finally
{
graph.getModel().endUpdate();
}
}
});
this.addAction('rotation', function()
{
var value = '0';
var state = graph.getView().getState(graph.getSelectionCell()); if (state != null)
{
value = state.style[mxConstants.STYLE_ROTATION] || value;
} value = mxUtils.prompt(mxResources.get('enterValue') + ' (' +
mxResources.get('rotation') + ' 0-360)', value); if (value != null)
{
graph.setCellStyles(mxConstants.STYLE_ROTATION, value);
}
});
this.addAction('rotate', function()
{
var cells = graph.getSelectionCells(); if (cells != null)
{
graph.getModel().beginUpdate();
try
{
for (var i = 0; i < cells.length; i++)
{
var cell = cells[i]; if (graph.getModel().isVertex(cell) && graph.getModel().getChildCount(cell) == 0)
{
var geo = graph.getCellGeometry(cell); if (geo != null)
{
//旋转的几何尺寸及位置
geo = geo.clone();
geo.x += geo.width / 2 - geo.height / 2;
geo.y += geo.height / 2 - geo.width / 2;
var tmp = geo.width;
geo.width = geo.height;
geo.height = tmp;
graph.getModel().setGeometry(cell, geo); //方向和进展90度读
var state = graph.view.getState(cell); if (state != null)
{
var dir = state.style[mxConstants.STYLE_DIRECTION] || 'east'/*default*/; if (dir == 'east')
{
dir = 'south';
}
else if (dir == 'south')
{
dir = 'west';
}
else if (dir == 'west')
{
dir = 'north';
}
else if (dir == 'north')
{
dir = 'east';
} graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);
}
}
}
}
}
finally
{
graph.getModel().endUpdate();
}
}
}, null, null, 'Ctrl+R'); //视图的操作
this.addAction('actualSize', function()
{
graph.zoomTo(1);
});
this.addAction('zoomIn', function() { graph.zoomIn(); }, null, null, 'Add');
this.addAction('zoomOut', function() { graph.zoomOut(); }, null, null, 'Subtract');
this.addAction('fitWindow', function() { graph.fit(); }); this.addAction('fitPage', mxUtils.bind(this, function()
{
if (!graph.pageVisible)
{
this.get('pageView').funct();
} var fmt = graph.pageFormat;
var ps = graph.pageScale;
var cw = graph.container.clientWidth - 20;
var ch = graph.container.clientHeight - 20; var scale = Math.floor(100 * Math.min(cw / fmt.width / ps, ch / fmt.height / ps)) / 100;
graph.zoomTo(scale); graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
}));
this.addAction('fitPageWidth', mxUtils.bind(this, function()
{
if (!graph.pageVisible)
{
this.get('pageView').funct();
} var fmt = graph.pageFormat;
var ps = graph.pageScale;
var cw = graph.container.clientWidth - 20; var scale = Math.floor(100 * cw / fmt.width / ps) / 100;
graph.zoomTo(scale); graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
}));
this.put('customZoom', new Action(mxResources.get('custom'), function()
{
var value = mxUtils.prompt(mxResources.get('enterValue') + ' (%)', parseInt(graph.getView().getScale() * 100)); if (value != null && value.length > 0 && !isNaN(parseInt(value)))
{
graph.zoomTo(parseInt(value) / 100);
}
})); //选择行动
var action = null;
action = this.addAction('grid', function()
{
graph.setGridEnabled(!graph.isGridEnabled());
editor.updateGraphComponents();
}, null, null, 'Ctrl+Shift+G');
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.isGridEnabled(); });
action = this.addAction('guides', function() { graph.graphHandler.guidesEnabled = !graph.graphHandler.guidesEnabled; });
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.graphHandler.guidesEnabled; });
action = this.addAction('tooltips', function()
{
graph.tooltipHandler.setEnabled(!graph.tooltipHandler.isEnabled());
});
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.tooltipHandler.isEnabled(); });
action = this.addAction('navigation', function()
{
graph.foldingEnabled = !graph.foldingEnabled;
graph.view.revalidate();
});
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.foldingEnabled; });
action = this.addAction('scrollbars', function()
{
graph.scrollbars = !graph.scrollbars;
editor.updateGraphComponents(); if (!graph.scrollbars)
{
var t = graph.view.translate;
graph.view.setTranslate(t.x - graph.container.scrollLeft / graph.view.scale, t.y - graph.container.scrollTop / graph.view.scale);
graph.container.scrollLeft = 0;
graph.container.scrollTop = 0;
graph.sizeDidChange();
}
else
{
var dx = graph.view.translate.x;
var dy = graph.view.translate.y; graph.view.translate.x = 0;
graph.view.translate.y = 0;
graph.sizeDidChange();
graph.container.scrollLeft -= Math.round(dx * graph.view.scale);
graph.container.scrollTop -= Math.round(dy * graph.view.scale);
}
}, !mxClient.IS_TOUCH);
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.container.style.overflow == 'auto'; });
action = this.addAction('pageView', mxUtils.bind(this, function()
{
graph.pageVisible = !graph.pageVisible;
graph.pageBreaksVisible = graph.pageVisible;
graph.preferPageSize = graph.pageBreaksVisible;
graph.view.validate();
graph.sizeDidChange(); editor.updateGraphComponents();
editor.outline.update(); if (mxUtils.hasScrollbars(graph.container))
{
if (graph.pageVisible)
{
graph.container.scrollLeft -= 20;
graph.container.scrollTop -= 20;
}
else
{
graph.container.scrollLeft += 20;
graph.container.scrollTop += 20;
}
}
}));
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.pageVisible; });
this.put('pageBackgroundColor', new Action(mxResources.get('backgroundColor'), function()
{
var apply = function(color)
{
graph.background = color;
editor.updateGraphComponents();
}; var cd = new ColorDialog(ui, graph.background || 'none', apply);
ui.showDialog(cd.container, 220, 360, true, false); if (!mxClient.IS_TOUCH)
{
cd.colorInput.focus();
}
}));
action = this.addAction('connect', function()
{
graph.setConnectable(!graph.connectionHandler.isEnabled());
}, null, null, 'Ctrl+Q');
action.setToggleAction(true);
action.setSelectedCallback(function() { return graph.connectionHandler.isEnabled(); }); //帮助行为
this.addAction('help', function()
{
var ext = ''; if (mxResources.isLanguageSupported(mxClient.language))
{
ext = '_' + mxClient.language;
} window.open(RESOURCES_PATH + '/help' + ext + '.html');
});
this.put('about', new Action(mxResources.get('about') + ' Graph Editor', function()
{
ui.showDialog(new AboutDialog(ui).container, 320, 280, true, true);
}, null, null, 'F1')); //字体风格的动作
var toggleFontStyle = mxUtils.bind(this, function(key, style)
{
this.addAction(key, function()
{
graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, style);
});
}); toggleFontStyle('bold', mxConstants.FONT_BOLD);
toggleFontStyle('italic', mxConstants.FONT_ITALIC);
toggleFontStyle('underline', mxConstants.FONT_UNDERLINE); //颜色动作
this.addAction('fontColor', function() { ui.menus.pickColor(mxConstants.STYLE_FONTCOLOR); });
this.addAction('strokeColor', function() { ui.menus.pickColor(mxConstants.STYLE_STROKECOLOR); });
this.addAction('fillColor', function() { ui.menus.pickColor(mxConstants.STYLE_FILLCOLOR); });
this.addAction('gradientColor', function() { ui.menus.pickColor(mxConstants.STYLE_GRADIENTCOLOR); });
this.addAction('backgroundColor', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR); });
this.addAction('borderColor', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BORDERCOLOR); }); //格式的行为
this.addAction('shadow', function() { graph.toggleCellStyles(mxConstants.STYLE_SHADOW); });
this.addAction('dashed', function() { graph.toggleCellStyles(mxConstants.STYLE_DASHED); });
this.addAction('rounded', function() { graph.toggleCellStyles(mxConstants.STYLE_ROUNDED); });
this.addAction('style', function()
{
var cells = graph.getSelectionCells(); if (cells != null && cells.length > 0)
{
var model = graph.getModel();
var style = mxUtils.prompt(mxResources.get('enterValue')+ ' (' + mxResources.get('style') + ')',
model.getStyle(cells[0]) || ''); if (style != null)
{
graph.setCellStyle(style, cells);
}
}
});
this.addAction('setAsDefaultEdge', function()
{
var cell = graph.getSelectionCell(); if (cell != null && graph.getModel().isEdge(cell))
{
//采取快照的细胞在调用的时刻
var proto = graph.getModel().cloneCells([cell])[0]; //删除输入/ exitxy风格
var style = proto.getStyle();
style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_X, '');
style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_Y, '');
style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_X, '');
style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_Y, '');
proto.setStyle(style); //使用边缘模板连接预览
graph.connectionHandler.createEdgeState = function(me)
{
return graph.view.createState(proto);
}; //创建新的连接边缘模板
graph.connectionHandler.factoryMethod = function()
{
return graph.cloneCells([proto])[0];
};
}
});
this.addAction('image', function()
{
function updateImage(value, w, h)
{
var select = null;
var cells = graph.getSelectionCells(); graph.getModel().beginUpdate();
try
{
//没有选中单元格
if (cells.length == 0)
{
var gs = graph.getGridSize();
cells = [graph.insertVertex(graph.getDefaultParent(), null, '', gs, gs, w, h)];
select = cells;
} graph.setCellStyles(mxConstants.STYLE_IMAGE, value, cells);
graph.setCellStyles(mxConstants.STYLE_SHAPE, 'image', cells); if (graph.getSelectionCount() == 1)
{
if (w != null && h != null)
{
var cell = cells[0];
var geo = graph.getModel().getGeometry(cell); if (geo != null)
{
geo = geo.clone();
geo.width = w;
geo.height = h;
graph.getModel().setGeometry(cell, geo);
}
}
}
}
finally
{
graph.getModel().endUpdate();
} if (select != null)
{
graph.setSelectionCells(select);
graph.scrollCellToVisible(select[0]);
}
}; var value = '';
var state = graph.getView().getState(graph.getSelectionCell()); if (state != null)
{
value = state.style[mxConstants.STYLE_IMAGE] || value;
} value = mxUtils.prompt(mxResources.get('enterValue') + ' (' + mxResources.get('url') + ')', value); if (value != null)
{
if (value.length > 0)
{
var img = new Image(); img.onload = function()
{
updateImage(value, img.width, img.height);
};
img.onerror = function()
{
mxUtils.alert(mxResources.get('fileNotFound'));
};
img.src = value;
}
}
});
}; /**
* 寄存器的作用在给定的名称.
*/
Actions.prototype.addAction = function(key, funct, enabled, iconCls, shortcut)
{
return this.put(key, new Action(mxResources.get(key), funct, enabled, iconCls, shortcut));
}; /**
* 寄存器的作用在给定的名称。
*/
Actions.prototype.put = function(name, action)
{
this.actions[name] = action; return action;
}; /**
* 返回给定名称或空如果没有这样的行动存在的动作。
*/
Actions.prototype.get = function(name)
{
return this.actions[name];
}; /**
* 对于给定的参数的一种新的活动构造。
*/
function Action(label, funct, enabled, iconCls, shortcut)
{
mxEventSource.call(this);
this.label = label;
this.funct = funct;
this.enabled = (enabled != null) ? enabled : true;
this.iconCls = iconCls;
this.shortcut = shortcut;
}; //行动继承mxeventsource
mxUtils.extend(Action, mxEventSource); Action.prototype.setEnabled = function(value)
{
if (this.enabled != value)
{
this.enabled = value;
this.fireEvent(new mxEventObject('stateChanged'));
}
}; /**
*套动作启用状态statechanged事件。
*/
Action.prototype.setToggleAction = function(value)
{
this.toggleAction = value;
}; /**
*套动作启用状态statechanged事件。
*/
Action.prototype.setSelectedCallback = function(funct)
{
this.selectedCallback = funct;
}; /**
* 套动作启用状态statechanged事件。
*/
Action.prototype.isSelected = function()
{
return this.selectedCallback();
};
工具栏~Sidebar.js
如:图标A区 ,图标B区的控制
源码:
/**
*$id:Action 。JS,V 2015-3-23
*$author Dana丶Li$
*/
/**
* Construcs a new sidebar for the given editor.
*/
function Sidebar(editorUi, container)
{
this.editorUi = editorUi;
this.container = container;
this.palettes = new Object();
this.showTooltips = true;
this.graph = new Graph(document.createElement('div'), null, null, this.editorUi.editor.graph.getStylesheet());
this.graph.foldingEnabled = false;
this.graph.autoScroll = false;
this.graph.setTooltips(false);
this.graph.setConnectable(false);
this.graph.resetViewOnRootChange = false;
this.graph.view.setTranslate(this.thumbBorder, this.thumbBorder);
this.graph.setEnabled(false); // Workaround for VML rendering in IE8 standards mode where the container must be in the DOM
// so that VML references can be restored via document.getElementById in mxShape.init.
if (document.documentMode == 8)
{
document.body.appendChild(this.graph.container);
} // Workaround for no rendering in 0 coordinate in FF 10
if (this.shiftThumbs)
{
this.graph.view.canvas.setAttribute('transform', 'translate(1, 1)');
} if (!mxClient.IS_TOUCH)
{
mxEvent.addListener(document, 'mouseup', mxUtils.bind(this, function()
{
this.showTooltips = true;
})); // Enables tooltips after scroll
mxEvent.addListener(container, 'scroll', mxUtils.bind(this, function()
{
this.showTooltips = true;
})); mxEvent.addListener(document, 'mousedown', mxUtils.bind(this, function()
{
this.showTooltips = false;
this.hideTooltip();
})); mxEvent.addListener(document, 'mousemove', mxUtils.bind(this, function(evt)
{
var src = mxEvent.getSource(evt); while (src != null)
{
if (src == this.currentElt)
{
return;
} src = src.parentNode;
} this.hideTooltip();
})); // Handles mouse leaving the window
mxEvent.addListener(document, 'mouseout', mxUtils.bind(this, function(evt)
{
if (evt.toElement == null && evt.relatedTarget == null)
{
this.hideTooltip();
}
}));
} this.init(); //图像预fetches提示
new Image().src = IMAGE_PATH + '/tooltip.png';
}; /**
* 将所有工具栏的侧边栏。
*/
Sidebar.prototype.init = function()
{
var dir = STENCIL_PATH; //this.addGeneralPalette(true);
//this.addUmlPalette(true);
//this.addBpmnPalette(dir, false);
//this.addStencilPalette('flowchart', 'Flowchart', dir + '/flowchart.xml',';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2');
//this.addStencilPalette('basic', mxResources.get('basic'), dir + '/basic.xml',';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2');
//this.addStencilPalette('arrows', mxResources.get('arrows'), dir + '/arrows.xml',';fillColor=#ffffff;strokeColor=#000000;strokeWidth=2'); this.addImagePalette('clipart', mxResources.get('clipart'), dir + '/clipart/', '_128x128.png',
[ 'colud', 'Firewall_02', 'Server_Tower', 'serverDB', 'serverAuth',
'serverPrint', 'serverEmail', 'serverDisk', 'Router_Icon', 'routerFirewall', 'route1', 'atm', 'police',
'accessServer','SIP', 'sipProxy', 'ITP', 'CA', '3U', 'ipv6Route',
'3layer', 'pbx', 'IDS', 'actionCheck', 'gateWayVPN', 'server1','server2','normalServer','IPSAN','H3Cswitch']); this.addImagePalette('clipartB', mxResources.get('clipartB'), dir + '/clipart/', '.png',
[ 'pic1','pic2','pic3','pic4','pic5','pic6','pic7','pic8','pic9','pic10','pic11','pic12','pic13','pic14','pic15']); }; /**
* 指定工具提示应该是可见的。默认的是真的。
*/
Sidebar.prototype.enableTooltips = !mxClient.IS_TOUCH; /**
* 将缩略图1像素。
*/
Sidebar.prototype.shiftThumbs = mxClient.IS_SVG || document.documentMode == 8; /**
* 指定工具提示的延迟。默认是16像素。
*/
Sidebar.prototype.tooltipBorder = 16; /**
* 指定工具提示的延迟。默认是2像素。
*/
Sidebar.prototype.thumbBorder = 2; /**
* Specifies the delay for the tooltip. Default is 300 ms.
*/
Sidebar.prototype.tooltipDelay = 300; /**
* Specifies if edges should be used as templates if clicked. Default is true.
*/
Sidebar.prototype.installEdges = true; /**
* Specifies the URL of the gear image.
*/
Sidebar.prototype.gearImage = STENCIL_PATH + '/clipart/Gear_128x128.png'; /**
* Specifies the width of the thumbnails.
*/
Sidebar.prototype.thumbWidth = 26; /**
* Specifies the height of the thumbnails.
*/
Sidebar.prototype.thumbHeight = 26; /**
* Adds all palettes to the sidebar.
*/
Sidebar.prototype.showTooltip = function(elt, cells)
{
if (this.enableTooltips && this.showTooltips)
{
if (this.currentElt != elt)
{
if (this.thread != null)
{
window.clearTimeout(this.thread);
this.thread = null;
} var show = mxUtils.bind(this, function()
{
// Workaround for off-screen text rendering in IE
var old = mxText.prototype.getTableSize; if (this.graph.dialect != mxConstants.DIALECT_SVG)
{
mxText.prototype.getTableSize = function(table)
{
var oldParent = table.parentNode; document.body.appendChild(table);
var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
oldParent.appendChild(table); return size;
};
} // Lazy creation of the DOM nodes and graph instance
if (this.tooltip == null)
{
this.tooltip = document.createElement('div');
this.tooltip.className = 'geSidebarTooltip';
document.body.appendChild(this.tooltip); this.graph2 = new Graph(this.tooltip, null, null, this.editorUi.editor.graph.getStylesheet());
this.graph2.view.setTranslate(this.tooltipBorder, this.tooltipBorder);
this.graph2.resetViewOnRootChange = false;
this.graph2.foldingEnabled = false;
this.graph2.autoScroll = false;
this.graph2.setTooltips(false);
this.graph2.setConnectable(false);
this.graph2.setEnabled(false); this.tooltipImage = mxUtils.createImage(IMAGE_PATH + '/tooltip.png');
this.tooltipImage.style.position = 'absolute';
this.tooltipImage.style.width = '14px';
this.tooltipImage.style.height = '27px'; document.body.appendChild(this.tooltipImage);
} this.graph2.model.clear();
this.graph2.addCells(cells); var bounds = this.graph2.getGraphBounds();
var width = bounds.x + bounds.width + this.tooltipBorder;
var height = bounds.y + bounds.height + this.tooltipBorder; if (mxClient.IS_QUIRKS)
{
width += 4;
height += 4;
} this.tooltip.style.display = 'block';
this.tooltip.style.overflow = 'visible';
this.tooltipImage.style.visibility = 'visible';
this.tooltip.style.width = width + 'px';
this.tooltip.style.height = height + 'px'; var left = this.container.clientWidth + this.editorUi.splitSize + 3;
var top = Math.max(0, (this.container.offsetTop + elt.offsetTop - this.container.scrollTop - height / 2 + 16)); // Workaround for ignored position CSS style in IE9
// (changes to relative without the following line)
this.tooltip.style.position = 'absolute';
this.tooltip.style.left = left + 'px';
this.tooltip.style.top = top + 'px';
this.tooltipImage.style.left = (left - 13) + 'px';
this.tooltipImage.style.top = (top + height / 2 - 13) + 'px'; mxText.prototype.getTableSize = old;
}); if (this.tooltip != null && this.tooltip.style.display != 'none')
{
show();
}
else
{
this.thread = window.setTimeout(show, this.tooltipDelay);
} this.currentElt = elt;
}
}
}; /**
* Hides the current tooltip.
*/
Sidebar.prototype.hideTooltip = function()
{
if (this.thread != null)
{
window.clearTimeout(this.thread);
this.thread = null;
} if (this.tooltip != null)
{
this.tooltip.style.display = 'none';
this.tooltipImage.style.visibility = 'hidden';
this.currentElt = null;
}
}; /**
* Adds the general palette to the sidebar.
*/
Sidebar.prototype.addGeneralPalette = function(expand)
{
this.addPalette('general', mxResources.get('general'), expand || true, mxUtils.bind(this, function(content)
{
content.appendChild(this.createVertexTemplate('swimlane', 200, 200, 'Container'));
content.appendChild(this.createVertexTemplate('swimlane;horizontal=0', 200, 200, 'Pool'));
content.appendChild(this.createVertexTemplate('text', 40, 26, 'Text'));
content.appendChild(this.createVertexTemplate('icon;image=' + this.gearImage, 60, 60, 'Image'));
content.appendChild(this.createVertexTemplate('label;image=' + this.gearImage, 140, 60, 'Label'));
content.appendChild(this.createVertexTemplate(null, 120, 60));
content.appendChild(this.createVertexTemplate('rounded=1', 120, 60));
content.appendChild(this.createVertexTemplate('ellipse', 80, 80));
content.appendChild(this.createVertexTemplate('ellipse;shape=doubleEllipse', 80, 80));
content.appendChild(this.createVertexTemplate('triangle', 60, 80));
content.appendChild(this.createVertexTemplate('rhombus', 80, 80));
content.appendChild(this.createVertexTemplate('shape=hexagon', 120, 80));
content.appendChild(this.createVertexTemplate('shape=actor;verticalLabelPosition=bottom;verticalAlign=top', 40, 60));
content.appendChild(this.createVertexTemplate('ellipse;shape=cloud', 120, 80));
content.appendChild(this.createVertexTemplate('shape=cylinder', 60, 80));
content.appendChild(this.createVertexTemplate('line', 160, 10));
content.appendChild(this.createVertexTemplate('line;direction=south', 10, 160));
content.appendChild(this.createVertexTemplate('shape=xor', 60, 80));
content.appendChild(this.createVertexTemplate('shape=or', 60, 80));
content.appendChild(this.createVertexTemplate('shape=step', 120, 80));
content.appendChild(this.createVertexTemplate('shape=tape', 120, 100));
content.appendChild(this.createVertexTemplate('shape=cube', 120, 80));
content.appendChild(this.createVertexTemplate('shape=note', 80, 100));
content.appendChild(this.createVertexTemplate('shape=folder', 120, 120));
content.appendChild(this.createVertexTemplate('shape=card', 60, 80));
content.appendChild(this.createVertexTemplate('shape=plus', 20, 20)); content.appendChild(this.createEdgeTemplate('edgeStyle=none;endArrow=none;', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=none', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=elbowEdgeStyle;elbow=horizontal', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=elbowEdgeStyle;elbow=vertical', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=entityRelationEdgeStyle', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=segmentEdgeStyle', 100, 100));
content.appendChild(this.createEdgeTemplate('edgeStyle=orthogonalEdgeStyle', 100, 100));
content.appendChild(this.createEdgeTemplate('shape=link', 100, 100));
content.appendChild(this.createEdgeTemplate('arrow', 100, 100));
}));
}; /**
* Adds the general palette to the sidebar.
*/
Sidebar.prototype.addUmlPalette = function(expand)
{
this.addPalette('uml', 'UML', expand || false, mxUtils.bind(this, function(content)
{
content.appendChild(this.createVertexTemplate('', 110, 50, 'Object')); var classCell = new mxCell('<p style="margin:0px;margin-top:4px;text-align:center;">' +
'<b>Class</b></p>' +
'<hr/><div style="height:2px;"></div><hr/>', new mxGeometry(0, 0, 140, 60),
'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1');
classCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60)); var classCell = new mxCell('<p style="margin:0px;margin-top:4px;text-align:center;">' +
'<b>Class</b></p>' +
'<hr/><p style="margin:0px;margin-left:4px;">+ field: Type</p><hr/>' +
'<p style="margin:0px;margin-left:4px;">+ method(): Type</p>', new mxGeometry(0, 0, 160, 90),
'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1');
classCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([classCell], 160, 90)); var classCell = new mxCell('<p style="margin:0px;margin-top:4px;text-align:center;">' +
'<i><<Interface>></i><br/><b>Interface</b></p>' +
'<hr/><p style="margin:0px;margin-left:4px;">+ field1: Type<br/>' +
'+ field2: Type</p>' +
'<hr/><p style="margin:0px;margin-left:4px;">' +
'+ method1(Type): Type<br/>' +
'+ method2(Type, Type): Type</p>', new mxGeometry(0, 0, 190, 140),
'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1');
classCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([classCell], 190, 140)); var classCell = new mxCell('Module', new mxGeometry(0, 0, 120, 60),
'shape=component;align=left;spacingLeft=36');
classCell.vertex = true; content.appendChild(this.createVertexTemplateFromCells([classCell], 120, 60)); var classCell = new mxCell('<<component>><br/><b>Component</b>', new mxGeometry(0, 0, 180, 90),
'overflow=fill;html=1');
classCell.vertex = true;
var classCell1 = new mxCell('', new mxGeometry(1, 0, 20, 20), 'shape=component;jettyWidth=8;jettyHeight=4;');
classCell1.vertex = true;
classCell1.connectable = false;
classCell1.geometry.relative = true;
classCell1.geometry.offset = new mxPoint(-30, 10);
classCell.insert(classCell1); content.appendChild(this.createVertexTemplateFromCells([classCell], 180, 90)); var classCell = new mxCell('<p style="margin:0px;margin-top:6px;text-align:center;"><b>Component</b></p>' +
'<hr/><p style="margin:0px;margin-left:8px;">+ Attribute1: Type<br/>+ Attribute2: Type</p>', new mxGeometry(0, 0, 180, 90),
'verticalAlign=top;align=left;overflow=fill;html=1');
classCell.vertex = true;
var classCell1 = new mxCell('', new mxGeometry(1, 0, 20, 20), 'shape=component;jettyWidth=8;jettyHeight=4;');
classCell1.vertex = true;
classCell1.connectable = false;
classCell1.geometry.relative = true;
classCell1.geometry.offset = new mxPoint(-23, 3);
classCell.insert(classCell1); content.appendChild(this.createVertexTemplateFromCells([classCell], 180, 90)); content.appendChild(this.createVertexTemplate('shape=lollipop;direction=south;', 30, 10)); var cardCell = new mxCell('Block', new mxGeometry(0, 0, 180, 120),
'verticalAlign=top;align=left;spacingTop=8;spacingLeft=2;spacingRight=12;shape=cube;size=10;direction=south;fontStyle=4;');
cardCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([cardCell], 180, 120)); content.appendChild(this.createVertexTemplate('shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;', 70, 50,
'package')); var classCell = new mxCell('<p style="margin:0px;margin-top:4px;text-align:center;text-decoration:underline;">' +
'<b>Object:Type</b></p><hr/>' +
'<p style="margin:0px;margin-left:8px;">field1 = value1<br/>field2 = value2<br>field3 = value3</p>',
new mxGeometry(0, 0, 160, 90),
'verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1');
classCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([classCell], 160, 90)); var tableCell = new mxCell('<table cellpadding="5" style="font-size:9pt;border:none;border-collapse:collapse;width:100%;">' +
'<tr><td colspan="2" style="border:1px solid gray;background:#e4e4e4;">Tablename</td></tr>' +
'<tr><td style="border:1px solid gray;">PK</td><td style="border:1px solid gray;">uniqueId</td></tr>' +
'<tr><td style="border:1px solid gray;">FK1</td><td style="border:1px solid gray;">foreignKey</td></tr>' +
'<tr><td style="border:1px solid gray;"></td><td style="border:1px solid gray;">fieldname</td></tr>' +
'</table>', new mxGeometry(0, 0, 180, 99), 'verticalAlign=top;align=left;overflow=fill;html=1');
tableCell.vertex = true;
content.appendChild(this.createVertexTemplateFromCells([tableCell], 180, 99)); content.appendChild(this.createVertexTemplate('shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top', 40, 80, 'Actor'));
content.appendChild(this.createVertexTemplate('ellipse', 140, 70, 'Use Case')); var cardCell = new mxCell('', new mxGeometry(0, 0, 30, 30),
'ellipse;shape=startState;fillColor=#000000;strokeColor=#ff0000;');
cardCell.vertex = true; var assoc2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;');
assoc2.geometry.setTerminalPoint(new mxPoint(15, 70), false);
assoc2.edge = true; cardCell.insertEdge(assoc2, true); content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 30, 30)); var cardCell = new mxCell('Activity', new mxGeometry(0, 0, 120, 40),
'rounded=1;arcSize=40;fillColor=#ffffc0;strokeColor=#ff0000;');
cardCell.vertex = true; var assoc2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;');
assoc2.geometry.setTerminalPoint(new mxPoint(60, 80), false);
assoc2.edge = true; cardCell.insertEdge(assoc2, true); content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 120, 40)); var cardCell = new mxCell('<div style="margin-top:8px;"><b>Composite State</b><hr/>Subtitle</div>', new mxGeometry(0, 0, 160, 60),
'rounded=1;arcSize=40;overflow=fill;html=1;verticalAlign=top;fillColor=#ffffc0;strokeColor=#ff0000;');
cardCell.vertex = true; var assoc2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;');
assoc2.geometry.setTerminalPoint(new mxPoint(80, 100), false);
assoc2.edge = true; cardCell.insertEdge(assoc2, true); content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 160, 60)); var cardCell = new mxCell('Condition', new mxGeometry(0, 0, 80, 40),
'rhombus;fillColor=#ffffc0;strokeColor=#ff0000;');
cardCell.vertex = true; 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;');
assoc1.geometry.setTerminalPoint(new mxPoint(120, 20), false);
assoc1.geometry.relative = true;
assoc1.geometry.x = -1;
assoc1.edge = true; cardCell.insertEdge(assoc1, true); 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;');
assoc2.geometry.setTerminalPoint(new mxPoint(40, 80), false);
assoc2.geometry.relative = true;
assoc2.geometry.x = -1;
assoc2.edge = true; cardCell.insertEdge(assoc2, true); content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc1, assoc2], 80, 40)); var cardCell = new mxCell('', new mxGeometry(0, 0, 200, 10),
'shape=line;strokeWidth=6;strokeColor=#ff0000;');
cardCell.vertex = true; var assoc2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=horizontal;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;');
assoc2.geometry.setTerminalPoint(new mxPoint(100, 50), false);
assoc2.edge = true; cardCell.insertEdge(assoc2, true); content.appendChild(this.createVertexTemplateFromCells([cardCell, assoc2], 200, 10)); content.appendChild(this.createVertexTemplate('ellipse;shape=endState;fillColor=#000000;strokeColor=#ff0000', 30, 30)); var classCell1 = new mxCell(':Object', new mxGeometry(0, 0, 100, 50));
classCell1.vertex = true; var classCell2 = new mxCell('', new mxGeometry(40, 50, 20, 240), 'shape=line;direction=north;dashed=1');
classCell2.vertex = true; content.appendChild(this.createVertexTemplateFromCells([classCell1, classCell2], 100, 290)); var classCell1 = new mxCell('', new mxGeometry(100, 0, 20, 70));
classCell1.vertex = true; var assoc1 = new mxCell('invoke', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;endArrow=block;');
assoc1.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc1.edge = true; classCell1.insertEdge(assoc1, false); content.appendChild(this.createVertexTemplateFromCells([classCell1, assoc1], 120, 70)); var classCell1 = new mxCell('', new mxGeometry(100, 0, 20, 70));
classCell1.vertex = true; var assoc1 = new mxCell('invoke', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;endArrow=block;');
assoc1.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc1.edge = true; classCell1.insertEdge(assoc1, false); var assoc2 = new mxCell('return', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=vertical;verticalAlign=bottom;dashed=1;endArrow=open;endSize=8;');
assoc2.geometry.setTerminalPoint(new mxPoint(0, 70), false);
assoc2.edge = true; classCell1.insertEdge(assoc2, true); var assoc3 = new mxCell('invoke', new mxGeometry(0, 0, 0, 0), 'edgeStyle=elbowEdgeStyle;elbow=vertical;align=left;endArrow=open;');
assoc3.edge = true; classCell1.insertEdge(assoc3, true);
classCell1.insertEdge(assoc3, false); content.appendChild(this.createVertexTemplateFromCells([classCell1, assoc1, assoc2, assoc3], 120, 70)); var assoc = new mxCell('name', new mxGeometry(0, 0, 0, 0), 'endArrow=block;endFill=1;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=top;');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.geometry.relative = true;
assoc.geometry.x = -1;
assoc.edge = true; var sourceLabel = new mxCell('1', new mxGeometry(-1, 0, 0, 0), 'resizable=0;align=left;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10');
sourceLabel.geometry.relative = true;
sourceLabel.setConnectable(false);
sourceLabel.vertex = true;
assoc.insert(sourceLabel); content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('', new mxGeometry(0, 0, 0, 0), 'endArrow=none;edgeStyle=orthogonalEdgeStyle;');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; var sourceLabel = new mxCell('parent', new mxGeometry(-1, 0, 0, 0), 'resizable=0;align=left;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10');
sourceLabel.geometry.relative = true;
sourceLabel.setConnectable(false);
sourceLabel.vertex = true;
assoc.insert(sourceLabel); var targetLabel = new mxCell('child', new mxGeometry(1, 0, 0, 0), 'resizable=0;align=right;verticalAlign=bottom;labelBackgroundColor=#ffffff;fontSize=10');
targetLabel.geometry.relative = true;
targetLabel.setConnectable(false);
targetLabel.vertex = true;
assoc.insert(targetLabel); content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); 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;');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.geometry.relative = true;
assoc.geometry.x = -1;
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('Relation', new mxGeometry(0, 0, 0, 0), 'endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; var sourceLabel = new mxCell('0..n', new mxGeometry(-1, 0, 0, 0), 'resizable=0;align=left;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10');
sourceLabel.geometry.relative = true;
sourceLabel.setConnectable(false);
sourceLabel.vertex = true;
assoc.insert(sourceLabel); var targetLabel = new mxCell('1', new mxGeometry(1, 0, 0, 0), 'resizable=0;align=right;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10');
targetLabel.geometry.relative = true;
targetLabel.setConnectable(false);
targetLabel.vertex = true;
assoc.insert(targetLabel); content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('Use', new mxGeometry(0, 0, 0, 0), 'endArrow=open;endSize=12;dashed=1');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('Extends', new mxGeometry(0, 0, 0, 0), 'endArrow=block;endSize=16;endFill=0;dashed=1');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('', new mxGeometry(0, 0, 0, 0), 'endArrow=block;startArrow=block;endFill=1;startFill=1');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
}));
}; /**
* Adds the BPMN library to the sidebar.
*/
Sidebar.prototype.addBpmnPalette = function(dir, expand)
{
this.addStencilPalette('bpmn', 'BPMN', dir + '/bpmn.xml',
';fillColor=#ffffff;strokeColor=#000000;perimeter=ellipsePerimeter;',
['Cancel', 'Error', 'Link', 'Message', 'Compensation', 'Multiple', 'Rule', 'Timer'],
function(content)
{
content.appendChild(this.createVertexTemplate('swimlane;horizontal=0;', 300, 160, 'Pool')); var classCell = new mxCell('Process', new mxGeometry(0, 0, 140, 60),
'rounded=1');
classCell.vertex = true;
var classCell1 = new mxCell('', new mxGeometry(1, 1, 30, 30), 'shape=mxgraph.bpmn.timer_start;perimeter=ellipsePerimeter;');
classCell1.vertex = true;
classCell1.geometry.relative = true;
classCell1.geometry.offset = new mxPoint(-40, -15);
classCell.insert(classCell1); content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60)); var classCell = new mxCell('Process', new mxGeometry(0, 0, 140, 60),
'rounded=1');
classCell.vertex = true;
var classCell1 = new mxCell('', new mxGeometry(0.5, 1, 12, 12), 'shape=plus');
classCell1.vertex = true;
classCell1.connectable = false;
classCell1.geometry.relative = true;
classCell1.geometry.offset = new mxPoint(-6, -12);
classCell.insert(classCell1); content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60)); var classCell = new mxCell('Process', new mxGeometry(0, 0, 140, 60),
'rounded=1');
classCell.vertex = true;
var classCell1 = new mxCell('', new mxGeometry(0, 0, 20, 14), 'shape=message');
classCell1.vertex = true;
classCell1.connectable = false;
classCell1.geometry.relative = true;
classCell1.geometry.offset = new mxPoint(5, 5);
classCell.insert(classCell1); content.appendChild(this.createVertexTemplateFromCells([classCell], 140, 60)); var classCell = new mxCell('', new mxGeometry(0, 0, 60, 40), 'shape=message');
classCell.vertex = true; content.appendChild(this.createEdgeTemplateFromCells([classCell], 60, 40)); var assoc = new mxCell('Sequence', new mxGeometry(0, 0, 0, 0), 'endArrow=block;endFill=1;endSize=6');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('Default', new mxGeometry(0, 0, 0, 0), 'startArrow=dash;startSize=8;endArrow=block;endFill=1;endSize=6');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('Conditional', new mxGeometry(0, 0, 0, 0), 'startArrow=diamondThin;startFill=0;startSize=14;endArrow=block;endFill=1;endSize=6');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('', new mxGeometry(0, 0, 0, 0), 'startArrow=oval;startFill=0;startSize=7;endArrow=block;endFill=0;endSize=10;dashed=1');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('', new mxGeometry(0, 0, 0, 0), 'startArrow=oval;startFill=0;startSize=7;endArrow=block;endFill=0;endSize=10;dashed=1');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; var sourceLabel = new mxCell('', new mxGeometry(0, 0, 20, 14), 'shape=message');
sourceLabel.geometry.relative = true;
sourceLabel.setConnectable(false);
sourceLabel.vertex = true;
sourceLabel.geometry.offset = new mxPoint(-10, -7);
assoc.insert(sourceLabel); content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0)); var assoc = new mxCell('', new mxGeometry(0, 0, 0, 0), 'shape=link');
assoc.geometry.setTerminalPoint(new mxPoint(0, 0), true);
assoc.geometry.setTerminalPoint(new mxPoint(160, 0), false);
assoc.edge = true; content.appendChild(this.createEdgeTemplateFromCells([assoc], 160, 0));
}, 0.5);
}; /**
* Creates and returns the given title element.
*/
Sidebar.prototype.createTitle = function(label)
{
var elt = document.createElement('a');
elt.setAttribute('href', 'javascript:void(0);');
elt.className = 'geTitle';
mxUtils.write(elt, label); return elt;
}; /**
* Creates a thumbnail for the given cells.
*/
Sidebar.prototype.createThumb = function(cells, width, height, parent)
{
// Workaround for off-screen text rendering in IE
var old = mxText.prototype.getTableSize; if (this.graph.dialect != mxConstants.DIALECT_SVG)
{
mxText.prototype.getTableSize = function(table)
{
var oldParent = table.parentNode; document.body.appendChild(table);
var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
oldParent.appendChild(table); return size;
};
} var prev = mxImageShape.prototype.preserveImageAspect;
mxImageShape.prototype.preserveImageAspect = false; this.graph.view.rendering = false;
this.graph.view.setScale(1);
this.graph.addCells(cells);
var bounds = this.graph.getGraphBounds(); var corr = (this.shiftThumbs) ? this.thumbBorder + 1 : this.thumbBorder;
var s = Math.min((width - 1) / (bounds.x + bounds.width + corr),
(height - 1) / (bounds.y + bounds.height + corr));
this.graph.view.setScale(s);
this.graph.view.rendering = true;
this.graph.refresh();
mxImageShape.prototype.preserveImageAspect = prev; bounds = this.graph.getGraphBounds();
var dx = Math.max(0, Math.floor((width - bounds.width) / 2));
var dy = Math.max(0, Math.floor((height - bounds.height) / 2)); var node = null; // For supporting HTML labels in IE9 standards mode the container is cloned instead
if (this.graph.dialect == mxConstants.DIALECT_SVG && !mxClient.IS_IE)
{
node = this.graph.view.getCanvas().ownerSVGElement.cloneNode(true);
}
// Workaround for VML rendering in IE8 standards mode
else if (document.documentMode == 8)
{
node = this.graph.container.cloneNode(false);
node.innerHTML = this.graph.container.innerHTML;
}
else
{
node = this.graph.container.cloneNode(true);
} this.graph.getModel().clear(); // Outer dimension is (32, 32)
var dd = (this.shiftThumbs) ? 2 : 3;
node.style.position = 'relative';
node.style.overflow = 'visible';
node.style.cursor = 'pointer';
node.style.left = (dx + dd) + 'px';
node.style.top = (dy + dd) + 'px';
node.style.width = width + 'px';
node.style.height = height + 'px'; parent.appendChild(node);
mxText.prototype.getTableSize = old;
}; /**
* Creates and returns a new palette item for the given image.
*/
Sidebar.prototype.createItem = function(cells)
{
var elt = document.createElement('a');
elt.setAttribute('href', 'javascript:void(0);');
elt.className = 'geItem'; // Blocks default click action
mxEvent.addListener(elt, 'click', function(evt)
{
mxEvent.consume(evt);
}); this.createThumb(cells, this.thumbWidth, this.thumbHeight, elt); return elt;
}; /**
* Creates a drop handler for inserting the given cells.
*/
Sidebar.prototype.createDropHandler = function(cells, allowSplit)
{
return function(graph, evt, target, x, y)
{
cells = graph.getImportableCells(cells); if (cells.length > 0)
{
var validDropTarget = (target != null) ?
graph.isValidDropTarget(target, cells, evt) : false;
var select = null; if (target != null && !validDropTarget)
{
target = null;
} // Splits the target edge or inserts into target group
if (allowSplit && graph.isSplitEnabled() && graph.isSplitTarget(target, cells, evt))
{
graph.splitEdge(target, cells, null, x, y);
select = cells;
}
else if (cells.length > 0)
{
select = graph.importCells(cells, x, y, target);
} if (select != null && select.length > 0)
{
graph.scrollCellToVisible(select[0]);
graph.setSelectionCells(select);
}
}
};
}; /**
* Creates and returns a preview element for the given width and height.
*/
Sidebar.prototype.createDragPreview = function(width, height)
{
var elt = document.createElement('div');
elt.style.border = '1px dashed black';
elt.style.width = width + 'px';
elt.style.height = height + 'px'; return elt;
}; /**
* Creates a drag source for the given element.
*/
Sidebar.prototype.createDragSource = function(elt, dropHandler, preview)
{
var dragSource = mxUtils.makeDraggable(elt, this.editorUi.editor.graph, dropHandler,
preview, 0, 0, this.editorUi.editor.graph.autoscroll, true, true); // Allows drop into cell only if target is a valid root
dragSource.getDropTarget = function(graph, x, y)
{
var target = mxDragSource.prototype.getDropTarget.apply(this, arguments); if (!graph.isValidRoot(target))
{
target = null;
} return target;
}; return dragSource;
}; /**
* Adds a handler for inserting the cell with a single click.
*/
Sidebar.prototype.addClickHandler = function(elt, ds)
{
var graph = this.editorUi.editor.graph;
var first = null; var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
mxEvent.addListener(elt, md, function(evt)
{
first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
}); var oldMouseUp = ds.mouseUp;
ds.mouseUp = function(evt)
{
if (!mxEvent.isPopupTrigger(evt) && this.currentGraph == null && first != null)
{
var tol = graph.tolerance; if (Math.abs(first.x - mxEvent.getClientX(evt)) <= tol &&
Math.abs(first.y - mxEvent.getClientY(evt)) <= tol)
{
var gs = graph.getGridSize();
ds.drop(graph, evt, null, gs, gs);
}
} oldMouseUp.apply(this, arguments);
first = null;
};
}; /**
* Creates a drop handler for inserting the given cells.
*/
Sidebar.prototype.createVertexTemplate = function(style, width, height, value)
{
var cells = [new mxCell((value != null) ? value : '', new mxGeometry(0, 0, width, height), style)];
cells[0].vertex = true; return this.createVertexTemplateFromCells(cells, width, height);
}; /**
* Creates a drop handler for inserting the given cells.
*/
Sidebar.prototype.createVertexTemplateFromCells = function(cells, width, height)
{
var elt = this.createItem(cells);
var ds = this.createDragSource(elt, this.createDropHandler(cells, true), this.createDragPreview(width, height));
this.addClickHandler(elt, ds); // Uses guides for vertices only if enabled in graph
ds.isGuidesEnabled = mxUtils.bind(this, function()
{
return this.editorUi.editor.graph.graphHandler.guidesEnabled;
}); // Shows a tooltip with the rendered cell
if (!touchStyle)
{
mxEvent.addListener(elt, 'mousemove', mxUtils.bind(this, function(evt)
{
this.showTooltip(elt, cells);
}));
} return elt;
}; /**
* Creates a drop handler for inserting the given cells.
*/
Sidebar.prototype.createEdgeTemplate = function(style, width, height, value)
{
var cells = [new mxCell((value != null) ? value : '', new mxGeometry(0, 0, width, height), style)];
cells[0].geometry.setTerminalPoint(new mxPoint(0, height), true);
cells[0].geometry.setTerminalPoint(new mxPoint(width, 0), false);
cells[0].edge = true; return this.createEdgeTemplateFromCells(cells, width, height);
}; /**
* Creates a drop handler for inserting the given cells.
*/
Sidebar.prototype.createEdgeTemplateFromCells = function(cells, width, height)
{
var elt = this.createItem(cells);
this.createDragSource(elt, this.createDropHandler(cells, false), this.createDragPreview(width, height)); // Installs the default edge
var graph = this.editorUi.editor.graph;
mxEvent.addListener(elt, 'click', mxUtils.bind(this, function(evt)
{
if (this.installEdges)
{
// Uses edge template for connect preview
graph.connectionHandler.createEdgeState = function(me)
{
return graph.view.createState(cells[0]);
}; // Creates new connections from edge template
graph.connectionHandler.factoryMethod = function()
{
return graph.cloneCells([cells[0]])[0];
};
} // Highlights the entry for 200ms
elt.style.backgroundColor = '#ffffff'; window.setTimeout(function()
{
elt.style.backgroundColor = '';
}, 200); mxEvent.consume(evt);
})); // Shows a tooltip with the rendered cell
if (!touchStyle)
{
mxEvent.addListener(elt, 'mousemove', mxUtils.bind(this, function(evt)
{
this.showTooltip(elt, cells);
}));
} return elt;
}; /**
* Adds the given palette.
*/
Sidebar.prototype.addPalette = function(id, title, expanded, onInit)
{
var elt = this.createTitle(title);
this.container.appendChild(elt); var div = document.createElement('div');
div.className = 'geSidebar'; if (expanded)
{
onInit(div);
onInit = null;
}
else
{
div.style.display = 'none';
} this.addFoldingHandler(elt, div, onInit); var outer = document.createElement('div');
outer.appendChild(div);
this.container.appendChild(outer); // Keeps references to the DOM nodes
if (id != null)
{
this.palettes[id] = [elt, outer];
}
}; /**
* Create the given title element.
*/
Sidebar.prototype.addFoldingHandler = function(title, content, funct)
{
var initialized = false; title.style.backgroundImage = (content.style.display == 'none') ?
'url(' + IMAGE_PATH + '/collapsed.gif)' : 'url(' + IMAGE_PATH + '/expanded.gif)';
title.style.backgroundRepeat = 'no-repeat';
title.style.backgroundPosition = '100% 50%'; mxEvent.addListener(title, 'click', function(evt)
{
if (content.style.display == 'none')
{
if (!initialized)
{
initialized = true; if (funct != null)
{
funct(content);
}
} title.style.backgroundImage = 'url(' + IMAGE_PATH + '/expanded.gif)';
content.style.display = 'block';
}
else
{
title.style.backgroundImage = 'url(' + IMAGE_PATH + '/collapsed.gif)';
content.style.display = 'none';
} mxEvent.consume(evt);
});
}; /**
* Removes the palette for the given ID.
*/
Sidebar.prototype.removePalette = function(id)
{
var elts = this.palettes[id]; if (elts != null)
{
this.palettes[id] = null; for (var i = 0; i < elts.length; i++)
{
this.container.removeChild(elts[i]);
} return true;
} return false;
}; /**
* Adds the given image palette.
*/
Sidebar.prototype.addImagePalette = function(id, title, prefix, postfix, items)
{
this.addPalette(id, title, true, mxUtils.bind(this, function(content)
{
for (var i = 0; i < items.length; i++)
{
var icon = prefix + items[i] + postfix;
content.appendChild(this.createVertexTemplate('image;image=' + icon, 80, 80, ''));
}
}));
}; /**
* Adds the given stencil palette.
*/
Sidebar.prototype.addStencilPalette = function(id, title, stencilFile, style, ignore, onInit, scale)
{
scale = (scale != null) ? scale : 1; this.addPalette(id, title, false, mxUtils.bind(this, function(content)
{
if (style == null)
{
style = '';
} if (onInit != null)
{
onInit.call(this, content);
} mxStencilRegistry.loadStencilSet(stencilFile, mxUtils.bind(this, function(packageName, stencilName, displayName, w, h)
{
if (ignore == null || mxUtils.indexOf(ignore, stencilName) < 0)
{
content.appendChild(this.createVertexTemplate('shape=' + packageName + stencilName.toLowerCase() + style,
Math.round(w * scale), Math.round(h * scale), ''));
}
}), true);
}));
};
对应于配置属性文件的参数变量:
右键菜单绑定设备,设置线宽
文档比较乱! 也有点赶~
欢迎加入一起讨论,后期的开发与研讨,还有一些瓶颈没有解决....
Demo下载地址:点击下载