2284 lines
64 KiB
JavaScript
2284 lines
64 KiB
JavaScript
/*
|
|
* $Id: MainPanel.js,v 1.1 2012/11/15 13:26:47 gaudenz Exp $
|
|
* Copyright (c) 2006-2010, JGraph Ltd
|
|
*/
|
|
MainPanel = function(graph, history)
|
|
{
|
|
var executeLayout = function(layout, animate, ignoreChildCount)
|
|
{
|
|
var cell = graph.getSelectionCell();
|
|
|
|
if (cell == null ||
|
|
(!ignoreChildCount &&
|
|
graph.getModel().getChildCount(cell) == 0))
|
|
{
|
|
cell = graph.getDefaultParent();
|
|
}
|
|
|
|
graph.getModel().beginUpdate();
|
|
try
|
|
{
|
|
layout.execute(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, function()
|
|
{
|
|
graph.getModel().endUpdate();
|
|
});
|
|
|
|
morph.startAnimation();
|
|
}
|
|
else
|
|
{
|
|
graph.getModel().endUpdate();
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
// Defines various color menus for different colors
|
|
var fillColorMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
var gradientColorMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'North',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_NORTH);
|
|
}
|
|
},
|
|
{
|
|
text: 'East',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_EAST);
|
|
}
|
|
},
|
|
{
|
|
text: 'South',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_SOUTH);
|
|
}
|
|
},
|
|
{
|
|
text: 'West',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_WEST);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENTCOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_GRADIENTCOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
var fontColorMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTCOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTCOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
var lineColorMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
var labelBackgroundMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
var labelBorderMenu = new Ext.menu.ColorMenu(
|
|
{
|
|
items: [
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_BORDERCOLOR, mxConstants.NONE);
|
|
}
|
|
},
|
|
'-'
|
|
],
|
|
handler : function(cm, color)
|
|
{
|
|
if (typeof(color) == "string")
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_BORDERCOLOR, '#'+color);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Defines the font family menu
|
|
var fonts = new Ext.data.SimpleStore(
|
|
{
|
|
fields: ['label', 'font'],
|
|
data : [['Helvetica', 'Helvetica'], ['Verdana', 'Verdana'],
|
|
['Times New Roman', 'Times New Roman'], ['Garamond', 'Garamond'],
|
|
['Courier New', 'Courier New']]
|
|
});
|
|
|
|
var fontCombo = new Ext.form.ComboBox(
|
|
{
|
|
store: fonts,
|
|
displayField:'label',
|
|
mode: 'local',
|
|
width:120,
|
|
triggerAction: 'all',
|
|
emptyText:'Select a font...',
|
|
selectOnFocus:true,
|
|
onSelect: function(entry)
|
|
{
|
|
if (entry != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTFAMILY, entry.data.font);
|
|
this.collapse();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handles typing a font name and pressing enter
|
|
fontCombo.on('specialkey', function(field, evt)
|
|
{
|
|
if (evt.keyCode == 10 ||
|
|
evt.keyCode == 13)
|
|
{
|
|
var family = field.getValue();
|
|
|
|
if (family != null &&
|
|
family.length > 0)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTFAMILY, family);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Defines the font size menu
|
|
var sizes = new Ext.data.SimpleStore({
|
|
fields: ['label', 'size'],
|
|
data : [['6pt', 6], ['8pt', 8], ['9pt', 9], ['10pt', 10], ['12pt', 12],
|
|
['14pt', 14], ['18pt', 18], ['24pt', 24], ['30pt', 30], ['36pt', 36],
|
|
['48pt', 48],['60pt', 60]]
|
|
});
|
|
|
|
var sizeCombo = new Ext.form.ComboBox(
|
|
{
|
|
store: sizes,
|
|
displayField:'label',
|
|
mode: 'local',
|
|
width:50,
|
|
triggerAction: 'all',
|
|
emptyText:'12pt',
|
|
selectOnFocus:true,
|
|
onSelect: function(entry)
|
|
{
|
|
if (entry != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTSIZE, entry.data.size);
|
|
this.collapse();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handles typing a font size and pressing enter
|
|
sizeCombo.on('specialkey', function(field, evt)
|
|
{
|
|
if (evt.keyCode == 10 ||
|
|
evt.keyCode == 13)
|
|
{
|
|
var size = parseInt(field.getValue());
|
|
|
|
if (!isNaN(size) &&
|
|
size > 0)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTSIZE, size);
|
|
}
|
|
}
|
|
});
|
|
|
|
var sizeCombo = new Ext.form.ComboBox(
|
|
{
|
|
store: sizes,
|
|
displayField:'label',
|
|
mode: 'local',
|
|
width:50,
|
|
triggerAction: 'all',
|
|
emptyText:'12pt',
|
|
selectOnFocus:true,
|
|
onSelect: function(entry)
|
|
{
|
|
if (entry != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_FONTSIZE, entry.data.size);
|
|
this.collapse();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Simplified file and modified state handling
|
|
this.filename = null;
|
|
this.modified = false;
|
|
|
|
var updateTitle = mxUtils.bind(this, function()
|
|
{
|
|
this.setTitle((this.filename || 'New Diagram') + ((this.modified) ? ' *' : '') + ' ');
|
|
});
|
|
|
|
var changeHandler = mxUtils.bind(this, function(sender, evt)
|
|
{
|
|
this.modified = true;
|
|
updateTitle();
|
|
});
|
|
|
|
graph.getModel().addListener(mxEvent.CHANGE, changeHandler);
|
|
|
|
this.saveDiagram = function(forceDialog)
|
|
{
|
|
var name = this.filename;
|
|
|
|
if (name == null ||
|
|
forceDialog)
|
|
{
|
|
var defaultValue = this.filename;
|
|
|
|
if (defaultValue == null)
|
|
{
|
|
defaultValue = "MyDiagram";
|
|
var current = defaultValue;
|
|
|
|
// Finds unused filename
|
|
var i = 2;
|
|
|
|
while (DiagramStore.get(current) != null)
|
|
{
|
|
current = defaultValue + i++;
|
|
}
|
|
|
|
defaultValue = current;
|
|
}
|
|
|
|
do
|
|
{
|
|
name = mxUtils.prompt('Enter filename', defaultValue);
|
|
|
|
if (name != null)
|
|
{
|
|
if (name.length > 0)
|
|
{
|
|
if (name != this.filename &&
|
|
DiagramStore.get(name) != null)
|
|
{
|
|
alert('File exists, please choose a different name');
|
|
defaultValue = name;
|
|
name = '';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
alert('Please choose a name');
|
|
}
|
|
}
|
|
}
|
|
while (name != null && name.length == 0);
|
|
}
|
|
|
|
if (name != null)
|
|
{
|
|
var enc = new mxCodec(mxUtils.createXmlDocument());
|
|
var node = enc.encode(graph.getModel());
|
|
var xml = mxUtils.getXml(node);
|
|
DiagramStore.put(name, xml);
|
|
this.filename = name;
|
|
this.modified = false;
|
|
updateTitle();
|
|
mxUtils.alert('Saved "'+name+'": '+xml.length+' byte(s)');
|
|
}
|
|
else
|
|
{
|
|
mxUtils.alert('Not saved');
|
|
}
|
|
};
|
|
|
|
this.openDiagram = function(name)
|
|
{
|
|
if (!this.modified ||
|
|
mxUtils.confirm('Lose changes?'))
|
|
{
|
|
var xml = DiagramStore.get(name);
|
|
|
|
if (xml != null && xml.length > 0)
|
|
{
|
|
var doc = mxUtils.parseXml(xml);
|
|
var dec = new mxCodec(doc);
|
|
dec.decode(doc.documentElement, graph.getModel());
|
|
history.clear();
|
|
this.filename = name;
|
|
this.modified = false;
|
|
updateTitle();
|
|
mxUtils.alert('Opened "'+name+'": '+xml.length+' byte(s)');
|
|
}
|
|
}
|
|
};
|
|
|
|
this.newDiagram = function()
|
|
{
|
|
if (!this.modified ||
|
|
mxUtils.confirm('Lose changes?'))
|
|
{
|
|
var cell = new mxCell();
|
|
cell.insert(new mxCell());
|
|
graph.getModel().setRoot(cell);
|
|
history.clear();
|
|
this.filename = null;
|
|
this.modified = false;
|
|
updateTitle();
|
|
}
|
|
};
|
|
|
|
this.graphPanel = new Ext.Panel(
|
|
{
|
|
region: 'center',
|
|
border:false,
|
|
tbar:[
|
|
{
|
|
text:'',
|
|
iconCls: 'new-icon',
|
|
tooltip: 'New Diagram',
|
|
handler: function()
|
|
{
|
|
this.newDiagram();
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'saveButton',
|
|
text:'',
|
|
iconCls: 'save-icon',
|
|
tooltip: 'Save Diagram',
|
|
handler: function()
|
|
{
|
|
this.saveDiagram();
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'saveAsButton',
|
|
text:'',
|
|
iconCls: 'saveas-icon',
|
|
tooltip: 'Save Diagram As',
|
|
handler: function()
|
|
{
|
|
this.saveDiagram(true);
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
{
|
|
id: 'print',
|
|
text:'',
|
|
iconCls: 'print-icon',
|
|
tooltip: 'Print Preview',
|
|
handler: function()
|
|
{
|
|
var preview = new mxPrintPreview(graph);
|
|
preview.autoOrigin = false;
|
|
preview.open();
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'posterprint',
|
|
text:'',
|
|
iconCls: 'press-icon',
|
|
tooltip: 'Poster Print Preview',
|
|
handler: function()
|
|
{
|
|
try
|
|
{
|
|
var pageCount = mxUtils.prompt('Enter maximum page count', '1');
|
|
|
|
if (pageCount != null)
|
|
{
|
|
var scale = mxUtils.getScaleForPageCount(pageCount, graph);
|
|
var preview = new mxPrintPreview(graph, scale);
|
|
preview.open();
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
// ignore
|
|
}
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'view',
|
|
text:'',
|
|
iconCls: 'preview-icon',
|
|
tooltip: 'Show',
|
|
handler: function()
|
|
{
|
|
mxUtils.show(graph, null, 10, 10);
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
{
|
|
id: 'cut',
|
|
text:'',
|
|
iconCls: 'cut-icon',
|
|
tooltip: 'Cut',
|
|
handler: function()
|
|
{
|
|
mxClipboard.cut(graph);
|
|
},
|
|
scope:this
|
|
},{
|
|
id: 'copy',
|
|
text:'',
|
|
iconCls: 'copy-icon',
|
|
tooltip: 'Copy',
|
|
handler: function()
|
|
{
|
|
mxClipboard.copy(graph);
|
|
},
|
|
scope:this
|
|
},{
|
|
text:'',
|
|
iconCls: 'paste-icon',
|
|
tooltip: 'Paste',
|
|
handler: function()
|
|
{
|
|
mxClipboard.paste(graph);
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
{
|
|
id: 'delete',
|
|
text:'',
|
|
iconCls: 'delete-icon',
|
|
tooltip: 'Delete',
|
|
handler: function()
|
|
{
|
|
graph.removeCells();
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
{
|
|
id: 'undo',
|
|
text:'',
|
|
iconCls: 'undo-icon',
|
|
tooltip: 'Undo',
|
|
handler: function()
|
|
{
|
|
history.undo();
|
|
},
|
|
scope:this
|
|
},{
|
|
id: 'redo',
|
|
text:'',
|
|
iconCls: 'redo-icon',
|
|
tooltip: 'Redo',
|
|
handler: function()
|
|
{
|
|
history.redo();
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
fontCombo,
|
|
' ',
|
|
sizeCombo,
|
|
'-',
|
|
{
|
|
id: 'bold',
|
|
text: '',
|
|
iconCls:'bold-icon',
|
|
tooltip: 'Bold',
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'italic',
|
|
text: '',
|
|
tooltip: 'Italic',
|
|
iconCls:'italic-icon',
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_ITALIC);
|
|
},
|
|
scope:this
|
|
},
|
|
{
|
|
id: 'underline',
|
|
text: '',
|
|
tooltip: 'Underline',
|
|
iconCls:'underline-icon',
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_UNDERLINE);
|
|
},
|
|
scope:this
|
|
},
|
|
'-',
|
|
{
|
|
id: 'align',
|
|
text:'',
|
|
iconCls: 'left-icon',
|
|
tooltip: 'Text Alignment',
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
id:'reading-menu',
|
|
cls:'reading-menu',
|
|
items: [
|
|
{
|
|
text:'Left',
|
|
checked:false,
|
|
group:'rp-group',
|
|
scope:this,
|
|
iconCls:'left-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT);
|
|
}
|
|
},
|
|
{
|
|
text:'Center',
|
|
checked:true,
|
|
group:'rp-group',
|
|
scope:this,
|
|
iconCls:'center-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER);
|
|
}
|
|
},
|
|
{
|
|
text:'Right',
|
|
checked:false,
|
|
group:'rp-group',
|
|
scope:this,
|
|
iconCls:'right-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_RIGHT);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Top',
|
|
checked:false,
|
|
group:'vrp-group',
|
|
scope:this,
|
|
iconCls:'top-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP);
|
|
}
|
|
},
|
|
{
|
|
text:'Middle',
|
|
checked:true,
|
|
group:'vrp-group',
|
|
scope:this,
|
|
iconCls:'middle-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE);
|
|
}
|
|
},
|
|
{
|
|
text:'Bottom',
|
|
checked:false,
|
|
group:'vrp-group',
|
|
scope:this,
|
|
iconCls:'bottom-icon',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_BOTTOM);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
id: 'fontcolor',
|
|
text: '',
|
|
tooltip: 'Fontcolor',
|
|
iconCls:'fontcolor-icon',
|
|
menu: fontColorMenu // <-- submenu by reference
|
|
},
|
|
{
|
|
id: 'linecolor',
|
|
text: '',
|
|
tooltip: 'Linecolor',
|
|
iconCls:'linecolor-icon',
|
|
menu: lineColorMenu // <-- submenu by reference
|
|
},
|
|
{
|
|
id: 'fillcolor',
|
|
text: '',
|
|
tooltip: 'Fillcolor',
|
|
iconCls:'fillcolor-icon',
|
|
menu: fillColorMenu // <-- submenu by reference
|
|
}],
|
|
bbar:[
|
|
{
|
|
text:'Zoom',
|
|
iconCls: 'zoom-icon',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Custom',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var value = mxUtils.prompt('Enter zoom (%)', parseInt(graph.getView().getScale() * 100));
|
|
|
|
if (value != null)
|
|
{
|
|
graph.getView().setScale(parseInt(value) / 100);
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'400%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(4);
|
|
}
|
|
},
|
|
{
|
|
text:'200%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(2);
|
|
}
|
|
},
|
|
{
|
|
text:'150%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(1.5);
|
|
}
|
|
},
|
|
{
|
|
text:'100%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(1);
|
|
}
|
|
},
|
|
{
|
|
text:'75%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(0.75);
|
|
}
|
|
},
|
|
{
|
|
text:'50%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(0.5);
|
|
}
|
|
},
|
|
{
|
|
text:'25%',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.getView().setScale(0.25);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Zoom In',
|
|
iconCls: 'zoomin-icon',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.zoomIn();
|
|
}
|
|
},
|
|
{
|
|
text:'Zoom Out',
|
|
iconCls: 'zoomout-icon',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.zoomOut();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Actual Size',
|
|
iconCls: 'zoomactual-icon',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.zoomActual();
|
|
}
|
|
},
|
|
{
|
|
text:'Fit Window',
|
|
iconCls: 'fit-icon',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
graph.fit();
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Layout',
|
|
iconCls: 'diagram-icon',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Vertical Partition Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
executeLayout(new mxPartitionLayout(graph, false));
|
|
}
|
|
},
|
|
{
|
|
text:'Horizontal Partition Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
executeLayout(new mxPartitionLayout(graph));
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Vertical Stack Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxStackLayout(graph, false);
|
|
layout.fill = true;
|
|
executeLayout(layout);
|
|
}
|
|
},
|
|
{
|
|
text:'Horizontal Stack Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxStackLayout(graph, false);
|
|
layout.fill = true;
|
|
executeLayout(layout);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Place Edge Labels',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
executeLayout(new mxEdgeLabelLayout(graph));
|
|
}
|
|
},
|
|
{
|
|
text:'Parallel Edges',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
executeLayout(new mxParallelEdgeLayout(graph));
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Vertical Hierarchical Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxHierarchicalLayout(graph);
|
|
executeLayout(layout, true);
|
|
}
|
|
},
|
|
{
|
|
text:'Horizontal Hierarchical Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxHierarchicalLayout(graph,
|
|
mxConstants.DIRECTION_WEST);
|
|
executeLayout(layout, true);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Vertical Tree Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxCompactTreeLayout(graph, false);
|
|
executeLayout(layout, true, true);
|
|
}
|
|
},
|
|
{
|
|
text:'Horizontal Tree Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxCompactTreeLayout(graph);
|
|
executeLayout(layout, true, true);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Organic Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var layout = new mxFastOrganicLayout(graph);
|
|
layout.forceConstant = 80;
|
|
executeLayout(layout, true);
|
|
}
|
|
},
|
|
{
|
|
text:'Circle Layout',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
executeLayout(new mxCircleLayout(graph), true);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Options',
|
|
iconCls: 'preferences-icon',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Grid',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Grid Size',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
var value = mxUtils.prompt('Enter Grid Size (Pixels)', graph.gridSize);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.gridSize = value;
|
|
}
|
|
}
|
|
},
|
|
{
|
|
checked: true,
|
|
text:'Grid Enabled',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setGridEnabled(checked);
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
text:'Stylesheet',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Basic Style',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var node = mxUtils.load('resources/basic-style.xml').getDocumentElement();
|
|
var dec = new mxCodec(node.ownerDocument);
|
|
dec.decode(node, graph.getStylesheet());
|
|
graph.refresh();
|
|
}
|
|
},
|
|
{
|
|
text:'Default Style',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var node = mxUtils.load('resources/default-style.xml').getDocumentElement();
|
|
var dec = new mxCodec(node.ownerDocument);
|
|
dec.decode(node, graph.getStylesheet());
|
|
graph.refresh();
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
text:'Labels',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
checked: true,
|
|
text:'Show Labels',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.labelsVisible = checked;
|
|
graph.refresh();
|
|
}
|
|
},
|
|
{
|
|
checked: true,
|
|
text:'Move Edge Labels',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.edgeLabelsMovable = checked;
|
|
}
|
|
},
|
|
{
|
|
checked: false,
|
|
text:'Move Vertex Labels',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.vertexLabelsMovable = checked;
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: false,
|
|
text:'HTML Labels',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setHtmlLabels(checked);
|
|
graph.refresh();
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Connections',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
checked: true,
|
|
text:'Connectable',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setConnectable(checked);
|
|
}
|
|
},
|
|
{
|
|
checked: false,
|
|
text:'Connectable Edges',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setConnectableEdges(checked);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: true,
|
|
text:'Create Target',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.connectionHandler.setCreateTarget(checked);
|
|
}
|
|
},
|
|
{
|
|
checked: true,
|
|
text:'Disconnect On Move',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setDisconnectOnMove(checked);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: false,
|
|
text:'Add/Remove Bends',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
mxEdgeHandler.prototype.addEnabled = checked;
|
|
mxEdgeHandler.prototype.removeEnabled = checked;
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
text:'Validation',
|
|
handler: function(menu) { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
checked: true,
|
|
text:'Allow Dangling Edges',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setAllowDanglingEdges(checked);
|
|
}
|
|
},
|
|
{
|
|
checked: false,
|
|
text:'Clone Invalid Edges',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setCloneInvalidEdges(checked);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: false,
|
|
text:'Allow Loops',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setAllowLoops(checked);
|
|
}
|
|
},
|
|
{
|
|
checked: true,
|
|
text:'Multigraph',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setMultigraph(checked);
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: false,
|
|
text:'Page Layout',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.pageVisible = checked;
|
|
graph.preferPageSize = graph.pageBreaksVisible;
|
|
graph.view.validate();
|
|
graph.sizeDidChange();
|
|
}
|
|
},
|
|
{
|
|
checked: false,
|
|
text:'Page Breaks',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.pageBreaksVisible = checked;
|
|
graph.preferPageSize = graph.pageBreaksVisible;
|
|
graph.sizeDidChange();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
checked: true,
|
|
text:'Strict Scrollarea',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.useScrollbarsForPanning = checked;
|
|
}
|
|
},
|
|
{
|
|
checked: true,
|
|
text:'Allow Negative Coordinates',
|
|
scope:this,
|
|
checkHandler: function(item, checked)
|
|
{
|
|
graph.setAllowNegativeCoordinates(checked);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Show XML',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var enc = new mxCodec(mxUtils.createXmlDocument());
|
|
var node = enc.encode(graph.getModel());
|
|
|
|
mxUtils.popup(mxUtils.getPrettyXml(node));
|
|
}
|
|
},
|
|
{
|
|
text:'Parse XML',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
var xml = mxUtils.prompt('Enter XML:', '');
|
|
|
|
if (xml != null && xml.length > 0)
|
|
{
|
|
var doc = mxUtils.parseXml(xml);
|
|
var dec = new mxCodec(doc);
|
|
dec.decode(doc.documentElement, graph.getModel());
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Console',
|
|
scope:this,
|
|
handler: function(item)
|
|
{
|
|
mxLog.setVisible(!mxLog.isVisible());
|
|
}
|
|
}]
|
|
}
|
|
}],
|
|
|
|
onContextMenu : function(node, e)
|
|
{
|
|
var selected = !graph.isSelectionEmpty();
|
|
|
|
this.menu = new Ext.menu.Menu(
|
|
{
|
|
items: [{
|
|
text:'Undo',
|
|
iconCls:'undo-icon',
|
|
disabled: !history.canUndo(),
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
history.undo();
|
|
}
|
|
},'-',{
|
|
text:'Cut',
|
|
iconCls:'cut-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
mxClipboard.cut(graph);
|
|
}
|
|
},{
|
|
text:'Copy',
|
|
iconCls:'copy-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
mxClipboard.copy(graph);
|
|
}
|
|
},{
|
|
text:'Paste',
|
|
iconCls:'paste-icon',
|
|
disabled: mxClipboard.isEmpty(),
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
mxClipboard.paste(graph);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Delete',
|
|
iconCls:'delete-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.removeCells();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Format',
|
|
disabled: !selected,
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Background',
|
|
disabled: !selected,
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Fillcolor',
|
|
iconCls:'fillcolor-icon',
|
|
menu: fillColorMenu
|
|
},
|
|
{
|
|
text: 'Gradient',
|
|
menu: gradientColorMenu
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Image',
|
|
handler: function()
|
|
{
|
|
var value = '';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_IMAGE] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Image URL', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_IMAGE, value);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
text:'Shadow',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_SHADOW);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Opacity',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
var value = mxUtils.prompt('Enter Opacity (0-100%)', '100');
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_OPACITY, value);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
text:'Label',
|
|
disabled: !selected,
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Fontcolor',
|
|
iconCls:'fontcolor-icon',
|
|
menu: fontColorMenu
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Label Fill',
|
|
menu: labelBackgroundMenu
|
|
},
|
|
{
|
|
text: 'Label Border',
|
|
menu: labelBorderMenu
|
|
},
|
|
'-',
|
|
{
|
|
text:'Rotate Label',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_HORIZONTAL, true);
|
|
}
|
|
},
|
|
{
|
|
text:'Text opacity',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
var value = mxUtils.prompt('Enter text opacity (0-100%)', '100');
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_TEXT_OPACITY, value);
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Position',
|
|
disabled: !selected,
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Top',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_TOP);
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_BOTTOM);
|
|
}
|
|
},
|
|
{
|
|
text: 'Middle',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE);
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE);
|
|
}
|
|
},
|
|
{
|
|
text: 'Bottom',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_BOTTOM);
|
|
graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Left',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_LEFT);
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_RIGHT);
|
|
}
|
|
},
|
|
{
|
|
text: 'Center',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER);
|
|
}
|
|
},
|
|
{
|
|
text: 'Right',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_RIGHT);
|
|
graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Hide',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_NOLABEL, false);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Line',
|
|
disabled: !selected,
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Linecolor',
|
|
iconCls:'linecolor-icon',
|
|
menu: lineColorMenu
|
|
},
|
|
'-',
|
|
{
|
|
text:'Dashed',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_DASHED);
|
|
}
|
|
},
|
|
{
|
|
text: 'Linewidth',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_STROKEWIDTH] || 1;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Linewidth (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
text:'Connector',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Straight',
|
|
icon: '../../images/straight.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyle('straight');
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Horizontal',
|
|
icon: '../../images/connect.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyle(null);
|
|
}
|
|
},
|
|
{
|
|
text: 'Vertical',
|
|
icon: '../../images/vertical.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyle('vertical');
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Entity Relation',
|
|
icon: '../../images/entity.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyle('edgeStyle=entityRelationEdgeStyle');
|
|
}
|
|
},
|
|
{
|
|
text: 'Arrow',
|
|
icon: '../../images/arrow.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyle('arrow');
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Plain',
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_NOEDGESTYLE, false);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Linestart',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Open',
|
|
icon: '../../images/open_start.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.ARROW_OPEN);
|
|
}
|
|
},
|
|
{
|
|
text: 'Classic',
|
|
icon: '../../images/classic_start.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.ARROW_CLASSIC);
|
|
}
|
|
},
|
|
{
|
|
text: 'Block',
|
|
icon: '../../images/block_start.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.ARROW_BLOCK);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Diamond',
|
|
icon: '../../images/diamond_start.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.ARROW_DIAMOND);
|
|
}
|
|
},
|
|
{
|
|
text: 'Oval',
|
|
icon: '../../images/oval_start.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.ARROW_OVAL);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTARROW, mxConstants.NONE);
|
|
}
|
|
},
|
|
{
|
|
text: 'Size',
|
|
handler: function()
|
|
{
|
|
var size = mxUtils.prompt('Enter Size', mxConstants.DEFAULT_MARKERSIZE);
|
|
|
|
if (size != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_STARTSIZE, size);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
text:'Lineend',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Open',
|
|
icon: '../../images/open_end.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_OPEN);
|
|
}
|
|
},
|
|
{
|
|
text: 'Classic',
|
|
icon: '../../images/classic_end.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_CLASSIC);
|
|
}
|
|
},
|
|
{
|
|
text: 'Block',
|
|
icon: '../../images/block_end.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_BLOCK);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Diamond',
|
|
icon: '../../images/diamond_end.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_DIAMOND);
|
|
}
|
|
},
|
|
{
|
|
text: 'Oval',
|
|
icon: '../../images/oval_end.gif',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_OVAL);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'None',
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDARROW, 'none');
|
|
}
|
|
},
|
|
{
|
|
text: 'Size',
|
|
handler: function()
|
|
{
|
|
var size = mxUtils.prompt('Enter Size', mxConstants.DEFAULT_MARKERSIZE);
|
|
|
|
if (size != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ENDSIZE, size);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Spacing',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Top',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SPACING_TOP] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Top Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SPACING_TOP, value);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
text: 'Right',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SPACING_RIGHT] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Right Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SPACING_RIGHT, value);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
text: 'Bottom',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SPACING_BOTTOM] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Bottom Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SPACING_BOTTOM, value);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
text: 'Left',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SPACING_LEFT] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Left Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SPACING_LEFT, value);
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Global',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SPACING] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SPACING, value);
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Source spacing',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter source spacing (pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_SOURCE_PERIMETER_SPACING, value);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
text: 'Target spacing',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter target spacing (pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_TARGET_PERIMETER_SPACING, value);
|
|
}
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Perimeter',
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_PERIMETER_SPACING] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Perimeter Spacing (Pixels)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_PERIMETER_SPACING, value);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
text:'Direction',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'North',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_NORTH);
|
|
}
|
|
},
|
|
{
|
|
text: 'East',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_EAST);
|
|
}
|
|
},
|
|
{
|
|
text: 'South',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_SOUTH);
|
|
}
|
|
},
|
|
{
|
|
text: 'West',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_WEST);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Rotation',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
var value = '0';
|
|
var state = graph.getView().getState(graph.getSelectionCell());
|
|
|
|
if (state != null)
|
|
{
|
|
value = state.style[mxConstants.STYLE_ROTATION] || value;
|
|
}
|
|
|
|
value = mxUtils.prompt('Enter Angle (0-360)', value);
|
|
|
|
if (value != null)
|
|
{
|
|
graph.setCellStyles(mxConstants.STYLE_ROTATION, value);
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Rounded',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.toggleCellStyles(mxConstants.STYLE_ROUNDED);
|
|
}
|
|
},
|
|
{
|
|
text:'Style',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
var cells = graph.getSelectionCells();
|
|
|
|
if (cells != null &&
|
|
cells.length > 0)
|
|
{
|
|
var model = graph.getModel();
|
|
var style = mxUtils.prompt('Enter Style', model.getStyle(cells[0]) || '');
|
|
|
|
if (style != null)
|
|
{
|
|
graph.setCellStyle(style, cells);
|
|
}
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
{
|
|
split:true,
|
|
text:'Shape',
|
|
handler: function() { },
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text:'Home',
|
|
iconCls: 'home-icon',
|
|
disabled: graph.view.currentRoot == null,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.home();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Exit group',
|
|
iconCls:'up-icon',
|
|
disabled: graph.view.currentRoot == null,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.exitGroup();
|
|
}
|
|
},
|
|
{
|
|
text:'Enter group',
|
|
iconCls:'down-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.enterGroup();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Group',
|
|
icon: '../../images/group.gif',
|
|
disabled: graph.getSelectionCount() <= 1,
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setSelectionCell(graph.groupCells(null, 20));
|
|
}
|
|
},
|
|
{
|
|
text:'Ungroup',
|
|
icon: '../../images/ungroup.gif',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.setSelectionCells(graph.ungroupCells());
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Remove from group',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.removeCellsFromParent();
|
|
}
|
|
},
|
|
{
|
|
text:'Update group bounds',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.updateGroupBounds(null, 20);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Collapse',
|
|
iconCls:'collapse-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.foldCells(true);
|
|
}
|
|
},
|
|
{
|
|
text:'Expand',
|
|
iconCls:'expand-icon',
|
|
disabled: !selected,
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.foldCells(false);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'To Back',
|
|
icon: '../../images/toback.gif',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.orderCells(true);
|
|
}
|
|
},
|
|
{
|
|
text:'To Front',
|
|
icon: '../../images/tofront.gif',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.orderCells(false);
|
|
}
|
|
},
|
|
'-',
|
|
|
|
|
|
{
|
|
text:'Align',
|
|
menu:
|
|
{
|
|
items: [
|
|
{
|
|
text: 'Left',
|
|
icon: '../../images/alignleft.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_LEFT);
|
|
}
|
|
},
|
|
{
|
|
text: 'Center',
|
|
icon: '../../images/aligncenter.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_CENTER);
|
|
}
|
|
},
|
|
{
|
|
text: 'Right',
|
|
icon: '../../images/alignright.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_RIGHT);
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text: 'Top',
|
|
icon: '../../images/aligntop.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_TOP);
|
|
}
|
|
},
|
|
{
|
|
text: 'Middle',
|
|
icon: '../../images/alignmiddle.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_MIDDLE);
|
|
}
|
|
},
|
|
{
|
|
text: 'Bottom',
|
|
icon: '../../images/alignbottom.gif',
|
|
handler: function()
|
|
{
|
|
graph.alignCells(mxConstants.ALIGN_BOTTOM);
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Autosize',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
if (!graph.isSelectionEmpty())
|
|
{
|
|
graph.updateCellSize(graph.getSelectionCell());
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Edit',
|
|
scope:this,
|
|
handler: function()
|
|
{
|
|
graph.startEditing();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Select Vertices',
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.selectVertices();
|
|
}
|
|
},
|
|
{
|
|
text:'Select Edges',
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.selectEdges();
|
|
}
|
|
},
|
|
'-',
|
|
{
|
|
text:'Select All',
|
|
scope: this,
|
|
handler:function()
|
|
{
|
|
graph.selectAll();
|
|
}
|
|
}]
|
|
});
|
|
|
|
this.menu.on('hide', this.onContextHide, this);
|
|
|
|
|
|
// Adds a small offset to make sure the mouse released event
|
|
// is routed via the shape which was initially clicked. This
|
|
// is required to avoid a reset of the selection in Safari.
|
|
this.menu.showAt([e.clientX + 1, e.clientY + 1]);
|
|
},
|
|
|
|
onContextHide : function()
|
|
{
|
|
if(this.ctxNode)
|
|
{
|
|
this.ctxNode.ui.removeClass('x-node-ctx');
|
|
this.ctxNode = null;
|
|
}
|
|
}
|
|
});
|
|
|
|
MainPanel.superclass.constructor.call(this,
|
|
{
|
|
region:'center',
|
|
layout: 'fit',
|
|
items: this.graphPanel
|
|
});
|
|
|
|
// Redirects the context menu to ExtJs menus
|
|
graph.panningHandler.popup = mxUtils.bind(this, function(x, y, cell, evt)
|
|
{
|
|
this.graphPanel.onContextMenu(null, evt);
|
|
});
|
|
|
|
graph.panningHandler.hideMenu = mxUtils.bind(this, function()
|
|
{
|
|
if (this.graphPanel.menuPanel != null)
|
|
{
|
|
this.graphPanel.menuPanel.hide();
|
|
}
|
|
});
|
|
|
|
// Fits the SVG container into the panel body
|
|
this.graphPanel.on('resize', function()
|
|
{
|
|
graph.sizeDidChange();
|
|
});
|
|
};
|
|
|
|
Ext.extend(MainPanel, Ext.Panel);
|