updates to js syntax

development
mcyph 2021-03-20 19:07:56 +11:00
parent a599a51ef9
commit fc98630dad
61 changed files with 9334 additions and 10586 deletions

View File

@ -40,7 +40,7 @@ echo($xml);</pre></blockquote><p>To open a local file, the file should be upload
&lt;mxDefaultToolbar&gt;
&lt;add as=&quot;save&quot; action=&quot;save&quot; icon=&quot;images/save.gif&quot;/&gt;
&lt;add as=&quot;Swimlane&quot; template=&quot;swimlane&quot; icon=&quot;images/swimlane.gif&quot;/&gt;
...</pre></blockquote><p>The format of the configuration is described in <a href="../io/mxDefaultToolbarCodec-js.html#mxDefaultToolbarCodec.decode" class=LFunction id=link200 onMouseOver="ShowTip(event, 'tt128', 'link200')" onMouseOut="HideTip('tt128')">mxDefaultToolbarCodec.decode</a>.</p><h4 class=CHeading>Ids</h4><p>For the IDs, there is an implicit behaviour in <a href="../io/mxCodec-js.html#mxCodec" class=LClass id=link201 onMouseOver="ShowTip(event, 'tt3', 'link201')" onMouseOut="HideTip('tt3')">mxCodec</a>: It moves the Id from the cell to the user object at encoding time and vice versa at decoding time.&nbsp; For example, if the Task node from above has an id attribute, then the <a href="../model/mxCell-js.html#mxCell.id" class=LVariable id=link202 onMouseOver="ShowTip(event, 'tt129', 'link202')" onMouseOut="HideTip('tt129')">mxCell.id</a> of the corresponding cell will have this value.&nbsp; If there is no Id collision in the model, then the cell may be retrieved using this Id with the <a href="../model/mxGraphModel-js.html#mxGraphModel.getCell" class=LFunction id=link203 onMouseOver="ShowTip(event, 'tt130', 'link203')" onMouseOut="HideTip('tt130')">mxGraphModel.getCell</a> function.&nbsp; If there is a collision, a new Id will be created for the cell using <a href="../model/mxGraphModel-js.html#mxGraphModel.createId" class=LFunction id=link204 onMouseOver="ShowTip(event, 'tt131', 'link204')" onMouseOut="HideTip('tt131')">mxGraphModel.createId</a>.&nbsp; At encoding time, this new Id will replace the value previously stored under the id attribute in the Task node.</p><p>See <a href="../io/mxEditorCodec-js.html#mxEditorCodec" class=LClass id=link205 onMouseOver="ShowTip(event, 'tt132', 'link205')" onMouseOut="HideTip('tt132')">mxEditorCodec</a>, <a href="../io/mxDefaultToolbarCodec-js.html#mxDefaultToolbarCodec" class=LClass id=link206 onMouseOver="ShowTip(event, 'tt133', 'link206')" onMouseOut="HideTip('tt133')">mxDefaultToolbarCodec</a> and <a href="../io/mxDefaultPopupMenuCodec-js.html#mxDefaultPopupMenuCodec" class=LClass id=link207 onMouseOver="ShowTip(event, 'tt127', 'link207')" onMouseOut="HideTip('tt127')">mxDefaultPopupMenuCodec</a> for information about configuring the editor and user interface.</p><h4 class=CHeading>Programmatically inserting cells</h4><p>For inserting a new cell, say, by clicking a button in the document, the following code can be used.&nbsp; This requires an reference to the editor.</p><blockquote><pre class="prettyprint">var userObject = new Object();
...</pre></blockquote><p>The format of the configuration is described in <a href="../io/mxDefaultToolbarCodec-js.html#mxDefaultToolbarCodec.decode" class=LFunction id=link200 onMouseOver="ShowTip(event, 'tt128', 'link200')" onMouseOut="HideTip('tt128')">mxDefaultToolbarCodec.decode</a>.</p><h4 class=CHeading>Ids</h4><p>For the IDs, there is an implicit behaviour in <a href="../io/mxCodec-js.html#mxCodec" class=LClass id=link201 onMouseOver="ShowTip(event, 'tt3', 'link201')" onMouseOut="HideTip('tt3')">mxCodec</a>: It moves the Id from the cell to the user object at encoding time and vice versa at decoding time.&nbsp; For example, if the Task node from above has an id attribute, then the <a href="../model/mxCell-js.html#mxCell.id" class=LVariable id=link202 onMouseOver="ShowTip(event, 'tt129', 'link202')" onMouseOut="HideTip('tt129')">mxCell.id</a> of the corresponding cell will have this value.&nbsp; If there is no Id collision in the model, then the cell may be retrieved using this Id with the <a href="../model/mxGraphModel-js.html#mxGraphModel.getCell" class=LFunction id=link203 onMouseOver="ShowTip(event, 'tt130', 'link203')" onMouseOut="HideTip('tt130')">mxGraphModel.getCell</a> function.&nbsp; If there is a collision, a new Id will be created for the cell using <a href="../model/mxGraphModel-js.html#mxGraphModel.createId" class=LFunction id=link204 onMouseOver="ShowTip(event, 'tt131', 'link204')" onMouseOut="HideTip('tt131')">mxGraphModel.createId</a>.&nbsp; At encoding time, this new Id will replace the value previously stored under the id attribute in the Task node.</p><p>See <a href="../io/mxEditorCodec-js.html#mxEditorCodec" class=LClass id=link205 onMouseOver="ShowTip(event, 'tt132', 'link205')" onMouseOut="HideTip('tt132')">mxEditorCodec</a>, <a href="../io/mxDefaultToolbarCodec-js.html#mxDefaultToolbarCodec" class=LClass id=link206 onMouseOver="ShowTip(event, 'tt133', 'link206')" onMouseOut="HideTip('tt133')">mxDefaultToolbarCodec</a> and <a href="../io/mxDefaultPopupMenuCodec-js.html#mxDefaultPopupMenuCodec" class=LClass id=link207 onMouseOver="ShowTip(event, 'tt127', 'link207')" onMouseOut="HideTip('tt127')">mxDefaultPopupMenuCodec</a> for information about configuring the editor and user interface.</p><h4 class=CHeading>Programmatically inserting cells</h4><p>For inserting a new cell, say, by clicking a button in the document, the following code can be used.&nbsp; This requires an reference to the editor.</p><blockquote><pre class="prettyprint">var userObject = {};
var parent = editor.graph.getDefaultParent();
var model = editor.graph.model;
model.beginUpdate();

View File

@ -11,7 +11,7 @@ if (browserType) {document.write("<div class=" + browserType + ">");if (browserV
<div id=Content><div class="CClass"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="mxObjectCodec"></a>mxObjectCodec</h1><div class=CBody><p>Generic codec for JavaScript objects that implements a mapping between JavaScript objects and XML nodes that maps each field or element to an attribute or child node, and vice versa.</p><h4 class=CHeading>Atomic Values</h4><p>Consider the following example.</p><blockquote><pre class="prettyprint">var obj = new Object();
<div id=Content><div class="CClass"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="mxObjectCodec"></a>mxObjectCodec</h1><div class=CBody><p>Generic codec for JavaScript objects that implements a mapping between JavaScript objects and XML nodes that maps each field or element to an attribute or child node, and vice versa.</p><h4 class=CHeading>Atomic Values</h4><p>Consider the following example.</p><blockquote><pre class="prettyprint">var obj = {};
obj.foo = &quot;Foo&quot;;
obj.bar = &quot;Bar&quot;;</pre></blockquote><p>This object is encoded into an XML node using the following.</p><blockquote><pre class="prettyprint">var enc = new mxCodec();
var node = enc.encode(obj);</pre></blockquote><p>The output of the encoding may be viewed using <a href="../util/mxLog-js.html#mxLog" class=LClass id=link48 onMouseOver="ShowTip(event, 'tt38', 'link48')" onMouseOut="HideTip('tt38')">mxLog</a> as follows.</p><blockquote><pre class="prettyprint">mxLog.show();
@ -29,7 +29,7 @@ obj[&quot;foo&quot;] = {bar: &quot;Bar&quot;};</pre></blockquote><p>This array i
<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="mxObjectCodec.Functions"></a>Functions</h3></div></div>
<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="mxObjectCodec.mxObjectCodec"></a>mxObjectCodec</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class="Prototype"><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class="PBeforeParameters prettyprint "nowrap>function mxObjectCodec(</td><td class="PParameter prettyprint " nowrap>template,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>exclude,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>idrefs,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>mapping</td><td class="PAfterParameters prettyprint "nowrap>)</td></tr></table></td></tr></table></blockquote><p>Constructs a new codec for the specified template object.&nbsp; The variables in the optional exclude array are ignored by the codec.&nbsp; Variables in the optional idrefs array are turned into references in the XML.&nbsp; The optional mapping may be used to map from variable names to XML attributes.&nbsp; The argument is created as follows:</p><blockquote><pre class="prettyprint">var mapping = new Object();
<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="mxObjectCodec.mxObjectCodec"></a>mxObjectCodec</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class="Prototype"><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class="PBeforeParameters prettyprint "nowrap>function mxObjectCodec(</td><td class="PParameter prettyprint " nowrap>template,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>exclude,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>idrefs,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>mapping</td><td class="PAfterParameters prettyprint "nowrap>)</td></tr></table></td></tr></table></blockquote><p>Constructs a new codec for the specified template object.&nbsp; The variables in the optional exclude array are ignored by the codec.&nbsp; Variables in the optional idrefs array are turned into references in the XML.&nbsp; The optional mapping may be used to map from variable names to XML attributes.&nbsp; The argument is created as follows:</p><blockquote><pre class="prettyprint">var mapping = {};
mapping['variableName'] = 'attribute-name';</pre></blockquote><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>template</td><td class=CDLDescription>Prototypical instance of the object to be encoded/decoded.</td></tr><tr><td class=CDLEntry>exclude</td><td class=CDLDescription>Optional array of fieldnames to be ignored.</td></tr><tr><td class=CDLEntry>idrefs</td><td class=CDLDescription>Optional array of fieldnames to be converted to/from references.</td></tr><tr><td class=CDLEntry>mapping</td><td class=CDLDescription>Optional mapping from field- to attributenames.</td></tr></table></div></div></div>
<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="mxObjectCodec.Variables"></a>Variables</h3></div></div>

View File

@ -17,7 +17,7 @@ mxClipboard.paste(graph2);</pre></blockquote><p>This copies the selection cells
cells = cells || graph.getSelectionCells();
var result = graph.getExportableCells(cells);
mxClipboard.parents = new Object();
mxClipboard.parents = {};
for (var i = 0; i &lt; result.length; i++)
{

View File

@ -27,7 +27,7 @@ style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;</pre></blockquote><p>F
var label = this.convertValueToString(cell);
return 'Tooltip for '+label;
}</pre></blockquote><h4 class=CHeading>Shapes &amp; Styles</h4><p>The implementation of new shapes is demonstrated in the examples.&nbsp; We&rsquo;ll assume that we have implemented a custom shape with the name BoxShape which we want to use for drawing vertices.&nbsp; To use this shape, it must first be registered in the cell renderer as follows:</p><blockquote><pre class="prettyprint">mxCellRenderer.registerShape('box', BoxShape);</pre></blockquote><p>The code registers the BoxShape constructor under the name box in the cell renderer of the graph.&nbsp; The shape can now be referenced using the shape-key in a style definition.&nbsp; (The cell renderer contains a set of additional shapes, namely one for each constant with a SHAPE-prefix in <a href="../util/mxConstants-js.html#mxConstants" class=LClass id=link770 onMouseOver="ShowTip(event, 'tt527', 'link770')" onMouseOut="HideTip('tt527')">mxConstants</a>.)</p><p>Styles are a collection of key, value pairs and a stylesheet is a collection of named styles.&nbsp; The names are referenced by the cellstyle, which is stored in <a href="../model/mxCell-js.html#mxCell.style" class=LVariable id=link771 onMouseOver="ShowTip(event, 'tt528', 'link771')" onMouseOut="HideTip('tt528')">mxCell.style</a> with the following format: [stylename;|key=value;].&nbsp; The string is resolved to a collection of key, value pairs, where the keys are overridden with the values in the string.</p><p>When introducing a new shape, the name under which the shape is registered must be used in the stylesheet.&nbsp; There are three ways of doing this:</p><ul><li>By changing the default style, so that all vertices will use the new shape</li><li>By defining a new style, so that only vertices with the respective cellstyle will use the new shape</li><li>By using shape=box in the cellstyle&rsquo;s optional list of key, value pairs to be overridden</li></ul><p>In the first case, the code to fetch and modify the default style for vertices is as follows:</p><blockquote><pre class="prettyprint">var style = graph.getStylesheet().getDefaultVertexStyle();
style[mxConstants.STYLE_SHAPE] = 'box';</pre></blockquote><p>The code takes the default vertex style, which is used for all vertices that do not have a specific cellstyle, and modifies the value for the shape-key in-place to use the new BoxShape for drawing vertices.&nbsp; This is done by assigning the box value in the second line, which refers to the name of the BoxShape in the cell renderer.</p><p>In the second case, a collection of key, value pairs is created and then added to the stylesheet under a new name.&nbsp; In order to distinguish the shapename and the stylename we&rsquo;ll use boxstyle for the stylename:</p><blockquote><pre class="prettyprint">var style = new Object();
style[mxConstants.STYLE_SHAPE] = 'box';</pre></blockquote><p>The code takes the default vertex style, which is used for all vertices that do not have a specific cellstyle, and modifies the value for the shape-key in-place to use the new BoxShape for drawing vertices.&nbsp; This is done by assigning the box value in the second line, which refers to the name of the BoxShape in the cell renderer.</p><p>In the second case, a collection of key, value pairs is created and then added to the stylesheet under a new name.&nbsp; In order to distinguish the shapename and the stylename we&rsquo;ll use boxstyle for the stylename:</p><blockquote><pre class="prettyprint">var style = {};
style[mxConstants.STYLE_SHAPE] = 'box';
style[mxConstants.STYLE_STROKECOLOR] = '#000000';
style[mxConstants.STYLE_FONTCOLOR] = '#000000';

View File

@ -34,7 +34,7 @@ edgeStyle[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;</pre></blockquot
<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="mxStylesheet.getDefaultEdgeStyle"></a>getDefaultEdgeStyle</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class="Prototype"><tr><td class="prettyprint">mxStylesheet.prototype.getDefaultEdgeStyle = function()</td></tr></table></blockquote><p>Sets the default style for edges.</p></div></div></div>
<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="mxStylesheet.putCellStyle"></a>putCellStyle</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class="Prototype"><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class="PBeforeParameters prettyprint "nowrap>mxStylesheet.prototype.putCellStyle = function(</td><td class="PParameter prettyprint " nowrap>name,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>style</td><td class="PAfterParameters prettyprint "nowrap>)</td></tr></table></td></tr></table></blockquote><p>Stores the given map of key, value pairs under the given name in <a href="#mxStylesheet.styles" class=LFunction id=link20 onMouseOver="ShowTip(event, 'tt9', 'link20')" onMouseOut="HideTip('tt9')">styles</a>.</p><h4 class=CHeading>Example</h4><p>The following example adds a new style called &lsquo;rounded&rsquo; into an existing stylesheet:</p><blockquote><pre class="prettyprint">var style = new Object();
<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="mxStylesheet.putCellStyle"></a>putCellStyle</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class="Prototype"><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class="PBeforeParameters prettyprint "nowrap>mxStylesheet.prototype.putCellStyle = function(</td><td class="PParameter prettyprint " nowrap>name,</td></tr><tr><td></td><td class="PParameter prettyprint " nowrap>style</td><td class="PAfterParameters prettyprint "nowrap>)</td></tr></table></td></tr></table></blockquote><p>Stores the given map of key, value pairs under the given name in <a href="#mxStylesheet.styles" class=LFunction id=link20 onMouseOver="ShowTip(event, 'tt9', 'link20')" onMouseOut="HideTip('tt9')">styles</a>.</p><h4 class=CHeading>Example</h4><p>The following example adds a new style called &lsquo;rounded&rsquo; into an existing stylesheet:</p><blockquote><pre class="prettyprint">var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_ROUNDED] = true;

View File

@ -1141,7 +1141,7 @@ follow this template to create a style and register it with
mxStyleSheet:</p>
<pre>
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
style[mxConstants.STYLE_OPACITY] = 50;
style[mxConstants.STYLE_FONTCOLOR]= '#774400';

View File

@ -424,9 +424,9 @@ var editor = new mxEditor(config);
For example, consider the following JavaScript object definition:
</p>
<pre>
var object = new Object();
var object = {};
object.myBool = true;
object.myObject = new Object();
object.myObject = {};
object.myObject.name = 'Test';
object.myArray = ['a', ['b', 'c'], 'd'];
</pre>

View File

@ -127,7 +127,7 @@
};
// Sample user objects with 2 fields
var value = new Object();
var value = {};
value.first = 'First value';
value.second = 'Second value';

View File

@ -11,7 +11,7 @@
var urlParams = (function(url)
{
var result = new Object();
var result = {};
var params = window.location.search.slice(1).split('&');
for (var i = 0; i < params.length; i++)

View File

@ -14,7 +14,7 @@
// - chrome=0: Chromeless mode.
var urlParams = (function(url)
{
var result = new Object();
var result = {};
var idx = url.lastIndexOf('?');
if (idx > 0)
@ -95,7 +95,7 @@
mxResources.parse(xhr[0].getText());
// Configures the default graph theme
var themes = new Object();
var themes = {};
themes[Graph.prototype.defaultThemeName] = xhr[1].getDocumentElement();
// Main

View File

@ -7,7 +7,7 @@
function Actions(editorUi)
{
this.editorUi = editorUi;
this.actions = new Object();
this.actions = {};
this.init();
};

View File

@ -1697,7 +1697,7 @@ PageSetupDialog.addPageFormatPanel = function(div, namePostfix, pageFormat, page
formatDiv.style.display = 'none';
customDiv.style.display = 'none';
var pf = new Object();
var pf = {};
var formats = PageSetupDialog.getFormats();
for (var i = 0; i < formats.length; i++)

View File

@ -1626,7 +1626,7 @@ EditorUi.prototype.initClipboard = function()
result = result || graph.getSelectionCells();
result = graph.getExportableCells(graph.model.getTopmostCells(result));
var cloneMap = new Object();
var cloneMap = {};
var lookup = graph.createCellLookup(result);
var clones = graph.cloneCells(result, null, cloneMap);

View File

@ -6356,7 +6356,7 @@ if (typeof mxVertexHandler != 'undefined')
*/
Graph.prototype.createCellLookup = function(cells, lookup)
{
lookup = (lookup != null) ? lookup : new Object();
lookup = (lookup != null) ? lookup : {};
for (var i = 0; i < cells.length; i++)
{
@ -6380,7 +6380,7 @@ if (typeof mxVertexHandler != 'undefined')
*/
Graph.prototype.createCellMapping = function(mapping, lookup, cellMapping)
{
cellMapping = (cellMapping != null) ? cellMapping : new Object();
cellMapping = (cellMapping != null) ? cellMapping : {};
for (var objectId in mapping)
{
@ -6411,8 +6411,8 @@ if (typeof mxVertexHandler != 'undefined')
var cells = []
// Clones cells to remove invalid edges
var cloneMap = new Object();
var cellMapping = new Object();
var cloneMap = {};
var cellMapping = {};
var layers = tempModel.getChildren(this.cloneCell(tempModel.root,
this.isCloneInvalidEdges(), cloneMap));
@ -6496,7 +6496,7 @@ if (typeof mxVertexHandler != 'undefined')
*/
Graph.prototype.encodeCells = function(cells)
{
var cloneMap = new Object();
var cloneMap = {};
var clones = this.cloneCells(cells, null, cloneMap);
// Creates a dictionary for fast lookups
@ -6664,7 +6664,7 @@ if (typeof mxVertexHandler != 'undefined')
var graphMoveCells = Graph.prototype.moveCells;
Graph.prototype.moveCells = function(cells, dx, dy, clone, target, evt, mapping)
{
mapping = (mapping != null) ? mapping : new Object();
mapping = (mapping != null) ? mapping : {};
// Replaces source tables with rows
if (this.isTable(target))

View File

@ -7,7 +7,7 @@
Menus = function(editorUi)
{
this.editorUi = editorUi;
this.menus = new Object();
this.menus = {};
this.init();
// Pre-fetches checkmark image

View File

@ -8,8 +8,8 @@ function Sidebar(editorUi, container)
{
this.editorUi = editorUi;
this.container = container;
this.palettes = new Object();
this.taglist = new Object();
this.palettes = {};
this.taglist = {};
this.showTooltips = true;
this.graph = editorUi.createTemporaryGraph(this.editorUi.editor.graph.getStylesheet());
this.graph.cellRenderer.minSvgStrokeWidth = this.minThumbStrokeWidth;
@ -769,7 +769,7 @@ Sidebar.prototype.addSearchPalette = function(expand)
var active = false;
var complete = false;
var page = 0;
var hash = new Object();
var hash = {};
// Count is dynamically updated below
var count = 12;
@ -822,7 +822,7 @@ Sidebar.prototype.addSearchPalette = function(expand)
{
clearDiv();
searchTerm = input.value;
hash = new Object();
hash = {};
complete = false;
page = 0;
}
@ -836,7 +836,7 @@ Sidebar.prototype.addSearchPalette = function(expand)
active = true;
// Ignores old results
var current = new Object();
var current = {};
this.currentSearch = current;
this.searchEntries(searchTerm, count, page, mxUtils.bind(this, function(results, len, more, terms)
@ -926,7 +926,7 @@ Sidebar.prototype.addSearchPalette = function(expand)
clearDiv();
input.value = '';
searchTerm = '';
hash = new Object();
hash = {};
button.style.display = 'none';
complete = false;
input.focus();

View File

@ -12,7 +12,7 @@
var urlParams = (function(url)
{
var result = new Object();
var result = {};
var idx = url.lastIndexOf('?');
if (idx > 0)

View File

@ -71,7 +71,7 @@
function configureStylesheet(graph)
{
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_IMAGE] = 'images/icons48/keys.png';

View File

@ -104,7 +104,7 @@
graph.view.setTranslate(4, 4);
// Sets default vertex style
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;
style[mxConstants.STYLE_FILLCOLOR] = '#8CCDF5';

View File

@ -493,7 +493,7 @@
function configureStylesheet(graph)
{
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
@ -512,7 +512,7 @@
// NOTE: Alternative vertex style for non-HTML labels should be as
// follows. This repaces the above style for HTML labels.
/*var style = new Object();
/*var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
@ -533,7 +533,7 @@
style[mxConstants.STYLE_OPACITY] = '80';
graph.getStylesheet().putDefaultVertexStyle(style);*/
style = new Object();
style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
@ -549,7 +549,7 @@
style[mxConstants.STYLE_FONTSTYLE] = 1;
graph.getStylesheet().putCellStyle('group', style);
style = new Object();
style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;
style[mxConstants.STYLE_FONTCOLOR] = '#774400';
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;

View File

@ -628,7 +628,7 @@
function configureStylesheet(graph)
{
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;
@ -641,7 +641,7 @@
style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';
graph.getStylesheet().putDefaultVertexStyle(style);
style = new Object();
style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;

View File

@ -250,7 +250,7 @@ class mxEditor extends mxEventSource {
* the following code can be used. This requires an reference to the editor.
*
* (code)
* var userObject = new Object();
* var userObject = {};
* var parent = editor.graph.getDefaultParent();
* var model = editor.graph.model;
* model.beginUpdate();

File diff suppressed because it is too large Load Diff

View File

@ -2,505 +2,455 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxConstraintHandler
*
* Handles constraints on connection targets. This class is in charge of
* showing fixed points when the mouse is over a vertex and handles constraints
* to establish new connections.
*
* Constructor: mxConstraintHandler
*
* Constructs an new constraint handler.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
* factoryMethod - Optional function to create the edge. The function takes
* the source and target <mxCell> as the first and second argument and
* returns the <mxCell> that represents the new edge.
*/
function mxConstraintHandler(graph)
{
this.graph = graph;
// Adds a graph model listener to update the current focus on changes
this.resetHandler = mxUtils.bind(this, (sender, evt)=>
{
if (this.currentFocus != null && this.graph.view.getState(this.currentFocus.cell) == null)
{
this.reset();
}
else
{
this.redraw();
}
});
this.graph.model.addListener(mxEvent.CHANGE, this.resetHandler);
this.graph.view.addListener(mxEvent.SCALE_AND_TRANSLATE, this.resetHandler);
this.graph.view.addListener(mxEvent.TRANSLATE, this.resetHandler);
this.graph.view.addListener(mxEvent.SCALE, this.resetHandler);
this.graph.addListener(mxEvent.ROOT, this.resetHandler);
};
/**
* Variable: pointImage
*
* <mxImage> to be used as the image for fixed connection points.
*/
pointImage = new mxImage(mxClient.imageBasePath + '/point.gif', 5, 5);
class mxConstraintHandler {
/**
* Variable: pointImage
*
* <mxImage> to be used as the image for fixed connection points.
*/
pointImage = new mxImage(mxClient.imageBasePath + '/point.gif', 5, 5);
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: highlightColor
*
* Specifies the color for the highlight. Default is <mxConstants.DEFAULT_VALID_COLOR>.
*/
highlightColor = mxConstants.DEFAULT_VALID_COLOR;
/**
* Variable: highlightColor
*
* Specifies the color for the highlight. Default is <mxConstants.DEFAULT_VALID_COLOR>.
*/
highlightColor = mxConstants.DEFAULT_VALID_COLOR;
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
isEnabled = ()=>
{
return this.enabled;
};
/**
* Function: setEnabled
*
* Enables or disables event handling. This implementation
* updates <enabled>.
*
* Parameters:
*
* enabled - Boolean that specifies the new enabled state.
*/
setEnabled = (enabled)=>
{
this.enabled = enabled;
};
/**
* Class: mxConstraintHandler
*
* Handles constraints on connection targets. This class is in charge of
* showing fixed points when the mouse is over a vertex and handles constraints
* to establish new connections.
*
* Constructor: mxConstraintHandler
*
* Constructs an new constraint handler.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
* factoryMethod - Optional function to create the edge. The function takes
* the source and target <mxCell> as the first and second argument and
* returns the <mxCell> that represents the new edge.
*/
constructor(graph) {
this.graph = graph;
/**
* Function: reset
*
* Resets the state of this handler.
*/
reset = ()=>
{
if (this.focusIcons != null)
{
for (var i = 0; i < this.focusIcons.length; i++)
{
this.focusIcons[i].destroy();
}
this.focusIcons = null;
}
if (this.focusHighlight != null)
{
this.focusHighlight.destroy();
this.focusHighlight = null;
}
this.currentConstraint = null;
this.currentFocusArea = null;
this.currentPoint = null;
this.currentFocus = null;
this.focusPoints = null;
};
/**
* Function: getTolerance
*
* Returns the tolerance to be used for intersecting connection points. This
* implementation returns <mxGraph.tolerance>.
*
* Parameters:
*
* me - <mxMouseEvent> whose tolerance should be returned.
*/
getTolerance = (me)=>
{
return this.graph.getTolerance();
};
/**
* Function: getImageForConstraint
*
* Returns the tolerance to be used for intersecting connection points.
*/
getImageForConstraint = (state, constraint, point)=>
{
return this.pointImage;
};
/**
* Function: isEventIgnored
*
* Returns true if the given <mxMouseEvent> should be ignored in <update>. This
* implementation always returns false.
*/
isEventIgnored = (me, source)=>
{
return false;
};
/**
* Function: isStateIgnored
*
* Returns true if the given state should be ignored. This always returns false.
*/
isStateIgnored = (state, source)=>
{
return false;
};
/**
* Function: destroyIcons
*
* Destroys the <focusIcons> if they exist.
*/
destroyIcons = ()=>
{
if (this.focusIcons != null)
{
for (var i = 0; i < this.focusIcons.length; i++)
{
this.focusIcons[i].destroy();
}
this.focusIcons = null;
this.focusPoints = null;
}
};
/**
* Function: destroyFocusHighlight
*
* Destroys the <focusHighlight> if one exists.
*/
destroyFocusHighlight = ()=>
{
if (this.focusHighlight != null)
{
this.focusHighlight.destroy();
this.focusHighlight = null;
}
};
/**
* Function: isKeepFocusEvent
*
* Returns true if the current focused state should not be changed for the given event.
* This returns true if shift and alt are pressed.
*/
isKeepFocusEvent = (me)=>
{
return mxEvent.isShiftDown(me.getEvent());
};
/**
* Function: getCellForEvent
*
* Returns the cell for the given event.
*/
getCellForEvent = (me, point)=>
{
var cell = me.getCell();
// Gets cell under actual point if different from event location
if (cell == null && point != null && (me.getGraphX() != point.x || me.getGraphY() != point.y))
{
cell = this.graph.getCellAt(point.x, point.y);
}
// Uses connectable parent vertex if one exists
if (cell != null && !this.graph.isCellConnectable(cell))
{
var parent = this.graph.getModel().getParent(cell);
if (this.graph.getModel().isVertex(parent) && this.graph.isCellConnectable(parent))
{
cell = parent;
}
}
return (this.graph.isCellLocked(cell)) ? null : cell;
};
/**
* Function: update
*
* Updates the state of this handler based on the given <mxMouseEvent>.
* Source is a boolean indicating if the cell is a source or target.
*/
update = (me, source, existingEdge, point)=>
{
if (this.isEnabled() && !this.isEventIgnored(me))
{
// Lazy installation of mouseleave handler
if (this.mouseleaveHandler == null && this.graph.container != null)
{
this.mouseleaveHandler = mxUtils.bind(this, ()=>
{
// Adds a graph model listener to update the current focus on changes
this.resetHandler = mxUtils.bind(this, (sender, evt) => {
if (this.currentFocus != null && this.graph.view.getState(this.currentFocus.cell) == null) {
this.reset();
});
mxEvent.addListener(this.graph.container, 'mouseleave', this.resetHandler);
}
var tol = this.getTolerance(me);
var x = (point != null) ? point.x : me.getGraphX();
var y = (point != null) ? point.y : me.getGraphY();
var grid = new mxRectangle(x - tol, y - tol, 2 * tol, 2 * tol);
var mouse = new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol);
var state = this.graph.view.getState(this.getCellForEvent(me, point));
// Keeps focus icons visible while over vertex bounds and no other cell under mouse or shift is pressed
if (!this.isKeepFocusEvent(me) && (this.currentFocusArea == null || this.currentFocus == null ||
(state != null) || !this.graph.getModel().isVertex(this.currentFocus.cell) ||
!mxUtils.intersects(this.currentFocusArea, mouse)) && (state != this.currentFocus))
{
this.currentFocusArea = null;
this.currentFocus = null;
this.setFocus(me, state, source);
}
this.currentConstraint = null;
this.currentPoint = null;
var minDistSq = null;
if (this.focusIcons != null && this.constraints != null &&
(state == null || this.currentFocus == state))
{
var cx = mouse.getCenterX();
var cy = mouse.getCenterY();
for (var i = 0; i < this.focusIcons.length; i++)
{
var dx = cx - this.focusIcons[i].bounds.getCenterX();
var dy = cy - this.focusIcons[i].bounds.getCenterY();
var tmp = dx * dx + dy * dy;
if ((this.intersects(this.focusIcons[i], mouse, source, existingEdge) || (point != null &&
this.intersects(this.focusIcons[i], grid, source, existingEdge))) &&
(minDistSq == null || tmp < minDistSq))
{
this.currentConstraint = this.constraints[i];
this.currentPoint = this.focusPoints[i];
minDistSq = tmp;
var tmp = this.focusIcons[i].bounds.clone();
tmp.grow(mxConstants.HIGHLIGHT_SIZE + 1);
tmp.width -= 1;
tmp.height -= 1;
if (this.focusHighlight == null)
{
var hl = this.createHighlightShape();
hl.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_SVG : mxConstants.DIALECT_VML;
hl.pointerEvents = false;
hl.init(this.graph.getView().getOverlayPane());
this.focusHighlight = hl;
var getState = mxUtils.bind(this, ()=>
{
return (this.currentFocus != null) ? this.currentFocus : state;
});
mxEvent.redirectMouseEvents(hl.node, this.graph, getState);
}
this.focusHighlight.bounds = tmp;
this.focusHighlight.redraw();
}
} else {
this.redraw();
}
}
if (this.currentConstraint == null)
{
this.destroyFocusHighlight();
}
}
else
{
this.currentConstraint = null;
this.currentFocus = null;
this.currentPoint = null;
}
};
});
/**
* Function: redraw
*
* Transfers the focus to the given state as a source or target terminal. If
* the handler is not enabled then the outline is painted, but the constraints
* are ignored.
*/
redraw = ()=>
{
if (this.currentFocus != null && this.constraints != null && this.focusIcons != null)
{
var state = this.graph.view.getState(this.currentFocus.cell);
this.currentFocus = state;
this.currentFocusArea = new mxRectangle(state.x, state.y, state.width, state.height);
for (var i = 0; i < this.constraints.length; i++)
{
var cp = this.graph.getConnectionPoint(state, this.constraints[i]);
var img = this.getImageForConstraint(state, this.constraints[i], cp);
this.graph.model.addListener(mxEvent.CHANGE, this.resetHandler);
this.graph.view.addListener(mxEvent.SCALE_AND_TRANSLATE, this.resetHandler);
this.graph.view.addListener(mxEvent.TRANSLATE, this.resetHandler);
this.graph.view.addListener(mxEvent.SCALE, this.resetHandler);
this.graph.addListener(mxEvent.ROOT, this.resetHandler);
};
var bounds = new mxRectangle(Math.round(cp.x - img.width / 2),
Math.round(cp.y - img.height / 2), img.width, img.height);
this.focusIcons[i].bounds = bounds;
this.focusIcons[i].redraw();
this.currentFocusArea.add(this.focusIcons[i].bounds);
this.focusPoints[i] = cp;
}
}
};
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
isEnabled = () => {
return this.enabled;
};
/**
* Function: setFocus
*
* Transfers the focus to the given state as a source or target terminal. If
* the handler is not enabled then the outline is painted, but the constraints
* are ignored.
*/
setFocus = (me, state, source)=>
{
this.constraints = (state != null && !this.isStateIgnored(state, source) &&
this.graph.isCellConnectable(state.cell)) ? ((this.isEnabled()) ?
(this.graph.getAllConnectionConstraints(state, source) || []) : []) : null;
/**
* Function: setEnabled
*
* Enables or disables event handling. This implementation
* updates <enabled>.
*
* Parameters:
*
* enabled - Boolean that specifies the new enabled state.
*/
setEnabled = (enabled) => {
this.enabled = enabled;
};
// Only uses cells which have constraints
if (this.constraints != null)
{
this.currentFocus = state;
this.currentFocusArea = new mxRectangle(state.x, state.y, state.width, state.height);
if (this.focusIcons != null)
{
for (var i = 0; i < this.focusIcons.length; i++)
{
/**
* Function: reset
*
* Resets the state of this handler.
*/
reset = () => {
if (this.focusIcons != null) {
for (var i = 0; i < this.focusIcons.length; i++) {
this.focusIcons[i].destroy();
}
this.focusIcons = null;
}
if (this.focusHighlight != null) {
this.focusHighlight.destroy();
this.focusHighlight = null;
}
this.currentConstraint = null;
this.currentFocusArea = null;
this.currentPoint = null;
this.currentFocus = null;
this.focusPoints = null;
};
/**
* Function: getTolerance
*
* Returns the tolerance to be used for intersecting connection points. This
* implementation returns <mxGraph.tolerance>.
*
* Parameters:
*
* me - <mxMouseEvent> whose tolerance should be returned.
*/
getTolerance = (me) => {
return this.graph.getTolerance();
};
/**
* Function: getImageForConstraint
*
* Returns the tolerance to be used for intersecting connection points.
*/
getImageForConstraint = (state, constraint, point) => {
return this.pointImage;
};
/**
* Function: isEventIgnored
*
* Returns true if the given <mxMouseEvent> should be ignored in <update>. This
* implementation always returns false.
*/
isEventIgnored = (me, source) => {
return false;
};
/**
* Function: isStateIgnored
*
* Returns true if the given state should be ignored. This always returns false.
*/
isStateIgnored = (state, source) => {
return false;
};
/**
* Function: destroyIcons
*
* Destroys the <focusIcons> if they exist.
*/
destroyIcons = () => {
if (this.focusIcons != null) {
for (var i = 0; i < this.focusIcons.length; i++) {
this.focusIcons[i].destroy();
}
this.focusIcons = null;
this.focusPoints = null;
}
this.focusPoints = [];
this.focusIcons = [];
for (var i = 0; i < this.constraints.length; i++)
{
var cp = this.graph.getConnectionPoint(state, this.constraints[i]);
var img = this.getImageForConstraint(state, this.constraints[i], cp);
};
var src = img.src;
var bounds = new mxRectangle(Math.round(cp.x - img.width / 2),
Math.round(cp.y - img.height / 2), img.width, img.height);
var icon = new mxImageShape(bounds, src);
icon.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_MIXEDHTML : mxConstants.DIALECT_SVG;
icon.preserveImageAspect = false;
icon.init(this.graph.getView().getDecoratorPane());
// Move the icon behind all other overlays
if (icon.node.previousSibling != null)
{
icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
/**
* Function: destroyFocusHighlight
*
* Destroys the <focusHighlight> if one exists.
*/
destroyFocusHighlight = () => {
if (this.focusHighlight != null) {
this.focusHighlight.destroy();
this.focusHighlight = null;
}
};
/**
* Function: isKeepFocusEvent
*
* Returns true if the current focused state should not be changed for the given event.
* This returns true if shift and alt are pressed.
*/
isKeepFocusEvent = (me) => {
return mxEvent.isShiftDown(me.getEvent());
};
/**
* Function: getCellForEvent
*
* Returns the cell for the given event.
*/
getCellForEvent = (me, point) => {
var cell = me.getCell();
// Gets cell under actual point if different from event location
if (cell == null && point != null && (me.getGraphX() != point.x || me.getGraphY() != point.y)) {
cell = this.graph.getCellAt(point.x, point.y);
}
// Uses connectable parent vertex if one exists
if (cell != null && !this.graph.isCellConnectable(cell)) {
var parent = this.graph.getModel().getParent(cell);
if (this.graph.getModel().isVertex(parent) && this.graph.isCellConnectable(parent)) {
cell = parent;
}
}
return (this.graph.isCellLocked(cell)) ? null : cell;
};
/**
* Function: update
*
* Updates the state of this handler based on the given <mxMouseEvent>.
* Source is a boolean indicating if the cell is a source or target.
*/
update = (me, source, existingEdge, point) => {
if (this.isEnabled() && !this.isEventIgnored(me)) {
// Lazy installation of mouseleave handler
if (this.mouseleaveHandler == null && this.graph.container != null) {
this.mouseleaveHandler = mxUtils.bind(this, () => {
this.reset();
});
mxEvent.addListener(this.graph.container, 'mouseleave', this.resetHandler);
}
var getState = mxUtils.bind(this, ()=>
{
return (this.currentFocus != null) ? this.currentFocus : state;
});
icon.redraw();
var tol = this.getTolerance(me);
var x = (point != null) ? point.x : me.getGraphX();
var y = (point != null) ? point.y : me.getGraphY();
var grid = new mxRectangle(x - tol, y - tol, 2 * tol, 2 * tol);
var mouse = new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol);
var state = this.graph.view.getState(this.getCellForEvent(me, point));
mxEvent.redirectMouseEvents(icon.node, this.graph, getState);
this.currentFocusArea.add(icon.bounds);
this.focusIcons.push(icon);
this.focusPoints.push(cp);
// Keeps focus icons visible while over vertex bounds and no other cell under mouse or shift is pressed
if (!this.isKeepFocusEvent(me) && (this.currentFocusArea == null || this.currentFocus == null ||
(state != null) || !this.graph.getModel().isVertex(this.currentFocus.cell) ||
!mxUtils.intersects(this.currentFocusArea, mouse)) && (state != this.currentFocus)) {
this.currentFocusArea = null;
this.currentFocus = null;
this.setFocus(me, state, source);
}
this.currentConstraint = null;
this.currentPoint = null;
var minDistSq = null;
if (this.focusIcons != null && this.constraints != null &&
(state == null || this.currentFocus == state)) {
var cx = mouse.getCenterX();
var cy = mouse.getCenterY();
for (var i = 0; i < this.focusIcons.length; i++) {
var dx = cx - this.focusIcons[i].bounds.getCenterX();
var dy = cy - this.focusIcons[i].bounds.getCenterY();
var tmp = dx * dx + dy * dy;
if ((this.intersects(this.focusIcons[i], mouse, source, existingEdge) || (point != null &&
this.intersects(this.focusIcons[i], grid, source, existingEdge))) &&
(minDistSq == null || tmp < minDistSq)) {
this.currentConstraint = this.constraints[i];
this.currentPoint = this.focusPoints[i];
minDistSq = tmp;
var tmp = this.focusIcons[i].bounds.clone();
tmp.grow(mxConstants.HIGHLIGHT_SIZE + 1);
tmp.width -= 1;
tmp.height -= 1;
if (this.focusHighlight == null) {
var hl = this.createHighlightShape();
hl.dialect = (this.graph.dialect == mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_SVG : mxConstants.DIALECT_VML;
hl.pointerEvents = false;
hl.init(this.graph.getView().getOverlayPane());
this.focusHighlight = hl;
var getState = mxUtils.bind(this, () => {
return (this.currentFocus != null) ? this.currentFocus : state;
});
mxEvent.redirectMouseEvents(hl.node, this.graph, getState);
}
this.focusHighlight.bounds = tmp;
this.focusHighlight.redraw();
}
}
}
if (this.currentConstraint == null) {
this.destroyFocusHighlight();
}
} else {
this.currentConstraint = null;
this.currentFocus = null;
this.currentPoint = null;
}
this.currentFocusArea.grow(this.getTolerance(me));
}
else
{
this.destroyIcons();
this.destroyFocusHighlight();
}
};
};
/**
* Function: createHighlightShape
*
* Create the shape used to paint the highlight.
*
* Returns true if the given icon intersects the given point.
*/
createHighlightShape = ()=>
{
var hl = new mxRectangleShape(null, this.highlightColor, this.highlightColor, mxConstants.HIGHLIGHT_STROKEWIDTH);
hl.opacity = mxConstants.HIGHLIGHT_OPACITY;
return hl;
};
/**
* Function: redraw
*
* Transfers the focus to the given state as a source or target terminal. If
* the handler is not enabled then the outline is painted, but the constraints
* are ignored.
*/
redraw = () => {
if (this.currentFocus != null && this.constraints != null && this.focusIcons != null) {
var state = this.graph.view.getState(this.currentFocus.cell);
this.currentFocus = state;
this.currentFocusArea = new mxRectangle(state.x, state.y, state.width, state.height);
/**
* Function: intersects
*
* Returns true if the given icon intersects the given rectangle.
*/
intersects = (icon, mouse, source, existingEdge)=>
{
return mxUtils.intersects(icon.bounds, mouse);
};
for (var i = 0; i < this.constraints.length; i++) {
var cp = this.graph.getConnectionPoint(state, this.constraints[i]);
var img = this.getImageForConstraint(state, this.constraints[i], cp);
/**
* Function: destroy
*
* Destroy this handler.
*/
destroy = ()=>
{
this.reset();
if (this.resetHandler != null)
{
this.graph.model.removeListener(this.resetHandler);
this.graph.view.removeListener(this.resetHandler);
this.graph.removeListener(this.resetHandler);
this.resetHandler = null;
}
if (this.mouseleaveHandler != null && this.graph.container != null)
{
mxEvent.removeListener(this.graph.container, 'mouseleave', this.mouseleaveHandler);
this.mouseleaveHandler = null;
}
};
var bounds = new mxRectangle(Math.round(cp.x - img.width / 2),
Math.round(cp.y - img.height / 2), img.width, img.height);
this.focusIcons[i].bounds = bounds;
this.focusIcons[i].redraw();
this.currentFocusArea.add(this.focusIcons[i].bounds);
this.focusPoints[i] = cp;
}
}
};
/**
* Function: setFocus
*
* Transfers the focus to the given state as a source or target terminal. If
* the handler is not enabled then the outline is painted, but the constraints
* are ignored.
*/
setFocus = (me, state, source) => {
this.constraints = (state != null && !this.isStateIgnored(state, source) &&
this.graph.isCellConnectable(state.cell)) ? ((this.isEnabled()) ?
(this.graph.getAllConnectionConstraints(state, source) || []) : []) : null;
// Only uses cells which have constraints
if (this.constraints != null) {
this.currentFocus = state;
this.currentFocusArea = new mxRectangle(state.x, state.y, state.width, state.height);
if (this.focusIcons != null) {
for (var i = 0; i < this.focusIcons.length; i++) {
this.focusIcons[i].destroy();
}
this.focusIcons = null;
this.focusPoints = null;
}
this.focusPoints = [];
this.focusIcons = [];
for (var i = 0; i < this.constraints.length; i++) {
var cp = this.graph.getConnectionPoint(state, this.constraints[i]);
var img = this.getImageForConstraint(state, this.constraints[i], cp);
var src = img.src;
var bounds = new mxRectangle(Math.round(cp.x - img.width / 2),
Math.round(cp.y - img.height / 2), img.width, img.height);
var icon = new mxImageShape(bounds, src);
icon.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_MIXEDHTML : mxConstants.DIALECT_SVG;
icon.preserveImageAspect = false;
icon.init(this.graph.getView().getDecoratorPane());
// Move the icon behind all other overlays
if (icon.node.previousSibling != null) {
icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
}
var getState = mxUtils.bind(this, () => {
return (this.currentFocus != null) ? this.currentFocus : state;
});
icon.redraw();
mxEvent.redirectMouseEvents(icon.node, this.graph, getState);
this.currentFocusArea.add(icon.bounds);
this.focusIcons.push(icon);
this.focusPoints.push(cp);
}
this.currentFocusArea.grow(this.getTolerance(me));
} else {
this.destroyIcons();
this.destroyFocusHighlight();
}
};
/**
* Function: createHighlightShape
*
* Create the shape used to paint the highlight.
*
* Returns true if the given icon intersects the given point.
*/
createHighlightShape = () => {
var hl = new mxRectangleShape(null, this.highlightColor, this.highlightColor, mxConstants.HIGHLIGHT_STROKEWIDTH);
hl.opacity = mxConstants.HIGHLIGHT_OPACITY;
return hl;
};
/**
* Function: intersects
*
* Returns true if the given icon intersects the given rectangle.
*/
intersects = (icon, mouse, source, existingEdge) => {
return mxUtils.intersects(icon.bounds, mouse);
};
/**
* Function: destroy
*
* Destroy this handler.
*/
destroy = () => {
this.reset();
if (this.resetHandler != null) {
this.graph.model.removeListener(this.resetHandler);
this.graph.view.removeListener(this.resetHandler);
this.graph.removeListener(this.resetHandler);
this.resetHandler = null;
}
if (this.mouseleaveHandler != null && this.graph.container != null) {
mxEvent.removeListener(this.graph.container, 'mouseleave', this.mouseleaveHandler);
this.mouseleaveHandler = null;
}
};
}
export default mxConstraintHandler;

File diff suppressed because it is too large Load Diff

View File

@ -2,412 +2,359 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
function mxEdgeSegmentHandler(state)
{
mxEdgeHandler.call(this, state);
};
/**
* Extends mxEdgeHandler.
*/
mxUtils.extend(mxEdgeSegmentHandler, mxElbowEdgeHandler);
class mxEdgeSegmentHandler extends mxElbowEdgeHandler {
constructor(state) {
// WARNING: should be super of mxEdgeHandler!
super(state);
};
/**
* Function: getCurrentPoints
*
* Returns the current absolute points.
*/
getCurrentPoints = ()=>
{
var pts = this.state.absolutePoints;
if (pts != null)
{
// Special case for straight edges where we add a virtual middle handle for moving the edge
var tol = Math.max(1, this.graph.view.scale);
if (pts.length == 2 || (pts.length == 3 &&
(Math.abs(pts[0].x - pts[1].x) < tol && Math.abs(pts[1].x - pts[2].x) < tol ||
Math.abs(pts[0].y - pts[1].y) < tol && Math.abs(pts[1].y - pts[2].y) < tol)))
{
var cx = pts[0].x + (pts[pts.length - 1].x - pts[0].x) / 2;
var cy = pts[0].y + (pts[pts.length - 1].y - pts[0].y) / 2;
pts = [pts[0], new mxPoint(cx, cy), new mxPoint(cx, cy), pts[pts.length - 1]];
}
}
/**
* Function: getCurrentPoints
*
* Returns the current absolute points.
*/
getCurrentPoints = () => {
var pts = this.state.absolutePoints;
return pts;
};
if (pts != null) {
// Special case for straight edges where we add a virtual middle handle for moving the edge
var tol = Math.max(1, this.graph.view.scale);
/**
* Function: getPreviewPoints
*
* Updates the given preview state taking into account the state of the constraint handler.
*/
getPreviewPoints = (point)=>
{
if (this.isSource || this.isTarget)
{
return getPreviewPoints.apply(this, arguments);
}
else
{
var pts = this.getCurrentPoints();
var last = this.convertPoint(pts[0].clone(), false);
point = this.convertPoint(point.clone(), false);
var result = [];
if (pts.length == 2 || (pts.length == 3 &&
(Math.abs(pts[0].x - pts[1].x) < tol && Math.abs(pts[1].x - pts[2].x) < tol ||
Math.abs(pts[0].y - pts[1].y) < tol && Math.abs(pts[1].y - pts[2].y) < tol))) {
var cx = pts[0].x + (pts[pts.length - 1].x - pts[0].x) / 2;
var cy = pts[0].y + (pts[pts.length - 1].y - pts[0].y) / 2;
for (var i = 1; i < pts.length; i++)
{
var pt = this.convertPoint(pts[i].clone(), false);
if (i == this.index)
{
if (Math.round(last.x - pt.x) == 0)
{
last.x = point.x;
pt.x = point.x;
}
if (Math.round(last.y - pt.y) == 0)
{
last.y = point.y;
pt.y = point.y;
}
}
if (i < pts.length - 1)
{
result.push(pt);
}
last = pt;
}
// Replaces single point that intersects with source or target
if (result.length == 1)
{
var source = this.state.getVisibleTerminalState(true);
var target = this.state.getVisibleTerminalState(false);
var scale = this.state.view.getScale();
var tr = this.state.view.getTranslate();
var x = result[0].x * scale + tr.x;
var y = result[0].y * scale + tr.y;
if ((source != null && mxUtils.contains(source, x, y)) ||
(target != null && mxUtils.contains(target, x, y)))
{
result = [point, point];
pts = [pts[0], new mxPoint(cx, cy), new mxPoint(cx, cy), pts[pts.length - 1]];
}
}
return result;
}
};
return pts;
};
/**
* Function: updatePreviewState
*
* Overridden to perform optimization of the edge style result.
*/
updatePreviewState = (edge, point, terminalState, me)=>
{
updatePreviewState.apply(this, arguments);
/**
* Function: getPreviewPoints
*
* Updates the given preview state taking into account the state of the constraint handler.
*/
getPreviewPoints = (point) => {
if (this.isSource || this.isTarget) {
return getPreviewPoints.apply(this, arguments);
} else {
var pts = this.getCurrentPoints();
var last = this.convertPoint(pts[0].clone(), false);
point = this.convertPoint(point.clone(), false);
var result = [];
// Checks and corrects preview by running edge style again
if (!this.isSource && !this.isTarget)
{
point = this.convertPoint(point.clone(), false);
var pts = edge.absolutePoints;
var pt0 = pts[0];
var pt1 = pts[1];
for (var i = 1; i < pts.length; i++) {
var pt = this.convertPoint(pts[i].clone(), false);
var result = [];
for (var i = 2; i < pts.length; i++)
{
var pt2 = pts[i];
// Merges adjacent segments only if more than 2 to allow for straight edges
if ((Math.round(pt0.x - pt1.x) != 0 || Math.round(pt1.x - pt2.x) != 0) &&
(Math.round(pt0.y - pt1.y) != 0 || Math.round(pt1.y - pt2.y) != 0))
{
result.push(this.convertPoint(pt1.clone(), false));
}
if (i == this.index) {
if (Math.round(last.x - pt.x) == 0) {
last.x = point.x;
pt.x = point.x;
}
pt0 = pt1;
pt1 = pt2;
}
var source = this.state.getVisibleTerminalState(true);
var target = this.state.getVisibleTerminalState(false);
var rpts = this.state.absolutePoints;
// A straight line is represented by 3 handles
if (result.length == 0 && (Math.round(pts[0].x - pts[pts.length - 1].x) == 0 ||
Math.round(pts[0].y - pts[pts.length - 1].y) == 0))
{
result = [point, point];
}
// Handles special case of transitions from straight vertical to routed
else if (pts.length == 5 && result.length == 2 && source != null && target != null &&
rpts != null && Math.round(rpts[0].x - rpts[rpts.length - 1].x) == 0)
{
var view = this.graph.getView();
var scale = view.getScale();
var tr = view.getTranslate();
var y0 = view.getRoutingCenterY(source) / scale - tr.y;
// Use fixed connection point y-coordinate if one exists
var sc = this.graph.getConnectionConstraint(edge, source, true);
if (sc != null)
{
var pt = this.graph.getConnectionPoint(source, sc);
if (pt != null)
{
this.convertPoint(pt, false);
y0 = pt.y;
}
}
var ye = view.getRoutingCenterY(target) / scale - tr.y;
// Use fixed connection point y-coordinate if one exists
var tc = this.graph.getConnectionConstraint(edge, target, false);
if (tc)
{
var pt = this.graph.getConnectionPoint(target, tc);
if (pt != null)
{
this.convertPoint(pt, false);
ye = pt.y;
}
}
result = [new mxPoint(point.x, y0), new mxPoint(point.x, ye)];
}
this.points = result;
// LATER: Check if points and result are different
edge.view.updateFixedTerminalPoints(edge, source, target);
edge.view.updatePoints(edge, this.points, source, target);
edge.view.updateFloatingTerminalPoints(edge, source, target);
}
};
/**
* Overriden to merge edge segments.
*/
connect = (edge, terminal, isSource, isClone, me)=>
{
var model = this.graph.getModel();
var geo = model.getGeometry(edge);
var result = null;
// Merges adjacent edge segments
if (geo != null && geo.points != null && geo.points.length > 0)
{
var pts = this.abspoints;
var pt0 = pts[0];
var pt1 = pts[1];
result = [];
for (var i = 2; i < pts.length; i++)
{
var pt2 = pts[i];
// Merges adjacent segments only if more than 2 to allow for straight edges
if ((Math.round(pt0.x - pt1.x) != 0 || Math.round(pt1.x - pt2.x) != 0) &&
(Math.round(pt0.y - pt1.y) != 0 || Math.round(pt1.y - pt2.y) != 0))
{
result.push(this.convertPoint(pt1.clone(), false));
}
pt0 = pt1;
pt1 = pt2;
}
}
model.beginUpdate();
try
{
if (result != null)
{
var geo = model.getGeometry(edge);
if (geo != null)
{
geo = geo.clone();
geo.points = result;
model.setGeometry(edge, geo);
}
}
edge = connect.apply(this, arguments);
}
finally
{
model.endUpdate();
}
return edge;
};
/**
* Function: getTooltipForNode
*
* Returns no tooltips.
*/
getTooltipForNode = (node)=>
{
return null;
};
/**
* Function: start
*
* Starts the handling of the mouse gesture.
*/
start = (x, y, index)=>
{
start.apply(this, arguments);
if (this.bends != null && this.bends[index] != null &&
!this.isSource && !this.isTarget)
{
mxUtils.setOpacity(this.bends[index].node, 100);
}
};
/**
* Function: createBends
*
* Adds custom bends for the center of each segment.
*/
createBends = ()=>
{
var bends = [];
// Source
var bend = this.createHandleShape(0);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
var pts = this.getCurrentPoints();
// Waypoints (segment handles)
if (this.graph.isCellBendable(this.state.cell))
{
if (this.points == null)
{
this.points = [];
}
for (var i = 0; i < pts.length - 1; i++)
{
bend = this.createVirtualBend();
bends.push(bend);
var horizontal = Math.round(pts[i].x - pts[i + 1].x) == 0;
// Special case where dy is 0 as well
if (Math.round(pts[i].y - pts[i + 1].y) == 0 && i < pts.length - 2)
{
horizontal = Math.round(pts[i].x - pts[i + 2].x) == 0;
}
bend.setCursor((horizontal) ? 'col-resize' : 'row-resize');
this.points.push(new mxPoint(0,0));
}
}
// Target
var bend = this.createHandleShape(pts.length);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
return bends;
};
/**
* Function: redraw
*
* Overridden to invoke <refresh> before the redraw.
*/
redraw = ()=>
{
this.refresh();
redraw.apply(this, arguments);
};
/**
* Function: redrawInnerBends
*
* Updates the position of the custom bends.
*/
redrawInnerBends = (p0, pe)=>
{
if (this.graph.isCellBendable(this.state.cell))
{
var pts = this.getCurrentPoints();
if (pts != null && pts.length > 1)
{
var straight = false;
// Puts handle in the center of straight edges
if (pts.length == 4 && Math.round(pts[1].x - pts[2].x) == 0 && Math.round(pts[1].y - pts[2].y) == 0)
{
straight = true;
if (Math.round(pts[0].y - pts[pts.length - 1].y) == 0)
{
var cx = pts[0].x + (pts[pts.length - 1].x - pts[0].x) / 2;
pts[1] = new mxPoint(cx, pts[1].y);
pts[2] = new mxPoint(cx, pts[2].y);
}
else
{
var cy = pts[0].y + (pts[pts.length - 1].y - pts[0].y) / 2;
pts[1] = new mxPoint(pts[1].x, cy);
pts[2] = new mxPoint(pts[2].x, cy);
}
}
for (var i = 0; i < pts.length - 1; i++)
{
if (this.bends[i + 1] != null)
{
var p0 = pts[i];
var pe = pts[i + 1];
var pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
var b = this.bends[i + 1].bounds;
this.bends[i + 1].bounds = new mxRectangle(Math.floor(pt.x - b.width / 2),
Math.floor(pt.y - b.height / 2), b.width, b.height);
this.bends[i + 1].redraw();
if (this.manageLabelHandle)
{
this.checkLabelHandle(this.bends[i + 1].bounds);
if (Math.round(last.y - pt.y) == 0) {
last.y = point.y;
pt.y = point.y;
}
}
if (i < pts.length - 1) {
result.push(pt);
}
last = pt;
}
if (straight)
{
mxUtils.setOpacity(this.bends[1].node, this.virtualBendOpacity);
mxUtils.setOpacity(this.bends[3].node, this.virtualBendOpacity);
// Replaces single point that intersects with source or target
if (result.length == 1) {
var source = this.state.getVisibleTerminalState(true);
var target = this.state.getVisibleTerminalState(false);
var scale = this.state.view.getScale();
var tr = this.state.view.getTranslate();
var x = result[0].x * scale + tr.x;
var y = result[0].y * scale + tr.y;
if ((source != null && mxUtils.contains(source, x, y)) ||
(target != null && mxUtils.contains(target, x, y))) {
result = [point, point];
}
}
return result;
}
};
/**
* Function: updatePreviewState
*
* Overridden to perform optimization of the edge style result.
*/
updatePreviewState = (edge, point, terminalState, me) => {
updatePreviewState.apply(this, arguments);
// Checks and corrects preview by running edge style again
if (!this.isSource && !this.isTarget) {
point = this.convertPoint(point.clone(), false);
var pts = edge.absolutePoints;
var pt0 = pts[0];
var pt1 = pts[1];
var result = [];
for (var i = 2; i < pts.length; i++) {
var pt2 = pts[i];
// Merges adjacent segments only if more than 2 to allow for straight edges
if ((Math.round(pt0.x - pt1.x) != 0 || Math.round(pt1.x - pt2.x) != 0) &&
(Math.round(pt0.y - pt1.y) != 0 || Math.round(pt1.y - pt2.y) != 0)) {
result.push(this.convertPoint(pt1.clone(), false));
}
pt0 = pt1;
pt1 = pt2;
}
var source = this.state.getVisibleTerminalState(true);
var target = this.state.getVisibleTerminalState(false);
var rpts = this.state.absolutePoints;
// A straight line is represented by 3 handles
if (result.length == 0 && (Math.round(pts[0].x - pts[pts.length - 1].x) == 0 ||
Math.round(pts[0].y - pts[pts.length - 1].y) == 0)) {
result = [point, point];
}
// Handles special case of transitions from straight vertical to routed
else if (pts.length == 5 && result.length == 2 && source != null && target != null &&
rpts != null && Math.round(rpts[0].x - rpts[rpts.length - 1].x) == 0) {
var view = this.graph.getView();
var scale = view.getScale();
var tr = view.getTranslate();
var y0 = view.getRoutingCenterY(source) / scale - tr.y;
// Use fixed connection point y-coordinate if one exists
var sc = this.graph.getConnectionConstraint(edge, source, true);
if (sc != null) {
var pt = this.graph.getConnectionPoint(source, sc);
if (pt != null) {
this.convertPoint(pt, false);
y0 = pt.y;
}
}
var ye = view.getRoutingCenterY(target) / scale - tr.y;
// Use fixed connection point y-coordinate if one exists
var tc = this.graph.getConnectionConstraint(edge, target, false);
if (tc) {
var pt = this.graph.getConnectionPoint(target, tc);
if (pt != null) {
this.convertPoint(pt, false);
ye = pt.y;
}
}
result = [new mxPoint(point.x, y0), new mxPoint(point.x, ye)];
}
this.points = result;
// LATER: Check if points and result are different
edge.view.updateFixedTerminalPoints(edge, source, target);
edge.view.updatePoints(edge, this.points, source, target);
edge.view.updateFloatingTerminalPoints(edge, source, target);
}
};
/**
* Overriden to merge edge segments.
*/
connect = (edge, terminal, isSource, isClone, me) => {
var model = this.graph.getModel();
var geo = model.getGeometry(edge);
var result = null;
// Merges adjacent edge segments
if (geo != null && geo.points != null && geo.points.length > 0) {
var pts = this.abspoints;
var pt0 = pts[0];
var pt1 = pts[1];
result = [];
for (var i = 2; i < pts.length; i++) {
var pt2 = pts[i];
// Merges adjacent segments only if more than 2 to allow for straight edges
if ((Math.round(pt0.x - pt1.x) != 0 || Math.round(pt1.x - pt2.x) != 0) &&
(Math.round(pt0.y - pt1.y) != 0 || Math.round(pt1.y - pt2.y) != 0)) {
result.push(this.convertPoint(pt1.clone(), false));
}
pt0 = pt1;
pt1 = pt2;
}
}
}
};
model.beginUpdate();
try {
if (result != null) {
var geo = model.getGeometry(edge);
if (geo != null) {
geo = geo.clone();
geo.points = result;
model.setGeometry(edge, geo);
}
}
edge = connect.apply(this, arguments);
} finally {
model.endUpdate();
}
return edge;
};
/**
* Function: getTooltipForNode
*
* Returns no tooltips.
*/
getTooltipForNode = (node) => {
return null;
};
/**
* Function: start
*
* Starts the handling of the mouse gesture.
*/
start = (x, y, index) => {
start.apply(this, arguments);
if (this.bends != null && this.bends[index] != null &&
!this.isSource && !this.isTarget) {
mxUtils.setOpacity(this.bends[index].node, 100);
}
};
/**
* Function: createBends
*
* Adds custom bends for the center of each segment.
*/
createBends = () => {
var bends = [];
// Source
var bend = this.createHandleShape(0);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
var pts = this.getCurrentPoints();
// Waypoints (segment handles)
if (this.graph.isCellBendable(this.state.cell)) {
if (this.points == null) {
this.points = [];
}
for (var i = 0; i < pts.length - 1; i++) {
bend = this.createVirtualBend();
bends.push(bend);
var horizontal = Math.round(pts[i].x - pts[i + 1].x) == 0;
// Special case where dy is 0 as well
if (Math.round(pts[i].y - pts[i + 1].y) == 0 && i < pts.length - 2) {
horizontal = Math.round(pts[i].x - pts[i + 2].x) == 0;
}
bend.setCursor((horizontal) ? 'col-resize' : 'row-resize');
this.points.push(new mxPoint(0, 0));
}
}
// Target
var bend = this.createHandleShape(pts.length);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
return bends;
};
/**
* Function: redraw
*
* Overridden to invoke <refresh> before the redraw.
*/
redraw = () => {
this.refresh();
redraw.apply(this, arguments);
};
/**
* Function: redrawInnerBends
*
* Updates the position of the custom bends.
*/
redrawInnerBends = (p0, pe) => {
if (this.graph.isCellBendable(this.state.cell)) {
var pts = this.getCurrentPoints();
if (pts != null && pts.length > 1) {
var straight = false;
// Puts handle in the center of straight edges
if (pts.length == 4 && Math.round(pts[1].x - pts[2].x) == 0 && Math.round(pts[1].y - pts[2].y) == 0) {
straight = true;
if (Math.round(pts[0].y - pts[pts.length - 1].y) == 0) {
var cx = pts[0].x + (pts[pts.length - 1].x - pts[0].x) / 2;
pts[1] = new mxPoint(cx, pts[1].y);
pts[2] = new mxPoint(cx, pts[2].y);
} else {
var cy = pts[0].y + (pts[pts.length - 1].y - pts[0].y) / 2;
pts[1] = new mxPoint(pts[1].x, cy);
pts[2] = new mxPoint(pts[2].x, cy);
}
}
for (var i = 0; i < pts.length - 1; i++) {
if (this.bends[i + 1] != null) {
var p0 = pts[i];
var pe = pts[i + 1];
var pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
var b = this.bends[i + 1].bounds;
this.bends[i + 1].bounds = new mxRectangle(Math.floor(pt.x - b.width / 2),
Math.floor(pt.y - b.height / 2), b.width, b.height);
this.bends[i + 1].redraw();
if (this.manageLabelHandle) {
this.checkLabelHandle(this.bends[i + 1].bounds);
}
}
}
if (straight) {
mxUtils.setOpacity(this.bends[1].node, this.virtualBendOpacity);
mxUtils.setOpacity(this.bends[3].node, this.virtualBendOpacity);
}
}
}
};
}
export default mxEdgeSegmentHandler;

View File

@ -2,229 +2,206 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxElbowEdgeHandler
*
* Graph event handler that reconnects edges and modifies control points and
* the edge label location. Uses <mxTerminalMarker> for finding and
* highlighting new source and target vertices. This handler is automatically
* created in <mxGraph.createHandler>. It extends <mxEdgeHandler>.
*
* Constructor: mxEdgeHandler
*
* Constructs an edge handler for the specified <mxCellState>.
*
* Parameters:
*
* state - <mxCellState> of the cell to be modified.
*/
function mxElbowEdgeHandler(state)
{
mxEdgeHandler.call(this, state);
};
/**
* Extends mxEdgeHandler.
*/
mxUtils.extend(mxElbowEdgeHandler, mxEdgeHandler);
class mxElbowEdgeHandler extends mxEdgeHandler {
/**
* Specifies if a double click on the middle handle should call
* <mxGraph.flipEdge>. Default is true.
*/
flipEnabled = true;
/**
* Specifies if a double click on the middle handle should call
* <mxGraph.flipEdge>. Default is true.
*/
flipEnabled = true;
/**
* Variable: doubleClickOrientationResource
*
* Specifies the resource key for the tooltip to be displayed on the single
* control point for routed edges. If the resource for this key does not
* exist then the value is used as the error message. Default is
* 'doubleClickOrientation'.
*/
doubleClickOrientationResource = (mxClient.language !== 'none') ? 'doubleClickOrientation' : '';
/**
* Variable: doubleClickOrientationResource
*
* Specifies the resource key for the tooltip to be displayed on the single
* control point for routed edges. If the resource for this key does not
* exist then the value is used as the error message. Default is
* 'doubleClickOrientation'.
*/
doubleClickOrientationResource =
(mxClient.language != 'none') ? 'doubleClickOrientation' : '';
/**
* Class: mxElbowEdgeHandler
*
* Graph event handler that reconnects edges and modifies control points and
* the edge label location. Uses <mxTerminalMarker> for finding and
* highlighting new source and target vertices. This handler is automatically
* created in <mxGraph.createHandler>. It extends <mxEdgeHandler>.
*
* Constructor: mxEdgeHandler
*
* Constructs an edge handler for the specified <mxCellState>.
*
* Parameters:
*
* state - <mxCellState> of the cell to be modified.
*/
constructor(state) {
super(state);
};
/**
* Function: createBends
*
* Overrides <mxEdgeHandler.createBends> to create custom bends.
*/
createBends = ()=>
{
var bends = [];
// Source
var bend = this.createHandleShape(0);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
/**
* Function: createBends
*
* Overrides <mxEdgeHandler.createBends> to create custom bends.
*/
createBends = () => {
var bends = [];
// Virtual
bends.push(this.createVirtualBend(mxUtils.bind(this, (evt)=>
{
if (!mxEvent.isConsumed(evt) && this.flipEnabled)
{
this.graph.flipEdge(this.state.cell, evt);
mxEvent.consume(evt);
// Source
var bend = this.createHandleShape(0);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
// Virtual
bends.push(this.createVirtualBend(mxUtils.bind(this, (evt) => {
if (!mxEvent.isConsumed(evt) && this.flipEnabled) {
this.graph.flipEdge(this.state.cell, evt);
mxEvent.consume(evt);
}
})));
this.points.push(new mxPoint(0, 0));
// Target
bend = this.createHandleShape(2);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
return bends;
};
/**
* Function: createVirtualBend
*
* Creates a virtual bend that supports double clicking and calls
* <mxGraph.flipEdge>.
*/
createVirtualBend = (dblClickHandler) => {
var bend = this.createHandleShape();
this.initBend(bend, dblClickHandler);
bend.setCursor(this.getCursorForBend());
if (!this.graph.isCellBendable(this.state.cell)) {
bend.node.style.display = 'none';
}
})));
this.points.push(new mxPoint(0,0));
// Target
bend = this.createHandleShape(2);
this.initBend(bend);
bend.setCursor(mxConstants.CURSOR_TERMINAL_HANDLE);
bends.push(bend);
return bends;
};
return bend;
};
/**
* Function: createVirtualBend
*
* Creates a virtual bend that supports double clicking and calls
* <mxGraph.flipEdge>.
*/
createVirtualBend = (dblClickHandler)=>
{
var bend = this.createHandleShape();
this.initBend(bend, dblClickHandler);
/**
* Function: getCursorForBend
*
* Returns the cursor to be used for the bend.
*/
getCursorForBend = () => {
return (this.state.style[mxConstants.STYLE_EDGE] === mxEdgeStyle.TopToBottom ||
this.state.style[mxConstants.STYLE_EDGE] === mxConstants.EDGESTYLE_TOPTOBOTTOM ||
((this.state.style[mxConstants.STYLE_EDGE] === mxEdgeStyle.ElbowConnector ||
this.state.style[mxConstants.STYLE_EDGE] === mxConstants.EDGESTYLE_ELBOW) &&
this.state.style[mxConstants.STYLE_ELBOW] === mxConstants.ELBOW_VERTICAL)) ?
'row-resize' : 'col-resize';
};
bend.setCursor(this.getCursorForBend());
/**
* Function: getTooltipForNode
*
* Returns the tooltip for the given node.
*/
getTooltipForNode = (node) => {
var tip = null;
if (!this.graph.isCellBendable(this.state.cell))
{
bend.node.style.display = 'none';
}
if (this.bends != null && this.bends[1] != null && (node === this.bends[1].node ||
node.parentNode === this.bends[1].node)) {
tip = this.doubleClickOrientationResource;
tip = mxResources.get(tip) || tip; // translate
}
return bend;
};
return tip;
};
/**
* Function: getCursorForBend
*
* Returns the cursor to be used for the bend.
*/
getCursorForBend = ()=>
{
return (this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.TopToBottom ||
this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_TOPTOBOTTOM ||
((this.state.style[mxConstants.STYLE_EDGE] == mxEdgeStyle.ElbowConnector ||
this.state.style[mxConstants.STYLE_EDGE] == mxConstants.EDGESTYLE_ELBOW)&&
this.state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL)) ?
'row-resize' : 'col-resize';
};
/**
* Function: convertPoint
*
* Converts the given point in-place from screen to unscaled, untranslated
* graph coordinates and applies the grid.
*
* Parameters:
*
* point - <mxPoint> to be converted.
* gridEnabled - Boolean that specifies if the grid should be applied.
*/
convertPoint = (point, gridEnabled) => {
var scale = this.graph.getView().getScale();
var tr = this.graph.getView().getTranslate();
var origin = this.state.origin;
/**
* Function: getTooltipForNode
*
* Returns the tooltip for the given node.
*/
getTooltipForNode = (node)=>
{
var tip = null;
if (this.bends != null && this.bends[1] != null && (node == this.bends[1].node ||
node.parentNode == this.bends[1].node))
{
tip = this.doubleClickOrientationResource;
tip = mxResources.get(tip) || tip; // translate
}
if (gridEnabled) {
point.x = this.graph.snap(point.x);
point.y = this.graph.snap(point.y);
}
return tip;
};
point.x = Math.round(point.x / scale - tr.x - origin.x);
point.y = Math.round(point.y / scale - tr.y - origin.y);
/**
* Function: convertPoint
*
* Converts the given point in-place from screen to unscaled, untranslated
* graph coordinates and applies the grid.
*
* Parameters:
*
* point - <mxPoint> to be converted.
* gridEnabled - Boolean that specifies if the grid should be applied.
*/
convertPoint = (point, gridEnabled)=>
{
var scale = this.graph.getView().getScale();
var tr = this.graph.getView().getTranslate();
var origin = this.state.origin;
if (gridEnabled)
{
point.x = this.graph.snap(point.x);
point.y = this.graph.snap(point.y);
}
point.x = Math.round(point.x / scale - tr.x - origin.x);
point.y = Math.round(point.y / scale - tr.y - origin.y);
return point;
};
return point;
};
/**
* Function: redrawInnerBends
*
* Updates and redraws the inner bends.
*
* Parameters:
*
* p0 - <mxPoint> that represents the location of the first point.
* pe - <mxPoint> that represents the location of the last point.
*/
redrawInnerBends = (p0, pe)=>
{
var g = this.graph.getModel().getGeometry(this.state.cell);
var pts = this.state.absolutePoints;
var pt = null;
/**
* Function: redrawInnerBends
*
* Updates and redraws the inner bends.
*
* Parameters:
*
* p0 - <mxPoint> that represents the location of the first point.
* pe - <mxPoint> that represents the location of the last point.
*/
redrawInnerBends = (p0, pe) => {
var g = this.graph.getModel().getGeometry(this.state.cell);
var pts = this.state.absolutePoints;
var pt = null;
// Keeps the virtual bend on the edge shape
if (pts.length > 1)
{
p0 = pts[1];
pe = pts[pts.length - 2];
}
else if (g.points != null && g.points.length > 0)
{
pt = pts[0];
}
if (pt == null)
{
pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
}
else
{
pt = new mxPoint(this.graph.getView().scale * (pt.x + this.graph.getView().translate.x + this.state.origin.x),
this.graph.getView().scale * (pt.y + this.graph.getView().translate.y + this.state.origin.y));
}
// Keeps the virtual bend on the edge shape
if (pts.length > 1) {
p0 = pts[1];
pe = pts[pts.length - 2];
} else if (g.points != null && g.points.length > 0) {
pt = pts[0];
}
// Makes handle slightly bigger if the yellow label handle
// exists and intersects this green handle
var b = this.bends[1].bounds;
var w = b.width;
var h = b.height;
var bounds = new mxRectangle(Math.round(pt.x - w / 2), Math.round(pt.y - h / 2), w, h);
if (pt == null) {
pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
} else {
pt = new mxPoint(this.graph.getView().scale * (pt.x + this.graph.getView().translate.x + this.state.origin.x),
this.graph.getView().scale * (pt.y + this.graph.getView().translate.y + this.state.origin.y));
}
if (this.manageLabelHandle)
{
this.checkLabelHandle(bounds);
}
else if (this.handleImage == null && this.labelShape.visible && mxUtils.intersects(bounds, this.labelShape.bounds))
{
w = mxConstants.HANDLE_SIZE + 3;
h = mxConstants.HANDLE_SIZE + 3;
bounds = new mxRectangle(Math.floor(pt.x - w / 2), Math.floor(pt.y - h / 2), w, h);
}
// Makes handle slightly bigger if the yellow label handle
// exists and intersects this green handle
var b = this.bends[1].bounds;
var w = b.width;
var h = b.height;
var bounds = new mxRectangle(Math.round(pt.x - w / 2), Math.round(pt.y - h / 2), w, h);
this.bends[1].bounds = bounds;
this.bends[1].redraw();
if (this.manageLabelHandle)
{
this.checkLabelHandle(this.bends[1].bounds);
}
};
if (this.manageLabelHandle) {
this.checkLabelHandle(bounds);
} else if (this.handleImage == null && this.labelShape.visible && mxUtils.intersects(bounds, this.labelShape.bounds)) {
w = mxConstants.HANDLE_SIZE + 3;
h = mxConstants.HANDLE_SIZE + 3;
bounds = new mxRectangle(Math.floor(pt.x - w / 2), Math.floor(pt.y - h / 2), w, h);
}
this.bends[1].bounds = bounds;
this.bends[1].redraw();
if (this.manageLabelHandle) {
this.checkLabelHandle(this.bends[1].bounds);
}
};
}
export default mxElbowEdgeHandler;

File diff suppressed because it is too large Load Diff

View File

@ -2,351 +2,322 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxHandle
*
* Implements a single custom handle for vertices.
*
* Constructor: mxHandle
*
* Constructs a new handle for the given state.
*
* Parameters:
*
* state - <mxCellState> of the cell to be handled.
*/
function mxHandle(state, cursor, image, shape)
{
this.graph = state.view.graph;
this.state = state;
this.cursor = (cursor != null) ? cursor : this.cursor;
this.image = (image != null) ? image : this.image;
this.shape = (shape != null) ? shape : null;
this.init();
};
/**
* Variable: cursor
*
* Specifies the cursor to be used for this handle. Default is 'default'.
*/
cursor = 'default';
class mxHandle {
/**
* Variable: cursor
*
* Specifies the cursor to be used for this handle. Default is 'default'.
*/
cursor = 'default';
/**
* Variable: image
*
* Specifies the <mxImage> to be used to render the handle. Default is null.
*/
image = null;
/**
* Variable: image
*
* Specifies the <mxImage> to be used to render the handle. Default is null.
*/
image = null;
/**
* Variable: ignoreGrid
*
* Default is false.
*/
ignoreGrid = false;
/**
* Variable: ignoreGrid
*
* Default is false.
*/
ignoreGrid = false;
/**
* Function: getPosition
*
* Hook for subclassers to return the current position of the handle.
*/
getPosition = (bounds)=> { };
/**
* Class: mxHandle
*
* Implements a single custom handle for vertices.
*
* Constructor: mxHandle
*
* Constructs a new handle for the given state.
*
* Parameters:
*
* state - <mxCellState> of the cell to be handled.
*/
constructor(state, cursor, image, shape) {
this.graph = state.view.graph;
this.state = state;
this.cursor = (cursor != null) ? cursor : this.cursor;
this.image = (image != null) ? image : this.image;
this.shape = (shape != null) ? shape : null;
this.init();
};
/**
* Function: setPosition
*
* Hooks for subclassers to update the style in the <state>.
*/
setPosition = (bounds, pt, me)=> { };
/**
* Function: getPosition
*
* Hook for subclassers to return the current position of the handle.
*/
getPosition = (bounds) => {
};
/**
* Function: execute
*
* Hook for subclassers to execute the handle.
*/
execute = (me)=> { };
/**
* Function: setPosition
*
* Hooks for subclassers to update the style in the <state>.
*/
setPosition = (bounds, pt, me) => {
};
/**
* Function: copyStyle
*
* Sets the cell style with the given name to the corresponding value in <state>.
*/
copyStyle = (key)=>
{
this.graph.setCellStyles(key, this.state.style[key], [this.state.cell]);
};
/**
* Function: execute
*
* Hook for subclassers to execute the handle.
*/
execute = (me) => {
};
/**
* Function: processEvent
*
* Processes the given <mxMouseEvent> and invokes <setPosition>.
*/
processEvent = (me)=>
{
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(me.getGraphX() / scale - tr.x, me.getGraphY() / scale - tr.y);
// Center shape on mouse cursor
if (this.shape != null && this.shape.bounds != null)
{
pt.x -= this.shape.bounds.width / scale / 4;
pt.y -= this.shape.bounds.height / scale / 4;
}
/**
* Function: copyStyle
*
* Sets the cell style with the given name to the corresponding value in <state>.
*/
copyStyle = (key) => {
this.graph.setCellStyles(key, this.state.style[key], [this.state.cell]);
};
// Snaps to grid for the rotated position then applies the rotation for the direction after that
var alpha1 = -mxUtils.toRadians(this.getRotation());
var alpha2 = -mxUtils.toRadians(this.getTotalRotation()) - alpha1;
pt = this.flipPoint(this.rotatePoint(this.snapPoint(this.rotatePoint(pt, alpha1),
this.ignoreGrid || !this.graph.isGridEnabledEvent(me.getEvent())), alpha2));
this.setPosition(this.state.getPaintBounds(), pt, me);
this.redraw();
};
/**
* Function: processEvent
*
* Processes the given <mxMouseEvent> and invokes <setPosition>.
*/
processEvent = (me) => {
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(me.getGraphX() / scale - tr.x, me.getGraphY() / scale - tr.y);
/**
* Function: positionChanged
*
* Should be called after <setPosition> in <processEvent>.
* This repaints the state using <mxCellRenderer>.
*/
positionChanged = ()=>
{
if (this.state.text != null)
{
this.state.text.apply(this.state);
}
if (this.state.shape != null)
{
this.state.shape.apply(this.state);
}
this.graph.cellRenderer.redraw(this.state, true);
};
/**
* Function: getRotation
*
* Returns the rotation defined in the style of the cell.
*/
getRotation = ()=>
{
if (this.state.shape != null)
{
return this.state.shape.getRotation();
}
return 0;
};
/**
* Function: getTotalRotation
*
* Returns the rotation from the style and the rotation from the direction of
* the cell.
*/
getTotalRotation = ()=>
{
if (this.state.shape != null)
{
return this.state.shape.getShapeRotation();
}
return 0;
};
/**
* Function: init
*
* Creates and initializes the shapes required for this handle.
*/
init = ()=>
{
var html = this.isHtmlRequired();
if (this.image != null)
{
this.shape = new mxImageShape(new mxRectangle(0, 0, this.image.width, this.image.height), this.image.src);
this.shape.preserveImageAspect = false;
}
else if (this.shape == null)
{
this.shape = this.createShape(html);
}
this.initShape(html);
};
/**
* Function: createShape
*
* Creates and returns the shape for this handle.
*/
createShape = (html)=>
{
var bounds = new mxRectangle(0, 0, mxConstants.HANDLE_SIZE, mxConstants.HANDLE_SIZE);
return new mxRectangleShape(bounds, mxConstants.HANDLE_FILLCOLOR, mxConstants.HANDLE_STROKECOLOR);
};
/**
* Function: initShape
*
* Initializes <shape> and sets its cursor.
*/
initShape = (html)=>
{
if (html && this.shape.isHtmlAllowed())
{
this.shape.dialect = mxConstants.DIALECT_STRICTHTML;
this.shape.init(this.graph.container);
}
else
{
this.shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_MIXEDHTML : mxConstants.DIALECT_SVG;
if (this.cursor != null)
{
this.shape.init(this.graph.getView().getOverlayPane());
// Center shape on mouse cursor
if (this.shape != null && this.shape.bounds != null) {
pt.x -= this.shape.bounds.width / scale / 4;
pt.y -= this.shape.bounds.height / scale / 4;
}
}
mxEvent.redirectMouseEvents(this.shape.node, this.graph, this.state);
this.shape.node.style.cursor = this.cursor;
};
// Snaps to grid for the rotated position then applies the rotation for the direction after that
var alpha1 = -mxUtils.toRadians(this.getRotation());
var alpha2 = -mxUtils.toRadians(this.getTotalRotation()) - alpha1;
pt = this.flipPoint(this.rotatePoint(this.snapPoint(this.rotatePoint(pt, alpha1),
this.ignoreGrid || !this.graph.isGridEnabledEvent(me.getEvent())), alpha2));
this.setPosition(this.state.getPaintBounds(), pt, me);
this.redraw();
};
/**
* Function: redraw
*
* Renders the shape for this handle.
*/
redraw = ()=>
{
if (this.shape != null && this.state.shape != null)
{
var pt = this.getPosition(this.state.getPaintBounds());
if (pt != null)
{
var alpha = mxUtils.toRadians(this.getTotalRotation());
pt = this.rotatePoint(this.flipPoint(pt), alpha);
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
this.shape.bounds.x = Math.floor((pt.x + tr.x) * scale - this.shape.bounds.width / 2);
this.shape.bounds.y = Math.floor((pt.y + tr.y) * scale - this.shape.bounds.height / 2);
// Needed to force update of text bounds
this.shape.redraw();
/**
* Function: positionChanged
*
* Should be called after <setPosition> in <processEvent>.
* This repaints the state using <mxCellRenderer>.
*/
positionChanged = () => {
if (this.state.text != null) {
this.state.text.apply(this.state);
}
}
};
/**
* Function: isHtmlRequired
*
* Returns true if this handle should be rendered in HTML. This returns true if
* the text node is in the graph container.
*/
isHtmlRequired = ()=>
{
return this.state.text != null && this.state.text.node.parentNode == this.graph.container;
};
if (this.state.shape != null) {
this.state.shape.apply(this.state);
}
/**
* Function: rotatePoint
*
* Rotates the point by the given angle.
*/
rotatePoint = (pt, alpha)=>
{
var bounds = this.state.getCellBounds();
var cx = new mxPoint(bounds.getCenterX(), bounds.getCenterY());
var cos = Math.cos(alpha);
var sin = Math.sin(alpha);
this.graph.cellRenderer.redraw(this.state, true);
};
return mxUtils.getRotatedPoint(pt, cos, sin, cx);
};
/**
* Function: getRotation
*
* Returns the rotation defined in the style of the cell.
*/
getRotation = () => {
if (this.state.shape != null) {
return this.state.shape.getRotation();
}
/**
* Function: flipPoint
*
* Flips the given point vertically and/or horizontally.
*/
flipPoint = (pt)=>
{
if (this.state.shape != null)
{
return 0;
};
/**
* Function: getTotalRotation
*
* Returns the rotation from the style and the rotation from the direction of
* the cell.
*/
getTotalRotation = () => {
if (this.state.shape != null) {
return this.state.shape.getShapeRotation();
}
return 0;
};
/**
* Function: init
*
* Creates and initializes the shapes required for this handle.
*/
init = () => {
var html = this.isHtmlRequired();
if (this.image != null) {
this.shape = new mxImageShape(new mxRectangle(0, 0, this.image.width, this.image.height), this.image.src);
this.shape.preserveImageAspect = false;
} else if (this.shape == null) {
this.shape = this.createShape(html);
}
this.initShape(html);
};
/**
* Function: createShape
*
* Creates and returns the shape for this handle.
*/
createShape = (html) => {
var bounds = new mxRectangle(0, 0, mxConstants.HANDLE_SIZE, mxConstants.HANDLE_SIZE);
return new mxRectangleShape(bounds, mxConstants.HANDLE_FILLCOLOR, mxConstants.HANDLE_STROKECOLOR);
};
/**
* Function: initShape
*
* Initializes <shape> and sets its cursor.
*/
initShape = (html) => {
if (html && this.shape.isHtmlAllowed()) {
this.shape.dialect = mxConstants.DIALECT_STRICTHTML;
this.shape.init(this.graph.container);
} else {
this.shape.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ?
mxConstants.DIALECT_MIXEDHTML : mxConstants.DIALECT_SVG;
if (this.cursor != null) {
this.shape.init(this.graph.getView().getOverlayPane());
}
}
mxEvent.redirectMouseEvents(this.shape.node, this.graph, this.state);
this.shape.node.style.cursor = this.cursor;
};
/**
* Function: redraw
*
* Renders the shape for this handle.
*/
redraw = () => {
if (this.shape != null && this.state.shape != null) {
var pt = this.getPosition(this.state.getPaintBounds());
if (pt != null) {
var alpha = mxUtils.toRadians(this.getTotalRotation());
pt = this.rotatePoint(this.flipPoint(pt), alpha);
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
this.shape.bounds.x = Math.floor((pt.x + tr.x) * scale - this.shape.bounds.width / 2);
this.shape.bounds.y = Math.floor((pt.y + tr.y) * scale - this.shape.bounds.height / 2);
// Needed to force update of text bounds
this.shape.redraw();
}
}
};
/**
* Function: isHtmlRequired
*
* Returns true if this handle should be rendered in HTML. This returns true if
* the text node is in the graph container.
*/
isHtmlRequired = () => {
return this.state.text != null && this.state.text.node.parentNode == this.graph.container;
};
/**
* Function: rotatePoint
*
* Rotates the point by the given angle.
*/
rotatePoint = (pt, alpha) => {
var bounds = this.state.getCellBounds();
if (this.state.shape.flipH)
{
pt.x = 2 * bounds.x + bounds.width - pt.x;
var cx = new mxPoint(bounds.getCenterX(), bounds.getCenterY());
var cos = Math.cos(alpha);
var sin = Math.sin(alpha);
return mxUtils.getRotatedPoint(pt, cos, sin, cx);
};
/**
* Function: flipPoint
*
* Flips the given point vertically and/or horizontally.
*/
flipPoint = (pt) => {
if (this.state.shape != null) {
var bounds = this.state.getCellBounds();
if (this.state.shape.flipH) {
pt.x = 2 * bounds.x + bounds.width - pt.x;
}
if (this.state.shape.flipV) {
pt.y = 2 * bounds.y + bounds.height - pt.y;
}
}
if (this.state.shape.flipV)
{
pt.y = 2 * bounds.y + bounds.height - pt.y;
return pt;
};
/**
* Function: snapPoint
*
* Snaps the given point to the grid if ignore is false. This modifies
* the given point in-place and also returns it.
*/
snapPoint = (pt, ignore) => {
if (!ignore) {
pt.x = this.graph.snap(pt.x);
pt.y = this.graph.snap(pt.y);
}
}
return pt;
};
/**
* Function: snapPoint
*
* Snaps the given point to the grid if ignore is false. This modifies
* the given point in-place and also returns it.
*/
snapPoint = (pt, ignore)=>
{
if (!ignore)
{
pt.x = this.graph.snap(pt.x);
pt.y = this.graph.snap(pt.y);
}
return pt;
};
return pt;
};
/**
* Function: setVisible
*
* Shows or hides this handle.
*/
setVisible = (visible)=>
{
if (this.shape != null && this.shape.node != null)
{
this.shape.node.style.display = (visible) ? '' : 'none';
}
};
/**
* Function: setVisible
*
* Shows or hides this handle.
*/
setVisible = (visible) => {
if (this.shape != null && this.shape.node != null) {
this.shape.node.style.display = (visible) ? '' : 'none';
}
};
/**
* Function: reset
*
* Resets the state of this handle by setting its visibility to true.
*/
reset = ()=>
{
this.setVisible(true);
this.state.style = this.graph.getCellStyle(this.state.cell);
this.positionChanged();
};
/**
* Function: reset
*
* Resets the state of this handle by setting its visibility to true.
*/
reset = () => {
this.setVisible(true);
this.state.style = this.graph.getCellStyle(this.state.cell);
this.positionChanged();
};
/**
* Function: destroy
*
* Destroys this handle.
*/
destroy = ()=>
{
if (this.shape != null)
{
this.shape.destroy();
this.shape = null;
}
};
/**
* Function: destroy
*
* Destroys this handle.
*/
destroy = () => {
if (this.shape != null) {
this.shape.destroy();
this.shape = null;
}
};
}
export default mxHandle;

View File

@ -2,416 +2,387 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxKeyHandler
*
* Event handler that listens to keystroke events. This is not a singleton,
* however, it is normally only required once if the target is the document
* element (default).
*
* This handler installs a key event listener in the topmost DOM node and
* processes all events that originate from descandants of <mxGraph.container>
* or from the topmost DOM node. The latter means that all unhandled keystrokes
* are handled by this object regardless of the focused state of the <graph>.
*
* Example:
*
* The following example creates a key handler that listens to the delete key
* (46) and deletes the selection cells if the graph is enabled.
*
* (code)
* var keyHandler = new mxKeyHandler(graph);
* keyHandler.bindKey(46, (evt)=>
* {
* if (graph.isEnabled())
* {
* graph.removeCells();
* }
* });
* (end)
*
* Keycodes:
*
* See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of
* keycodes or install a key event listener into the document element and print
* the key codes of the respective events to the console.
*
* To support the Command key and the Control key on the Mac, the following
* code can be used.
*
* (code)
* keyHandler.getFunction = (evt)=>
* {
* if (evt != null)
* {
* return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
* }
*
* return null;
* };
* (end)
*
* Constructor: mxKeyHandler
*
* Constructs an event handler that executes functions bound to specific
* keystrokes.
*
* Parameters:
*
* graph - Reference to the associated <mxGraph>.
* target - Optional reference to the event target. If null, the document
* element is used as the event target, that is, the object where the key
* event listener is installed.
*/
function mxKeyHandler(graph, target)
{
if (graph != null)
{
this.graph = graph;
this.target = target || document.documentElement;
// Creates the arrays to map from keycodes to functions
this.normalKeys = [];
this.shiftKeys = [];
this.controlKeys = [];
this.controlShiftKeys = [];
this.keydownHandler = mxUtils.bind(this, (evt)=>
{
this.keyDown(evt);
});
// Installs the keystroke listener in the target
mxEvent.addListener(this.target, 'keydown', this.keydownHandler);
}
};
class mxKeyHandler {
/**
* Variable: graph
*
* Reference to the <mxGraph> associated with this handler.
*/
graph = null;
/**
* Variable: graph
*
* Reference to the <mxGraph> associated with this handler.
*/
graph = null;
/**
* Variable: target
*
* Reference to the target DOM, that is, the DOM node where the key event
* listeners are installed.
*/
target = null;
/**
* Variable: target
*
* Reference to the target DOM, that is, the DOM node where the key event
* listeners are installed.
*/
target = null;
/**
* Variable: normalKeys
*
* Maps from keycodes to functions for non-pressed control keys.
*/
normalKeys = null;
/**
* Variable: normalKeys
*
* Maps from keycodes to functions for non-pressed control keys.
*/
normalKeys = null;
/**
* Variable: shiftKeys
*
* Maps from keycodes to functions for pressed shift keys.
*/
shiftKeys = null;
/**
* Variable: shiftKeys
*
* Maps from keycodes to functions for pressed shift keys.
*/
shiftKeys = null;
/**
* Variable: controlKeys
*
* Maps from keycodes to functions for pressed control keys.
*/
controlKeys = null;
/**
* Variable: controlKeys
*
* Maps from keycodes to functions for pressed control keys.
*/
controlKeys = null;
/**
* Variable: controlShiftKeys
*
* Maps from keycodes to functions for pressed control and shift keys.
*/
controlShiftKeys = null;
/**
* Variable: controlShiftKeys
*
* Maps from keycodes to functions for pressed control and shift keys.
*/
controlShiftKeys = null;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Class: mxKeyHandler
*
* Event handler that listens to keystroke events. This is not a singleton,
* however, it is normally only required once if the target is the document
* element (default).
*
* This handler installs a key event listener in the topmost DOM node and
* processes all events that originate from descandants of <mxGraph.container>
* or from the topmost DOM node. The latter means that all unhandled keystrokes
* are handled by this object regardless of the focused state of the <graph>.
*
* Example:
*
* The following example creates a key handler that listens to the delete key
* (46) and deletes the selection cells if the graph is enabled.
*
* (code)
* var keyHandler = new mxKeyHandler(graph);
* keyHandler.bindKey(46, (evt)=>
* {
* if (graph.isEnabled())
* {
* graph.removeCells();
* }
* });
* (end)
*
* Keycodes:
*
* See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of
* keycodes or install a key event listener into the document element and print
* the key codes of the respective events to the console.
*
* To support the Command key and the Control key on the Mac, the following
* code can be used.
*
* (code)
* keyHandler.getFunction = (evt)=>
* {
* if (evt != null)
* {
* return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
* }
*
* return null;
* };
* (end)
*
* Constructor: mxKeyHandler
*
* Constructs an event handler that executes functions bound to specific
* keystrokes.
*
* Parameters:
*
* graph - Reference to the associated <mxGraph>.
* target - Optional reference to the event target. If null, the document
* element is used as the event target, that is, the object where the key
* event listener is installed.
*/
constructor(graph, target) {
if (graph != null) {
this.graph = graph;
this.target = target || document.documentElement;
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation returns
* <enabled>.
*/
isEnabled = ()=>
{
return this.enabled;
};
// Creates the arrays to map from keycodes to functions
this.normalKeys = [];
this.shiftKeys = [];
this.controlKeys = [];
this.controlShiftKeys = [];
/**
* Function: setEnabled
*
* Enables or disables event handling by updating <enabled>.
*
* Parameters:
*
* enabled - Boolean that specifies the new enabled state.
*/
setEnabled = (enabled)=>
{
this.enabled = enabled;
};
this.keydownHandler = mxUtils.bind(this, (evt) => {
this.keyDown(evt);
});
/**
* Function: bindKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control key is not pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindKey = (code, funct)=>
{
this.normalKeys[code] = funct;
};
// Installs the keystroke listener in the target
mxEvent.addListener(this.target, 'keydown', this.keydownHandler);
}
};
/**
* Function: bindShiftKey
*
* Binds the specified keycode to the given function. This binding is used
* if the shift key is pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindShiftKey = (code, funct)=>
{
this.shiftKeys[code] = funct;
};
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation returns
* <enabled>.
*/
isEnabled = () => {
return this.enabled;
};
/**
* Function: bindControlKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control key is pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindControlKey = (code, funct)=>
{
this.controlKeys[code] = funct;
};
/**
* Function: setEnabled
*
* Enables or disables event handling by updating <enabled>.
*
* Parameters:
*
* enabled - Boolean that specifies the new enabled state.
*/
setEnabled = (enabled) => {
this.enabled = enabled;
};
/**
* Function: bindControlShiftKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control and shift key are pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindControlShiftKey = (code, funct)=>
{
this.controlShiftKeys[code] = funct;
};
/**
* Function: bindKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control key is not pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindKey = (code, funct) => {
this.normalKeys[code] = funct;
};
/**
* Function: isControlDown
*
* Returns true if the control key is pressed. This uses <mxEvent.isControlDown>.
*
* Parameters:
*
* evt - Key event whose control key pressed state should be returned.
*/
isControlDown = (evt)=>
{
return mxEvent.isControlDown(evt);
};
/**
* Function: bindShiftKey
*
* Binds the specified keycode to the given function. This binding is used
* if the shift key is pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindShiftKey = (code, funct) => {
this.shiftKeys[code] = funct;
};
/**
* Function: getFunction
*
* Returns the function associated with the given key event or null if no
* function is associated with the given event.
*
* Parameters:
*
* evt - Key event whose associated function should be returned.
*/
getFunction = (evt)=>
{
if (evt != null && !mxEvent.isAltDown(evt))
{
if (this.isControlDown(evt))
{
if (mxEvent.isShiftDown(evt))
{
return this.controlShiftKeys[evt.keyCode];
}
else
{
return this.controlKeys[evt.keyCode];
/**
* Function: bindControlKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control key is pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindControlKey = (code, funct) => {
this.controlKeys[code] = funct;
};
/**
* Function: bindControlShiftKey
*
* Binds the specified keycode to the given function. This binding is used
* if the control and shift key are pressed.
*
* Parameters:
*
* code - Integer that specifies the keycode.
* funct - JavaScript function that takes the key event as an argument.
*/
bindControlShiftKey = (code, funct) => {
this.controlShiftKeys[code] = funct;
};
/**
* Function: isControlDown
*
* Returns true if the control key is pressed. This uses <mxEvent.isControlDown>.
*
* Parameters:
*
* evt - Key event whose control key pressed state should be returned.
*/
isControlDown = (evt) => {
return mxEvent.isControlDown(evt);
};
/**
* Function: getFunction
*
* Returns the function associated with the given key event or null if no
* function is associated with the given event.
*
* Parameters:
*
* evt - Key event whose associated function should be returned.
*/
getFunction = (evt) => {
if (evt != null && !mxEvent.isAltDown(evt)) {
if (this.isControlDown(evt)) {
if (mxEvent.isShiftDown(evt)) {
return this.controlShiftKeys[evt.keyCode];
} else {
return this.controlKeys[evt.keyCode];
}
} else {
if (mxEvent.isShiftDown(evt)) {
return this.shiftKeys[evt.keyCode];
} else {
return this.normalKeys[evt.keyCode];
}
}
}
else
{
if (mxEvent.isShiftDown(evt))
{
return this.shiftKeys[evt.keyCode];
return null;
};
/**
* Function: isGraphEvent
*
* Returns true if the event should be processed by this handler, that is,
* if the event source is either the target, one of its direct children, a
* descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the
* <graph>.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isGraphEvent = (evt) => {
var source = mxEvent.getSource(evt);
// Accepts events from the target object or
// in-place editing inside graph
if ((source == this.target || source.parentNode == this.target) ||
(this.graph.cellEditor != null && this.graph.cellEditor.isEventSource(evt))) {
return true;
}
// Accepts events from inside the container
return mxUtils.isAncestorNode(this.graph.container, source);
};
/**
* Function: keyDown
*
* Handles the event by invoking the function bound to the respective keystroke
* if <isEnabledForEvent> returns true for the given event and if
* <isEventIgnored> returns false, except for escape for which
* <isEventIgnored> is not invoked.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
keyDown = (evt) => {
if (this.isEnabledForEvent(evt)) {
// Cancels the editing if escape is pressed
if (evt.keyCode == 27 /* Escape */) {
this.escape(evt);
}
else
{
return this.normalKeys[evt.keyCode];
// Invokes the function for the keystroke
else if (!this.isEventIgnored(evt)) {
var boundFunction = this.getFunction(evt);
if (boundFunction != null) {
boundFunction(evt);
mxEvent.consume(evt);
}
}
}
}
return null;
};
/**
* Function: isGraphEvent
*
* Returns true if the event should be processed by this handler, that is,
* if the event source is either the target, one of its direct children, a
* descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the
* <graph>.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isGraphEvent = (evt)=>
{
var source = mxEvent.getSource(evt);
// Accepts events from the target object or
// in-place editing inside graph
if ((source == this.target || source.parentNode == this.target) ||
(this.graph.cellEditor != null && this.graph.cellEditor.isEventSource(evt)))
{
return true;
}
// Accepts events from inside the container
return mxUtils.isAncestorNode(this.graph.container, source);
};
};
/**
* Function: keyDown
*
* Handles the event by invoking the function bound to the respective keystroke
* if <isEnabledForEvent> returns true for the given event and if
* <isEventIgnored> returns false, except for escape for which
* <isEventIgnored> is not invoked.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
keyDown = (evt)=>
{
if (this.isEnabledForEvent(evt))
{
// Cancels the editing if escape is pressed
if (evt.keyCode == 27 /* Escape */)
{
this.escape(evt);
/**
* Function: isEnabledForEvent
*
* Returns true if the given event should be handled. <isEventIgnored> is
* called later if the event is not an escape key stroke, in which case
* <escape> is called. This implementation returns true if <isEnabled>
* returns true for both, this handler and <graph>, if the event is not
* consumed and if <isGraphEvent> returns true.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isEnabledForEvent = (evt) => {
return (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
this.isGraphEvent(evt) && this.isEnabled());
};
/**
* Function: isEventIgnored
*
* Returns true if the given keystroke should be ignored. This returns
* graph.isEditing().
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isEventIgnored = (evt) => {
return this.graph.isEditing();
};
/**
* Function: escape
*
* Hook to process ESCAPE keystrokes. This implementation invokes
* <mxGraph.stopEditing> to cancel the current editing, connecting
* and/or other ongoing modifications.
*
* Parameters:
*
* evt - Key event that represents the keystroke. Possible keycode in this
* case is 27 (ESCAPE).
*/
escape = (evt) => {
if (this.graph.isEscapeEnabled()) {
this.graph.escape(evt);
}
// Invokes the function for the keystroke
else if (!this.isEventIgnored(evt))
{
var boundFunction = this.getFunction(evt);
if (boundFunction != null)
{
boundFunction(evt);
mxEvent.consume(evt);
}
};
/**
* Function: destroy
*
* Destroys the handler and all its references into the DOM. This does
* normally not need to be called, it is called automatically when the
* window unloads (in IE).
*/
destroy = () => {
if (this.target != null && this.keydownHandler != null) {
mxEvent.removeListener(this.target, 'keydown', this.keydownHandler);
this.keydownHandler = null;
}
}
};
/**
* Function: isEnabledForEvent
*
* Returns true if the given event should be handled. <isEventIgnored> is
* called later if the event is not an escape key stroke, in which case
* <escape> is called. This implementation returns true if <isEnabled>
* returns true for both, this handler and <graph>, if the event is not
* consumed and if <isGraphEvent> returns true.
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isEnabledForEvent = (evt)=>
{
return (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
this.isGraphEvent(evt) && this.isEnabled());
};
this.target = null;
};
}
/**
* Function: isEventIgnored
*
* Returns true if the given keystroke should be ignored. This returns
* graph.isEditing().
*
* Parameters:
*
* evt - Key event that represents the keystroke.
*/
isEventIgnored = (evt)=>
{
return this.graph.isEditing();
};
/**
* Function: escape
*
* Hook to process ESCAPE keystrokes. This implementation invokes
* <mxGraph.stopEditing> to cancel the current editing, connecting
* and/or other ongoing modifications.
*
* Parameters:
*
* evt - Key event that represents the keystroke. Possible keycode in this
* case is 27 (ESCAPE).
*/
escape = (evt)=>
{
if (this.graph.isEscapeEnabled())
{
this.graph.escape(evt);
}
};
/**
* Function: destroy
*
* Destroys the handler and all its references into the DOM. This does
* normally not need to be called, it is called automatically when the
* window unloads (in IE).
*/
destroy = ()=>
{
if (this.target != null && this.keydownHandler != null)
{
mxEvent.removeListener(this.target, 'keydown', this.keydownHandler);
this.keydownHandler = null;
}
this.target = null;
};
export default mxKeyHandler;

View File

@ -2,493 +2,450 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxPanningHandler
*
* Event handler that pans and creates popupmenus. To use the left
* mousebutton for panning without interfering with cell moving and
* resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size
* steps while panning, use <useGrid>. This handler is built-into
* <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>.
*
* Constructor: mxPanningHandler
*
* Constructs an event handler that creates a <mxPopupMenu>
* and pans the graph.
*
* Event: mxEvent.PAN_START
*
* Fires when the panning handler changes its <active> state to true. The
* <code>event</code> property contains the corresponding <mxMouseEvent>.
*
* Event: mxEvent.PAN
*
* Fires while handle is processing events. The <code>event</code> property contains
* the corresponding <mxMouseEvent>.
*
* Event: mxEvent.PAN_END
*
* Fires when the panning handler changes its <active> state to false. The
* <code>event</code> property contains the corresponding <mxMouseEvent>.
*/
function mxPanningHandler(graph)
{
if (graph != null)
{
this.graph = graph;
this.graph.addMouseListener(this);
// Handles force panning event
this.forcePanningHandler = mxUtils.bind(this, (sender, evt)=>
{
var evtName = evt.getProperty('eventName');
var me = evt.getProperty('event');
class mxPanningHandler extends mxEventSource {
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
if (evtName == mxEvent.MOUSE_DOWN && this.isForcePanningEvent(me))
{
this.start(me);
this.active = true;
this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me));
me.consume();
}
});
/**
* Variable: useLeftButtonForPanning
*
* Specifies if panning should be active for the left mouse button.
* Setting this to true may conflict with <mxRubberband>. Default is false.
*/
useLeftButtonForPanning = false;
this.graph.addListener(mxEvent.FIRE_MOUSE_EVENT, this.forcePanningHandler);
/**
* Variable: usePopupTrigger
*
* Specifies if <mxEvent.isPopupTrigger> should also be used for panning.
*/
usePopupTrigger = true;
// Handles pinch gestures
this.gestureHandler = mxUtils.bind(this, (sender, eo)=>
{
if (this.isPinchEnabled())
{
var evt = eo.getProperty('event');
/**
* Variable: ignoreCell
*
* Specifies if panning should be active even if there is a cell under the
* mousepointer. Default is false.
*/
ignoreCell = false;
if (!mxEvent.isConsumed(evt) && evt.type == 'gesturestart')
{
this.initialScale = this.graph.view.scale;
/**
* Variable: previewEnabled
*
* Specifies if the panning should be previewed. Default is true.
*/
previewEnabled = true;
// Forces start of panning when pinch gesture starts
if (!this.active && this.mouseDownEvent != null)
{
this.start(this.mouseDownEvent);
this.mouseDownEvent = null;
/**
* Variable: useGrid
*
* Specifies if the panning steps should be aligned to the grid size.
* Default is false.
*/
useGrid = false;
/**
* Variable: panningEnabled
*
* Specifies if panning should be enabled. Default is true.
*/
panningEnabled = true;
/**
* Variable: pinchEnabled
*
* Specifies if pinch gestures should be handled as zoom. Default is true.
*/
pinchEnabled = true;
/**
* Variable: maxScale
*
* Specifies the maximum scale. Default is 8.
*/
maxScale = 8;
/**
* Variable: minScale
*
* Specifies the minimum scale. Default is 0.01.
*/
minScale = 0.01;
/**
* Variable: dx
*
* Holds the current horizontal offset.
*/
dx = null;
/**
* Variable: dy
*
* Holds the current vertical offset.
*/
dy = null;
/**
* Variable: startX
*
* Holds the x-coordinate of the start point.
*/
startX = 0;
/**
* Variable: startY
*
* Holds the y-coordinate of the start point.
*/
startY = 0;
/**
* Class: mxPanningHandler
*
* Event handler that pans and creates popupmenus. To use the left
* mousebutton for panning without interfering with cell moving and
* resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size
* steps while panning, use <useGrid>. This handler is built-into
* <mxGraph.panningHandler> and enabled using <mxGraph.setPanning>.
*
* Constructor: mxPanningHandler
*
* Constructs an event handler that creates a <mxPopupMenu>
* and pans the graph.
*
* Event: mxEvent.PAN_START
*
* Fires when the panning handler changes its <active> state to true. The
* <code>event</code> property contains the corresponding <mxMouseEvent>.
*
* Event: mxEvent.PAN
*
* Fires while handle is processing events. The <code>event</code> property contains
* the corresponding <mxMouseEvent>.
*
* Event: mxEvent.PAN_END
*
* Fires when the panning handler changes its <active> state to false. The
* <code>event</code> property contains the corresponding <mxMouseEvent>.
*/
constructor(graph) {
// super not called
if (graph != null) {
this.graph = graph;
this.graph.addMouseListener(this);
// Handles force panning event
this.forcePanningHandler = mxUtils.bind(this, (sender, evt) => {
var evtName = evt.getProperty('eventName');
var me = evt.getProperty('event');
if (evtName == mxEvent.MOUSE_DOWN && this.isForcePanningEvent(me)) {
this.start(me);
this.active = true;
this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me));
me.consume();
}
});
this.graph.addListener(mxEvent.FIRE_MOUSE_EVENT, this.forcePanningHandler);
// Handles pinch gestures
this.gestureHandler = mxUtils.bind(this, (sender, eo) => {
if (this.isPinchEnabled()) {
var evt = eo.getProperty('event');
if (!mxEvent.isConsumed(evt) && evt.type == 'gesturestart') {
this.initialScale = this.graph.view.scale;
// Forces start of panning when pinch gesture starts
if (!this.active && this.mouseDownEvent != null) {
this.start(this.mouseDownEvent);
this.mouseDownEvent = null;
}
} else if (evt.type == 'gestureend' && this.initialScale != null) {
this.initialScale = null;
}
if (this.initialScale != null) {
this.zoomGraph(evt);
}
}
else if (evt.type == 'gestureend' && this.initialScale != null)
{
this.initialScale = null;
}
});
if (this.initialScale != null)
{
this.zoomGraph(evt);
}
}
});
this.graph.addListener(mxEvent.GESTURE, this.gestureHandler);
this.graph.addListener(mxEvent.GESTURE, this.gestureHandler);
this.mouseUpListener = mxUtils.bind(this, ()=>
{
if (this.active)
{
this.mouseUpListener = mxUtils.bind(this, () => {
if (this.active) {
this.reset();
}
});
});
// Stops scrolling on every mouseup anywhere in the document
mxEvent.addListener(document, 'mouseup', this.mouseUpListener);
}
};
/**
* Extends mxEventSource.
*/
mxPanningHandler.prototype = new mxEventSource();
constructor = mxPanningHandler;
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: useLeftButtonForPanning
*
* Specifies if panning should be active for the left mouse button.
* Setting this to true may conflict with <mxRubberband>. Default is false.
*/
useLeftButtonForPanning = false;
/**
* Variable: usePopupTrigger
*
* Specifies if <mxEvent.isPopupTrigger> should also be used for panning.
*/
usePopupTrigger = true;
/**
* Variable: ignoreCell
*
* Specifies if panning should be active even if there is a cell under the
* mousepointer. Default is false.
*/
ignoreCell = false;
/**
* Variable: previewEnabled
*
* Specifies if the panning should be previewed. Default is true.
*/
previewEnabled = true;
/**
* Variable: useGrid
*
* Specifies if the panning steps should be aligned to the grid size.
* Default is false.
*/
useGrid = false;
/**
* Variable: panningEnabled
*
* Specifies if panning should be enabled. Default is true.
*/
panningEnabled = true;
/**
* Variable: pinchEnabled
*
* Specifies if pinch gestures should be handled as zoom. Default is true.
*/
pinchEnabled = true;
/**
* Variable: maxScale
*
* Specifies the maximum scale. Default is 8.
*/
maxScale = 8;
/**
* Variable: minScale
*
* Specifies the minimum scale. Default is 0.01.
*/
minScale = 0.01;
/**
* Variable: dx
*
* Holds the current horizontal offset.
*/
dx = null;
/**
* Variable: dy
*
* Holds the current vertical offset.
*/
dy = null;
/**
* Variable: startX
*
* Holds the x-coordinate of the start point.
*/
startX = 0;
/**
* Variable: startY
*
* Holds the y-coordinate of the start point.
*/
startY = 0;
/**
* Function: isActive
*
* Returns true if the handler is currently active.
*/
isActive = ()=>
{
return this.active || this.initialScale != null;
};
/**
* Function: isPanningEnabled
*
* Returns <panningEnabled>.
*/
isPanningEnabled = ()=>
{
return this.panningEnabled;
};
/**
* Function: setPanningEnabled
*
* Sets <panningEnabled>.
*/
setPanningEnabled = (value)=>
{
this.panningEnabled = value;
};
/**
* Function: isPinchEnabled
*
* Returns <pinchEnabled>.
*/
isPinchEnabled = ()=>
{
return this.pinchEnabled;
};
/**
* Function: setPinchEnabled
*
* Sets <pinchEnabled>.
*/
setPinchEnabled = (value)=>
{
this.pinchEnabled = value;
};
/**
* Function: isPanningTrigger
*
* Returns true if the given event is a panning trigger for the optional
* given cell. This returns true if control-shift is pressed or if
* <usePopupTrigger> is true and the event is a popup trigger.
*/
isPanningTrigger = (me)=>
{
var evt = me.getEvent();
return (this.useLeftButtonForPanning && me.getState() == null &&
mxEvent.isLeftMouseButton(evt)) || (mxEvent.isControlDown(evt) &&
mxEvent.isShiftDown(evt)) || (this.usePopupTrigger && mxEvent.isPopupTrigger(evt));
};
/**
* Function: isForcePanningEvent
*
* Returns true if the given <mxMouseEvent> should start panning. This
* implementation always returns true if <ignoreCell> is true or for
* multi touch events.
*/
isForcePanningEvent = (me)=>
{
return this.ignoreCell || mxEvent.isMultiTouchEvent(me.getEvent());
};
/**
* Function: mouseDown
*
* Handles the event by initiating the panning. By consuming the event all
* subsequent events of the gesture are redirected to this handler.
*/
mouseDown = (sender, me)=>
{
this.mouseDownEvent = me;
if (!me.isConsumed() && this.isPanningEnabled() && !this.active && this.isPanningTrigger(me))
{
this.start(me);
this.consumePanningTrigger(me);
}
};
/**
* Function: start
*
* Starts panning at the given event.
*/
start = (me)=>
{
this.dx0 = -this.graph.container.scrollLeft;
this.dy0 = -this.graph.container.scrollTop;
// Stores the location of the trigger event
this.startX = me.getX();
this.startY = me.getY();
this.dx = null;
this.dy = null;
this.panningTrigger = true;
};
/**
* Function: consumePanningTrigger
*
* Consumes the given <mxMouseEvent> if it was a panning trigger in
* <mouseDown>. The default is to invoke <mxMouseEvent.consume>. Note that this
* will block any further event processing. If you haven't disabled built-in
* context menus and require immediate selection of the cell on mouseDown in
* Safari and/or on the Mac, then use the following code:
*
* (code)
* consumePanningTrigger = (me)=>
* {
* if (me.evt.preventDefault)
* {
* me.evt.preventDefault();
* }
*
* // Stops event processing in IE
* me.evt.returnValue = false;
*
* // Sets local consumed state
* if (!mxClient.IS_SF && !mxClient.IS_MAC)
* {
* me.consumed = true;
* }
* };
* (end)
*/
consumePanningTrigger = (me)=>
{
me.consume();
};
/**
* Function: mouseMove
*
* Handles the event by updating the panning on the graph.
*/
mouseMove = (sender, me)=>
{
this.dx = me.getX() - this.startX;
this.dy = me.getY() - this.startY;
if (this.active)
{
if (this.previewEnabled)
{
// Applies the grid to the panning steps
if (this.useGrid)
{
this.dx = this.graph.snap(this.dx);
this.dy = this.graph.snap(this.dy);
}
this.graph.panGraph(this.dx + this.dx0, this.dy + this.dy0);
// Stops scrolling on every mouseup anywhere in the document
mxEvent.addListener(document, 'mouseup', this.mouseUpListener);
}
};
this.fireEvent(new mxEventObject(mxEvent.PAN, 'event', me));
}
else if (this.panningTrigger)
{
var tmp = this.active;
/**
* Function: isActive
*
* Returns true if the handler is currently active.
*/
isActive = () => {
return this.active || this.initialScale != null;
};
// Panning is activated only if the mouse is moved
// beyond the graph tolerance
this.active = Math.abs(this.dx) > this.graph.tolerance || Math.abs(this.dy) > this.graph.tolerance;
/**
* Function: isPanningEnabled
*
* Returns <panningEnabled>.
*/
isPanningEnabled = () => {
return this.panningEnabled;
};
if (!tmp && this.active)
{
this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me));
/**
* Function: setPanningEnabled
*
* Sets <panningEnabled>.
*/
setPanningEnabled = (value) => {
this.panningEnabled = value;
};
/**
* Function: isPinchEnabled
*
* Returns <pinchEnabled>.
*/
isPinchEnabled = () => {
return this.pinchEnabled;
};
/**
* Function: setPinchEnabled
*
* Sets <pinchEnabled>.
*/
setPinchEnabled = (value) => {
this.pinchEnabled = value;
};
/**
* Function: isPanningTrigger
*
* Returns true if the given event is a panning trigger for the optional
* given cell. This returns true if control-shift is pressed or if
* <usePopupTrigger> is true and the event is a popup trigger.
*/
isPanningTrigger = (me) => {
var evt = me.getEvent();
return (this.useLeftButtonForPanning && me.getState() == null &&
mxEvent.isLeftMouseButton(evt)) || (mxEvent.isControlDown(evt) &&
mxEvent.isShiftDown(evt)) || (this.usePopupTrigger && mxEvent.isPopupTrigger(evt));
};
/**
* Function: isForcePanningEvent
*
* Returns true if the given <mxMouseEvent> should start panning. This
* implementation always returns true if <ignoreCell> is true or for
* multi touch events.
*/
isForcePanningEvent = (me) => {
return this.ignoreCell || mxEvent.isMultiTouchEvent(me.getEvent());
};
/**
* Function: mouseDown
*
* Handles the event by initiating the panning. By consuming the event all
* subsequent events of the gesture are redirected to this handler.
*/
mouseDown = (sender, me) => {
this.mouseDownEvent = me;
if (!me.isConsumed() && this.isPanningEnabled() && !this.active && this.isPanningTrigger(me)) {
this.start(me);
this.consumePanningTrigger(me);
}
}
};
if (this.active || this.panningTrigger)
{
/**
* Function: start
*
* Starts panning at the given event.
*/
start = (me) => {
this.dx0 = -this.graph.container.scrollLeft;
this.dy0 = -this.graph.container.scrollTop;
// Stores the location of the trigger event
this.startX = me.getX();
this.startY = me.getY();
this.dx = null;
this.dy = null;
this.panningTrigger = true;
};
/**
* Function: consumePanningTrigger
*
* Consumes the given <mxMouseEvent> if it was a panning trigger in
* <mouseDown>. The default is to invoke <mxMouseEvent.consume>. Note that this
* will block any further event processing. If you haven't disabled built-in
* context menus and require immediate selection of the cell on mouseDown in
* Safari and/or on the Mac, then use the following code:
*
* (code)
* consumePanningTrigger = (me)=>
* {
* if (me.evt.preventDefault)
* {
* me.evt.preventDefault();
* }
*
* // Stops event processing in IE
* me.evt.returnValue = false;
*
* // Sets local consumed state
* if (!mxClient.IS_SF && !mxClient.IS_MAC)
* {
* me.consumed = true;
* }
* };
* (end)
*/
consumePanningTrigger = (me) => {
me.consume();
}
};
};
/**
* Function: mouseUp
*
* Handles the event by setting the translation on the view or showing the
* popupmenu.
*/
mouseUp = (sender, me)=>
{
if (this.active)
{
if (this.dx != null && this.dy != null)
{
// Ignores if scrollbars have been used for panning
if (!this.graph.useScrollbarsForPanning || !mxUtils.hasScrollbars(this.graph.container))
{
var scale = this.graph.getView().scale;
var t = this.graph.getView().translate;
this.graph.panGraph(0, 0);
this.panGraph(t.x + this.dx / scale, t.y + this.dy / scale);
/**
* Function: mouseMove
*
* Handles the event by updating the panning on the graph.
*/
mouseMove = (sender, me) => {
this.dx = me.getX() - this.startX;
this.dy = me.getY() - this.startY;
if (this.active) {
if (this.previewEnabled) {
// Applies the grid to the panning steps
if (this.useGrid) {
this.dx = this.graph.snap(this.dx);
this.dy = this.graph.snap(this.dy);
}
this.graph.panGraph(this.dx + this.dx0, this.dy + this.dy0);
}
this.fireEvent(new mxEventObject(mxEvent.PAN, 'event', me));
} else if (this.panningTrigger) {
var tmp = this.active;
// Panning is activated only if the mouse is moved
// beyond the graph tolerance
this.active = Math.abs(this.dx) > this.graph.tolerance || Math.abs(this.dy) > this.graph.tolerance;
if (!tmp && this.active) {
this.fireEvent(new mxEventObject(mxEvent.PAN_START, 'event', me));
}
}
if (this.active || this.panningTrigger) {
me.consume();
}
};
this.fireEvent(new mxEventObject(mxEvent.PAN_END, 'event', me));
}
/**
* Function: mouseUp
*
* Handles the event by setting the translation on the view or showing the
* popupmenu.
*/
mouseUp = (sender, me) => {
if (this.active) {
if (this.dx != null && this.dy != null) {
// Ignores if scrollbars have been used for panning
if (!this.graph.useScrollbarsForPanning || !mxUtils.hasScrollbars(this.graph.container)) {
var scale = this.graph.getView().scale;
var t = this.graph.getView().translate;
this.graph.panGraph(0, 0);
this.panGraph(t.x + this.dx / scale, t.y + this.dy / scale);
}
this.reset();
};
me.consume();
}
/**
* Function: zoomGraph
*
* Zooms the graph to the given value and consumed the event if needed.
*/
zoomGraph = (evt)=>
{
var value = Math.round(this.initialScale * evt.scale * 100) / 100;
this.fireEvent(new mxEventObject(mxEvent.PAN_END, 'event', me));
}
if (this.minScale != null)
{
value = Math.max(this.minScale, value);
}
this.reset();
};
if (this.maxScale != null)
{
value = Math.min(this.maxScale, value);
}
/**
* Function: zoomGraph
*
* Zooms the graph to the given value and consumed the event if needed.
*/
zoomGraph = (evt) => {
var value = Math.round(this.initialScale * evt.scale * 100) / 100;
if (this.graph.view.scale != value)
{
this.graph.zoomTo(value);
mxEvent.consume(evt);
}
};
if (this.minScale != null) {
value = Math.max(this.minScale, value);
}
/**
* Function: reset
*
* Resets the state of this handler.
*/
reset = ()=>
{
this.panningTrigger = false;
this.mouseDownEvent = null;
this.active = false;
this.dx = null;
this.dy = null;
};
if (this.maxScale != null) {
value = Math.min(this.maxScale, value);
}
/**
* Function: panGraph
*
* Pans <graph> by the given amount.
*/
panGraph = (dx, dy)=>
{
this.graph.getView().setTranslate(dx, dy);
};
if (this.graph.view.scale != value) {
this.graph.zoomTo(value);
mxEvent.consume(evt);
}
};
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = ()=>
{
this.graph.removeMouseListener(this);
this.graph.removeListener(this.forcePanningHandler);
this.graph.removeListener(this.gestureHandler);
mxEvent.removeListener(document, 'mouseup', this.mouseUpListener);
};
/**
* Function: reset
*
* Resets the state of this handler.
*/
reset = () => {
this.panningTrigger = false;
this.mouseDownEvent = null;
this.active = false;
this.dx = null;
this.dy = null;
};
/**
* Function: panGraph
*
* Pans <graph> by the given amount.
*/
panGraph = (dx, dy) => {
this.graph.getView().setTranslate(dx, dy);
};
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = () => {
this.graph.removeMouseListener(this);
this.graph.removeListener(this.forcePanningHandler);
this.graph.removeListener(this.gestureHandler);
mxEvent.removeListener(document, 'mouseup', this.mouseUpListener);
};
}
export default mxPanningHandler;

View File

@ -2,343 +2,302 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxSelectionCellsHandler
*
* An event handler that manages cell handlers and invokes their mouse event
* processing functions.
*
* Group: Events
*
* Event: mxEvent.ADD
*
* Fires if a cell has been added to the selection. The <code>state</code>
* property contains the <mxCellState> that has been added.
*
* Event: mxEvent.REMOVE
*
* Fires if a cell has been remove from the selection. The <code>state</code>
* property contains the <mxCellState> that has been removed.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
*/
function mxSelectionCellsHandler(graph)
{
mxEventSource.call(this);
this.graph = graph;
this.handlers = new mxDictionary();
this.graph.addMouseListener(this);
this.refreshHandler = mxUtils.bind(this, (sender, evt)=>
{
if (this.isEnabled())
{
this.refresh();
}
});
this.graph.getSelectionModel().addListener(mxEvent.CHANGE, this.refreshHandler);
this.graph.getModel().addListener(mxEvent.CHANGE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.SCALE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.TRANSLATE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.DOWN, this.refreshHandler);
this.graph.getView().addListener(mxEvent.UP, this.refreshHandler);
};
/**
* Extends mxEventSource.
*/
mxUtils.extend(mxSelectionCellsHandler, mxEventSource);
class mxSelectionCellsHandler extends mxEventSource {
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: refreshHandler
*
* Keeps a reference to an event listener for later removal.
*/
refreshHandler = null;
/**
* Variable: refreshHandler
*
* Keeps a reference to an event listener for later removal.
*/
refreshHandler = null;
/**
* Variable: maxHandlers
*
* Defines the maximum number of handlers to paint individually. Default is 100.
*/
maxHandlers = 100;
/**
* Variable: maxHandlers
*
* Defines the maximum number of handlers to paint individually. Default is 100.
*/
maxHandlers = 100;
/**
* Variable: handlers
*
* <mxDictionary> that maps from cells to handlers.
*/
handlers = null;
/**
* Variable: handlers
*
* <mxDictionary> that maps from cells to handlers.
*/
handlers = null;
/**
* Class: mxSelectionCellsHandler
*
* An event handler that manages cell handlers and invokes their mouse event
* processing functions.
*
* Group: Events
*
* Event: mxEvent.ADD
*
* Fires if a cell has been added to the selection. The <code>state</code>
* property contains the <mxCellState> that has been added.
*
* Event: mxEvent.REMOVE
*
* Fires if a cell has been remove from the selection. The <code>state</code>
* property contains the <mxCellState> that has been removed.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
*/
constructor(graph) {
super();
/**
* Function: isEnabled
*
* Returns <enabled>.
*/
isEnabled = ()=>
{
return this.enabled;
};
this.graph = graph;
this.handlers = new mxDictionary();
this.graph.addMouseListener(this);
/**
* Function: setEnabled
*
* Sets <enabled>.
*/
setEnabled = (value)=>
{
this.enabled = value;
};
this.refreshHandler = mxUtils.bind(this, (sender, evt) => {
if (this.isEnabled()) {
this.refresh();
}
});
/**
* Function: getHandler
*
* Returns the handler for the given cell.
*/
getHandler = (cell)=>
{
return this.handlers.get(cell);
};
this.graph.getSelectionModel().addListener(mxEvent.CHANGE, this.refreshHandler);
this.graph.getModel().addListener(mxEvent.CHANGE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.SCALE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.TRANSLATE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, this.refreshHandler);
this.graph.getView().addListener(mxEvent.DOWN, this.refreshHandler);
this.graph.getView().addListener(mxEvent.UP, this.refreshHandler);
};
/**
* Function: isHandled
*
* Returns true if the given cell has a handler.
*/
isHandled = (cell)=>
{
return this.getHandler(cell) != null;
};
/**
* Function: isEnabled
*
* Returns <enabled>.
*/
isEnabled = () => {
return this.enabled;
};
/**
* Function: reset
*
* Resets all handlers.
*/
reset = ()=>
{
this.handlers.visit((key, handler)=>
{
handler.reset.apply(handler);
});
};
/**
* Function: setEnabled
*
* Sets <enabled>.
*/
setEnabled = (value) => {
this.enabled = value;
};
/**
* Function: getHandledSelectionCells
*
* Reloads or updates all handlers.
*/
getHandledSelectionCells = ()=>
{
return this.graph.getSelectionCells();
};
/**
* Function: getHandler
*
* Returns the handler for the given cell.
*/
getHandler = (cell) => {
return this.handlers.get(cell);
};
/**
* Function: refresh
*
* Reloads or updates all handlers.
*/
refresh = ()=>
{
// Removes all existing handlers
var oldHandlers = this.handlers;
this.handlers = new mxDictionary();
// Creates handles for all selection cells
var tmp = mxUtils.sortCells(this.getHandledSelectionCells(), false);
/**
* Function: isHandled
*
* Returns true if the given cell has a handler.
*/
isHandled = (cell) => {
return this.getHandler(cell) != null;
};
// Destroys or updates old handlers
for (var i = 0; i < tmp.length; i++)
{
var state = this.graph.view.getState(tmp[i]);
/**
* Function: reset
*
* Resets all handlers.
*/
reset = () => {
this.handlers.visit((key, handler) => {
handler.reset.apply(handler);
});
};
if (state != null)
{
var handler = oldHandlers.remove(tmp[i]);
/**
* Function: getHandledSelectionCells
*
* Reloads or updates all handlers.
*/
getHandledSelectionCells = () => {
return this.graph.getSelectionCells();
};
if (handler != null)
{
if (handler.state != state)
{
handler.destroy();
handler = null;
}
else if (!this.isHandlerActive(handler))
{
if (handler.refresh != null)
{
handler.refresh();
/**
* Function: refresh
*
* Reloads or updates all handlers.
*/
refresh = () => {
// Removes all existing handlers
var oldHandlers = this.handlers;
this.handlers = new mxDictionary();
// Creates handles for all selection cells
var tmp = mxUtils.sortCells(this.getHandledSelectionCells(), false);
// Destroys or updates old handlers
for (var i = 0; i < tmp.length; i++) {
var state = this.graph.view.getState(tmp[i]);
if (state != null) {
var handler = oldHandlers.remove(tmp[i]);
if (handler != null) {
if (handler.state != state) {
handler.destroy();
handler = null;
} else if (!this.isHandlerActive(handler)) {
if (handler.refresh != null) {
handler.refresh();
}
handler.redraw();
}
handler.redraw();
}
if (handler != null) {
this.handlers.put(tmp[i], handler);
}
}
if (handler != null)
{
this.handlers.put(tmp[i], handler);
}
// Destroys unused handlers
oldHandlers.visit(mxUtils.bind(this, (key, handler) => {
this.fireEvent(new mxEventObject(mxEvent.REMOVE, 'state', handler.state));
handler.destroy();
}));
// Creates new handlers and updates parent highlight on existing handlers
for (var i = 0; i < tmp.length; i++) {
var state = this.graph.view.getState(tmp[i]);
if (state != null) {
var handler = this.handlers.get(tmp[i]);
if (handler == null) {
handler = this.graph.createHandler(state);
this.fireEvent(new mxEventObject(mxEvent.ADD, 'state', state));
this.handlers.put(tmp[i], handler);
} else {
handler.updateParentHighlight();
}
}
}
}
// Destroys unused handlers
oldHandlers.visit(mxUtils.bind(this, (key, handler)=>
{
this.fireEvent(new mxEventObject(mxEvent.REMOVE, 'state', handler.state));
handler.destroy();
}));
// Creates new handlers and updates parent highlight on existing handlers
for (var i = 0; i < tmp.length; i++)
{
var state = this.graph.view.getState(tmp[i]);
};
if (state != null)
{
var handler = this.handlers.get(tmp[i]);
/**
* Function: isHandlerActive
*
* Returns true if the given handler is active and should not be redrawn.
*/
isHandlerActive = (handler) => {
return handler.index != null;
};
if (handler == null)
{
handler = this.graph.createHandler(state);
this.fireEvent(new mxEventObject(mxEvent.ADD, 'state', state));
this.handlers.put(tmp[i], handler);
}
else
{
handler.updateParentHighlight();
/**
* Function: updateHandler
*
* Updates the handler for the given shape if one exists.
*/
updateHandler = (state) => {
var handler = this.handlers.remove(state.cell);
if (handler != null) {
// Transfers the current state to the new handler
var index = handler.index;
var x = handler.startX;
var y = handler.startY;
handler.destroy();
handler = this.graph.createHandler(state);
if (handler != null) {
this.handlers.put(state.cell, handler);
if (index != null && x != null && y != null) {
handler.start(x, y, index);
}
}
}
}
};
};
/**
* Function: isHandlerActive
*
* Returns true if the given handler is active and should not be redrawn.
*/
isHandlerActive = (handler)=>
{
return handler.index != null;
};
/**
* Function: mouseDown
*
* Redirects the given event to the handlers.
*/
mouseDown = (sender, me) => {
if (this.graph.isEnabled() && this.isEnabled()) {
var args = [sender, me];
/**
* Function: updateHandler
*
* Updates the handler for the given shape if one exists.
*/
updateHandler = (state)=>
{
var handler = this.handlers.remove(state.cell);
if (handler != null)
{
// Transfers the current state to the new handler
var index = handler.index;
var x = handler.startX;
var y = handler.startY;
handler.destroy();
handler = this.graph.createHandler(state);
if (handler != null)
{
this.handlers.put(state.cell, handler);
if (index != null && x != null && y != null)
{
handler.start(x, y, index);
}
this.handlers.visit((key, handler) => {
handler.mouseDown.apply(handler, args);
});
}
}
};
};
/**
* Function: mouseDown
*
* Redirects the given event to the handlers.
*/
mouseDown = (sender, me)=>
{
if (this.graph.isEnabled() && this.isEnabled())
{
var args = [sender, me];
/**
* Function: mouseMove
*
* Redirects the given event to the handlers.
*/
mouseMove = (sender, me) => {
if (this.graph.isEnabled() && this.isEnabled()) {
var args = [sender, me];
this.handlers.visit((key, handler)=>
{
handler.mouseDown.apply(handler, args);
});
}
};
this.handlers.visit((key, handler) => {
handler.mouseMove.apply(handler, args);
});
}
};
/**
* Function: mouseMove
*
* Redirects the given event to the handlers.
*/
mouseMove = (sender, me)=>
{
if (this.graph.isEnabled() && this.isEnabled())
{
var args = [sender, me];
/**
* Function: mouseUp
*
* Redirects the given event to the handlers.
*/
mouseUp = (sender, me) => {
if (this.graph.isEnabled() && this.isEnabled()) {
var args = [sender, me];
this.handlers.visit((key, handler)=>
{
handler.mouseMove.apply(handler, args);
});
}
};
this.handlers.visit((key, handler) => {
handler.mouseUp.apply(handler, args);
});
}
};
/**
* Function: mouseUp
*
* Redirects the given event to the handlers.
*/
mouseUp = (sender, me)=>
{
if (this.graph.isEnabled() && this.isEnabled())
{
var args = [sender, me];
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = () => {
this.graph.removeMouseListener(this);
this.handlers.visit((key, handler)=>
{
handler.mouseUp.apply(handler, args);
});
}
};
if (this.refreshHandler != null) {
this.graph.getSelectionModel().removeListener(this.refreshHandler);
this.graph.getModel().removeListener(this.refreshHandler);
this.graph.getView().removeListener(this.refreshHandler);
this.refreshHandler = null;
}
};
}
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = ()=>
{
this.graph.removeMouseListener(this);
if (this.refreshHandler != null)
{
this.graph.getSelectionModel().removeListener(this.refreshHandler);
this.graph.getModel().removeListener(this.refreshHandler);
this.graph.getView().removeListener(this.refreshHandler);
this.refreshHandler = null;
}
};
export default mxSelectionCellsHandler;

View File

@ -2,352 +2,322 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxTooltipHandler
*
* Graph event handler that displays tooltips. <mxGraph.getTooltip> is used to
* get the tooltip for a cell or handle. This handler is built-into
* <mxGraph.tooltipHandler> and enabled using <mxGraph.setTooltips>.
*
* Example:
*
* (code>
* new mxTooltipHandler(graph);
* (end)
*
* Constructor: mxTooltipHandler
*
* Constructs an event handler that displays tooltips with the specified
* delay (in milliseconds). If no delay is specified then a default delay
* of 500 ms (0.5 sec) is used.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
* delay - Optional delay in milliseconds.
*/
function mxTooltipHandler(graph, delay)
{
if (graph != null)
{
this.graph = graph;
this.delay = delay || 500;
this.graph.addMouseListener(this);
}
};
/**
* Variable: zIndex
*
* Specifies the zIndex for the tooltip and its shadow. Default is 10005.
*/
zIndex = 10005;
class mxTooltipHandler {
/**
* Class: mxTooltipHandler
*
* Graph event handler that displays tooltips. <mxGraph.getTooltip> is used to
* get the tooltip for a cell or handle. This handler is built-into
* <mxGraph.tooltipHandler> and enabled using <mxGraph.setTooltips>.
*
* Example:
*
* (code>
* new mxTooltipHandler(graph);
* (end)
*
* Constructor: mxTooltipHandler
*
* Constructs an event handler that displays tooltips with the specified
* delay (in milliseconds). If no delay is specified then a default delay
* of 500 ms (0.5 sec) is used.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
* delay - Optional delay in milliseconds.
*/
constructor(graph, delay) {
if (graph != null) {
this.graph = graph;
this.delay = delay || 500;
this.graph.addMouseListener(this);
}
};
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: zIndex
*
* Specifies the zIndex for the tooltip and its shadow. Default is 10005.
*/
zIndex = 10005;
/**
* Variable: delay
*
* Delay to show the tooltip in milliseconds. Default is 500.
*/
delay = null;
/**
* Variable: graph
*
* Reference to the enclosing <mxGraph>.
*/
graph = null;
/**
* Variable: ignoreTouchEvents
*
* Specifies if touch and pen events should be ignored. Default is true.
*/
ignoreTouchEvents = true;
/**
* Variable: delay
*
* Delay to show the tooltip in milliseconds. Default is 500.
*/
delay = null;
/**
* Variable: hideOnHover
*
* Specifies if the tooltip should be hidden if the mouse is moved over the
* current cell. Default is false.
*/
hideOnHover = false;
/**
* Variable: ignoreTouchEvents
*
* Specifies if touch and pen events should be ignored. Default is true.
*/
ignoreTouchEvents = true;
/**
* Variable: destroyed
*
* True if this handler was destroyed using <destroy>.
*/
destroyed = false;
/**
* Variable: hideOnHover
*
* Specifies if the tooltip should be hidden if the mouse is moved over the
* current cell. Default is false.
*/
hideOnHover = false;
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Variable: destroyed
*
* True if this handler was destroyed using <destroy>.
*/
destroyed = false;
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
isEnabled = ()=>
{
return this.enabled;
};
/**
* Variable: enabled
*
* Specifies if events are handled. Default is true.
*/
enabled = true;
/**
* Function: setEnabled
*
* Enables or disables event handling. This implementation
* updates <enabled>.
*/
setEnabled = (enabled)=>
{
this.enabled = enabled;
};
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
isEnabled = () => {
return this.enabled;
};
/**
* Function: isHideOnHover
*
* Returns <hideOnHover>.
*/
isHideOnHover = ()=>
{
return this.hideOnHover;
};
/**
* Function: setEnabled
*
* Enables or disables event handling. This implementation
* updates <enabled>.
*/
setEnabled = (enabled) => {
this.enabled = enabled;
};
/**
* Function: setHideOnHover
*
* Sets <hideOnHover>.
*/
setHideOnHover = (value)=>
{
this.hideOnHover = value;
};
/**
* Function: isHideOnHover
*
* Returns <hideOnHover>.
*/
isHideOnHover = () => {
return this.hideOnHover;
};
/**
* Function: init
*
* Initializes the DOM nodes required for this tooltip handler.
*/
init = ()=>
{
if (document.body != null)
{
this.div = document.createElement('div');
this.div.className = 'mxTooltip';
this.div.style.visibility = 'hidden';
/**
* Function: setHideOnHover
*
* Sets <hideOnHover>.
*/
setHideOnHover = (value) => {
this.hideOnHover = value;
};
document.body.appendChild(this.div);
/**
* Function: init
*
* Initializes the DOM nodes required for this tooltip handler.
*/
init = () => {
if (document.body != null) {
this.div = document.createElement('div');
this.div.className = 'mxTooltip';
this.div.style.visibility = 'hidden';
mxEvent.addGestureListeners(this.div, mxUtils.bind(this, (evt)=>
{
var source = mxEvent.getSource(evt);
if (source.nodeName != 'A')
{
document.body.appendChild(this.div);
mxEvent.addGestureListeners(this.div, mxUtils.bind(this, (evt) => {
var source = mxEvent.getSource(evt);
if (source.nodeName != 'A') {
this.hideTooltip();
}
}));
}
};
/**
* Function: getStateForEvent
*
* Returns the <mxCellState> to be used for showing a tooltip for this event.
*/
getStateForEvent = (me) => {
return me.getState();
};
/**
* Function: mouseDown
*
* Handles the event by initiating a rubberband selection. By consuming the
* event all subsequent events of the gesture are redirected to this
* handler.
*/
mouseDown = (sender, me) => {
this.reset(me, false);
this.hideTooltip();
};
/**
* Function: mouseMove
*
* Handles the event by updating the rubberband selection.
*/
mouseMove = (sender, me) => {
if (me.getX() != this.lastX || me.getY() != this.lastY) {
this.reset(me, true);
var state = this.getStateForEvent(me);
if (this.isHideOnHover() || state != this.state || (me.getSource() != this.node &&
(!this.stateSource || (state != null && this.stateSource ==
(me.isSource(state.shape) || !me.isSource(state.text)))))) {
this.hideTooltip();
}
}));
}
};
}
/**
* Function: getStateForEvent
*
* Returns the <mxCellState> to be used for showing a tooltip for this event.
*/
getStateForEvent = (me)=>
{
return me.getState();
};
this.lastX = me.getX();
this.lastY = me.getY();
};
/**
* Function: mouseDown
*
* Handles the event by initiating a rubberband selection. By consuming the
* event all subsequent events of the gesture are redirected to this
* handler.
*/
mouseDown = (sender, me)=>
{
this.reset(me, false);
this.hideTooltip();
};
/**
* Function: mouseMove
*
* Handles the event by updating the rubberband selection.
*/
mouseMove = (sender, me)=>
{
if (me.getX() != this.lastX || me.getY() != this.lastY)
{
/**
* Function: mouseUp
*
* Handles the event by resetting the tooltip timer or hiding the existing
* tooltip.
*/
mouseUp = (sender, me) => {
this.reset(me, true);
var state = this.getStateForEvent(me);
if (this.isHideOnHover() || state != this.state || (me.getSource() != this.node &&
(!this.stateSource || (state != null && this.stateSource ==
(me.isSource(state.shape) || !me.isSource(state.text))))))
{
this.hideTooltip();
this.hideTooltip();
};
/**
* Function: resetTimer
*
* Resets the timer.
*/
resetTimer = () => {
if (this.thread != null) {
window.clearTimeout(this.thread);
this.thread = null;
}
}
this.lastX = me.getX();
this.lastY = me.getY();
};
};
/**
* Function: mouseUp
*
* Handles the event by resetting the tooltip timer or hiding the existing
* tooltip.
*/
mouseUp = (sender, me)=>
{
this.reset(me, true);
this.hideTooltip();
};
/**
* Function: reset
*
* Resets and/or restarts the timer to trigger the display of the tooltip.
*/
reset = (me, restart, state) => {
if (!this.ignoreTouchEvents || mxEvent.isMouseEvent(me.getEvent())) {
this.resetTimer();
state = (state != null) ? state : this.getStateForEvent(me);
if (restart && this.isEnabled() && state != null && (this.div == null ||
this.div.style.visibility == 'hidden')) {
var node = me.getSource();
var x = me.getX();
var y = me.getY();
var stateSource = me.isSource(state.shape) || me.isSource(state.text);
/**
* Function: resetTimer
*
* Resets the timer.
*/
resetTimer = ()=>
{
if (this.thread != null)
{
window.clearTimeout(this.thread);
this.thread = null;
}
};
this.thread = window.setTimeout(mxUtils.bind(this, () => {
if (!this.graph.isEditing() && !this.graph.popupMenuHandler.isMenuShowing() && !this.graph.isMouseDown) {
// Uses information from inside event cause using the event at
// this (delayed) point in time is not possible in IE as it no
// longer contains the required information (member not found)
var tip = this.graph.getTooltip(state, node, x, y);
this.show(tip, x, y);
this.state = state;
this.node = node;
this.stateSource = stateSource;
}
}), this.delay);
}
}
};
/**
* Function: reset
*
* Resets and/or restarts the timer to trigger the display of the tooltip.
*/
reset = (me, restart, state)=>
{
if (!this.ignoreTouchEvents || mxEvent.isMouseEvent(me.getEvent()))
{
/**
* Function: hide
*
* Hides the tooltip and resets the timer.
*/
hide = () => {
this.resetTimer();
state = (state != null) ? state : this.getStateForEvent(me);
if (restart && this.isEnabled() && state != null && (this.div == null ||
this.div.style.visibility == 'hidden'))
{
var node = me.getSource();
var x = me.getX();
var y = me.getY();
var stateSource = me.isSource(state.shape) || me.isSource(state.text);
this.thread = window.setTimeout(mxUtils.bind(this, ()=>
{
if (!this.graph.isEditing() && !this.graph.popupMenuHandler.isMenuShowing() && !this.graph.isMouseDown)
{
// Uses information from inside event cause using the event at
// this (delayed) point in time is not possible in IE as it no
// longer contains the required information (member not found)
var tip = this.graph.getTooltip(state, node, x, y);
this.show(tip, x, y);
this.state = state;
this.node = node;
this.stateSource = stateSource;
}
}), this.delay);
}
}
};
this.hideTooltip();
};
/**
* Function: hide
*
* Hides the tooltip and resets the timer.
*/
hide = ()=>
{
this.resetTimer();
this.hideTooltip();
};
/**
* Function: hideTooltip
*
* Hides the tooltip.
*/
hideTooltip = ()=>
{
if (this.div != null)
{
this.div.style.visibility = 'hidden';
this.div.innerHTML = '';
}
};
/**
* Function: show
*
* Shows the tooltip for the specified cell and optional index at the
* specified location (with a vertical offset of 10 pixels).
*/
show = (tip, x, y)=>
{
if (!this.destroyed && tip != null && tip.length > 0)
{
// Initializes the DOM nodes if required
if (this.div == null)
{
this.init();
}
var origin = mxUtils.getScrollOrigin();
this.div.style.zIndex = this.zIndex;
this.div.style.left = (x + origin.x) + 'px';
this.div.style.top = (y + mxConstants.TOOLTIP_VERTICAL_OFFSET +
origin.y) + 'px';
if (!mxUtils.isNode(tip))
{
this.div.innerHTML = tip.replace(/\n/g, '<br>');
}
else
{
/**
* Function: hideTooltip
*
* Hides the tooltip.
*/
hideTooltip = () => {
if (this.div != null) {
this.div.style.visibility = 'hidden';
this.div.innerHTML = '';
this.div.appendChild(tip);
}
this.div.style.visibility = '';
mxUtils.fit(this.div);
}
};
};
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = ()=>
{
if (!this.destroyed)
{
this.graph.removeMouseListener(this);
mxEvent.release(this.div);
if (this.div != null && this.div.parentNode != null)
{
this.div.parentNode.removeChild(this.div);
/**
* Function: show
*
* Shows the tooltip for the specified cell and optional index at the
* specified location (with a vertical offset of 10 pixels).
*/
show = (tip, x, y) => {
if (!this.destroyed && tip != null && tip.length > 0) {
// Initializes the DOM nodes if required
if (this.div == null) {
this.init();
}
var origin = mxUtils.getScrollOrigin();
this.div.style.zIndex = this.zIndex;
this.div.style.left = (x + origin.x) + 'px';
this.div.style.top = (y + mxConstants.TOOLTIP_VERTICAL_OFFSET +
origin.y) + 'px';
if (!mxUtils.isNode(tip)) {
this.div.innerHTML = tip.replace(/\n/g, '<br>');
} else {
this.div.innerHTML = '';
this.div.appendChild(tip);
}
this.div.style.visibility = '';
mxUtils.fit(this.div);
}
this.destroyed = true;
this.div = null;
}
};
};
/**
* Function: destroy
*
* Destroys the handler and all its resources and DOM nodes.
*/
destroy = () => {
if (!this.destroyed) {
this.graph.removeMouseListener(this);
mxEvent.release(this.div);
if (this.div != null && this.div.parentNode != null) {
this.div.parentNode.removeChild(this.div);
}
this.destroyed = true;
this.div = null;
}
};
}
export default mxTooltipHandler;

View File

@ -3,8 +3,12 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxCell from "FIXME";
import mxObjectCodec from "./mxObjectCodec";
import mxCodecRegistry from "./mxCodecRegistry";
/**
class mxCellCodec extends mxObjectCodec {
/**
* Class: mxCellCodec
*
* Codec for <mxCell>s. This class is created and registered
@ -43,26 +47,27 @@
* mxCodecRegistry.addAlias('CustomCell', 'mxCell');
* (end)
*/
var codec = new mxObjectCodec(new mxCell(),
['children', 'edges', 'overlays', 'mxTransient'],
['parent', 'source', 'target']);
constructor() {
super(new mxCell(),
['children', 'edges', 'overlays', 'mxTransient'],
['parent', 'source', 'target']);
}
/**
* Function: isCellCodec
*
* Returns true since this is a cell codec.
*/
codec.isCellCodec = ()=>
{
isCellCodec = () => {
return true;
};
/**
* Overidden to disable conversion of value to number.
*/
codec.isNumericAttribute = (dec, attr, obj)=>
{
return attr.nodeName !== 'value' && isNumericAttribute.apply(this, arguments);
isNumericAttribute = (dec, attr, obj) => {
return attr.nodeName !== 'value' &&
super.isNumericAttribute(dec, attr, obj);
};
/**
@ -70,11 +75,10 @@
*
* Excludes user objects that are XML nodes.
*/
codec.isExcluded = (obj, attr, value, isWrite)=>
{
return isExcluded.apply(this, arguments) ||
(isWrite && attr == 'value' &&
value.nodeType == mxConstants.NODETYPE_ELEMENT);
isExcluded = (obj, attr, value, isWrite) => {
return super.isExcluded(obj, attr, value, isWrite) ||
(isWrite && attr === 'value' &&
value.nodeType === mxConstants.NODETYPE_ELEMENT);
};
/**
@ -83,10 +87,8 @@
* Encodes an <mxCell> and wraps the XML up inside the
* XML of the user object (inversion).
*/
codec.afterEncode = (enc, obj, node)=>
{
if (obj.value != null && obj.value.nodeType == mxConstants.NODETYPE_ELEMENT)
{
afterEncode = (enc, obj, node) => {
if (obj.value != null && obj.value.nodeType === mxConstants.NODETYPE_ELEMENT) {
// Wraps the graphical annotation up in the user object (inversion)
// by putting the result of the default encoding into a clone of the
// user object (node type 1) and returning this cloned user object.
@ -110,26 +112,21 @@
* Decodes an <mxCell> and uses the enclosing XML node as
* the user object for the cell (inversion).
*/
codec.beforeDecode = (dec, node, obj)=>
{
beforeDecode = (dec, node, obj) => {
var inner = node.cloneNode(true);
var classname = this.getName();
if (node.nodeName != classname)
{
if (node.nodeName !== classname) {
// Passes the inner graphical annotation node to the
// object codec for further processing of the cell.
var tmp = node.getElementsByTagName(classname)[0];
if (tmp != null && tmp.parentNode == node)
{
if (tmp != null && tmp.parentNode === node) {
mxUtils.removeWhitespace(tmp, true);
mxUtils.removeWhitespace(tmp, false);
tmp.parentNode.removeChild(tmp);
inner = tmp;
}
else
{
} else {
inner = null;
}
@ -137,39 +134,31 @@
obj.value = node.cloneNode(true);
var id = obj.value.getAttribute('id');
if (id != null)
{
if (id != null) {
obj.setId(id);
obj.value.removeAttribute('id');
}
}
else
{
} else {
// Uses ID from XML file as ID for cell in model
obj.setId(node.getAttribute('id'));
}
// Preprocesses and removes all Id-references in order to use the
// correct encoder (this) for the known references to cells (all).
if (inner != null)
{
for (var i = 0; i < this.idrefs.length; i++)
{
if (inner != null) {
for (var i = 0; i < this.idrefs.length; i++) {
var attr = this.idrefs[i];
var ref = inner.getAttribute(attr);
if (ref != null)
{
if (ref != null) {
inner.removeAttribute(attr);
var object = dec.objects[ref] || dec.lookup(ref);
if (object == null)
{
if (object == null) {
// Needs to decode forward reference
var element = dec.getElementById(ref);
if (element != null)
{
if (element != null) {
var decoder = mxCodecRegistry.codecs[element.nodeName] || this;
object = decoder.decode(dec, element);
}
@ -182,6 +171,7 @@
return inner;
};
}
mxCodecRegistry.register(new mxCellCodec());
export default mxCellCodec;

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxObjectCodec from "FIXME";
import mxChildChange from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxChildChangeCodec extends mxObjectCodec {
/**
* Class: mxChildChangeCodec
@ -48,7 +52,7 @@ class mxChildChangeCodec extends mxObjectCodec {
* Excludes references to parent or previous if not in the model.
*/
isExcluded = (obj, attr, value, write) => {
return isExcluded.apply(this, arguments) ||
return super.isExcluded(obj, attr, value, write) ||
(write && value != null && (attr === 'previous' ||
attr === 'parent') && !obj.model.contains(value));
};

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,11 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
var mxCodecRegistry =
{
import mxUtils from "../util/mxUtils";
import mxObjectCodec from "./mxObjectCodec";
var mxCodecRegistry = {
/**
* Class: mxCodecRegistry
*
@ -11,7 +14,7 @@ var mxCodecRegistry =
*
* Adding an <mxCodec>:
*
* 1. Define a default codec with a new instance of the
* 1. Define a default codec with a new instance of the
* object to be handled.
*
* (code)
@ -32,18 +35,18 @@ var mxCodecRegistry =
* mxCodecRegistry.register(codec);
* (end)
*
* <mxObjectCodec.decode> may be used to either create a new
* instance of an object or to configure an existing instance,
* <mxObjectCodec.decode> may be used to either create a new
* instance of an object or to configure an existing instance,
* in which case the into argument points to the existing
* object. In this case, we say the codec "configures" the
* object.
*
*
* Variable: codecs
*
* Maps from constructor names to codecs.
*/
codecs: [],
/**
* Variable: aliases
*
@ -61,17 +64,14 @@ var mxCodecRegistry =
*
* codec - <mxObjectCodec> to be registered.
*/
register: (codec)=>
{
if (codec != null)
{
register: (codec) => {
if (codec != null) {
var name = codec.getName();
mxCodecRegistry.codecs[name] = codec;
var classname = mxUtils.getFunctionName(codec.template.constructor);
if (classname != name)
{
if (classname !== name) {
mxCodecRegistry.addAlias(classname, name);
}
}
@ -84,8 +84,7 @@ var mxCodecRegistry =
*
* Adds an alias for mapping a classname to a codecname.
*/
addAlias: (classname, codecname)=>
{
addAlias: (classname, codecname) => {
mxCodecRegistry.aliases[classname] = codecname;
},
@ -97,41 +96,35 @@ var mxCodecRegistry =
*
* Parameters:
*
* ctor - JavaScript constructor function.
* ctor - JavaScript constructor function.
*/
getCodec: (ctor)=>
{
getCodec: (ctor) => {
var codec = null;
if (ctor != null)
{
if (ctor != null) {
var name = mxUtils.getFunctionName(ctor);
var tmp = mxCodecRegistry.aliases[name];
if (tmp != null)
{
if (tmp != null) {
name = tmp;
}
codec = mxCodecRegistry.codecs[name];
// Registers a new default codec for the given constructor
// if no codec has been previously defined.
if (codec == null)
{
try
{
if (codec == null) {
try {
codec = new mxObjectCodec(new ctor());
mxCodecRegistry.register(codec);
}
catch (e)
{
} catch (e) {
// ignore
}
}
}
return codec;
}
};
export default mxCodecRegistry;

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxObjectCodec from "FIXME";
import mxDefaultKeyHandler from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxDefaultKeyHandlerCodec extends mxObjectCodec {
/**
* Class: mxDefaultKeyHandlerCodec

View File

@ -3,6 +3,9 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxDefaultPopupMenu from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxDefaultPopupMenuCodec extends mxObjectCodec {
/**
* Class: mxDefaultPopupMenuCodec

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxObjectCodec from "FIXME";
import mxDefaultToolbar from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxDefaultToolbarCodec extends mxObjectCodec {
/**
* Class: mxDefaultToolbarCodec

View File

@ -2,8 +2,13 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
mxCodecRegistry.register(()=>
{
import mxEditor from "FIXME";
import mxWindow from "FIXME";
import mxObjectCodec from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxEditorCodec extends mxObjectCodec {
/**
* Class: mxEditorCodec
*
@ -20,9 +25,11 @@ mxCodecRegistry.register(()=>
* - graphContainer
* - toolbarContainer
*/
var codec = new mxObjectCodec(new mxEditor(),
['modified', 'lastSnapshot', 'ignoredChanges',
'undoManager', 'graphContainer', 'toolbarContainer']);
constructor() {
super(new mxEditor(),
['modified', 'lastSnapshot', 'ignoredChanges',
'undoManager', 'graphContainer', 'toolbarContainer']);
}
/**
* Function: beforeDecode
@ -78,13 +85,11 @@ mxCodecRegistry.register(()=>
* </ui>
* (end)
*/
codec.afterDecode = (dec, node, obj)=>
{
afterDecode = (dec, node, obj) => {
// Assigns the specified templates for edges
var defaultEdge = node.getAttribute('defaultEdge');
if (defaultEdge != null)
{
if (defaultEdge != null) {
node.removeAttribute('defaultEdge');
obj.defaultEdge = obj.templates[defaultEdge];
}
@ -92,8 +97,7 @@ mxCodecRegistry.register(()=>
// Assigns the specified templates for groups
var defaultGroup = node.getAttribute('defaultGroup');
if (defaultGroup != null)
{
if (defaultGroup != null) {
node.removeAttribute('defaultGroup');
obj.defaultGroup = obj.templates[defaultGroup];
}
@ -106,20 +110,15 @@ mxCodecRegistry.register(()=>
*
* Overrides decode child to handle special child nodes.
*/
codec.decodeChild = (dec, child, obj)=>
{
if (child.nodeName == 'Array')
{
decodeChild = (dec, child, obj) => {
if (child.nodeName === 'Array') {
var role = child.getAttribute('as');
if (role == 'templates')
{
if (role === 'templates') {
this.decodeTemplates(dec, child, obj);
return;
}
}
else if (child.nodeName == 'ui')
{
} else if (child.nodeName === 'ui') {
this.decodeUi(dec, child, obj);
return;
}
@ -132,29 +131,22 @@ mxCodecRegistry.register(()=>
*
* Decodes the ui elements from the given node.
*/
codec.decodeUi = (dec, node, editor)=>
{
decodeUi = (dec, node, editor) => {
var tmp = node.firstChild;
while (tmp != null)
{
if (tmp.nodeName == 'add')
{
while (tmp != null) {
if (tmp.nodeName === 'add') {
var as = tmp.getAttribute('as');
var elt = tmp.getAttribute('element');
var style = tmp.getAttribute('style');
var element = null;
if (elt != null)
{
if (elt != null) {
element = document.getElementById(elt);
if (element != null && style != null)
{
if (element != null && style != null) {
element.style.cssText += ';' + style;
}
}
else
{
} else {
var x = parseInt(tmp.getAttribute('x'));
var y = parseInt(tmp.getAttribute('y'));
var width = tmp.getAttribute('width');
@ -165,38 +157,25 @@ mxCodecRegistry.register(()=>
element.style.cssText = style;
var wnd = new mxWindow(mxResources.get(as) || as,
element, x, y, width, height, false, true);
element, x, y, width, height, false, true);
wnd.setVisible(true);
}
// TODO: Make more generic
if (as == 'graph')
{
if (as === 'graph') {
editor.setGraphContainer(element);
}
else if (as == 'toolbar')
{
} else if (as === 'toolbar') {
editor.setToolbarContainer(element);
}
else if (as == 'title')
{
} else if (as === 'title') {
editor.setTitleContainer(element);
}
else if (as == 'status')
{
} else if (as === 'status') {
editor.setStatusContainer(element);
}
else if (as == 'map')
{
} else if (as === 'map') {
editor.setMapContainer(element);
}
}
else if (tmp.nodeName == 'resource')
{
} else if (tmp.nodeName === 'resource') {
mxResources.add(tmp.getAttribute('basename'));
}
else if (tmp.nodeName == 'stylesheet')
{
} else if (tmp.nodeName === 'stylesheet') {
mxClient.link('stylesheet', tmp.getAttribute('name'));
}
@ -209,26 +188,21 @@ mxCodecRegistry.register(()=>
*
* Decodes the cells from the given node as templates.
*/
codec.decodeTemplates = (dec, node, editor)=>
{
if (editor.templates == null)
{
decodeTemplates = (dec, node, editor) => {
if (editor.templates == null) {
editor.templates = [];
}
var children = mxUtils.getChildNodes(node);
for (var j=0; j<children.length; j++)
{
for (var j = 0; j < children.length; j++) {
var name = children[j].getAttribute('as');
var child = children[j].firstChild;
while (child != null && child.nodeType != 1)
{
while (child != null && child.nodeType !== 1) {
child = child.nextSibling;
}
if (child != null)
{
if (child != null) {
// LATER: Only single cells means you need
// to group multiple cells within another
// cell. This should be changed to support
@ -238,8 +212,7 @@ mxCodecRegistry.register(()=>
}
}
};
}
// Returns the codec into the registry
return codec;
}());
mxCodecRegistry.register(new mxEditorCodec());
export default mxEditorCodec;

View File

@ -2,58 +2,65 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxGenericChangeCodec
*
* Codec for <mxValueChange>s, <mxStyleChange>s, <mxGeometryChange>s,
* <mxCollapseChange>s and <mxVisibleChange>s. This class is created
* and registered dynamically at load time and used implicitly
* via <mxCodec> and the <mxCodecRegistry>.
*
* Transient Fields:
*
* - model
* - previous
*
* Reference Fields:
*
* - cell
*
* Constructor: mxGenericChangeCodec
*
* Factory function that creates a <mxObjectCodec> for
* the specified change and fieldname.
*
* Parameters:
*
* obj - An instance of the change object.
* variable - The fieldname for the change data.
*/
var mxGenericChangeCodec = (obj, variable)=>
{
var codec = new mxObjectCodec(obj, ['model', 'previous'], ['cell']);
import mxObjectCodec from "FIXME";
import mxValueChange from "FIXME";
import mxStyleChange from "FIXME";
import mxGeometryChange from "FIXME";
import mxCollapseChange from "FIXME";
import mxVisibleChange from "FIXME";
import mxCellAttributeChange from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxGenericChangeCodec extends mxObjectCodec {
/**
* Class: mxGenericChangeCodec
*
* Codec for <mxValueChange>s, <mxStyleChange>s, <mxGeometryChange>s,
* <mxCollapseChange>s and <mxVisibleChange>s. This class is created
* and registered dynamically at load time and used implicitly
* via <mxCodec> and the <mxCodecRegistry>.
*
* Transient Fields:
*
* - model
* - previous
*
* Reference Fields:
*
* - cell
*
* Constructor: mxGenericChangeCodec
*
* Factory function that creates a <mxObjectCodec> for
* the specified change and fieldname.
*
* Parameters:
*
* obj - An instance of the change object.
* variable - The fieldname for the change data.
*/
constructor(obj, variable) {
super(obj, ['model', 'previous'], ['cell']);
this.variable = variable;
}
/**
* Function: afterDecode
*
* Restores the state by assigning the previous value.
*/
codec.afterDecode = (dec, node, obj)=>
{
afterDecode = (dec, node, obj) => {
// Allows forward references in sessions. This is a workaround
// for the sequence of edits in mxGraph.moveCells and cellsAdded.
if (mxUtils.isNode(obj.cell))
{
if (mxUtils.isNode(obj.cell)) {
obj.cell = dec.decodeCell(obj.cell, false);
}
obj.previous = obj[variable];
obj.previous = obj[this.variable];
return obj;
};
return codec;
};
}
// Registers the codecs
mxCodecRegistry.register(mxGenericChangeCodec(new mxValueChange(), 'value'));

View File

@ -2,8 +2,11 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
mxCodecRegistry.register(()=>
{
import mxGraph from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxGraphCodec extends mxObjectCodec {
/**
* Class: mxGraphCodec
*
@ -21,8 +24,11 @@ mxCodecRegistry.register(()=>
* - editor
* - selection
*/
return new mxObjectCodec(new mxGraph(),
['graphListeners', 'eventListeners', 'view', 'container',
'cellRenderer', 'editor', 'selection']);
constructor() {
super(new mxGraph(), ['graphListeners', 'eventListeners', 'view', 'container',
'cellRenderer', 'editor', 'selection']);
}
}
}());
mxCodecRegistry.register(new mxGraphCodec());
export default mxGraphCodec;

View File

@ -2,8 +2,12 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
mxCodecRegistry.register(()=>
{
import mxGraphView from "FIXME";
import mxObjectCodec from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxGraphViewCodec extends mxObjectCodec {
/**
* Class: mxGraphViewCodec
*
@ -14,7 +18,9 @@ mxCodecRegistry.register(()=>
* the graph, that is, it contains absolute coordinates with
* computed perimeters, edge styles and cell styles.
*/
var codec = new mxObjectCodec(new mxGraphView());
constructor() {
super(new mxGraphView())
}
/**
* Function: encode
@ -23,10 +29,9 @@ mxCodecRegistry.register(()=>
* starting at the model's root. This returns the
* top-level graph node of the recursive encoding.
*/
codec.encode = (enc, view)=>
{
encode = (enc, view) => {
return this.encodeCell(enc, view,
view.graph.getModel().getRoot());
view.graph.getModel().getRoot());
};
/**
@ -49,60 +54,44 @@ mxCodecRegistry.register(()=>
* values from the cell style are added as attribute
* values to the node.
*/
codec.encodeCell = (enc, view, cell)=>
{
encodeCell = (enc, view, cell) => {
var model = view.graph.getModel();
var state = view.getState(cell);
var parent = model.getParent(cell);
if (parent == null || state != null)
{
if (parent == null || state != null) {
var childCount = model.getChildCount(cell);
var geo = view.graph.getCellGeometry(cell);
var name = null;
if (parent == model.getRoot())
{
if (parent === model.getRoot()) {
name = 'layer';
}
else if (parent == null)
{
} else if (parent == null) {
name = 'graph';
}
else if (model.isEdge(cell))
{
} else if (model.isEdge(cell)) {
name = 'edge';
}
else if (childCount > 0 && geo != null)
{
} else if (childCount > 0 && geo != null) {
name = 'group';
}
else if (model.isVertex(cell))
{
} else if (model.isVertex(cell)) {
name = 'vertex';
}
if (name != null)
{
if (name != null) {
var node = enc.document.createElement(name);
var lab = view.graph.getLabel(cell);
if (lab != null)
{
if (lab != null) {
node.setAttribute('label', view.graph.getLabel(cell));
if (view.graph.isHtmlLabel(cell))
{
if (view.graph.isHtmlLabel(cell)) {
node.setAttribute('html', true);
}
}
if (parent == null)
{
if (parent == null) {
var bounds = view.getGraphBounds();
if (bounds != null)
{
if (bounds != null) {
node.setAttribute('x', Math.round(bounds.x));
node.setAttribute('y', Math.round(bounds.y));
node.setAttribute('width', Math.round(bounds.width));
@ -110,48 +99,40 @@ mxCodecRegistry.register(()=>
}
node.setAttribute('scale', view.scale);
}
else if (state != null && geo != null)
{
} else if (state != null && geo != null) {
// Writes each key, value in the style pair to an attribute
for (var i in state.style)
{
var value = state.style[i];
for (var i in state.style) {
var value = state.style[i];
// Tries to turn objects and functions into strings
if (typeof(value) == 'function' &&
typeof(value) == 'object')
{
value = mxStyleRegistry.getName(value);
}
if (value != null &&
typeof(value) != 'function' &&
typeof(value) != 'object')
{
node.setAttribute(i, value);
}
// Tries to turn objects and functions into strings
if (typeof (value) == 'function' &&
typeof (value) == 'object') {
value = mxStyleRegistry.getName(value);
}
if (value != null &&
typeof (value) != 'function' &&
typeof (value) != 'object') {
node.setAttribute(i, value);
}
}
var abs = state.absolutePoints;
// Writes the list of points into one attribute
if (abs != null && abs.length > 0)
{
if (abs != null && abs.length > 0) {
var pts = Math.round(abs[0].x) + ',' + Math.round(abs[0].y);
for (var i=1; i<abs.length; i++)
{
for (var i = 1; i < abs.length; i++) {
pts += ' ' + Math.round(abs[i].x) + ',' +
Math.round(abs[i].y);
Math.round(abs[i].y);
}
node.setAttribute('points', pts);
}
// Writes the bounds into 4 attributes
else
{
else {
node.setAttribute('x', Math.round(state.x));
node.setAttribute('y', Math.round(state.y));
node.setAttribute('width', Math.round(state.width));
@ -161,37 +142,30 @@ mxCodecRegistry.register(()=>
var offset = state.absoluteOffset;
// Writes the offset into 2 attributes
if (offset != null)
{
if (offset.x != 0)
{
if (offset != null) {
if (offset.x !== 0) {
node.setAttribute('dx', Math.round(offset.x));
}
if (offset.y != 0)
{
if (offset.y !== 0) {
node.setAttribute('dy', Math.round(offset.y));
}
}
}
for (var i=0; i<childCount; i++)
{
for (var i = 0; i < childCount; i++) {
var childNode = this.encodeCell(enc,
view, model.getChildAt(cell, i));
if (childNode != null)
{
if (childNode != null) {
node.appendChild(childNode);
}
}
}
}
return node;
};
}
// Returns the codec into the registry
return codec;
}());
mxCodecRegistry.register(new mxGraphViewCodec());
export default mxGraphViewCodec;

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxGraphModel from "FIXME";
import mxObjectCodec from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxModelCodec extends mxObjectCodec {
/**
* Class: mxModelCodec
@ -70,4 +74,3 @@ class mxModelCodec extends mxObjectCodec {
mxCodecRegistry.register(new mxModelCodec());
export default mxModelCodec;

View File

@ -62,7 +62,7 @@ class mxObjectCodec {
* Consider the following example.
*
* (code)
* var obj = new Object();
* var obj = {};
* obj.foo = "Foo";
* obj.bar = "Bar";
* (end)
@ -232,7 +232,7 @@ class mxObjectCodec {
* The argument is created as follows:
*
* (code)
* var mapping = new Object();
* var mapping = {};
* mapping['variableName'] = 'attribute-name';
* (end)
*
@ -252,7 +252,7 @@ class mxObjectCodec {
this.idrefs = (idrefs != null) ? idrefs : [];
this.mapping = (mapping != null) ? mapping : [];
this.reverse = new Object();
this.reverse = {};
for (var i in this.mapping) {
this.reverse[this.mapping[i]] = i;
@ -616,11 +616,11 @@ class mxObjectCodec {
*/
isNumericAttribute = (dec, attr, obj) => {
// Handles known numeric attributes for generic objects
var result = (obj.constructor == mxGeometry &&
(attr.name == 'x' || attr.name == 'y' ||
attr.name == 'width' || attr.name == 'height')) ||
(obj.constructor == mxPoint &&
(attr.name == 'x' || attr.name == 'y')) ||
var result = (obj.constructor === mxGeometry &&
(attr.name === 'x' || attr.name === 'y' ||
attr.name === 'width' || attr.name === 'height')) ||
(obj.constructor === mxPoint &&
(attr.name === 'x' || attr.name === 'y')) ||
mxUtils.isNumeric(attr.value);
return result;
@ -787,7 +787,7 @@ class mxObjectCodec {
* obj - Objec to encode the attribute into.
*/
isIgnoredAttribute = (dec, attr, obj) => {
return attr.nodeName == 'as' || attr.nodeName == 'id';
return attr.nodeName === 'as' || attr.nodeName === 'id';
};
/**
@ -875,7 +875,7 @@ class mxObjectCodec {
var template = this.getFieldTemplate(obj, fieldname, child);
var value = null;
if (child.nodeName == 'add') {
if (child.nodeName === 'add') {
value = child.getAttribute('value');
if (value == null && mxObjectCodec.allowEval) {
@ -925,7 +925,7 @@ class mxObjectCodec {
* override this with the correct code to add an entry to an object.
*/
addObjectValue = (obj, fieldname, value, template) => {
if (value != null && value != template) {
if (value != null && value !== template) {
if (fieldname != null && fieldname.length > 0) {
obj[fieldname] = value;
} else {
@ -949,7 +949,7 @@ class mxObjectCodec {
* into - Optional object to pass-thru to the codec.
*/
processInclude = (dec, node, into) => {
if (node.nodeName == 'include') {
if (node.nodeName === 'include') {
var name = node.getAttribute('name');
if (name != null) {

View File

@ -4,6 +4,7 @@
*/
import mxRootChange from "FIXME";
import mxCodecRegistry from "./mxCodecRegistry";
class mxRootChangeCodec extends mxObjectCodec {
/**

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder
*/
import mxUtils from "../util/mxUtils";
import mxCodecRegistry from "./mxCodecRegistry";
import mxStylesheet from "FIXME";
class mxStylesheetCodec extends mxObjectCodec {
/**
* Variable: allowEval
@ -142,7 +146,7 @@ class mxStylesheetCodec extends mxObjectCodec {
extend + ' not found to extend');
}
style = new Object();
style = {};
}
var entry = node.firstChild;

View File

@ -2,8 +2,11 @@
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
mxCodecRegistry.register(()=>
{
import mxObjectCodec from "FIXME";
import mxTerminalChange from "FIXME";
class mxTerminalChangeCodec extends mxObjectCodec {
/**
* Class: mxTerminalChangeCodec
*
@ -21,22 +24,21 @@ mxCodecRegistry.register(()=>
* - cell
* - terminal
*/
var codec = new mxObjectCodec(new mxTerminalChange(),
['model', 'previous'], ['cell', 'terminal']);
constructor() {
super(new mxTerminalChange(), ['model', 'previous'], ['cell', 'terminal']);
}
/**
* Function: afterDecode
*
* Restores the state by assigning the previous value.
*/
codec.afterDecode = (dec, node, obj)=>
{
afterDecode = (dec, node, obj) => {
obj.previous = obj.terminal;
return obj;
};
}
// Returns the codec into the registry
return codec;
}());
mxCodecRegistry.register(new mxTerminalChangeCodec());
export default mxTerminalChangeCodec;

View File

@ -472,7 +472,7 @@ class mxGraphHierarchyModel {
if (internalNode != null) {
if (seenNodes == null) {
seenNodes = new Object();
seenNodes = {};
}
if (trackAncestors) {

View File

@ -279,7 +279,7 @@ class mxSwimlaneModel {
this.ranksPerGroup = [];
var startNodes = [];
var seen = new Object();
var seen = {};
if (this.roots != null) {
for (var i = 0; i < this.roots.length; i++) {
@ -559,7 +559,7 @@ class mxSwimlaneModel {
if (internalNode != null) {
if (seenNodes == null) {
seenNodes = new Object();
seenNodes = {};
}
if (trackAncestors) {

View File

@ -492,7 +492,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// , the order is given by the weighted sum of the in or out edges,
// depending on whether we're traveling up or down the hierarchy.
var weightedValues = [];
var cellMap = new Object();
var cellMap = {};
for (var i = 0; i < rank.length; i++) {
var currentCell = rank[i];

View File

@ -35,9 +35,9 @@ class mxMinimumCycleRemover extends mxHierarchicalLayoutStage {
*/
execute = (parent) => {
var model = this.layout.getModel();
var seenNodes = new Object();
var seenNodes = {};
var unseenNodesArray = model.vertexMapper.getValues();
var unseenNodes = new Object();
var unseenNodes = {};
for (var i = 0; i < unseenNodesArray.length; i++) {
unseenNodes[unseenNodesArray[i].id] = unseenNodesArray[i];

View File

@ -35,7 +35,7 @@ class mxSwimlaneOrdering extends mxHierarchicalLayoutStage {
*/
execute = (parent) => {
var model = this.layout.getModel();
var seenNodes = new Object();
var seenNodes = {};
var unseenNodes = mxUtils.clone(model.vertexMapper, null, true);
// Perform a dfs through the internal model. If a cycle is found,

View File

@ -291,7 +291,7 @@ class mxCompactTreeLayout extends mxGraphLayout {
if (this.root != null) {
if (this.resizeParent) {
this.parentsChanged = new Object();
this.parentsChanged = {};
} else {
this.parentsChanged = null;
}
@ -312,7 +312,7 @@ class mxCompactTreeLayout extends mxGraphLayout {
model.beginUpdate();
try {
this.visited = new Object();
this.visited = {};
this.node = this.dfs(this.root, parent);
if (this.alignRanks) {
@ -768,7 +768,7 @@ class mxCompactTreeLayout extends mxGraphLayout {
* Function: createNode
*/
createNode = (cell) => {
var node = new Object();
var node = {};
node.cell = cell;
node.x = 0;
node.y = 0;
@ -789,7 +789,7 @@ class mxCompactTreeLayout extends mxGraphLayout {
node.offsetX = 0;
node.offsetY = 0;
node.contour = new Object();
node.contour = {};
return node;
};
@ -834,7 +834,7 @@ class mxCompactTreeLayout extends mxGraphLayout {
* Function: createLine
*/
createLine = (dx, dy, next) => {
var line = new Object();
var line = {};
line.dx = dx;
line.dy = dy;
line.next = next;

View File

@ -646,7 +646,7 @@ class mxGraphModel extends mxEventSource {
// Lazily creates the cells dictionary
if (this.cells == null) {
this.cells = new Object();
this.cells = {};
}
this.cells[cell.getId()] = cell;
@ -1853,7 +1853,7 @@ class mxGraphModel extends mxEventSource {
this.beginUpdate();
try {
var mapping = new Object();
var mapping = {};
this.mergeChildrenImpl(from, to, cloneAllEdges, mapping);
// Post-processes all edges in the mapping and
@ -2000,7 +2000,7 @@ class mxGraphModel extends mxEventSource {
*/
cloneCells = (cells, includeChildren, mapping) => {
includeChildren = (includeChildren != null) ? includeChildren : true;
mapping = (mapping != null) ? mapping : new Object();
mapping = (mapping != null) ? mapping : {};
var clones = [];
for (var i = 0; i < cells.length; i++) {

View File

@ -31,7 +31,7 @@ var mxClipboard =
* cells = cells || graph.getSelectionCells();
* var result = graph.getExportableCells(cells);
*
* mxClipboard.parents = new Object();
* mxClipboard.parents = {};
*
* for (var i = 0; i < result.length; i++)
* {

View File

@ -2,454 +2,427 @@
* Copyright (c) 2006-2020, JGraph Ltd
* Copyright (c) 2006-2020, draw.io AG
*/
/**
* Class: mxXmlRequest
*
* XML HTTP request wrapper. See also: <mxUtils.get>, <mxUtils.post> and
* <mxUtils.load>. This class provides a cross-browser abstraction for Ajax
* requests.
*
* Encoding:
*
* For encoding parameter values, the built-in encodeURIComponent JavaScript
* method must be used. For automatic encoding of post data in <mxEditor> the
* <mxEditor.escapePostData> switch can be set to true (default). The encoding
* will be carried out using the conte type of the page. That is, the page
* containting the editor should contain a meta tag in the header, eg.
* <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
*
* Example:
*
* (code)
* var onload = (req)=>
* {
* mxUtils.alert(req.getDocumentElement());
* }
*
* var onerror = (req)=>
* {
* mxUtils.alert('Error');
* }
* new mxXmlRequest(url, 'key=value').send(onload, onerror);
* (end)
*
* Sends an asynchronous POST request to the specified URL.
*
* Example:
*
* (code)
* var req = new mxXmlRequest(url, 'key=value', 'POST', false);
* req.send();
* mxUtils.alert(req.getDocumentElement());
* (end)
*
* Sends a synchronous POST request to the specified URL.
*
* Example:
*
* (code)
* var encoder = new mxCodec();
* var result = encoder.encode(graph.getModel());
* var xml = encodeURIComponent(mxUtils.getXml(result));
* new mxXmlRequest(url, 'xml='+xml).send();
* (end)
*
* Sends an encoded graph model to the specified URL using xml as the
* parameter name. The parameter can then be retrieved in C# as follows:
*
* (code)
* string xml = HttpUtility.UrlDecode(context.Request.Params["xml"]);
* (end)
*
* Or in Java as follows:
*
* (code)
* String xml = URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "&#xa;");
* (end)
*
* Note that the linefeeds should only be replaced if the XML is
* processed in Java, for example when creating an image.
*
* Constructor: mxXmlRequest
*
* Constructs an XML HTTP request.
*
* Parameters:
*
* url - Target URL of the request.
* params - Form encoded parameters to send with a POST request.
* method - String that specifies the request method. Possible values are
* POST and GET. Default is POST.
* async - Boolean specifying if an asynchronous request should be used.
* Default is true.
* username - String specifying the username to be used for the request.
* password - String specifying the password to be used for the request.
*/
function mxXmlRequest(url, params, method, async, username, password)
{
this.url = url;
this.params = params;
this.method = method || 'POST';
this.async = (async != null) ? async : true;
this.username = username;
this.password = password;
};
/**
* Variable: url
*
* Holds the target URL of the request.
*/
url = null;
class mxXmlRequest {
/**
* Variable: url
*
* Holds the target URL of the request.
*/
url = null;
/**
* Variable: params
*
* Holds the form encoded data for the POST request.
*/
params = null;
/**
* Variable: params
*
* Holds the form encoded data for the POST request.
*/
params = null;
/**
* Variable: method
*
* Specifies the request method. Possible values are POST and GET. Default
* is POST.
*/
method = null;
/**
* Variable: method
*
* Specifies the request method. Possible values are POST and GET. Default
* is POST.
*/
method = null;
/**
* Variable: async
*
* Boolean indicating if the request is asynchronous.
*/
async = null;
/**
* Variable: async
*
* Boolean indicating if the request is asynchronous.
*/
async = null;
/**
* Variable: binary
*
* Boolean indicating if the request is binary. This option is ignored in IE.
* In all other browsers the requested mime type is set to
* text/plain; charset=x-user-defined. Default is false.
*/
binary = false;
/**
* Variable: binary
*
* Boolean indicating if the request is binary. This option is ignored in IE.
* In all other browsers the requested mime type is set to
* text/plain; charset=x-user-defined. Default is false.
*/
binary = false;
/**
* Variable: withCredentials
*
* Specifies if withCredentials should be used in HTML5-compliant browsers. Default is
* false.
*/
withCredentials = false;
/**
* Variable: withCredentials
*
* Specifies if withCredentials should be used in HTML5-compliant browsers. Default is
* false.
*/
withCredentials = false;
/**
* Variable: username
*
* Specifies the username to be used for authentication.
*/
username = null;
/**
* Variable: username
*
* Specifies the username to be used for authentication.
*/
username = null;
/**
* Variable: password
*
* Specifies the password to be used for authentication.
*/
password = null;
/**
* Variable: password
*
* Specifies the password to be used for authentication.
*/
password = null;
/**
* Variable: request
*
* Holds the inner, browser-specific request object.
*/
request = null;
/**
* Variable: request
*
* Holds the inner, browser-specific request object.
*/
request = null;
/**
* Variable: decodeSimulateValues
*
* Specifies if request values should be decoded as URIs before setting the
* textarea value in <simulate>. Defaults to false for backwards compatibility,
* to avoid another decode on the server this should be set to true.
*/
decodeSimulateValues = false;
/**
* Variable: decodeSimulateValues
*
* Specifies if request values should be decoded as URIs before setting the
* textarea value in <simulate>. Defaults to false for backwards compatibility,
* to avoid another decode on the server this should be set to true.
*/
decodeSimulateValues = false;
/**
* Function: isBinary
*
* Returns <binary>.
*/
isBinary = ()=>
{
return this.binary;
};
/**
* Class: mxXmlRequest
*
* XML HTTP request wrapper. See also: <mxUtils.get>, <mxUtils.post> and
* <mxUtils.load>. This class provides a cross-browser abstraction for Ajax
* requests.
*
* Encoding:
*
* For encoding parameter values, the built-in encodeURIComponent JavaScript
* method must be used. For automatic encoding of post data in <mxEditor> the
* <mxEditor.escapePostData> switch can be set to true (default). The encoding
* will be carried out using the conte type of the page. That is, the page
* containting the editor should contain a meta tag in the header, eg.
* <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
*
* Example:
*
* (code)
* var onload = (req)=>
* {
* mxUtils.alert(req.getDocumentElement());
* }
*
* var onerror = (req)=>
* {
* mxUtils.alert('Error');
* }
* new mxXmlRequest(url, 'key=value').send(onload, onerror);
* (end)
*
* Sends an asynchronous POST request to the specified URL.
*
* Example:
*
* (code)
* var req = new mxXmlRequest(url, 'key=value', 'POST', false);
* req.send();
* mxUtils.alert(req.getDocumentElement());
* (end)
*
* Sends a synchronous POST request to the specified URL.
*
* Example:
*
* (code)
* var encoder = new mxCodec();
* var result = encoder.encode(graph.getModel());
* var xml = encodeURIComponent(mxUtils.getXml(result));
* new mxXmlRequest(url, 'xml='+xml).send();
* (end)
*
* Sends an encoded graph model to the specified URL using xml as the
* parameter name. The parameter can then be retrieved in C# as follows:
*
* (code)
* string xml = HttpUtility.UrlDecode(context.Request.Params["xml"]);
* (end)
*
* Or in Java as follows:
*
* (code)
* String xml = URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "&#xa;");
* (end)
*
* Note that the linefeeds should only be replaced if the XML is
* processed in Java, for example when creating an image.
*
* Constructor: mxXmlRequest
*
* Constructs an XML HTTP request.
*
* Parameters:
*
* url - Target URL of the request.
* params - Form encoded parameters to send with a POST request.
* method - String that specifies the request method. Possible values are
* POST and GET. Default is POST.
* async - Boolean specifying if an asynchronous request should be used.
* Default is true.
* username - String specifying the username to be used for the request.
* password - String specifying the password to be used for the request.
*/
constructor(url, params, method, async, username, password) {
this.url = url;
this.params = params;
this.method = method || 'POST';
this.async = (async != null) ? async : true;
this.username = username;
this.password = password;
};
/**
* Function: setBinary
*
* Sets <binary>.
*/
setBinary = (value)=>
{
this.binary = value;
};
/**
* Function: isBinary
*
* Returns <binary>.
*/
isBinary = () => {
return this.binary;
};
/**
* Function: getText
*
* Returns the response as a string.
*/
getText = ()=>
{
return this.request.responseText;
};
/**
* Function: setBinary
*
* Sets <binary>.
*/
setBinary = (value) => {
this.binary = value;
};
/**
* Function: isReady
*
* Returns true if the response is ready.
*/
isReady = ()=>
{
return this.request.readyState == 4;
};
/**
* Function: getText
*
* Returns the response as a string.
*/
getText = () => {
return this.request.responseText;
};
/**
* Function: getDocumentElement
*
* Returns the document element of the response XML document.
*/
getDocumentElement = ()=>
{
var doc = this.getXml();
/**
* Function: isReady
*
* Returns true if the response is ready.
*/
isReady = () => {
return this.request.readyState == 4;
};
if (doc != null)
{
return doc.documentElement;
}
/**
* Function: getDocumentElement
*
* Returns the document element of the response XML document.
*/
getDocumentElement = () => {
var doc = this.getXml();
return null;
};
if (doc != null) {
return doc.documentElement;
}
/**
* Function: getXml
*
* Returns the response as an XML document. Use <getDocumentElement> to get
* the document element of the XML document.
*/
getXml = ()=>
{
var xml = this.request.responseXML;
return null;
};
// Handles missing response headers in IE, the first condition handles
// the case where responseXML is there, but using its nodes leads to
// type errors in the mxCellCodec when putting the nodes into a new
// document. This happens in IE9 standards mode and with XML user
// objects only, as they are used directly as values in cells.
if (xml == null || xml.documentElement == null)
{
xml = mxUtils.parseXml(this.request.responseText);
}
/**
* Function: getXml
*
* Returns the response as an XML document. Use <getDocumentElement> to get
* the document element of the XML document.
*/
getXml = () => {
var xml = this.request.responseXML;
return xml;
};
// Handles missing response headers in IE, the first condition handles
// the case where responseXML is there, but using its nodes leads to
// type errors in the mxCellCodec when putting the nodes into a new
// document. This happens in IE9 standards mode and with XML user
// objects only, as they are used directly as values in cells.
if (xml == null || xml.documentElement == null) {
xml = mxUtils.parseXml(this.request.responseText);
}
/**
* Function: getStatus
*
* Returns the status as a number, eg. 404 for "Not found" or 200 for "OK".
* Note: The NS_ERROR_NOT_AVAILABLE for invalid responses cannot be cought.
*/
getStatus = ()=>
{
return (this.request != null) ? this.request.status : null;
};
return xml;
};
/**
* Function: create
*
* Creates and returns the inner <request> object.
*/
create = ()=>
{
if (window.XMLHttpRequest)
{
return ()=>
{
var req = new XMLHttpRequest();
/**
* Function: getStatus
*
* Returns the status as a number, eg. 404 for "Not found" or 200 for "OK".
* Note: The NS_ERROR_NOT_AVAILABLE for invalid responses cannot be cought.
*/
getStatus = () => {
return (this.request != null) ? this.request.status : null;
};
// TODO: Check for overrideMimeType required here?
if (this.isBinary() && req.overrideMimeType)
{
req.overrideMimeType('text/plain; charset=x-user-defined');
}
/**
* Function: create
*
* Creates and returns the inner <request> object.
*/
create = () => {
if (window.XMLHttpRequest) {
return () => {
var req = new XMLHttpRequest();
return req;
};
}
else if (typeof(ActiveXObject) != 'undefined')
{
return ()=>
{
// TODO: Implement binary option
return new ActiveXObject('Microsoft.XMLHTTP');
};
}
}();
/**
* Function: send
*
* Send the <request> to the target URL using the specified functions to
* process the response asychronously.
*
* Note: Due to technical limitations, onerror is currently ignored.
*
* Parameters:
*
* onload - Function to be invoked if a successful response was received.
* onerror - Function to be called on any error. Unused in this implementation, intended for overriden function.
* timeout - Optional timeout in ms before calling ontimeout.
* ontimeout - Optional function to execute on timeout.
*/
send = (onload, onerror, timeout, ontimeout)=>
{
this.request = this.create();
if (this.request != null)
{
if (onload != null)
{
this.request.onreadystatechange = mxUtils.bind(this, ()=>
{
if (this.isReady())
{
onload(this);
this.request.onreadystatechange = null;
// TODO: Check for overrideMimeType required here?
if (this.isBinary() && req.overrideMimeType) {
req.overrideMimeType('text/plain; charset=x-user-defined');
}
});
return req;
};
} else if (typeof (ActiveXObject) != 'undefined') {
return () => {
// TODO: Implement binary option
return new ActiveXObject('Microsoft.XMLHTTP');
};
}
this.request.open(this.method, this.url, this.async,
this.username, this.password);
this.setRequestHeaders(this.request, this.params);
if (window.XMLHttpRequest && this.withCredentials)
{
this.request.withCredentials = 'true';
}
if ((document.documentMode == null) &&
window.XMLHttpRequest && timeout != null && ontimeout != null)
{
this.request.timeout = timeout;
this.request.ontimeout = ontimeout;
}
this.request.send(this.params);
}
};
()
;
/**
* Function: setRequestHeaders
*
* Sets the headers for the given request and parameters. This sets the
* content-type to application/x-www-form-urlencoded if any params exist.
*
* Example:
*
* (code)
* request.setRequestHeaders = (request, params)=>
* {
* if (params != null)
* {
* request.setRequestHeader('Content-Type',
* 'multipart/form-data');
* request.setRequestHeader('Content-Length',
* params.length);
* }
* };
* (end)
*
* Use the code above before calling <send> if you require a
* multipart/form-data request.
*/
setRequestHeaders = (request, params)=>
{
if (params != null)
{
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
};
/**
* Function: send
*
* Send the <request> to the target URL using the specified functions to
* process the response asychronously.
*
* Note: Due to technical limitations, onerror is currently ignored.
*
* Parameters:
*
* onload - Function to be invoked if a successful response was received.
* onerror - Function to be called on any error. Unused in this implementation, intended for overriden function.
* timeout - Optional timeout in ms before calling ontimeout.
* ontimeout - Optional function to execute on timeout.
*/
send = (onload, onerror, timeout, ontimeout) => {
this.request = this.create();
/**
* Function: simulate
*
* Creates and posts a request to the given target URL using a dynamically
* created form inside the given document.
*
* Parameters:
*
* docs - Document that contains the form element.
* target - Target to send the form result to.
*/
simulate = (doc, target)=>
{
doc = doc || document;
var old = null;
if (doc == document)
{
old = window.onbeforeunload;
window.onbeforeunload = null;
}
var form = doc.createElement('form');
form.setAttribute('method', this.method);
form.setAttribute('action', this.url);
if (target != null)
{
form.setAttribute('target', target);
}
form.style.display = 'none';
form.style.visibility = 'hidden';
var pars = (this.params.indexOf('&') > 0) ?
this.params.split('&') :
this.params.split();
// Adds the parameters as textareas to the form
for (var i=0; i<pars.length; i++)
{
var pos = pars[i].indexOf('=');
if (pos > 0)
{
var name = pars[i].substring(0, pos);
var value = pars[i].substring(pos+1);
if (this.decodeSimulateValues)
{
value = decodeURIComponent(value);
if (this.request != null) {
if (onload != null) {
this.request.onreadystatechange = mxUtils.bind(this, () => {
if (this.isReady()) {
onload(this);
this.request.onreadystatechange = null;
}
});
}
var textarea = doc.createElement('textarea');
textarea.setAttribute('wrap', 'off');
textarea.setAttribute('name', name);
mxUtils.write(textarea, value);
form.appendChild(textarea);
this.request.open(this.method, this.url, this.async,
this.username, this.password);
this.setRequestHeaders(this.request, this.params);
if (window.XMLHttpRequest && this.withCredentials) {
this.request.withCredentials = 'true';
}
if ((document.documentMode == null) &&
window.XMLHttpRequest && timeout != null && ontimeout != null) {
this.request.timeout = timeout;
this.request.ontimeout = ontimeout;
}
this.request.send(this.params);
}
}
};
doc.body.appendChild(form);
form.submit();
/**
* Function: setRequestHeaders
*
* Sets the headers for the given request and parameters. This sets the
* content-type to application/x-www-form-urlencoded if any params exist.
*
* Example:
*
* (code)
* request.setRequestHeaders = (request, params)=>
* {
* if (params != null)
* {
* request.setRequestHeader('Content-Type',
* 'multipart/form-data');
* request.setRequestHeader('Content-Length',
* params.length);
* }
* };
* (end)
*
* Use the code above before calling <send> if you require a
* multipart/form-data request.
*/
setRequestHeaders = (request, params) => {
if (params != null) {
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
};
if (form.parentNode != null)
{
form.parentNode.removeChild(form);
}
/**
* Function: simulate
*
* Creates and posts a request to the given target URL using a dynamically
* created form inside the given document.
*
* Parameters:
*
* docs - Document that contains the form element.
* target - Target to send the form result to.
*/
simulate = (doc, target) => {
doc = doc || document;
var old = null;
if (old != null)
{
window.onbeforeunload = old;
}
};
if (doc == document) {
old = window.onbeforeunload;
window.onbeforeunload = null;
}
var form = doc.createElement('form');
form.setAttribute('method', this.method);
form.setAttribute('action', this.url);
if (target != null) {
form.setAttribute('target', target);
}
form.style.display = 'none';
form.style.visibility = 'hidden';
var pars = (this.params.indexOf('&') > 0) ?
this.params.split('&') :
this.params.split();
// Adds the parameters as textareas to the form
for (var i = 0; i < pars.length; i++) {
var pos = pars[i].indexOf('=');
if (pos > 0) {
var name = pars[i].substring(0, pos);
var value = pars[i].substring(pos + 1);
if (this.decodeSimulateValues) {
value = decodeURIComponent(value);
}
var textarea = doc.createElement('textarea');
textarea.setAttribute('wrap', 'off');
textarea.setAttribute('name', name);
mxUtils.write(textarea, value);
form.appendChild(textarea);
}
}
doc.body.appendChild(form);
form.submit();
if (form.parentNode != null) {
form.parentNode.removeChild(form);
}
if (old != null) {
window.onbeforeunload = old;
}
};
}
export default mxXmlRequest;

View File

@ -41,7 +41,7 @@ function mxCellRenderer() { };
* known to all instances of this class. For adding new shapes you should
* use the static <mxCellRenderer.registerShape> function.
*/
mxCellRenderer.defaultShapes = new Object();
mxCellRenderer.defaultShapes = {};
/**
* Variable: defaultEdgeShape

View File

@ -199,7 +199,7 @@
* shapename and the stylename we'll use boxstyle for the stylename:
*
* (code)
* var style = new Object();
* var style = {};
* style[mxConstants.STYLE_SHAPE] = 'box';
* style[mxConstants.STYLE_STROKECOLOR] = '#000000';
* style[mxConstants.STYLE_FONTCOLOR] = '#000000';
@ -3325,7 +3325,7 @@ getCellStyle = (cell)=>
// Returns a non-null value if no style can be found
if (style == null)
{
style = new Object();
style = {};
}
return style;
@ -8690,7 +8690,7 @@ validateEdge = (edge, source, target)=>
validateGraph = (cell, context)=>
{
cell = (cell != null) ? cell : this.model.getRoot();
context = (context != null) ? context : new Object();
context = (context != null) ? context : {};
var isValid = true;
var childCount = this.model.getChildCount(cell);
@ -8702,7 +8702,7 @@ validateGraph = (cell, context)=>
if (this.isValidRoot(tmp))
{
ctx = new Object();
ctx = {};
}
var warn = this.validateGraph(tmp, ctx);

View File

@ -53,7 +53,7 @@
*/
function mxStylesheet()
{
this.styles = new Object();
this.styles = {};
this.putDefaultVertexStyle(this.createDefaultVertexStyle());
this.putDefaultEdgeStyle(this.createDefaultEdgeStyle());
@ -75,7 +75,7 @@ FIXME;
*/
createDefaultVertexStyle = ()=>
{
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
@ -95,7 +95,7 @@ createDefaultVertexStyle = ()=>
*/
createDefaultEdgeStyle = ()=>
{
var style = new Object();
var style = {};
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_CONNECTOR;
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
@ -163,7 +163,7 @@ getDefaultEdgeStyle = ()=>
* existing stylesheet:
*
* (code)
* var style = new Object();
* var style = {};
* style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
* style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
* style[mxConstants.STYLE_ROUNDED] = true;
@ -220,7 +220,7 @@ getCellStyle = (name, defaultStyle)=>
}
else
{
style = new Object();
style = {};
}
// Parses each key, value pair into the existing style