From 8fe52f410698e5bbea995c5141d28dd245f57454 Mon Sep 17 00:00:00 2001 From: mcyph <20507948+mcyph@users.noreply.github.com> Date: Fri, 26 Mar 2021 13:26:24 +1100 Subject: [PATCH] cleanups and bugfixes --- src/mxgraph/handler/mxGraphHandler.js | 6 +- .../stage/mxMedianHybridCrossingReduction.js | 14 - src/mxgraph/util/mxGuide.js | 2 + src/pages/ContextIcons.js | 267 ++++++++---------- src/pages/Control.js | 24 +- src/pages/DragSource.js | 82 ++++-- src/pages/Overlays.js | 40 +-- src/pages/examplesListing.json | 138 ++++----- 8 files changed, 293 insertions(+), 280 deletions(-) diff --git a/src/mxgraph/handler/mxGraphHandler.js b/src/mxgraph/handler/mxGraphHandler.js index 89cdd1361..5e3aca31c 100644 --- a/src/mxgraph/handler/mxGraphHandler.js +++ b/src/mxgraph/handler/mxGraphHandler.js @@ -789,6 +789,10 @@ class mxGraphHandler { return shape; } + createGuide() { + return new mxGuide(this.graph, this.getGuideStates()); + } + /** * Function: start * @@ -809,7 +813,7 @@ class mxGraphHandler { } if (this.guidesEnabled) { - this.guide = new mxGuide(this.graph, this.getGuideStates()); + this.guide = this.createGuide(); const parent = this.graph.model.getParent(cell); const ignore = this.graph.model.getChildCount(parent) < 2; diff --git a/src/mxgraph/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js b/src/mxgraph/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js index bc15cac4d..d80ea5b3e 100644 --- a/src/mxgraph/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js +++ b/src/mxgraph/layout/hierarchical/stage/mxMedianHybridCrossingReduction.js @@ -63,20 +63,6 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage { */ function; - /** - * Variable: medianValue - * - * The weighted value of the cell stored. - */ - medianValue = 0; - - /** - * Variable: cell - * - * The cell whose median value is being calculated - */ - cell = false; - /** * Class: mxMedianHybridCrossingReduction * diff --git a/src/mxgraph/util/mxGuide.js b/src/mxgraph/util/mxGuide.js index c754be7c6..e5ba1074f 100644 --- a/src/mxgraph/util/mxGuide.js +++ b/src/mxgraph/util/mxGuide.js @@ -4,6 +4,8 @@ * Updated to ES9 syntax by David Morrissey 2021 */ import mxConstants from './mxConstants'; +import mxPoint from "./mxPoint"; +import mxPolyline from "../shape/mxPolyline"; /** * Class: mxGuide diff --git a/src/pages/ContextIcons.js b/src/pages/ContextIcons.js index da8280275..66447e610 100644 --- a/src/pages/ContextIcons.js +++ b/src/pages/ContextIcons.js @@ -39,82 +39,67 @@ class ContextIcons extends React.Component { }; componentDidMount = () => { - // Defines a subclass for mxVertexHandler that adds a set of clickable - // icons to every selected vertex. - function mxVertexToolHandler(state) { - mxVertexHandler.apply(this, arguments); - } + class mxVertexToolHandler extends mxVertexHandler { + // Defines a subclass for mxVertexHandler that adds a set of clickable + // icons to every selected vertex. - mxVertexToolHandler.prototype = new mxVertexHandler(); - mxVertexToolHandler.prototype.constructor = mxVertexToolHandler; + domNode = null; - mxVertexToolHandler.prototype.domNode = null; + init() { + super.init(); - mxVertexToolHandler.prototype.init = function() { - mxVertexHandler.prototype.init.apply(this, arguments); + // In this example we force the use of DIVs for images in IE. This + // handles transparency in PNG images properly in IE and fixes the + // problem that IE routes all mouse events for a gesture via the + // initial IMG node, which means the target vertices + this.domNode = document.createElement('div'); + this.domNode.style.position = 'absolute'; + this.domNode.style.whiteSpace = 'nowrap'; - // In this example we force the use of DIVs for images in IE. This - // handles transparency in PNG images properly in IE and fixes the - // problem that IE routes all mouse events for a gesture via the - // initial IMG node, which means the target vertices - this.domNode = document.createElement('div'); - this.domNode.style.position = 'absolute'; - this.domNode.style.whiteSpace = 'nowrap'; + // Workaround for event redirection via image tag in quirks and IE8 + const createImage = src => { + return mxUtils.createImage(src); + }; - // Workaround for event redirection via image tag in quirks and IE8 - function createImage(src) { - return mxUtils.createImage(src); - } - - // Delete - let img = createImage('images/delete2.png'); - img.setAttribute('title', 'Delete'); - img.style.cursor = 'pointer'; - img.style.width = '16px'; - img.style.height = '16px'; - mxEvent.addGestureListeners( - img, - mxUtils.bind(this, function(evt) { + // Delete + let img = createImage('images/delete2.png'); + img.setAttribute('title', 'Delete'); + img.style.cursor = 'pointer'; + img.style.width = '16px'; + img.style.height = '16px'; + mxEvent.addGestureListeners(img, evt => { // Disables dragging the image mxEvent.consume(evt); - }) - ); - mxEvent.addListener( - img, - 'click', - mxUtils.bind(this, function(evt) { + }); + mxEvent.addListener(img, 'click', evt => { this.graph.removeCells([this.state.cell]); mxEvent.consume(evt); - }) - ); - this.domNode.appendChild(img); + }); + this.domNode.appendChild(img); - // Size - img = createImage('images/fit_to_size.png'); - img.setAttribute('title', 'Resize'); - img.style.cursor = 'se-resize'; - img.style.width = '16px'; - img.style.height = '16px'; - mxEvent.addGestureListeners( - img, - mxUtils.bind(this, function(evt) { + // Size + img = createImage('images/fit_to_size.png'); + img.setAttribute('title', 'Resize'); + img.style.cursor = 'se-resize'; + img.style.width = '16px'; + img.style.height = '16px'; + + mxEvent.addGestureListeners(img, evt => { this.start(mxEvent.getClientX(evt), mxEvent.getClientY(evt), 7); this.graph.isMouseDown = true; this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt); mxEvent.consume(evt); - }) - ); - this.domNode.appendChild(img); + }); + this.domNode.appendChild(img); - // Move - img = createImage('images/plus.png'); - img.setAttribute('title', 'Move'); - img.style.cursor = 'move'; - img.style.width = '16px'; - img.style.height = '16px'; - mxEvent.addGestureListeners( - img, - mxUtils.bind(this, function(evt) { + // Move + img = createImage('images/plus.png'); + img.setAttribute('title', 'Move'); + img.style.cursor = 'move'; + img.style.width = '16px'; + img.style.height = '16px'; + + mxEvent.addGestureListeners(img, evt => { this.graph.graphHandler.start( this.state.cell, mxEvent.getClientX(evt), @@ -124,19 +109,17 @@ class ContextIcons extends React.Component { this.graph.isMouseDown = true; this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt); mxEvent.consume(evt); - }) - ); - this.domNode.appendChild(img); + }); + this.domNode.appendChild(img); - // Connect - img = createImage('images/check.png'); - img.setAttribute('title', 'Connect'); - img.style.cursor = 'pointer'; - img.style.width = '16px'; - img.style.height = '16px'; - mxEvent.addGestureListeners( - img, - mxUtils.bind(this, function(evt) { + // Connect + img = createImage('images/check.png'); + img.setAttribute('title', 'Connect'); + img.style.cursor = 'pointer'; + img.style.width = '16px'; + img.style.height = '16px'; + + mxEvent.addGestureListeners(img, evt => { const pt = mxUtils.convertPoint( this.graph.container, mxEvent.getClientX(evt), @@ -146,89 +129,81 @@ class ContextIcons extends React.Component { this.graph.isMouseDown = true; this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt); mxEvent.consume(evt); - }) - ); - this.domNode.appendChild(img); + }); + this.domNode.appendChild(img); - this.graph.container.appendChild(this.domNode); - this.redrawTools(); - }; - - mxVertexToolHandler.prototype.redraw = function() { - mxVertexHandler.prototype.redraw.apply(this); - this.redrawTools(); - }; - - mxVertexToolHandler.prototype.redrawTools = function() { - if (this.state != null && this.domNode != null) { - const dy = 4; - this.domNode.style.left = `${this.state.x + this.state.width - 56}px`; - this.domNode.style.top = `${this.state.y + this.state.height + dy}px`; + this.graph.container.appendChild(this.domNode); + this.redrawTools(); } - }; - mxVertexToolHandler.prototype.destroy = function(sender, me) { - mxVertexHandler.prototype.destroy.apply(this, arguments); - - if (this.domNode != null) { - this.domNode.parentNode.removeChild(this.domNode); - this.domNode = null; + redraw() { + super.redraw(); + this.redrawTools(); } - }; - // Program starts here. Creates a sample graph in the - // DOM node with the specified ID. This function is invoked - // from the onLoad event handler of the document (see below). - function main(container) { - // Checks if the browser is supported - if (!mxClient.isBrowserSupported()) { - // Displays an error message if the browser is not supported. - mxUtils.error('Browser is not supported!', 200, false); - } else { - // Creates the graph inside the given container - const graph = new mxGraph(container); - graph.setConnectable(true); - graph.connectionHandler.createTarget = true; + redrawTools() { + if (this.state != null && this.domNode != null) { + const dy = 4; + this.domNode.style.left = `${this.state.x + this.state.width - 56}px`; + this.domNode.style.top = `${this.state.y + this.state.height + dy}px`; + } + } - graph.createHandler = function(state) { - if (state != null && this.model.isVertex(state.cell)) { - return new mxVertexToolHandler(state); - } + destroy(sender, me) { + super.destroy(sender, me); - return mxGraph.prototype.createHandler.apply(this, arguments); - }; - - // Uncomment the following if you want the container - // to fit the size of the graph - // graph.setResizeContainer(true); - - // Enables rubberband selection - new mxRubberband(graph); - - // Gets the default parent for inserting new cells. This - // is normally the first child of the root (ie. layer 0). - const parent = graph.getDefaultParent(); - - // Adds cells to the model in a single step - graph.getModel().beginUpdate(); - try { - const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); - const v2 = graph.insertVertex( - parent, - null, - 'World!', - 200, - 150, - 80, - 30 - ); - const e1 = graph.insertEdge(parent, null, '', v1, v2); - } finally { - // Updates the display - graph.getModel().endUpdate(); + if (this.domNode != null) { + this.domNode.parentNode.removeChild(this.domNode); + this.domNode = null; } } } + + class MyCustomGraph extends mxGraph { + createHandler(state) { + if (state != null && this.model.isVertex(state.cell)) { + return new mxVertexToolHandler(state); + } + return super.createHandler(state); + } + } + + // Creates the graph inside the given container + const graph = new MyCustomGraph(this.el); + graph.setConnectable(true); + graph.connectionHandler.createTarget = true; + + // Uncomment the following if you want the container + // to fit the size of the graph + // graph.setResizeContainer(true); + + // Enables rubberband selection + new mxRubberband(graph); + + // Gets the default parent for inserting new cells. This + // is normally the first child of the root (ie. layer 0). + const parent = graph.getDefaultParent(); + + // Adds cells to the model in a single step + graph.batchUpdate(() => { + const v1 = graph.insertVertex({ + parent, + value: 'Hello,', + position: [20, 20], + size: [80, 30], + }); + const v2 = graph.insertVertex({ + parent, + value: 'World!', + position: [200, 150], + size: [80, 30], + }); + const e1 = graph.insertEdge({ + parent, + source: v1, + target: v2, + }); + }); }; } diff --git a/src/pages/Control.js b/src/pages/Control.js index 9389bd712..9968422f1 100644 --- a/src/pages/Control.js +++ b/src/pages/Control.js @@ -162,9 +162,23 @@ class Control extends React.Component { // Adds cells to the model in a single step graph.getModel().beginUpdate(); try { - const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); - const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30); - const e1 = graph.insertEdge(parent, null, '', v1, v2); + const v1 = graph.insertVertex({ + parent, + value: 'Hello,', + position: [20, 20], + size: [80, 30], + }); + const v2 = graph.insertVertex({ + parent, + value: 'World!', + position: [200, 150], + size: [80, 30], + }); + const e1 = graph.insertEdge({ + parent, + source: v1, + target: v2, + }); } finally { // Updates the display graph.getModel().endUpdate(); @@ -173,13 +187,13 @@ class Control extends React.Component { graph.centerZoom = false; this.el2.appendChild( - mxUtils.button('Zoom In', function() { + mxUtils.button('Zoom In', () => { graph.zoomIn(); }) ); this.el2.appendChild( - mxUtils.button('Zoom Out', function() { + mxUtils.button('Zoom Out', () => { graph.zoomOut(); }) ); diff --git a/src/pages/DragSource.js b/src/pages/DragSource.js index f3f655311..871622820 100644 --- a/src/pages/DragSource.js +++ b/src/pages/DragSource.js @@ -38,16 +38,36 @@ class DragSource extends React.Component { }; componentDidMount = () => { - // Enables guides - mxGraphHandler.prototype.guidesEnabled = true; + class MyCustomGuide extends mxGuide { + isEnabledForEvent(evt) { + // Alt disables guides + return !mxEvent.isAltDown(evt); + } + } - // Alt disables guides - mxGuide.prototype.isEnabledForEvent = function(evt) { - return !mxEvent.isAltDown(evt); - }; + class MyCustomGraphHandler extends mxGraphHandler { + // Enables guides + guidesEnabled = true; - // Enables snapping waypoints to terminals - mxEdgeHandler.prototype.snapToTerminals = true; + createGuide() { + return new MyCustomGuide(this.graph, this.getGuideStates()); + } + } + + class MyCustomEdgeHandler extends mxEdgeHandler { + // Enables snapping waypoints to terminals + snapToTerminals = true; + } + + class MyCustomGraph extends mxGraph { + createGraphHandler() { + return new MyCustomGraphHandler(this); + } + + createEdgeHandler(state, edgeStyle) { + return new MyCustomEdgeHandler(state, edgeStyle); + } + } const graphs = []; @@ -63,7 +83,7 @@ class DragSource extends React.Component { this.el.appendChild(container); - var graph = new mxGraph(container); + const graph = new MyCustomGraph(container); graph.gridSize = 30; // Uncomment the following if you want the container @@ -78,28 +98,38 @@ class DragSource extends React.Component { const parent = graph.getDefaultParent(); // Adds cells to the model in a single step - graph.getModel().beginUpdate(); - try { - const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); - const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30); - const e1 = graph.insertEdge(parent, null, '', v1, v2); - } finally { - // Updates the display - graph.getModel().endUpdate(); - } + graph.batchUpdate(() => { + const v1 = graph.insertVertex({ + parent, + value: 'Hello,', + position: [20, 20], + size: [80, 30], + }); + const v2 = graph.insertVertex({ + parent, + value: 'World!', + position: [200, 150], + size: [80, 30], + }); + const e1 = graph.insertEdge({ + parent, + source: v1, + target: v2, + }); + }); graphs.push(graph); } // Returns the graph under the mouse - const graphF = function(evt) { + const graphF = evt => { const x = mxEvent.getClientX(evt); const y = mxEvent.getClientY(evt); const elt = document.elementFromPoint(x, y); - for (let i = 0; i < graphs.length; i++) { - if (mxUtils.isAncestorNode(graphs[i].container, elt)) { - return graphs[i]; + for (const graph of graphs) { + if (mxUtils.isAncestorNode(graph.container, elt)) { + return graph; } } @@ -107,7 +137,7 @@ class DragSource extends React.Component { }; // Inserts a cell at the given location - const funct = function(graph, evt, target, x, y) { + const funct = (graph, evt, target, x, y) => { const cell = new mxCell('Test', new mxGeometry(0, 0, 120, 40)); cell.vertex = true; const cells = graph.importCells([cell], x, y, target); @@ -141,14 +171,14 @@ class DragSource extends React.Component { dragElt, null, null, - graph.autoscroll, + graphs[0].autoscroll, true ); // Redirects feature to global switch. Note that this feature should only be used // if the the x and y arguments are used in funct to insert the cell. - ds.isGuidesEnabled = function() { - return graph.graphHandler.guidesEnabled; + ds.isGuidesEnabled = () => { + return graphs[0].graphHandler.guidesEnabled; }; // Restores original drag icon while outside of graph diff --git a/src/pages/Overlays.js b/src/pages/Overlays.js index c14008bb5..d5ed6618c 100644 --- a/src/pages/Overlays.js +++ b/src/pages/Overlays.js @@ -53,7 +53,7 @@ class Overlays extends React.Component { // Installs a handler for click events in the graph // that toggles the overlay for the respective cell - graph.addListener(mxEvent.CLICK, function(sender, evt) { + graph.addListener(mxEvent.CLICK, (sender, evt) => { const cell = evt.getProperty('cell'); if (cell != null) { @@ -67,7 +67,7 @@ class Overlays extends React.Component { ); // Installs a handler for clicks on the overlay - overlay.addListener(mxEvent.CLICK, function(sender, evt2) { + overlay.addListener(mxEvent.CLICK, (sender, evt2) => { mxUtils.alert('Overlay clicked'); }); @@ -81,7 +81,7 @@ class Overlays extends React.Component { // Installs a handler for double click events in the graph // that shows an alert box - graph.addListener(mxEvent.DOUBLE_CLICK, function(sender, evt) { + graph.addListener(mxEvent.DOUBLE_CLICK, (sender, evt) => { const cell = evt.getProperty('cell'); mxUtils.alert(`Doubleclick: ${cell != null ? 'Cell' : 'Graph'}`); evt.consume(); @@ -92,23 +92,25 @@ class Overlays extends React.Component { const parent = graph.getDefaultParent(); // Adds cells to the model in a single step - graph.getModel().beginUpdate(); - try { - const v1 = graph.insertVertex(parent, null, 'Click,', 20, 20, 60, 40); - const v2 = graph.insertVertex( + graph.batchUpdate(() => { + const v1 = graph.insertVertex({ parent, - null, - 'Doubleclick', - 200, - 150, - 100, - 40 - ); - const e1 = graph.insertEdge(parent, null, '', v1, v2); - } finally { - // Updates the display - graph.getModel().endUpdate(); - } + value: 'Click,', + position: [20, 20], + size: [60, 40], + }); + const v2 = graph.insertVertex({ + parent, + value: 'Doubleclick', + position: [200, 150], + size: [100, 40], + }); + const e1 = graph.insertEdge({ + parent, + source: v1, + target: v2, + }); + }); } } diff --git a/src/pages/examplesListing.json b/src/pages/examplesListing.json index edf8c359f..138c82a92 100644 --- a/src/pages/examplesListing.json +++ b/src/pages/examplesListing.json @@ -1,73 +1,73 @@ { - "Morph": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxMorphing from '../mxgraph/util/mxMorphing';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Morph extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Morph

\n This example demonstrates using\n mxMorphing for simple cell animations.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n var v2;\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n let mult = 1;\n\n this.el2.appendChild(\n mxUtils.button('Morph', function() {\n graph.clearSelection();\n\n graph.getModel().beginUpdate();\n try {\n let geo = graph.getCellGeometry(v1);\n geo = geo.clone();\n geo.x += 180 * mult;\n graph.getModel().setGeometry(v1, geo);\n\n geo = graph.getCellGeometry(v2);\n geo = geo.clone();\n geo.x -= 180 * mult;\n graph.getModel().setGeometry(v2, geo);\n } finally {\n // Arguments are number of steps, ease and delay\n const morph = new mxMorphing(graph, 20, 1.2, 20);\n morph.addListener(mxEvent.DONE, function() {\n graph.getModel().endUpdate();\n });\n morph.startAnimation();\n }\n\n mult *= -1;\n })\n );\n }\n}\n\nexport default Morph;\n", - "FixedPoints": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstraintHandler from '../mxgraph/handler/mxConstraintHandler';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCellState from '../mxgraph/view/mxCellState';\n\nclass FixedPoints extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Fixed points

\n This example demonstrates using\n fixed connection points for connecting edges to vertices.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Snaps to fixed points\n mxConstraintHandler.prototype.intersects = function(\n icon,\n point,\n source,\n existingEdge\n ) {\n return !source || existingEdge || mxUtils.intersects(icon.bounds, point);\n };\n\n // Special case: Snaps source of new connections to fixed points\n // Without a connect preview in connectionHandler.createEdgeState mouseMove\n // and getSourcePerimeterPoint should be overriden by setting sourceConstraint\n // sourceConstraint to null in mouseMove and updating it and returning the\n // nearest point (cp) in getSourcePerimeterPoint (see below)\n const mxConnectionHandlerUpdateEdgeState =\n mxConnectionHandler.prototype.updateEdgeState;\n mxConnectionHandler.prototype.updateEdgeState = function(pt, constraint) {\n if (pt != null && this.previous != null) {\n const constraints = this.graph.getAllConnectionConstraints(\n this.previous\n );\n let nearestConstraint = null;\n let dist = null;\n\n for (let i = 0; i < constraints.length; i++) {\n const cp = this.graph.getConnectionPoint(\n this.previous,\n constraints[i]\n );\n\n if (cp != null) {\n const tmp =\n (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);\n\n if (dist == null || tmp < dist) {\n nearestConstraint = constraints[i];\n dist = tmp;\n }\n }\n }\n\n if (nearestConstraint != null) {\n this.sourceConstraint = nearestConstraint;\n }\n\n // In case the edge style must be changed during the preview:\n // this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';\n // And to use the new edge style in the new edge inserted into the graph,\n // update the cell style as follows:\n // this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);\n }\n\n mxConnectionHandlerUpdateEdgeState.apply(this, arguments);\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // graph.connectionHandler.connectImage = new mxImage('images/connector.gif', 16, 16);\n\n // Disables floating connections (only use with no connect image)\n if (graph.connectionHandler.connectImage == null) {\n graph.connectionHandler.isConnectableCell = function(cell) {\n return false;\n };\n mxEdgeHandler.prototype.isConnectableCell = function(cell) {\n return graph.connectionHandler.isConnectableCell(cell);\n };\n }\n\n graph.getAllConnectionConstraints = function(terminal) {\n if (terminal != null && this.model.isVertex(terminal.cell)) {\n return [\n new mxConnectionConstraint(new mxPoint(0, 0), true),\n new mxConnectionConstraint(new mxPoint(0.5, 0), true),\n new mxConnectionConstraint(new mxPoint(1, 0), true),\n new mxConnectionConstraint(new mxPoint(0, 0.5), true),\n new mxConnectionConstraint(new mxPoint(1, 0.5), true),\n new mxConnectionConstraint(new mxPoint(0, 1), true),\n new mxConnectionConstraint(new mxPoint(0.5, 1), true),\n new mxConnectionConstraint(new mxPoint(1, 1), true),\n ];\n }\n\n return null;\n };\n\n // Connect preview\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(\n null,\n null,\n null,\n null,\n null,\n 'edgeStyle=orthogonalEdgeStyle'\n );\n\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 60,\n 'shape=triangle;perimeter=trianglePerimeter'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 200,\n 150,\n 80,\n 60,\n 'shape=ellipse;perimeter=ellipsePerimeter'\n );\n const v3 = graph.insertVertex(parent, null, 'Hello,', 200, 20, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=elbowEdgeStyle;elbow=horizontal;' +\n 'exitX=0.5;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v3,\n v2,\n 'edgeStyle=elbowEdgeStyle;elbow=horizontal;orthogonal=0;' +\n 'entryX=0;entryY=0;entryPerimeter=1;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Use this code to snap the source point for new connections without a connect preview,\n // ie. without an overridden graph.connectionHandler.createEdgeState\n /*\n let mxConnectionHandlerMouseMove = mxConnectionHandler.prototype.mouseMove;\n mxConnectionHandler.prototype.mouseMove = function(sender, me)\n {\n this.sourceConstraint = null;\n\n mxConnectionHandlerMouseMove.apply(this, arguments);\n };\n\n let mxConnectionHandlerGetSourcePerimeterPoint = mxConnectionHandler.prototype.getSourcePerimeterPoint;\n mxConnectionHandler.prototype.getSourcePerimeterPoint = function(state, pt, me)\n {\n let result = null;\n\n if (this.previous != null && pt != null)\n {\n let constraints = this.graph.getAllConnectionConstraints(this.previous);\n let nearestConstraint = null;\n let nearest = null;\n let dist = null;\n\n for (let i = 0; i < constraints.length; i++)\n {\n let cp = this.graph.getConnectionPoint(this.previous, constraints[i]);\n\n if (cp != null)\n {\n let tmp = (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);\n\n if (dist == null || tmp < dist)\n {\n nearestConstraint = constraints[i];\n nearest = cp;\n dist = tmp;\n }\n }\n }\n\n if (nearestConstraint != null)\n {\n this.sourceConstraint = nearestConstraint;\n result = nearest;\n }\n }\n\n if (result == null)\n {\n result = mxConnectionHandlerGetSourcePerimeterPoint.apply(this, arguments);\n }\n\n return result;\n };\n */\n };\n}\n\nexport default FixedPoints;\n", - "FileIO": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCellTracker from \"../mxgraph/handler/mxCellTracker\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxFastOrganicLayout from \"../mxgraph/layout/mxFastOrganicLayout\";\nimport mxEventObject from \"../mxgraph/util/mxEventObject\";\nimport mxCodec from \"../mxgraph/io/mxCodec\";\nimport mxPerimeter from \"../mxgraph/view/mxPerimeter\";\nimport mxClient from \"../mxgraph/mxClient\";\n\nclass FileIO extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

File I/O

\n This example demonstrates reading an\n XML file, writing a custom parser, applying an automatic layout and\n defining a 2-way edge.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '80vh',\n borderTop: 'gray 1px solid',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Program starts here. Creates a sample graph in the\n // DOM node with the specified ID. This function is invoked\n // from the onLoad event handler of the document (see below).\n function main(container) {\n // Checks if browser is supported\n if (!mxClient.isBrowserSupported()) {\n // Displays an error message if the browser is\n // not supported.\n mxUtils.error('Browser is not supported!', 200, false);\n } else {\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n graph.setEnabled(false);\n graph.setPanning(true);\n graph.setTooltips(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Adds a highlight on the cell under the mousepointer\n new mxCellTracker(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ROUNDED;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 4;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_CLASSIC;\n graph.getStylesheet().putCellStyle('2way', style);\n\n graph.isHtmlLabel = function(cell) {\n return true;\n };\n\n // Larger grid size yields cleaner layout result\n graph.gridSize = 20;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxFastOrganicLayout(graph);\n\n // Moves stuff wider apart than usual\n layout.forceConstant = 140;\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Arrange', function(evt) {\n const parent = graph.getDefaultParent();\n layout.execute(parent);\n })\n );\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n // Loads the custom file format (TXT file)\n parse(graph, 'fileio.txt');\n\n // Loads the mxGraph file format (XML file)\n // read(graph, 'fileio.xml');\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.dblClick = function(evt, cell) {\n const mxe = new mxEventObject(\n mxEvent.DOUBLE_CLICK,\n 'event',\n evt,\n 'cell',\n cell\n );\n this.fireEvent(mxe);\n\n if (\n this.isEnabled() &&\n !mxEvent.isConsumed(evt) &&\n !mxe.isConsumed() &&\n cell != null\n ) {\n mxUtils.alert(\n `Show properties for cell ${cell.customId || cell.getId()}`\n );\n }\n };\n }\n }\n\n // Custom parser for simple file format\n function parse(graph, filename) {\n const model = graph.getModel();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const req = mxUtils.load(filename);\n const text = req.getText();\n\n const lines = text.split('\\n');\n\n // Creates the lookup table for the vertices\n const vertices = [];\n\n // Parses all lines (vertices must be first in the file)\n graph.getModel().beginUpdate();\n try {\n for (let i = 0; i < lines.length; i++) {\n // Ignores comments (starting with #)\n const colon = lines[i].indexOf(':');\n\n if (lines[i].substring(0, 1) != '#' || colon == -1) {\n const comma = lines[i].indexOf(',');\n const value = lines[i].substring(colon + 2, lines[i].length);\n\n if (comma == -1 || comma > colon) {\n const key = lines[i].substring(0, colon);\n\n if (key.length > 0) {\n vertices[key] = graph.insertVertex(\n parent,\n null,\n value,\n 0,\n 0,\n 80,\n 70\n );\n }\n } else if (comma < colon) {\n // Looks up the vertices in the lookup table\n const source = vertices[lines[i].substring(0, comma)];\n const target = vertices[lines[i].substring(comma + 1, colon)];\n\n if (source != null && target != null) {\n const e = graph.insertEdge(parent, null, value, source, target);\n\n // Uses the special 2-way style for 2-way labels\n if (value.indexOf('2-Way') >= 0) {\n e.style = '2way';\n }\n }\n }\n }\n }\n } finally {\n graph.getModel().endUpdate();\n }\n }\n\n // Parses the mxGraph XML file format\n function read(graph, filename) {\n const req = mxUtils.load(filename);\n const root = req.getDocumentElement();\n const dec = new mxCodec(root.ownerDocument);\n\n dec.decode(root, graph.getModel());\n }\n };\n}\n\nexport default FileIO;\n", - "Grid": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxLog from '../mxgraph/util/mxLog';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\n\nclass Grid extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Grid

\n This example demonstrates drawing\n a grid dynamically using HTML 5 canvas.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '481px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.graphHandler.scaleGrid = true;\n graph.setPanning(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n let repaintGrid;\n\n // Create grid dynamically (requires canvas)\n (function() {\n try {\n const canvas = document.createElement('canvas');\n canvas.style.position = 'absolute';\n canvas.style.top = '0px';\n canvas.style.left = '0px';\n canvas.style.zIndex = -1;\n graph.container.appendChild(canvas);\n\n const ctx = canvas.getContext('2d');\n\n // Modify event filtering to accept canvas as container\n const mxGraphViewIsContainerEvent =\n mxGraphView.prototype.isContainerEvent;\n mxGraphView.prototype.isContainerEvent = function(evt) {\n return (\n mxGraphViewIsContainerEvent.apply(this, arguments) ||\n mxEvent.getSource(evt) === canvas\n );\n };\n\n let s = 0;\n let gs = 0;\n let tr = new mxPoint();\n let w = 0;\n let h = 0;\n\n repaintGrid = function() {\n if (ctx != null) {\n const bounds = graph.getGraphBounds();\n const width = Math.max(\n bounds.x + bounds.width,\n graph.container.clientWidth\n );\n const height = Math.max(\n bounds.y + bounds.height,\n graph.container.clientHeight\n );\n const sizeChanged = width !== w || height !== h;\n\n if (\n graph.view.scale !== s ||\n graph.view.translate.x !== tr.x ||\n graph.view.translate.y !== tr.y ||\n gs !== graph.gridSize ||\n sizeChanged\n ) {\n tr = graph.view.translate.clone();\n s = graph.view.scale;\n gs = graph.gridSize;\n w = width;\n h = height;\n\n // Clears the background if required\n if (!sizeChanged) {\n ctx.clearRect(0, 0, w, h);\n } else {\n canvas.setAttribute('width', w);\n canvas.setAttribute('height', h);\n }\n\n const tx = tr.x * s;\n const ty = tr.y * s;\n\n // Sets the distance of the grid lines in pixels\n const minStepping = graph.gridSize;\n let stepping = minStepping * s;\n\n if (stepping < minStepping) {\n const count =\n Math.round(Math.ceil(minStepping / stepping) / 2) * 2;\n stepping = count * stepping;\n }\n\n const xs = Math.floor((0 - tx) / stepping) * stepping + tx;\n let xe = Math.ceil(w / stepping) * stepping;\n const ys = Math.floor((0 - ty) / stepping) * stepping + ty;\n let ye = Math.ceil(h / stepping) * stepping;\n\n xe += Math.ceil(stepping);\n ye += Math.ceil(stepping);\n\n const ixs = Math.round(xs);\n const ixe = Math.round(xe);\n const iys = Math.round(ys);\n const iye = Math.round(ye);\n\n // Draws the actual grid\n ctx.strokeStyle = '#f6f6f6';\n ctx.beginPath();\n\n for (let x = xs; x <= xe; x += stepping) {\n x = Math.round((x - tx) / stepping) * stepping + tx;\n const ix = Math.round(x);\n\n ctx.moveTo(ix + 0.5, iys + 0.5);\n ctx.lineTo(ix + 0.5, iye + 0.5);\n }\n\n for (let y = ys; y <= ye; y += stepping) {\n y = Math.round((y - ty) / stepping) * stepping + ty;\n const iy = Math.round(y);\n\n ctx.moveTo(ixs + 0.5, iy + 0.5);\n ctx.lineTo(ixe + 0.5, iy + 0.5);\n }\n\n ctx.closePath();\n ctx.stroke();\n }\n }\n }\n } catch (e) {\n mxLog.show();\n mxLog.debug('Using background image');\n\n this.el.style.backgroundImage = \"url('editors/images/grid.gif')\";\n }\n\n const mxGraphViewValidateBackground =\n mxGraphView.prototype.validateBackground;\n mxGraphView.prototype.validateBackground = function() {\n mxGraphViewValidateBackground.apply(this, arguments);\n repaintGrid();\n };\n })();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.centerZoom = false;\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Grid;\n", - "Handles": "/**\n * Copyright (c) 2006-2014, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxVertexHandler from '../mxgraph/handler/mxVertexHandler';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxHandle from '../mxgraph/handler/mxHandle';\n\nclass Handles extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Handles

\n This example demonstrates using mxHandle to change custom styles interactively.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n class MyShape extends mxCylinder {\n defaultPos1 = 20;\n\n defaultPos2 = 60;\n\n getLabelBounds(rect) {\n const pos1 =\n mxUtils.getValue(this.style, 'pos1', this.defaultPos1) * this.scale;\n const pos2 =\n mxUtils.getValue(this.style, 'pos2', this.defaultPos2) * this.scale;\n return new mxRectangle(\n rect.x,\n rect.y + pos1,\n rect.width,\n Math.min(rect.height, pos2) - Math.max(0, pos1)\n );\n }\n\n redrawPath(path, x, y, w, h, isForeground) {\n const pos1 = mxUtils.getValue(this.style, 'pos1', this.defaultPos1);\n const pos2 = mxUtils.getValue(this.style, 'pos2', this.defaultPos2);\n\n if (isForeground) {\n if (pos1 < h) {\n path.moveTo(0, pos1);\n path.lineTo(w, pos1);\n }\n\n if (pos2 < h) {\n path.moveTo(0, pos2);\n path.lineTo(w, pos2);\n }\n } else {\n path.rect(0, 0, w, h);\n }\n }\n }\n mxCellRenderer.registerShape('myShape', MyShape);\n\n class MyCustomVertexHandler extends mxVertexHandler {\n livePreview = true;\n\n rotationEnabled = true;\n\n createCustomHandles() {\n if (this.state.style.shape === 'myShape') {\n // Implements the handle for the first divider\n const firstHandle = new mxHandle(this.state);\n\n firstHandle.getPosition = function(bounds) {\n const pos2 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n const pos1 = Math.max(\n 0,\n Math.min(\n pos2,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n\n return new mxPoint(bounds.getCenterX(), bounds.y + pos1);\n };\n\n firstHandle.setPosition = function(bounds, pt) {\n const pos2 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n\n this.state.style.pos1 = Math.round(\n Math.max(0, Math.min(pos2, pt.y - bounds.y))\n );\n };\n\n firstHandle.execute = function() {\n this.copyStyle('pos1');\n };\n\n firstHandle.ignoreGrid = true;\n\n // Implements the handle for the second divider\n const secondHandle = new mxHandle(this.state);\n\n secondHandle.getPosition = function(bounds) {\n const pos1 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n const pos2 = Math.max(\n pos1,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n\n return new mxPoint(bounds.getCenterX(), bounds.y + pos2);\n };\n\n secondHandle.setPosition = function(bounds, pt) {\n const pos1 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n\n this.state.style.pos2 = Math.round(\n Math.max(pos1, Math.min(bounds.height, pt.y - bounds.y))\n );\n };\n\n secondHandle.execute = function() {\n this.copyStyle('pos2');\n };\n\n secondHandle.ignoreGrid = true;\n\n return [firstHandle, secondHandle];\n }\n\n return null;\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createVertexHandler(state) {\n return new MyCustomVertexHandler(state);\n }\n }\n\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setCellsCloneable(true);\n graph.setHtmlLabels(true);\n graph.setPanning(true);\n graph.centerZoom = false;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n 20,\n 20,\n 240,\n 120,\n 'shape=myShape;whiteSpace=wrap;overflow=hidden;pos1=30;pos2=80;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Handles;\n", - "Windows": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxLog from '../mxgraph/util/mxLog';\nimport mxWindow from '../mxgraph/util/mxWindow';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Windows extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Windows

\n This example demonstrates using\n the mxWindow class for displaying windows.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'auto',\n position: 'relative',\n height: '500px',\n background: 'lightyellow',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Note that we're using the container scrollbars for the graph so that the\n // container extends to the parent div inside the window\n let wnd = new mxWindow(\n 'Scrollable, resizable, given height',\n this.el,\n 50,\n 50,\n 220,\n 224,\n true,\n true\n );\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection and keystrokes\n graph.setTooltips(true);\n graph.setPanning(true);\n const rubberband = new mxRubberband(graph);\n new mxKeyHandler(graph);\n\n mxEvent.disableContextMenu(this.el);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n wnd.setMaximizable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n const lorem =\n 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ';\n let content = document.createElement('div');\n mxUtils.write(content, lorem + lorem + lorem);\n\n wnd = new mxWindow(\n 'Scrollable, resizable, auto height',\n content,\n 300,\n 50,\n 200,\n null,\n true,\n true\n );\n wnd.setMaximizable(true);\n wnd.setScrollable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n content = content.cloneNode(true);\n content.style.width = '400px';\n\n wnd = new mxWindow(\n 'Scrollable, resizable, fixed content',\n content,\n 520,\n 50,\n 220,\n 200,\n true,\n true\n );\n wnd.setMaximizable(true);\n wnd.setScrollable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n mxLog.show();\n }\n}\n\nexport default Windows;\n", - "Template": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n \n Template. This is used as a template HTML file by the\n backends to demonstrate the deployment of the client with a graph embedded\n in the page as XML data (see graph variable in the onload-handler).\n \n *** THIS FILE MUST BE DEPLOYED BY ONE OF THE BACKENDS! ***\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxCodec from \"../mxgraph/io/mxCodec\";\n\nclass Template extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('/mxgraph/javascript/examples/editors/images/grid.gif')\",\n cursor: 'default'\n }}\n />\n \n );\n };\n\n componentDidMount() {\n // Creates the graph inside the given container\n let graph = new mxGraph(this.el);\n\n // Adds rubberband selection to the graph\n new mxRubberband(graph);\n\n let doc = mxUtils.parseXml(xml);\n let codec = new mxCodec(doc);\n codec.decode(doc.documentElement, graph.getModel());\n };\n}\n\nexport default Template;\n\n\n\n", - "Anchors": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxShape from '../mxgraph/shape/mxShape';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxPolyline from '../mxgraph/shape/mxPolyline';\nimport mxCellState from '../mxgraph/view/mxCellState';\n\nclass Anchors extends React.Component {\n constructor(props) {\n super(props);\n }\n\n componentDidMount() {\n // Overridden to define per-shape connection points\n mxGraph.prototype.getAllConnectionConstraints = function(terminal, source) {\n if (terminal != null && terminal.shape != null) {\n if (terminal.shape.stencil != null) {\n if (terminal.shape.stencil.constraints != null) {\n return terminal.shape.stencil.constraints;\n }\n } else if (terminal.shape.constraints != null) {\n return terminal.shape.constraints;\n }\n }\n return null;\n };\n\n // Defines the default constraints for all shapes\n mxShape.prototype.constraints = [\n new mxConnectionConstraint(new mxPoint(0.25, 0), true),\n new mxConnectionConstraint(new mxPoint(0.5, 0), true),\n new mxConnectionConstraint(new mxPoint(0.75, 0), true),\n new mxConnectionConstraint(new mxPoint(0, 0.25), true),\n new mxConnectionConstraint(new mxPoint(0, 0.5), true),\n new mxConnectionConstraint(new mxPoint(0, 0.75), true),\n new mxConnectionConstraint(new mxPoint(1, 0.25), true),\n new mxConnectionConstraint(new mxPoint(1, 0.5), true),\n new mxConnectionConstraint(new mxPoint(1, 0.75), true),\n new mxConnectionConstraint(new mxPoint(0.25, 1), true),\n new mxConnectionConstraint(new mxPoint(0.5, 1), true),\n new mxConnectionConstraint(new mxPoint(0.75, 1), true),\n ];\n\n // Edges have no connection points\n mxPolyline.prototype.constraints = null;\n\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Enables connect preview for the default edge style\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(null, null, null, null, null);\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Specifies the default edge style\n graph.getStylesheet().getDefaultEdgeStyle().edgeStyle =\n 'orthogonalEdgeStyle';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Anchors

\n This example demonstrates defining\n fixed connection points for all shapes.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n}\n\nexport default Anchors;\n", - "SecondLabel": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxRectangleShape from '../mxgraph/shape/mxRectangleShape';\nimport mxText from \"../mxgraph/shape/mxText\";\n\nclass SecondLabel extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Second label

\n This example demonstrates how to\n add another string label to vertices.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Simple solution to add additional text to the rectangle shape definition:\n (function() {\n const mxRectangleShapeIsHtmlAllowed =\n mxRectangleShape.prototype.isHtmlAllowed;\n mxRectangleShape.prototype.isHtmlAllowed = function() {\n return (\n mxRectangleShapeIsHtmlAllowed.apply(this, arguments) &&\n this.state == null\n );\n };\n\n const mxRectangleShapePaintForeground =\n mxRectangleShape.prototype.paintForeground;\n mxRectangleShape.prototype.paintForeground = function(c, x, y, w, h) {\n if (\n this.state != null &&\n this.state.cell.geometry != null &&\n !this.state.cell.geometry.relative\n ) {\n c.setFontColor('#a0a0a0');\n c.text(x + 2, y, 0, 0, this.state.cell.id, 'left', 'top');\n }\n\n mxRectangleShapePaintForeground.apply(this, arguments);\n };\n })();\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables the folding icon\n graph.isCellFoldable = function(cell) {\n return false;\n };\n\n let secondLabelVisible = true;\n\n // Hook for returning shape number for a given cell\n graph.getSecondLabel = function(cell) {\n if (!this.model.isEdge(cell)) {\n // Possible to return any string here\n return `The ID of this cell is ${cell.id}`;\n }\n\n return null;\n };\n\n let relativeChildVerticesVisible = true;\n\n // Overrides method to hide relative child vertices\n graph.isCellVisible = function(cell) {\n return (\n !this.model.isVertex(cell) ||\n cell.geometry == null ||\n !cell.geometry.relative ||\n cell.geometry.relative == relativeChildVerticesVisible\n );\n };\n\n // Creates the shape for the shape number and puts it into the draw pane\n const { redrawShape } = graph.cellRenderer;\n graph.cellRenderer.redrawShape = function(state, force, rendering) {\n const result = redrawShape.apply(this, arguments);\n\n if (\n result &&\n secondLabelVisible &&\n state.cell.geometry != null &&\n !state.cell.geometry.relative\n ) {\n const secondLabel = graph.getSecondLabel(state.cell);\n\n if (\n secondLabel != null &&\n state.shape != null &&\n state.secondLabel == null\n ) {\n state.secondLabel = new mxText(\n secondLabel,\n new mxRectangle(),\n mxConstants.ALIGN_LEFT,\n mxConstants.ALIGN_BOTTOM\n );\n\n // Styles the label\n state.secondLabel.color = 'black';\n state.secondLabel.family = 'Verdana';\n state.secondLabel.size = 8;\n state.secondLabel.fontStyle = mxConstants.FONT_ITALIC;\n state.secondLabel.background = 'yellow';\n state.secondLabel.border = 'black';\n state.secondLabel.valign = 'bottom';\n state.secondLabel.dialect = state.shape.dialect;\n state.secondLabel.dialect = mxConstants.DIALECT_STRICTHTML;\n state.secondLabel.wrap = true;\n graph.cellRenderer.initializeLabel(state, state.secondLabel);\n }\n }\n\n if (state.secondLabel != null) {\n const scale = graph.getView().getScale();\n const bounds = new mxRectangle(\n state.x + state.width - 8 * scale,\n state.y + 8 * scale,\n 35,\n 0\n );\n state.secondLabel.state = state;\n state.secondLabel.value = graph.getSecondLabel(state.cell);\n state.secondLabel.scale = scale;\n state.secondLabel.bounds = bounds;\n state.secondLabel.redraw();\n }\n\n return result;\n };\n\n // Destroys the shape number\n const { destroy } = graph.cellRenderer;\n graph.cellRenderer.destroy = function(state) {\n destroy.apply(this, arguments);\n\n if (state.secondLabel != null) {\n state.secondLabel.destroy();\n state.secondLabel = null;\n }\n };\n\n graph.cellRenderer.getShapesForState = function(state) {\n return [state.shape, state.text, state.secondLabel, state.control];\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 30, 40, 80, 30);\n // Alternative solution of creating a second label by creating a realtive child vertex\n // with size (0, 0). This will not be selectable and only the label colors can be used\n // for coloring as the actual shape will have zero size.\n const v11 = graph.insertVertex(\n v1,\n null,\n 'World',\n 1,\n 1,\n 0,\n 0,\n 'align=left;verticalAlign=top;labelBackgroundColor=red;labelBorderColor=black',\n true\n );\n v11.geometry.offset = new mxPoint(-8, -8);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n // Another alternative solution of creating a second label as a relative child vertex\n // but this time with an automatic size so that the cell is actually selectable and\n // the background is painted as a shape.\n const v21 = graph.insertVertex(\n v2,\n null,\n 'World',\n 1,\n 1,\n 0,\n 0,\n 'align=left;verticalAlign=top;fillColor=red;rounded=1;spacingLeft=4;spacingRight=4',\n true\n );\n v21.geometry.offset = new mxPoint(-8, -8);\n graph.updateCellSize(v21);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Toggle Child Vertices', function(evt) {\n relativeChildVerticesVisible = !relativeChildVerticesVisible;\n graph.refresh();\n })\n );\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Toggle IDs', function(evt) {\n secondLabelVisible = !secondLabelVisible;\n graph.refresh();\n })\n );\n }\n}\n\nexport default SecondLabel;\n", - "PageBreaks": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxPrintPreview from \"../mxgraph/view/mxPrintPreview\";\n\nclass PageBreaks extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Pagebreaks

\n This example demonstrates using the\n pageBreaksVisible and preferPageSize switches and adding headers and\n footers to print output.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '481px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.view.setScale(0.15);\n graph.pageBreaksVisible = true;\n graph.pageBreakDashed = true;\n graph.preferPageSize = true;\n graph.centerZoom = false;\n graph.setPanning(true);\n\n // Account for the header and footer size in the page format\n const headerSize = 100;\n const footerSize = 100;\n\n // Removes header and footer from page height\n graph.pageFormat.height -= headerSize + footerSize;\n\n // Takes zoom into account for moving cells\n graph.graphHandler.scaleGrid = true;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 10, 10, 280, 330);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n graph.pageFormat.width * graph.pageScale - 280 - 10,\n graph.pageFormat.height * graph.pageScale - 330 - 10,\n 280,\n 330\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('Toggle Page Breaks', function(evt) {\n graph.pageBreaksVisible = !graph.pageBreaksVisible;\n graph.sizeDidChange();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom In', function(evt) {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom Out', function(evt) {\n graph.zoomOut();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Print', function(evt) {\n // Matches actual printer paper size and avoids blank pages\n const scale = 0.5;\n\n // Applies scale to page\n const pf = mxRectangle.fromRectangle(\n graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT\n );\n pf.width = Math.round(pf.width * scale * graph.pageScale);\n pf.height = Math.round(pf.height * scale * graph.pageScale);\n\n // Finds top left corner of top left page\n const bounds = mxRectangle.fromRectangle(graph.getGraphBounds());\n bounds.x -= graph.view.translate.x * graph.view.scale;\n bounds.y -= graph.view.translate.y * graph.view.scale;\n\n const x0 = Math.floor(bounds.x / pf.width) * pf.width;\n const y0 = Math.floor(bounds.y / pf.height) * pf.height;\n\n const preview = new mxPrintPreview(graph, scale, pf, 0, -x0, -y0);\n preview.marginTop = headerSize * scale * graph.pageScale;\n preview.marginBottom = footerSize * scale * graph.pageScale;\n preview.autoOrigin = false;\n\n const oldRenderPage = preview.renderPage;\n preview.renderPage = function(w, h, x, y, content, pageNumber) {\n const div = oldRenderPage.apply(this, arguments);\n\n const header = document.createElement('div');\n header.style.position = 'absolute';\n header.style.boxSizing = 'border-box';\n header.style.fontFamily = 'Arial,Helvetica';\n header.style.height = `${this.marginTop - 10}px`;\n header.style.textAlign = 'center';\n header.style.verticalAlign = 'middle';\n header.style.marginTop = 'auto';\n header.style.fontSize = '12px';\n header.style.width = '100%';\n\n // Vertical centering for text in header/footer\n header.style.lineHeight = `${this.marginTop - 10}px`;\n\n const footer = header.cloneNode(true);\n\n mxUtils.write(header, `Page ${pageNumber} - Header`);\n header.style.borderBottom = '1px solid gray';\n header.style.top = '0px';\n\n mxUtils.write(footer, `Page ${pageNumber} - Footer`);\n footer.style.borderTop = '1px solid gray';\n footer.style.bottom = '0px';\n\n div.firstChild.appendChild(footer);\n div.firstChild.appendChild(header);\n\n return div;\n };\n\n preview.open();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Reset View', function(evt) {\n graph.view.scaleAndTranslate(0.15, 0, 0);\n })\n );\n }\n}\n\nexport default PageBreaks;\n", - "SwimLanes": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxStackLayout from '../mxgraph/layout/mxStackLayout';\nimport mxSwimlaneManager from '../mxgraph/view/mxSwimlaneManager';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxEditor from '../mxgraph/editor/mxEditor';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxLayoutManager from \"../mxgraph/view/mxLayoutManager\";\nimport mxEdgeStyle from \"../mxgraph/view/mxEdgeStyle\";\n\nclass SwimLanes extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Swimlanes

\n This example demonstrates using\n swimlanes for pools and lanes and adding cells and edges between\n them. This also demonstrates using the stack layout as an\n automatic layout.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n border: 'gray dotted 1px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates a wrapper editor around a new graph inside\n // the given container using an XML config for the\n // keyboard bindings\n const config = mxUtils\n .load('editors/config/keyhandler-commons.xml')\n .getDocumentElement();\n const editor = new mxEditor(config);\n editor.setGraphContainer(this.el);\n const { graph } = editor;\n const model = graph.getModel();\n\n // Auto-resizes the container\n graph.border = 80;\n graph.getView().translate = new mxPoint(graph.border / 2, graph.border / 2);\n graph.setResizeContainer(true);\n graph.graphHandler.setRemoveCellsFromParent(false);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'middle';\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n style[mxConstants.STYLE_FONTSIZE] = 11;\n style[mxConstants.STYLE_STARTSIZE] = 22;\n style[mxConstants.STYLE_HORIZONTAL] = false;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = 'black';\n delete style[mxConstants.STYLE_FILLCOLOR];\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_FONTSIZE] = 10;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_HORIZONTAL] = true;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'middle';\n delete style[mxConstants.STYLE_STARTSIZE];\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'none';\n graph.getStylesheet().putCellStyle('process', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n delete style[mxConstants.STYLE_ROUNDED];\n graph.getStylesheet().putCellStyle('state', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RHOMBUS;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RhombusPerimeter;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'top';\n style[mxConstants.STYLE_SPACING_TOP] = 40;\n style[mxConstants.STYLE_SPACING_RIGHT] = 64;\n graph.getStylesheet().putCellStyle('condition', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_DOUBLE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_SPACING_TOP] = 28;\n style[mxConstants.STYLE_FONTSIZE] = 14;\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n delete style[mxConstants.STYLE_SPACING_RIGHT];\n graph.getStylesheet().putCellStyle('end', style);\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_BLOCK;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = 'black';\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_DASHED] = true;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_OPEN;\n style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_OVAL;\n graph.getStylesheet().putCellStyle('crossover', style);\n\n // Installs double click on middle control point and\n // changes style of edges between empty and this value\n graph.alternateEdgeStyle = 'elbow=vertical';\n\n // Adds automatic layout and various switches if the\n // graph is enabled\n if (graph.isEnabled()) {\n // Allows new connections but no dangling edges\n graph.setConnectable(true);\n graph.setAllowDanglingEdges(false);\n\n // End-states are no valid sources\n const previousIsValidSource = graph.isValidSource;\n\n graph.isValidSource = function(cell) {\n if (previousIsValidSource.apply(this, arguments)) {\n const style = this.getModel().getStyle(cell);\n\n return (\n style == null || !(style == 'end' || style.indexOf('end') == 0)\n );\n }\n\n return false;\n };\n\n // Start-states are no valid targets, we do not\n // perform a call to the superclass function because\n // this would call isValidSource\n // Note: All states are start states in\n // the example below, so we use the state\n // style below\n graph.isValidTarget = function(cell) {\n const style = this.getModel().getStyle(cell);\n\n return (\n !this.getModel().isEdge(cell) &&\n !this.isSwimlane(cell) &&\n (style == null || !(style == 'state' || style.indexOf('state') == 0))\n );\n };\n\n // Allows dropping cells into new lanes and\n // lanes into new pools, but disallows dropping\n // cells on edges to split edges\n graph.setDropEnabled(true);\n graph.setSplitEnabled(false);\n\n // Returns true for valid drop operations\n graph.isValidDropTarget = function(target, cells, evt) {\n if (this.isSplitEnabled() && this.isSplitTarget(target, cells, evt)) {\n return true;\n }\n\n const model = this.getModel();\n let lane = false;\n let pool = false;\n let cell = false;\n\n // Checks if any lanes or pools are selected\n for (let i = 0; i < cells.length; i++) {\n const tmp = model.getParent(cells[i]);\n lane = lane || this.isPool(tmp);\n pool = pool || this.isPool(cells[i]);\n\n cell = cell || !(lane || pool);\n }\n\n return (\n !pool &&\n cell != lane &&\n ((lane && this.isPool(target)) ||\n (cell && this.isPool(model.getParent(target))))\n );\n };\n\n // Adds new method for identifying a pool\n graph.isPool = function(cell) {\n const model = this.getModel();\n const parent = model.getParent(cell);\n\n return parent != null && model.getParent(parent) == model.getRoot();\n };\n\n // Changes swimlane orientation while collapsed\n graph.model.getStyle = function(cell) {\n let style = mxGraphModel.prototype.getStyle.apply(this, arguments);\n\n if (graph.isCellCollapsed(cell)) {\n if (style != null) {\n style += ';';\n } else {\n style = '';\n }\n\n style += 'horizontal=1;align=left;spacingLeft=14;';\n }\n\n return style;\n };\n\n // Keeps widths on collapse/expand\n const foldingHandler = function(sender, evt) {\n const cells = evt.getProperty('cells');\n\n for (let i = 0; i < cells.length; i++) {\n const geo = graph.model.getGeometry(cells[i]);\n\n if (geo.alternateBounds != null) {\n geo.width = geo.alternateBounds.width;\n }\n }\n };\n\n graph.addListener(mxEvent.FOLD_CELLS, foldingHandler);\n }\n\n // Applies size changes to siblings and parents\n new mxSwimlaneManager(graph);\n\n // Creates a stack depending on the orientation of the swimlane\n const layout = new mxStackLayout(graph, false);\n\n // Makes sure all children fit into the parent swimlane\n layout.resizeParent = true;\n\n // Applies the size to children if parent size changes\n layout.fill = true;\n\n // Only update the size of swimlanes\n layout.isVertexIgnored = function(vertex) {\n return !graph.isSwimlane(vertex);\n };\n\n // Keeps the lanes and pools stacked\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (\n !model.isEdge(cell) &&\n graph.getModel().getChildCount(cell) > 0 &&\n (model.getParent(cell) == model.getRoot() || graph.isPool(cell))\n ) {\n layout.fill = graph.isPool(cell);\n\n return layout;\n }\n\n return null;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n model.beginUpdate();\n try {\n const pool1 = graph.insertVertex(parent, null, 'Pool 1', 0, 0, 640, 0);\n pool1.setConnectable(false);\n\n const lane1a = graph.insertVertex(pool1, null, 'Lane A', 0, 0, 640, 110);\n lane1a.setConnectable(false);\n\n const lane1b = graph.insertVertex(pool1, null, 'Lane B', 0, 0, 640, 110);\n lane1b.setConnectable(false);\n\n const pool2 = graph.insertVertex(parent, null, 'Pool 2', 0, 0, 640, 0);\n pool2.setConnectable(false);\n\n const lane2a = graph.insertVertex(pool2, null, 'Lane A', 0, 0, 640, 140);\n lane2a.setConnectable(false);\n\n const lane2b = graph.insertVertex(pool2, null, 'Lane B', 0, 0, 640, 110);\n lane2b.setConnectable(false);\n\n const start1 = graph.insertVertex(\n lane1a,\n null,\n null,\n 40,\n 40,\n 30,\n 30,\n 'state'\n );\n const end1 = graph.insertVertex(\n lane1a,\n null,\n 'A',\n 560,\n 40,\n 30,\n 30,\n 'end'\n );\n\n const step1 = graph.insertVertex(\n lane1a,\n null,\n 'Contact\\nProvider',\n 90,\n 30,\n 80,\n 50,\n 'process'\n );\n const step11 = graph.insertVertex(\n lane1a,\n null,\n 'Complete\\nAppropriate\\nRequest',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n const step111 = graph.insertVertex(\n lane1a,\n null,\n 'Receive and\\nAcknowledge',\n 385,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const start2 = graph.insertVertex(\n lane2b,\n null,\n null,\n 40,\n 40,\n 30,\n 30,\n 'state'\n );\n\n const step2 = graph.insertVertex(\n lane2b,\n null,\n 'Receive\\nRequest',\n 90,\n 30,\n 80,\n 50,\n 'process'\n );\n const step22 = graph.insertVertex(\n lane2b,\n null,\n 'Refer to Tap\\nSystems\\nCoordinator',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const step3 = graph.insertVertex(\n lane1b,\n null,\n 'Request 1st-\\nGate\\nInformation',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n const step33 = graph.insertVertex(\n lane1b,\n null,\n 'Receive 1st-\\nGate\\nInformation',\n 290,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const step4 = graph.insertVertex(\n lane2a,\n null,\n 'Receive and\\nAcknowledge',\n 290,\n 20,\n 80,\n 50,\n 'process'\n );\n const step44 = graph.insertVertex(\n lane2a,\n null,\n 'Contract\\nConstraints?',\n 400,\n 20,\n 50,\n 50,\n 'condition'\n );\n const step444 = graph.insertVertex(\n lane2a,\n null,\n 'Tap for gas\\ndelivery?',\n 480,\n 20,\n 50,\n 50,\n 'condition'\n );\n\n const end2 = graph.insertVertex(\n lane2a,\n null,\n 'B',\n 560,\n 30,\n 30,\n 30,\n 'end'\n );\n const end3 = graph.insertVertex(\n lane2a,\n null,\n 'C',\n 560,\n 84,\n 30,\n 30,\n 'end'\n );\n\n let e = null;\n\n graph.insertEdge(lane1a, null, null, start1, step1);\n graph.insertEdge(lane1a, null, null, step1, step11);\n graph.insertEdge(lane1a, null, null, step11, step111);\n\n graph.insertEdge(lane2b, null, null, start2, step2);\n graph.insertEdge(lane2b, null, null, step2, step22);\n graph.insertEdge(parent, null, null, step22, step3);\n\n graph.insertEdge(lane1b, null, null, step3, step33);\n graph.insertEdge(lane2a, null, null, step4, step44);\n graph.insertEdge(\n lane2a,\n null,\n 'No',\n step44,\n step444,\n 'verticalAlign=bottom'\n );\n graph.insertEdge(\n parent,\n null,\n 'Yes',\n step44,\n step111,\n 'verticalAlign=bottom;horizontal=0;labelBackgroundColor=white;'\n );\n\n graph.insertEdge(\n lane2a,\n null,\n 'Yes',\n step444,\n end2,\n 'verticalAlign=bottom'\n );\n e = graph.insertEdge(\n lane2a,\n null,\n 'No',\n step444,\n end3,\n 'verticalAlign=top'\n );\n e.geometry.points = [\n new mxPoint(\n step444.geometry.x + step444.geometry.width / 2,\n end3.geometry.y + end3.geometry.height / 2\n ),\n ];\n\n graph.insertEdge(parent, null, null, step1, step2, 'crossover');\n graph.insertEdge(parent, null, null, step3, step11, 'crossover');\n e = graph.insertEdge(lane1a, null, null, step11, step33, 'crossover');\n e.geometry.points = [\n new mxPoint(\n step33.geometry.x + step33.geometry.width / 2 + 20,\n step11.geometry.y + (step11.geometry.height * 4) / 5\n ),\n ];\n graph.insertEdge(parent, null, null, step33, step4);\n graph.insertEdge(lane1a, null, null, step111, end1);\n } finally {\n // Updates the display\n model.endUpdate();\n }\n }\n}\n\nexport default SwimLanes;\n", - "Previews": "import React, { useState } from \"react\";\n\nimport SourceCodeDisplay from './SourceCodeDisplay';\nimport examplesListing from './examplesListing.json';\n\nfunction Preview({ sourceKey, content }) {\n const [sourceShown, setSourceShown] = useState(false);\n\n return (\n <>\n {content}\n\n {sourceShown ? (\n
\n setSourceShown(false)}\n style={{ float: 'right', color: 'blue', cursor: 'pointer' }}\n >\n hide source\n \n
\n \n
\n
\n ) : (\n
\n setSourceShown(true)}\n style={{ float: 'right', color: 'blue', cursor: 'pointer' }}\n >\n show source\n \n
\n )}\n \n );\n}\n\nexport default Preview;\n", - "Folding": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxStackLayout from '../mxgraph/layout/mxStackLayout';\n\nclass Folding extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Folding

\n This example demonstrates using a layout to implement a nested group structure.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Enables crisp rendering of rectangles in SVG\n mxConstants.ENTITY_SEGMENT = 20;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setDropEnabled(true);\n\n // Disables global features\n graph.collapseToPreferredSize = false;\n graph.constrainChildren = false;\n graph.cellsSelectable = false;\n graph.extendParentsOnAdd = false;\n graph.extendParents = false;\n graph.border = 10;\n\n // Sets global styles\n let style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';\n style[mxConstants.STYLE_SHAPE] = 'swimlane';\n style[mxConstants.STYLE_STARTSIZE] = 30;\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_STROKECOLOR] = 'none';\n style[mxConstants.STYLE_FILLCOLOR] = 'none';\n style[mxConstants.STYLE_FOLDABLE] = false;\n graph.getStylesheet().putCellStyle('column', style);\n\n // Installs auto layout for all levels\n const layout = new mxStackLayout(graph, true);\n layout.border = graph.border;\n const layoutMgr = new mxLayoutManager(graph);\n layoutMgr.getLayout = function(cell) {\n if (!cell.collapsed) {\n if (cell.parent !== graph.model.root) {\n layout.resizeParent = true;\n layout.horizontal = false;\n layout.spacing = 10;\n } else {\n layout.resizeParent = true;\n layout.horizontal = true;\n layout.spacing = 40;\n }\n\n return layout;\n }\n\n return null;\n };\n\n // Resizes the container\n graph.setResizeContainer(true);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const col1 = graph.insertVertex(parent, null, '', 0, 0, 120, 0, 'column');\n\n const v1 = graph.insertVertex(col1, null, '1', 0, 0, 100, 30);\n v1.collapsed = true;\n\n const v11 = graph.insertVertex(v1, null, '1.1', 0, 0, 80, 30);\n v11.collapsed = true;\n\n const v111 = graph.insertVertex(v11, null, '1.1.1', 0, 0, 60, 30);\n const v112 = graph.insertVertex(v11, null, '1.1.2', 0, 0, 60, 30);\n\n const v12 = graph.insertVertex(v1, null, '1.2', 0, 0, 80, 30);\n\n const col2 = graph.insertVertex(parent, null, '', 0, 0, 120, 0, 'column');\n\n const v2 = graph.insertVertex(col2, null, '2', 0, 0, 100, 30);\n v2.collapsed = true;\n\n const v21 = graph.insertVertex(v2, null, '2.1', 0, 0, 80, 30);\n v21.collapsed = true;\n\n const v211 = graph.insertVertex(v21, null, '2.1.1', 0, 0, 60, 30);\n const v212 = graph.insertVertex(v21, null, '2.1.2', 0, 0, 60, 30);\n\n const v22 = graph.insertVertex(v2, null, '2.2', 0, 0, 80, 30);\n\n const v3 = graph.insertVertex(col2, null, '3', 0, 0, 100, 30);\n v3.collapsed = true;\n\n const v31 = graph.insertVertex(v3, null, '3.1', 0, 0, 80, 30);\n v31.collapsed = true;\n\n const v311 = graph.insertVertex(v31, null, '3.1.1', 0, 0, 60, 30);\n const v312 = graph.insertVertex(v31, null, '3.1.2', 0, 0, 60, 30);\n\n const v32 = graph.insertVertex(v3, null, '3.2', 0, 0, 80, 30);\n\n graph.insertEdge(parent, null, '', v111, v211);\n graph.insertEdge(parent, null, '', v112, v212);\n graph.insertEdge(parent, null, '', v112, v22);\n\n graph.insertEdge(parent, null, '', v12, v311);\n graph.insertEdge(parent, null, '', v12, v312);\n graph.insertEdge(parent, null, '', v12, v32);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default Folding;\n", - "EdgeTolerance": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass EdgeTolerance extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Edge tolerance

\n This example demonstrates increasing\n the tolerance for hit detection on edges.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '481px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n let el = this.el;\n\n class MyCustomGraph extends mxGraph {\n fireMouseEvent(evtName, me, sender) {\n // Overrides the mouse event dispatching mechanism to update the\n // cell which is associated with the event in case the native hit\n // detection did not return anything.\n\n // Checks if native hit detection did not return anything\n if (me.getState() == null) {\n // Updates the graph coordinates in the event since we need\n // them here. Storing them in the event means the overridden\n // method doesn't have to do this again.\n if (me.graphX == null || me.graphY == null) {\n const pt = mxUtils.convertPoint(el, me.getX(), me.getY());\n\n me.graphX = pt.x;\n me.graphY = pt.y;\n }\n\n const cell = this.getCellAt(me.graphX, me.graphY);\n\n if (this.getModel().isEdge(cell)) {\n me.state = this.view.getState(cell);\n\n if (me.state != null && me.state.shape != null) {\n this.container.style.cursor = me.state.shape.node.style.cursor;\n }\n }\n }\n\n if (me.state == null) {\n this.container.style.cursor = 'default';\n }\n\n super.fireMouseEvent(evtName, me, sender);\n };\n\n dblClick(evt, cell) {\n // Overrides double click handling to use the tolerance\n if (cell == null) {\n const pt = mxUtils.convertPoint(\n el,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n cell = this.getCellAt(pt.x, pt.y);\n }\n\n super.dblClick(evt, cell);\n };\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setTolerance(20);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 120, 120, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 400, 250, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=orthogonalEdgeStyle;'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v2,\n v1,\n 'edgeStyle=orthogonalEdgeStyle;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default EdgeTolerance;\n", - "Events": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxParallelEdgeLayout from '../mxgraph/layout/mxParallelEdgeLayout';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Events extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Events

\n Events. This example demonstrates creating\n a graph container and using the mxDivResizer to update the size,\n interaction on the graph, including marquee selection, custom\n tooltips, context menu handling and changing the default menu\n opacity. It also demonstrates how to use an edgestyle in the\n default stylesheet, and handle the doubleclick on the adjustment\n point. See also: overlays.html for click event handling.\n\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n };\n\n componentDidMount() {\n // Program starts here. Creates a sample graph in the dynamically\n // created DOM node called container which is created below.\n\n class MyCustomConnectionHandler extends mxConnectionHandler {\n // Sets the image to be used for creating new connections\n connectImage = new mxImage('images/green-dot.gif', 14, 14);\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '0px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n // Disables built-in context menu\n mxEvent.disableContextMenu(container);\n this.el.appendChild(container);\n\n class MyCustomGraph extends mxGraph {\n alternateEdgeStyle = 'elbow=vertical';\n\n getTooltipForCell(cell) {\n // Installs a custom tooltip for cells\n return 'Doubleclick and right- or shiftclick';\n }\n\n createConnectionHandler() {\n return new MyCustomConnectionHandler(this);\n }\n }\n\n // Creates the graph inside the DOM node.\n // Optionally you can enable panning, tooltips and connections\n // using graph.setPanning(), setTooltips() & setConnectable().\n // To enable rubberband selection and basic keyboard events,\n // use new mxRubberband(graph) and new mxKeyHandler(graph).\n const graph = new MyCustomGraph(container);\n\n // Enables tooltips, new connections and panning\n graph.setPanning(true);\n graph.setTooltips(true);\n graph.setConnectable(true);\n\n // Automatically handle parallel edges\n const layout = new mxParallelEdgeLayout(graph);\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Enables rubberband (marquee) selection and a handler\n // for basic keystrokes (eg. return, escape during editing).\n const rubberband = new mxRubberband(graph);\n const keyHandler = new mxKeyHandler(graph);\n\n // Changes the default style for edges \"in-place\" and assigns\n // an alternate edge style which is applied in mxGraph.flip\n // when the user double clicks on the adjustment control point\n // of the edge. The ElbowConnector edge style switches to TopToBottom\n // if the horizontal style is true.\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n\n // Installs a popupmenu handler using local function (see below).\n graph.popupMenuHandler.factoryMethod = (menu, cell, evt) => {\n return this.createPopupMenu(graph, menu, cell, evt);\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Doubleclick',\n 20,\n 20,\n 80,\n 30\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Right-/Shiftclick',\n 200,\n 150,\n 120,\n 30\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Connect/Reconnect',\n 200,\n 20,\n 120,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n 'Control-Drag',\n 20,\n 150,\n 100,\n 30\n );\n const e1 = graph.insertEdge(parent, null, 'Tooltips', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v2, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n\n createPopupMenu(graph, menu, cell, evt) {\n // Function to create the entries in the popupmenu\n if (cell != null) {\n menu.addItem('Cell Item', 'editors/images/image.gif', () => {\n mxUtils.alert('MenuItem1');\n });\n } else {\n menu.addItem('No-Cell Item', 'editors/images/image.gif', () => {\n mxUtils.alert('MenuItem2');\n });\n }\n menu.addSeparator();\n menu.addItem('MenuItem3', '../src/images/warning.gif', () => {\n mxUtils.alert(`MenuItem3: ${graph.getSelectionCount()} selected`);\n });\n }\n}\n\nexport default Events;\n", - "Layers": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Layers extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Layers

\n This example demonstrates using\n multiple layers to contain cells.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container using a model\n // with a custom root and two layers. Layers can also be added\n // dynamically using let layer = model.add(root, new mxCell()).\n const root = new mxCell();\n const layer0 = root.insert(new mxCell());\n const layer1 = root.insert(new mxCell());\n const model = new mxGraphModel(root);\n\n const graph = new mxGraph(this.el, model);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n model.beginUpdate();\n try {\n const v1 = graph.insertVertex(\n layer1,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 30,\n 'fillColor=#C0C0C0'\n );\n const v2 = graph.insertVertex(\n layer1,\n null,\n 'Hello,',\n 200,\n 20,\n 80,\n 30,\n 'fillColor=#C0C0C0'\n );\n const v3 = graph.insertVertex(layer0, null, 'World!', 110, 150, 80, 30);\n const e1 = graph.insertEdge(\n layer1,\n null,\n '',\n v1,\n v3,\n 'strokeColor=#0C0C0C'\n );\n e1.geometry.points = [new mxPoint(60, 165)];\n const e2 = graph.insertEdge(layer0, null, '', v2, v3);\n e2.geometry.points = [new mxPoint(240, 165)];\n const e3 = graph.insertEdge(\n layer0,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=topToBottomEdgeStyle'\n );\n e3.geometry.points = [new mxPoint(150, 30)];\n const e4 = graph.insertEdge(\n layer1,\n null,\n '',\n v2,\n v1,\n 'strokeColor=#0C0C0C;edgeStyle=topToBottomEdgeStyle'\n );\n e4.geometry.points = [new mxPoint(150, 40)];\n } finally {\n // Updates the display\n model.endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('Layer 0', function() {\n model.setVisible(layer0, !model.isVisible(layer0));\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Layer 1', function() {\n model.setVisible(layer1, !model.isVisible(layer1));\n })\n );\n }\n}\n\nexport default Layers;\n", - "Monitor": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxPerimeter from \"../mxgraph/view/mxPerimeter\";\nimport mxEdgeStyle from \"../mxgraph/view/mxEdgeStyle\";\n\nclass Monitor extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

mxGraph Workflow Monitor

\n This example demonstrates using a\n graph to display the current state of a workflow.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '406px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxConstants.SHADOWCOLOR = '#e0e0e0';\n\n // Creates the graph inside the given container\n const graph = createGraph(this.el);\n\n // Creates a process display using the activity names as IDs to refer to the elements\n const xml =\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '';\n const doc = mxUtils.parseXml(xml);\n const codec = new mxCodec(doc);\n codec.decode(doc.documentElement, graph.getModel());\n\n // Creates a button to invoke the refresh function\n this.el2.appendChild(\n mxUtils.button('Update', function(evt) {\n // XML is normally fetched from URL at server using mxUtils.get - this is a client-side\n // string with randomized states to demonstrate the idea of the workflow monitor\n const xml =\n `` +\n `` +\n ``;\n update(graph, xml);\n })\n );\n\n /**\n * Updates the display of the given graph using the XML data\n */\n function update(graph, xml) {\n if (xml != null && xml.length > 0) {\n const doc = mxUtils.parseXml(xml);\n\n if (doc != null && doc.documentElement != null) {\n const model = graph.getModel();\n const nodes = doc.documentElement.getElementsByTagName('update');\n\n if (nodes != null && nodes.length > 0) {\n model.beginUpdate();\n\n try {\n for (let i = 0; i < nodes.length; i++) {\n // Processes the activity nodes inside the process node\n const id = nodes[i].getAttribute('id');\n const state = nodes[i].getAttribute('state');\n\n // Gets the cell for the given activity name from the model\n const cell = model.getCell(id);\n\n // Updates the cell color and adds some tooltip information\n if (cell != null) {\n // Resets the fillcolor and the overlay\n graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, 'white', [\n cell,\n ]);\n graph.removeCellOverlays(cell);\n\n // Changes the cell color for the known states\n if (state == 'Running') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#f8cecc',\n [cell]\n );\n } else if (state == 'Waiting') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#fff2cc',\n [cell]\n );\n } else if (state == 'Completed') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#d4e1f5',\n [cell]\n );\n }\n\n // Adds tooltip information using an overlay icon\n if (state != 'Init') {\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(\n cell,\n createOverlay(graph.warningImage, `State: ${state}`)\n );\n }\n }\n } // for\n } finally {\n model.endUpdate();\n }\n }\n }\n }\n }\n\n /**\n * Creates an overlay object using the given tooltip and text for the alert window\n * which is being displayed on click.\n */\n function createOverlay(image, tooltip) {\n const overlay = new mxCellOverlay(image, tooltip);\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, function(sender, evt) {\n mxUtils.alert(`${tooltip}\\nLast update: ${new Date()}`);\n });\n\n return overlay;\n }\n\n /**\n * Creates and returns an empty graph inside the given container.\n */\n function createGraph(container) {\n const graph = new mxGraph(container);\n graph.setTooltips(true);\n graph.setEnabled(false);\n\n // Disables folding\n graph.isCellFoldable = function(cell, collapse) {\n return false;\n };\n\n // Creates the stylesheet for the process display\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FONTSIZE] = 11;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = '#808080';\n style[mxConstants.STYLE_FILLCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENT_DIRECTION] = mxConstants.DIRECTION_EAST;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_STROKECOLOR] = '#808080';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = '#a0a0a0';\n style[mxConstants.STYLE_FONTCOLOR] = '#606060';\n style[mxConstants.STYLE_FILLCOLOR] = '#E0E0DF';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_STARTSIZE] = 30;\n style[mxConstants.STYLE_ROUNDED] = false;\n style[mxConstants.STYLE_FONTSIZE] = 12;\n style[mxConstants.STYLE_FONTSTYLE] = 0;\n style[mxConstants.STYLE_HORIZONTAL] = false;\n // To improve text quality for vertical labels in some old IE versions...\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = '#efefef';\n\n graph.getStylesheet().putCellStyle('swimlane', style);\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RHOMBUS;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RhombusPerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = '#91BCC0';\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FILLCOLOR] = '#91BCC0';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = 16;\n graph.getStylesheet().putCellStyle('step', style);\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FILLCOLOR] = '#A0C88F';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_STROKECOLOR] = '#A0C88F';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = 16;\n graph.getStylesheet().putCellStyle('start', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_FILLCOLOR] = '#DACCBC';\n style[mxConstants.STYLE_STROKECOLOR] = '#AF7F73';\n graph.getStylesheet().putCellStyle('end', style);\n\n return graph;\n }\n\n /**\n * Returns a random state.\n */\n function getState() {\n let state = 'Init';\n const rnd = Math.random() * 4;\n\n if (rnd > 3) {\n state = 'Completed';\n } else if (rnd > 2) {\n state = 'Running';\n } else if (rnd > 1) {\n state = 'Waiting';\n }\n\n return state;\n }\n }\n}\n\nexport default Monitor;\n", - "Permissions": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nfunction Permission(locked, createEdges, editEdges, editVertices, cloneCells) {\n this.locked = locked != null ? locked : false;\n this.createEdges = createEdges != null ? createEdges : true;\n this.editEdges = editEdges != null ? editEdges : true;\n this.editVertices = editVertices != null ? editVertices : true;\n this.cloneCells = cloneCells != null ? cloneCells : true;\n}\n\nPermission.prototype.apply = function(graph) {\n graph.setConnectable(this.createEdges);\n graph.setCellsLocked(this.locked);\n};\n\nclass Permissions extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Permissions

\n This example demonstrates creating\n permissions to define the available operations a the graph.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300px',\n //background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '00px';\n container.style.top = '40px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n // Enable tooltips, disables mutligraphs, enable loops\n graph.setMultigraph(false);\n graph.setAllowLoops(true);\n\n // Enables rubberband selection and key handling\n const rubberband = new mxRubberband(graph);\n const keyHandler = new mxKeyHandler(graph);\n\n // Assigns the delete key\n keyHandler.bindKey(46, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells();\n }\n });\n\n // Shared variable between child function scopes\n // aka \"private\" variable\n let currentPermission = null;\n\n const apply = function(permission) {\n graph.clearSelection();\n permission.apply(graph);\n graph.setEnabled(true);\n graph.setTooltips(true);\n\n // Updates the icons on the shapes - rarely\n // needed and very slow for large graphs\n graph.refresh();\n currentPermission = permission;\n };\n\n apply(new Permission());\n\n let button = mxUtils.button('Allow All', function(evt) {\n apply(new Permission());\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Connect Only', function(evt) {\n apply(new Permission(false, true, false, false, true));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Edges Only', function(evt) {\n apply(new Permission(false, false, true, false, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Vertices Only', function(evt) {\n apply(new Permission(false, false, false, true, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Select Only', function(evt) {\n apply(new Permission(false, false, false, false, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Locked', function(evt) {\n apply(new Permission(true, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Disabled', function(evt) {\n graph.clearSelection();\n graph.setEnabled(false);\n graph.setTooltips(false);\n });\n this.el.appendChild(button);\n\n // Extends hook functions to use permission object. This could\n // be done by assigning the respective switches (eg.\n // setMovable), but this approach is more flexible, doesn't\n // override any existing behaviour or settings, and allows for\n // dynamic conditions to be used in the functions. See the\n // specification for more functions to extend (eg.\n // isSelectable).\n const oldDisconnectable = graph.isCellDisconnectable;\n graph.isCellDisconnectable = function(cell, terminal, source) {\n return (\n oldDisconnectable.apply(this, arguments) && currentPermission.editEdges\n );\n };\n\n const oldTerminalPointMovable = graph.isTerminalPointMovable;\n graph.isTerminalPointMovable = function(cell) {\n return (\n oldTerminalPointMovable.apply(this, arguments) &&\n currentPermission.editEdges\n );\n };\n\n const oldBendable = graph.isCellBendable;\n graph.isCellBendable = function(cell) {\n return oldBendable.apply(this, arguments) && currentPermission.editEdges;\n };\n\n const oldLabelMovable = graph.isLabelMovable;\n graph.isLabelMovable = function(cell) {\n return (\n oldLabelMovable.apply(this, arguments) && currentPermission.editEdges\n );\n };\n\n const oldMovable = graph.isCellMovable;\n graph.isCellMovable = function(cell) {\n return (\n oldMovable.apply(this, arguments) && currentPermission.editVertices\n );\n };\n\n const oldResizable = graph.isCellResizable;\n graph.isCellResizable = function(cell) {\n return (\n oldResizable.apply(this, arguments) && currentPermission.editVertices\n );\n };\n\n const oldEditable = graph.isCellEditable;\n graph.isCellEditable = function(cell) {\n return (\n (oldEditable.apply(this, arguments) &&\n this.getModel().isVertex(cell) &&\n currentPermission.editVertices) ||\n (this.getModel().isEdge(cell) && currentPermission.editEdges)\n );\n };\n\n const oldDeletable = graph.isCellDeletable;\n graph.isCellDeletable = function(cell) {\n return (\n (oldDeletable.apply(this, arguments) &&\n this.getModel().isVertex(cell) &&\n currentPermission.editVertices) ||\n (this.getModel().isEdge(cell) && currentPermission.editEdges)\n );\n };\n\n const oldCloneable = graph.isCellCloneable;\n graph.isCellCloneable = function(cell) {\n return (\n oldCloneable.apply(this, arguments) && currentPermission.cloneCells\n );\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'Hello,', 200, 20, 80, 30);\n const v3 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, 'Connection', v1, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Permissions;\n", + "Morph": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxMorphing from '../mxgraph/util/mxMorphing';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Morph extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Morph

\n This example demonstrates using mxMorphing for simple cell animations.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n var v2;\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n let mult = 1;\n\n this.el2.appendChild(\n mxUtils.button('Morph', function() {\n graph.clearSelection();\n\n graph.getModel().beginUpdate();\n try {\n let geo = graph.getCellGeometry(v1);\n geo = geo.clone();\n geo.x += 180 * mult;\n graph.getModel().setGeometry(v1, geo);\n\n geo = graph.getCellGeometry(v2);\n geo = geo.clone();\n geo.x -= 180 * mult;\n graph.getModel().setGeometry(v2, geo);\n } finally {\n // Arguments are number of steps, ease and delay\n const morph = new mxMorphing(graph, 20, 1.2, 20);\n morph.addListener(mxEvent.DONE, function() {\n graph.getModel().endUpdate();\n });\n morph.startAnimation();\n }\n\n mult *= -1;\n })\n );\n }\n}\n\nexport default Morph;\n", + "FixedPoints": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstraintHandler from '../mxgraph/handler/mxConstraintHandler';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCellState from '../mxgraph/view/mxCellState';\n\nclass FixedPoints extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Fixed points

\n This example demonstrates using fixed connection points for connecting\n edges to vertices.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Snaps to fixed points\n mxConstraintHandler.prototype.intersects = function(\n icon,\n point,\n source,\n existingEdge\n ) {\n return !source || existingEdge || mxUtils.intersects(icon.bounds, point);\n };\n\n // Special case: Snaps source of new connections to fixed points\n // Without a connect preview in connectionHandler.createEdgeState mouseMove\n // and getSourcePerimeterPoint should be overriden by setting sourceConstraint\n // sourceConstraint to null in mouseMove and updating it and returning the\n // nearest point (cp) in getSourcePerimeterPoint (see below)\n const mxConnectionHandlerUpdateEdgeState =\n mxConnectionHandler.prototype.updateEdgeState;\n mxConnectionHandler.prototype.updateEdgeState = function(pt, constraint) {\n if (pt != null && this.previous != null) {\n const constraints = this.graph.getAllConnectionConstraints(\n this.previous\n );\n let nearestConstraint = null;\n let dist = null;\n\n for (let i = 0; i < constraints.length; i++) {\n const cp = this.graph.getConnectionPoint(\n this.previous,\n constraints[i]\n );\n\n if (cp != null) {\n const tmp =\n (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);\n\n if (dist == null || tmp < dist) {\n nearestConstraint = constraints[i];\n dist = tmp;\n }\n }\n }\n\n if (nearestConstraint != null) {\n this.sourceConstraint = nearestConstraint;\n }\n\n // In case the edge style must be changed during the preview:\n // this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';\n // And to use the new edge style in the new edge inserted into the graph,\n // update the cell style as follows:\n // this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);\n }\n\n mxConnectionHandlerUpdateEdgeState.apply(this, arguments);\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // graph.connectionHandler.connectImage = new mxImage('images/connector.gif', 16, 16);\n\n // Disables floating connections (only use with no connect image)\n if (graph.connectionHandler.connectImage == null) {\n graph.connectionHandler.isConnectableCell = function(cell) {\n return false;\n };\n mxEdgeHandler.prototype.isConnectableCell = function(cell) {\n return graph.connectionHandler.isConnectableCell(cell);\n };\n }\n\n graph.getAllConnectionConstraints = function(terminal) {\n if (terminal != null && this.model.isVertex(terminal.cell)) {\n return [\n new mxConnectionConstraint(new mxPoint(0, 0), true),\n new mxConnectionConstraint(new mxPoint(0.5, 0), true),\n new mxConnectionConstraint(new mxPoint(1, 0), true),\n new mxConnectionConstraint(new mxPoint(0, 0.5), true),\n new mxConnectionConstraint(new mxPoint(1, 0.5), true),\n new mxConnectionConstraint(new mxPoint(0, 1), true),\n new mxConnectionConstraint(new mxPoint(0.5, 1), true),\n new mxConnectionConstraint(new mxPoint(1, 1), true),\n ];\n }\n\n return null;\n };\n\n // Connect preview\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(\n null,\n null,\n null,\n null,\n null,\n 'edgeStyle=orthogonalEdgeStyle'\n );\n\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 60,\n 'shape=triangle;perimeter=trianglePerimeter'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 200,\n 150,\n 80,\n 60,\n 'shape=ellipse;perimeter=ellipsePerimeter'\n );\n const v3 = graph.insertVertex(parent, null, 'Hello,', 200, 20, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=elbowEdgeStyle;elbow=horizontal;' +\n 'exitX=0.5;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v3,\n v2,\n 'edgeStyle=elbowEdgeStyle;elbow=horizontal;orthogonal=0;' +\n 'entryX=0;entryY=0;entryPerimeter=1;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Use this code to snap the source point for new connections without a connect preview,\n // ie. without an overridden graph.connectionHandler.createEdgeState\n /*\n let mxConnectionHandlerMouseMove = mxConnectionHandler.prototype.mouseMove;\n mxConnectionHandler.prototype.mouseMove = function(sender, me)\n {\n this.sourceConstraint = null;\n\n mxConnectionHandlerMouseMove.apply(this, arguments);\n };\n\n let mxConnectionHandlerGetSourcePerimeterPoint = mxConnectionHandler.prototype.getSourcePerimeterPoint;\n mxConnectionHandler.prototype.getSourcePerimeterPoint = function(state, pt, me)\n {\n let result = null;\n\n if (this.previous != null && pt != null)\n {\n let constraints = this.graph.getAllConnectionConstraints(this.previous);\n let nearestConstraint = null;\n let nearest = null;\n let dist = null;\n\n for (let i = 0; i < constraints.length; i++)\n {\n let cp = this.graph.getConnectionPoint(this.previous, constraints[i]);\n\n if (cp != null)\n {\n let tmp = (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);\n\n if (dist == null || tmp < dist)\n {\n nearestConstraint = constraints[i];\n nearest = cp;\n dist = tmp;\n }\n }\n }\n\n if (nearestConstraint != null)\n {\n this.sourceConstraint = nearestConstraint;\n result = nearest;\n }\n }\n\n if (result == null)\n {\n result = mxConnectionHandlerGetSourcePerimeterPoint.apply(this, arguments);\n }\n\n return result;\n };\n */\n };\n}\n\nexport default FixedPoints;\n", + "FileIO": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCellTracker from '../mxgraph/handler/mxCellTracker';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxFastOrganicLayout from '../mxgraph/layout/mxFastOrganicLayout';\nimport mxEventObject from '../mxgraph/util/mxEventObject';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxClient from '../mxgraph/mxClient';\n\nclass FileIO extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

File I/O

\n This example demonstrates reading an XML file, writing a custom parser,\n applying an automatic layout and defining a 2-way edge.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '80vh',\n borderTop: 'gray 1px solid',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Program starts here. Creates a sample graph in the\n // DOM node with the specified ID. This function is invoked\n // from the onLoad event handler of the document (see below).\n function main(container) {\n // Checks if browser is supported\n if (!mxClient.isBrowserSupported()) {\n // Displays an error message if the browser is\n // not supported.\n mxUtils.error('Browser is not supported!', 200, false);\n } else {\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n graph.setEnabled(false);\n graph.setPanning(true);\n graph.setTooltips(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Adds a highlight on the cell under the mousepointer\n new mxCellTracker(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ROUNDED;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 4;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_CLASSIC;\n graph.getStylesheet().putCellStyle('2way', style);\n\n graph.isHtmlLabel = function(cell) {\n return true;\n };\n\n // Larger grid size yields cleaner layout result\n graph.gridSize = 20;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxFastOrganicLayout(graph);\n\n // Moves stuff wider apart than usual\n layout.forceConstant = 140;\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Arrange', function(evt) {\n const parent = graph.getDefaultParent();\n layout.execute(parent);\n })\n );\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n // Loads the custom file format (TXT file)\n parse(graph, 'fileio.txt');\n\n // Loads the mxGraph file format (XML file)\n // read(graph, 'fileio.xml');\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.dblClick = function(evt, cell) {\n const mxe = new mxEventObject(\n mxEvent.DOUBLE_CLICK,\n 'event',\n evt,\n 'cell',\n cell\n );\n this.fireEvent(mxe);\n\n if (\n this.isEnabled() &&\n !mxEvent.isConsumed(evt) &&\n !mxe.isConsumed() &&\n cell != null\n ) {\n mxUtils.alert(\n `Show properties for cell ${cell.customId || cell.getId()}`\n );\n }\n };\n }\n }\n\n // Custom parser for simple file format\n function parse(graph, filename) {\n const model = graph.getModel();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const req = mxUtils.load(filename);\n const text = req.getText();\n\n const lines = text.split('\\n');\n\n // Creates the lookup table for the vertices\n const vertices = [];\n\n // Parses all lines (vertices must be first in the file)\n graph.getModel().beginUpdate();\n try {\n for (let i = 0; i < lines.length; i++) {\n // Ignores comments (starting with #)\n const colon = lines[i].indexOf(':');\n\n if (lines[i].substring(0, 1) != '#' || colon == -1) {\n const comma = lines[i].indexOf(',');\n const value = lines[i].substring(colon + 2, lines[i].length);\n\n if (comma == -1 || comma > colon) {\n const key = lines[i].substring(0, colon);\n\n if (key.length > 0) {\n vertices[key] = graph.insertVertex(\n parent,\n null,\n value,\n 0,\n 0,\n 80,\n 70\n );\n }\n } else if (comma < colon) {\n // Looks up the vertices in the lookup table\n const source = vertices[lines[i].substring(0, comma)];\n const target = vertices[lines[i].substring(comma + 1, colon)];\n\n if (source != null && target != null) {\n const e = graph.insertEdge(parent, null, value, source, target);\n\n // Uses the special 2-way style for 2-way labels\n if (value.indexOf('2-Way') >= 0) {\n e.style = '2way';\n }\n }\n }\n }\n }\n } finally {\n graph.getModel().endUpdate();\n }\n }\n\n // Parses the mxGraph XML file format\n function read(graph, filename) {\n const req = mxUtils.load(filename);\n const root = req.getDocumentElement();\n const dec = new mxCodec(root.ownerDocument);\n\n dec.decode(root, graph.getModel());\n }\n };\n}\n\nexport default FileIO;\n", + "Grid": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxLog from '../mxgraph/util/mxLog';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\n\nclass Grid extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Grid

\n This example demonstrates drawing a grid dynamically using HTML 5\n canvas.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '481px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.graphHandler.scaleGrid = true;\n graph.setPanning(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n let repaintGrid;\n\n // Create grid dynamically (requires canvas)\n (function() {\n try {\n const canvas = document.createElement('canvas');\n canvas.style.position = 'absolute';\n canvas.style.top = '0px';\n canvas.style.left = '0px';\n canvas.style.zIndex = -1;\n graph.container.appendChild(canvas);\n\n const ctx = canvas.getContext('2d');\n\n // Modify event filtering to accept canvas as container\n const mxGraphViewIsContainerEvent =\n mxGraphView.prototype.isContainerEvent;\n mxGraphView.prototype.isContainerEvent = function(evt) {\n return (\n mxGraphViewIsContainerEvent.apply(this, arguments) ||\n mxEvent.getSource(evt) === canvas\n );\n };\n\n let s = 0;\n let gs = 0;\n let tr = new mxPoint();\n let w = 0;\n let h = 0;\n\n repaintGrid = function() {\n if (ctx != null) {\n const bounds = graph.getGraphBounds();\n const width = Math.max(\n bounds.x + bounds.width,\n graph.container.clientWidth\n );\n const height = Math.max(\n bounds.y + bounds.height,\n graph.container.clientHeight\n );\n const sizeChanged = width !== w || height !== h;\n\n if (\n graph.view.scale !== s ||\n graph.view.translate.x !== tr.x ||\n graph.view.translate.y !== tr.y ||\n gs !== graph.gridSize ||\n sizeChanged\n ) {\n tr = graph.view.translate.clone();\n s = graph.view.scale;\n gs = graph.gridSize;\n w = width;\n h = height;\n\n // Clears the background if required\n if (!sizeChanged) {\n ctx.clearRect(0, 0, w, h);\n } else {\n canvas.setAttribute('width', w);\n canvas.setAttribute('height', h);\n }\n\n const tx = tr.x * s;\n const ty = tr.y * s;\n\n // Sets the distance of the grid lines in pixels\n const minStepping = graph.gridSize;\n let stepping = minStepping * s;\n\n if (stepping < minStepping) {\n const count =\n Math.round(Math.ceil(minStepping / stepping) / 2) * 2;\n stepping = count * stepping;\n }\n\n const xs = Math.floor((0 - tx) / stepping) * stepping + tx;\n let xe = Math.ceil(w / stepping) * stepping;\n const ys = Math.floor((0 - ty) / stepping) * stepping + ty;\n let ye = Math.ceil(h / stepping) * stepping;\n\n xe += Math.ceil(stepping);\n ye += Math.ceil(stepping);\n\n const ixs = Math.round(xs);\n const ixe = Math.round(xe);\n const iys = Math.round(ys);\n const iye = Math.round(ye);\n\n // Draws the actual grid\n ctx.strokeStyle = '#f6f6f6';\n ctx.beginPath();\n\n for (let x = xs; x <= xe; x += stepping) {\n x = Math.round((x - tx) / stepping) * stepping + tx;\n const ix = Math.round(x);\n\n ctx.moveTo(ix + 0.5, iys + 0.5);\n ctx.lineTo(ix + 0.5, iye + 0.5);\n }\n\n for (let y = ys; y <= ye; y += stepping) {\n y = Math.round((y - ty) / stepping) * stepping + ty;\n const iy = Math.round(y);\n\n ctx.moveTo(ixs + 0.5, iy + 0.5);\n ctx.lineTo(ixe + 0.5, iy + 0.5);\n }\n\n ctx.closePath();\n ctx.stroke();\n }\n }\n };\n } catch (e) {\n mxLog.show();\n mxLog.debug('Using background image');\n\n this.el.style.backgroundImage = \"url('editors/images/grid.gif')\";\n }\n\n const mxGraphViewValidateBackground =\n mxGraphView.prototype.validateBackground;\n mxGraphView.prototype.validateBackground = function() {\n mxGraphViewValidateBackground.apply(this, arguments);\n repaintGrid();\n };\n })();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.centerZoom = false;\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Grid;\n", + "Handles": "/**\n * Copyright (c) 2006-2014, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxVertexHandler from '../mxgraph/handler/mxVertexHandler';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxHandle from '../mxgraph/handler/mxHandle';\n\nclass Handles extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Handles

\n This example demonstrates using mxHandle to change custom styles\n interactively.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n class MyShape extends mxCylinder {\n defaultPos1 = 20;\n\n defaultPos2 = 60;\n\n getLabelBounds(rect) {\n const pos1 =\n mxUtils.getValue(this.style, 'pos1', this.defaultPos1) * this.scale;\n const pos2 =\n mxUtils.getValue(this.style, 'pos2', this.defaultPos2) * this.scale;\n return new mxRectangle(\n rect.x,\n rect.y + pos1,\n rect.width,\n Math.min(rect.height, pos2) - Math.max(0, pos1)\n );\n }\n\n redrawPath(path, x, y, w, h, isForeground) {\n const pos1 = mxUtils.getValue(this.style, 'pos1', this.defaultPos1);\n const pos2 = mxUtils.getValue(this.style, 'pos2', this.defaultPos2);\n\n if (isForeground) {\n if (pos1 < h) {\n path.moveTo(0, pos1);\n path.lineTo(w, pos1);\n }\n\n if (pos2 < h) {\n path.moveTo(0, pos2);\n path.lineTo(w, pos2);\n }\n } else {\n path.rect(0, 0, w, h);\n }\n }\n }\n mxCellRenderer.registerShape('myShape', MyShape);\n\n class MyCustomVertexHandler extends mxVertexHandler {\n livePreview = true;\n\n rotationEnabled = true;\n\n createCustomHandles() {\n if (this.state.style.shape === 'myShape') {\n // Implements the handle for the first divider\n const firstHandle = new mxHandle(this.state);\n\n firstHandle.getPosition = function(bounds) {\n const pos2 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n const pos1 = Math.max(\n 0,\n Math.min(\n pos2,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n\n return new mxPoint(bounds.getCenterX(), bounds.y + pos1);\n };\n\n firstHandle.setPosition = function(bounds, pt) {\n const pos2 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n\n this.state.style.pos1 = Math.round(\n Math.max(0, Math.min(pos2, pt.y - bounds.y))\n );\n };\n\n firstHandle.execute = function() {\n this.copyStyle('pos1');\n };\n\n firstHandle.ignoreGrid = true;\n\n // Implements the handle for the second divider\n const secondHandle = new mxHandle(this.state);\n\n secondHandle.getPosition = function(bounds) {\n const pos1 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n const pos2 = Math.max(\n pos1,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos2',\n MyShape.prototype.defaultPos2\n )\n )\n )\n );\n\n return new mxPoint(bounds.getCenterX(), bounds.y + pos2);\n };\n\n secondHandle.setPosition = function(bounds, pt) {\n const pos1 = Math.max(\n 0,\n Math.min(\n bounds.height,\n parseFloat(\n mxUtils.getValue(\n this.state.style,\n 'pos1',\n MyShape.prototype.defaultPos1\n )\n )\n )\n );\n\n this.state.style.pos2 = Math.round(\n Math.max(pos1, Math.min(bounds.height, pt.y - bounds.y))\n );\n };\n\n secondHandle.execute = function() {\n this.copyStyle('pos2');\n };\n\n secondHandle.ignoreGrid = true;\n\n return [firstHandle, secondHandle];\n }\n\n return null;\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createVertexHandler(state) {\n return new MyCustomVertexHandler(state);\n }\n }\n\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setCellsCloneable(true);\n graph.setHtmlLabels(true);\n graph.setPanning(true);\n graph.centerZoom = false;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n 20,\n 20,\n 240,\n 120,\n 'shape=myShape;whiteSpace=wrap;overflow=hidden;pos1=30;pos2=80;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Handles;\n", + "Windows": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxLog from '../mxgraph/util/mxLog';\nimport mxWindow from '../mxgraph/util/mxWindow';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Windows extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Windows

\n This example demonstrates using the mxWindow class for displaying\n windows.\n {\n this.el = el;\n }}\n style={{\n overflow: 'auto',\n position: 'relative',\n height: '500px',\n background: 'lightyellow',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Note that we're using the container scrollbars for the graph so that the\n // container extends to the parent div inside the window\n let wnd = new mxWindow(\n 'Scrollable, resizable, given height',\n this.el,\n 50,\n 50,\n 220,\n 224,\n true,\n true\n );\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection and keystrokes\n graph.setTooltips(true);\n graph.setPanning(true);\n const rubberband = new mxRubberband(graph);\n new mxKeyHandler(graph);\n\n mxEvent.disableContextMenu(this.el);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n wnd.setMaximizable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n const lorem =\n 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ';\n let content = document.createElement('div');\n mxUtils.write(content, lorem + lorem + lorem);\n\n wnd = new mxWindow(\n 'Scrollable, resizable, auto height',\n content,\n 300,\n 50,\n 200,\n null,\n true,\n true\n );\n wnd.setMaximizable(true);\n wnd.setScrollable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n content = content.cloneNode(true);\n content.style.width = '400px';\n\n wnd = new mxWindow(\n 'Scrollable, resizable, fixed content',\n content,\n 520,\n 50,\n 220,\n 200,\n true,\n true\n );\n wnd.setMaximizable(true);\n wnd.setScrollable(true);\n wnd.setResizable(true);\n wnd.setVisible(true);\n\n mxLog.show();\n }\n}\n\nexport default Windows;\n", + "Template": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n \n Template. This is used as a template HTML file by the\n backends to demonstrate the deployment of the client with a graph embedded\n in the page as XML data (see graph variable in the onload-handler).\n \n *** THIS FILE MUST BE DEPLOYED BY ONE OF THE BACKENDS! ***\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCodec from '../mxgraph/io/mxCodec';\n\nclass Template extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background:\n \"url('/mxgraph/javascript/examples/editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection to the graph\n new mxRubberband(graph);\n\n const doc = mxUtils.parseXml(xml);\n const codec = new mxCodec(doc);\n codec.decode(doc.documentElement, graph.getModel());\n }\n}\n\nexport default Template;\n", + "Anchors": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxShape from '../mxgraph/shape/mxShape';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxPolyline from '../mxgraph/shape/mxPolyline';\nimport mxCellState from '../mxgraph/view/mxCellState';\n\nclass Anchors extends React.Component {\n constructor(props) {\n super(props);\n }\n\n componentDidMount() {\n // Overridden to define per-shape connection points\n mxGraph.prototype.getAllConnectionConstraints = function(terminal, source) {\n if (terminal != null && terminal.shape != null) {\n if (terminal.shape.stencil != null) {\n if (terminal.shape.stencil.constraints != null) {\n return terminal.shape.stencil.constraints;\n }\n } else if (terminal.shape.constraints != null) {\n return terminal.shape.constraints;\n }\n }\n return null;\n };\n\n // Defines the default constraints for all shapes\n mxShape.prototype.constraints = [\n new mxConnectionConstraint(new mxPoint(0.25, 0), true),\n new mxConnectionConstraint(new mxPoint(0.5, 0), true),\n new mxConnectionConstraint(new mxPoint(0.75, 0), true),\n new mxConnectionConstraint(new mxPoint(0, 0.25), true),\n new mxConnectionConstraint(new mxPoint(0, 0.5), true),\n new mxConnectionConstraint(new mxPoint(0, 0.75), true),\n new mxConnectionConstraint(new mxPoint(1, 0.25), true),\n new mxConnectionConstraint(new mxPoint(1, 0.5), true),\n new mxConnectionConstraint(new mxPoint(1, 0.75), true),\n new mxConnectionConstraint(new mxPoint(0.25, 1), true),\n new mxConnectionConstraint(new mxPoint(0.5, 1), true),\n new mxConnectionConstraint(new mxPoint(0.75, 1), true),\n ];\n\n // Edges have no connection points\n mxPolyline.prototype.constraints = null;\n\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Enables connect preview for the default edge style\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(null, null, null, null, null);\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Specifies the default edge style\n graph.getStylesheet().getDefaultEdgeStyle().edgeStyle =\n 'orthogonalEdgeStyle';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n value: '',\n position: v1,\n size: v2,\n });\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Anchors

\n This example demonstrates defining fixed connection points for all\n shapes.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n}\n\nexport default Anchors;\n", + "SecondLabel": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxRectangleShape from '../mxgraph/shape/mxRectangleShape';\nimport mxText from '../mxgraph/shape/mxText';\n\nclass SecondLabel extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Second label

\n This example demonstrates how to add another string label to vertices.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Simple solution to add additional text to the rectangle shape definition:\n (function() {\n const mxRectangleShapeIsHtmlAllowed =\n mxRectangleShape.prototype.isHtmlAllowed;\n mxRectangleShape.prototype.isHtmlAllowed = function() {\n return (\n mxRectangleShapeIsHtmlAllowed.apply(this, arguments) &&\n this.state == null\n );\n };\n\n const mxRectangleShapePaintForeground =\n mxRectangleShape.prototype.paintForeground;\n mxRectangleShape.prototype.paintForeground = function(c, x, y, w, h) {\n if (\n this.state != null &&\n this.state.cell.geometry != null &&\n !this.state.cell.geometry.relative\n ) {\n c.setFontColor('#a0a0a0');\n c.text(x + 2, y, 0, 0, this.state.cell.id, 'left', 'top');\n }\n\n mxRectangleShapePaintForeground.apply(this, arguments);\n };\n })();\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables the folding icon\n graph.isCellFoldable = function(cell) {\n return false;\n };\n\n let secondLabelVisible = true;\n\n // Hook for returning shape number for a given cell\n graph.getSecondLabel = function(cell) {\n if (!this.model.isEdge(cell)) {\n // Possible to return any string here\n return `The ID of this cell is ${cell.id}`;\n }\n\n return null;\n };\n\n let relativeChildVerticesVisible = true;\n\n // Overrides method to hide relative child vertices\n graph.isCellVisible = function(cell) {\n return (\n !this.model.isVertex(cell) ||\n cell.geometry == null ||\n !cell.geometry.relative ||\n cell.geometry.relative == relativeChildVerticesVisible\n );\n };\n\n // Creates the shape for the shape number and puts it into the draw pane\n const { redrawShape } = graph.cellRenderer;\n graph.cellRenderer.redrawShape = function(state, force, rendering) {\n const result = redrawShape.apply(this, arguments);\n\n if (\n result &&\n secondLabelVisible &&\n state.cell.geometry != null &&\n !state.cell.geometry.relative\n ) {\n const secondLabel = graph.getSecondLabel(state.cell);\n\n if (\n secondLabel != null &&\n state.shape != null &&\n state.secondLabel == null\n ) {\n state.secondLabel = new mxText(\n secondLabel,\n new mxRectangle(),\n mxConstants.ALIGN_LEFT,\n mxConstants.ALIGN_BOTTOM\n );\n\n // Styles the label\n state.secondLabel.color = 'black';\n state.secondLabel.family = 'Verdana';\n state.secondLabel.size = 8;\n state.secondLabel.fontStyle = mxConstants.FONT_ITALIC;\n state.secondLabel.background = 'yellow';\n state.secondLabel.border = 'black';\n state.secondLabel.valign = 'bottom';\n state.secondLabel.dialect = state.shape.dialect;\n state.secondLabel.dialect = mxConstants.DIALECT_STRICTHTML;\n state.secondLabel.wrap = true;\n graph.cellRenderer.initializeLabel(state, state.secondLabel);\n }\n }\n\n if (state.secondLabel != null) {\n const scale = graph.getView().getScale();\n const bounds = new mxRectangle(\n state.x + state.width - 8 * scale,\n state.y + 8 * scale,\n 35,\n 0\n );\n state.secondLabel.state = state;\n state.secondLabel.value = graph.getSecondLabel(state.cell);\n state.secondLabel.scale = scale;\n state.secondLabel.bounds = bounds;\n state.secondLabel.redraw();\n }\n\n return result;\n };\n\n // Destroys the shape number\n const { destroy } = graph.cellRenderer;\n graph.cellRenderer.destroy = function(state) {\n destroy.apply(this, arguments);\n\n if (state.secondLabel != null) {\n state.secondLabel.destroy();\n state.secondLabel = null;\n }\n };\n\n graph.cellRenderer.getShapesForState = function(state) {\n return [state.shape, state.text, state.secondLabel, state.control];\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 30, 40, 80, 30);\n // Alternative solution of creating a second label by creating a realtive child vertex\n // with size (0, 0). This will not be selectable and only the label colors can be used\n // for coloring as the actual shape will have zero size.\n const v11 = graph.insertVertex(\n v1,\n null,\n 'World',\n 1,\n 1,\n 0,\n 0,\n 'align=left;verticalAlign=top;labelBackgroundColor=red;labelBorderColor=black',\n true\n );\n v11.geometry.offset = new mxPoint(-8, -8);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n // Another alternative solution of creating a second label as a relative child vertex\n // but this time with an automatic size so that the cell is actually selectable and\n // the background is painted as a shape.\n const v21 = graph.insertVertex(\n v2,\n null,\n 'World',\n 1,\n 1,\n 0,\n 0,\n 'align=left;verticalAlign=top;fillColor=red;rounded=1;spacingLeft=4;spacingRight=4',\n true\n );\n v21.geometry.offset = new mxPoint(-8, -8);\n graph.updateCellSize(v21);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Toggle Child Vertices', function(evt) {\n relativeChildVerticesVisible = !relativeChildVerticesVisible;\n graph.refresh();\n })\n );\n\n // Adds a button to execute the layout\n this.el2.appendChild(\n mxUtils.button('Toggle IDs', function(evt) {\n secondLabelVisible = !secondLabelVisible;\n graph.refresh();\n })\n );\n }\n}\n\nexport default SecondLabel;\n", + "PageBreaks": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPrintPreview from '../mxgraph/view/mxPrintPreview';\n\nclass PageBreaks extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Pagebreaks

\n This example demonstrates using the pageBreaksVisible and preferPageSize\n switches and adding headers and footers to print output.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '481px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.view.setScale(0.15);\n graph.pageBreaksVisible = true;\n graph.pageBreakDashed = true;\n graph.preferPageSize = true;\n graph.centerZoom = false;\n graph.setPanning(true);\n\n // Account for the header and footer size in the page format\n const headerSize = 100;\n const footerSize = 100;\n\n // Removes header and footer from page height\n graph.pageFormat.height -= headerSize + footerSize;\n\n // Takes zoom into account for moving cells\n graph.graphHandler.scaleGrid = true;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 10, 10, 280, 330);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n graph.pageFormat.width * graph.pageScale - 280 - 10,\n graph.pageFormat.height * graph.pageScale - 330 - 10,\n 280,\n 330\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('Toggle Page Breaks', function(evt) {\n graph.pageBreaksVisible = !graph.pageBreaksVisible;\n graph.sizeDidChange();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom In', function(evt) {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom Out', function(evt) {\n graph.zoomOut();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Print', function(evt) {\n // Matches actual printer paper size and avoids blank pages\n const scale = 0.5;\n\n // Applies scale to page\n const pf = mxRectangle.fromRectangle(\n graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT\n );\n pf.width = Math.round(pf.width * scale * graph.pageScale);\n pf.height = Math.round(pf.height * scale * graph.pageScale);\n\n // Finds top left corner of top left page\n const bounds = mxRectangle.fromRectangle(graph.getGraphBounds());\n bounds.x -= graph.view.translate.x * graph.view.scale;\n bounds.y -= graph.view.translate.y * graph.view.scale;\n\n const x0 = Math.floor(bounds.x / pf.width) * pf.width;\n const y0 = Math.floor(bounds.y / pf.height) * pf.height;\n\n const preview = new mxPrintPreview(graph, scale, pf, 0, -x0, -y0);\n preview.marginTop = headerSize * scale * graph.pageScale;\n preview.marginBottom = footerSize * scale * graph.pageScale;\n preview.autoOrigin = false;\n\n const oldRenderPage = preview.renderPage;\n preview.renderPage = function(w, h, x, y, content, pageNumber) {\n const div = oldRenderPage.apply(this, arguments);\n\n const header = document.createElement('div');\n header.style.position = 'absolute';\n header.style.boxSizing = 'border-box';\n header.style.fontFamily = 'Arial,Helvetica';\n header.style.height = `${this.marginTop - 10}px`;\n header.style.textAlign = 'center';\n header.style.verticalAlign = 'middle';\n header.style.marginTop = 'auto';\n header.style.fontSize = '12px';\n header.style.width = '100%';\n\n // Vertical centering for text in header/footer\n header.style.lineHeight = `${this.marginTop - 10}px`;\n\n const footer = header.cloneNode(true);\n\n mxUtils.write(header, `Page ${pageNumber} - Header`);\n header.style.borderBottom = '1px solid gray';\n header.style.top = '0px';\n\n mxUtils.write(footer, `Page ${pageNumber} - Footer`);\n footer.style.borderTop = '1px solid gray';\n footer.style.bottom = '0px';\n\n div.firstChild.appendChild(footer);\n div.firstChild.appendChild(header);\n\n return div;\n };\n\n preview.open();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Reset View', function(evt) {\n graph.view.scaleAndTranslate(0.15, 0, 0);\n })\n );\n }\n}\n\nexport default PageBreaks;\n", + "SwimLanes": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxStackLayout from '../mxgraph/layout/mxStackLayout';\nimport mxSwimlaneManager from '../mxgraph/view/mxSwimlaneManager';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxEditor from '../mxgraph/editor/mxEditor';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\n\nclass SwimLanes extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Swimlanes

\n This example demonstrates using swimlanes for pools and lanes and adding\n cells and edges between them. This also demonstrates using the stack\n layout as an automatic layout.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n border: 'gray dotted 1px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates a wrapper editor around a new graph inside\n // the given container using an XML config for the\n // keyboard bindings\n const config = mxUtils\n .load('editors/config/keyhandler-commons.xml')\n .getDocumentElement();\n const editor = new mxEditor(config);\n editor.setGraphContainer(this.el);\n const { graph } = editor;\n const model = graph.getModel();\n\n // Auto-resizes the container\n graph.border = 80;\n graph.getView().translate = new mxPoint(graph.border / 2, graph.border / 2);\n graph.setResizeContainer(true);\n graph.graphHandler.setRemoveCellsFromParent(false);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'middle';\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n style[mxConstants.STYLE_FONTSIZE] = 11;\n style[mxConstants.STYLE_STARTSIZE] = 22;\n style[mxConstants.STYLE_HORIZONTAL] = false;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = 'black';\n delete style[mxConstants.STYLE_FILLCOLOR];\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_FONTSIZE] = 10;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_HORIZONTAL] = true;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'middle';\n delete style[mxConstants.STYLE_STARTSIZE];\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'none';\n graph.getStylesheet().putCellStyle('process', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n delete style[mxConstants.STYLE_ROUNDED];\n graph.getStylesheet().putCellStyle('state', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RHOMBUS;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RhombusPerimeter;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'top';\n style[mxConstants.STYLE_SPACING_TOP] = 40;\n style[mxConstants.STYLE_SPACING_RIGHT] = 64;\n graph.getStylesheet().putCellStyle('condition', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_DOUBLE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_SPACING_TOP] = 28;\n style[mxConstants.STYLE_FONTSIZE] = 14;\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n delete style[mxConstants.STYLE_SPACING_RIGHT];\n graph.getStylesheet().putCellStyle('end', style);\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_BLOCK;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = 'black';\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_DASHED] = true;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_OPEN;\n style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_OVAL;\n graph.getStylesheet().putCellStyle('crossover', style);\n\n // Installs double click on middle control point and\n // changes style of edges between empty and this value\n graph.alternateEdgeStyle = 'elbow=vertical';\n\n // Adds automatic layout and various switches if the\n // graph is enabled\n if (graph.isEnabled()) {\n // Allows new connections but no dangling edges\n graph.setConnectable(true);\n graph.setAllowDanglingEdges(false);\n\n // End-states are no valid sources\n const previousIsValidSource = graph.isValidSource;\n\n graph.isValidSource = function(cell) {\n if (previousIsValidSource.apply(this, arguments)) {\n const style = this.getModel().getStyle(cell);\n\n return (\n style == null || !(style == 'end' || style.indexOf('end') == 0)\n );\n }\n\n return false;\n };\n\n // Start-states are no valid targets, we do not\n // perform a call to the superclass function because\n // this would call isValidSource\n // Note: All states are start states in\n // the example below, so we use the state\n // style below\n graph.isValidTarget = function(cell) {\n const style = this.getModel().getStyle(cell);\n\n return (\n !this.getModel().isEdge(cell) &&\n !this.isSwimlane(cell) &&\n (style == null || !(style == 'state' || style.indexOf('state') == 0))\n );\n };\n\n // Allows dropping cells into new lanes and\n // lanes into new pools, but disallows dropping\n // cells on edges to split edges\n graph.setDropEnabled(true);\n graph.setSplitEnabled(false);\n\n // Returns true for valid drop operations\n graph.isValidDropTarget = function(target, cells, evt) {\n if (this.isSplitEnabled() && this.isSplitTarget(target, cells, evt)) {\n return true;\n }\n\n const model = this.getModel();\n let lane = false;\n let pool = false;\n let cell = false;\n\n // Checks if any lanes or pools are selected\n for (let i = 0; i < cells.length; i++) {\n const tmp = model.getParent(cells[i]);\n lane = lane || this.isPool(tmp);\n pool = pool || this.isPool(cells[i]);\n\n cell = cell || !(lane || pool);\n }\n\n return (\n !pool &&\n cell != lane &&\n ((lane && this.isPool(target)) ||\n (cell && this.isPool(model.getParent(target))))\n );\n };\n\n // Adds new method for identifying a pool\n graph.isPool = function(cell) {\n const model = this.getModel();\n const parent = model.getParent(cell);\n\n return parent != null && model.getParent(parent) == model.getRoot();\n };\n\n // Changes swimlane orientation while collapsed\n graph.model.getStyle = function(cell) {\n let style = mxGraphModel.prototype.getStyle.apply(this, arguments);\n\n if (graph.isCellCollapsed(cell)) {\n if (style != null) {\n style += ';';\n } else {\n style = '';\n }\n\n style += 'horizontal=1;align=left;spacingLeft=14;';\n }\n\n return style;\n };\n\n // Keeps widths on collapse/expand\n const foldingHandler = function(sender, evt) {\n const cells = evt.getProperty('cells');\n\n for (let i = 0; i < cells.length; i++) {\n const geo = graph.model.getGeometry(cells[i]);\n\n if (geo.alternateBounds != null) {\n geo.width = geo.alternateBounds.width;\n }\n }\n };\n\n graph.addListener(mxEvent.FOLD_CELLS, foldingHandler);\n }\n\n // Applies size changes to siblings and parents\n new mxSwimlaneManager(graph);\n\n // Creates a stack depending on the orientation of the swimlane\n const layout = new mxStackLayout(graph, false);\n\n // Makes sure all children fit into the parent swimlane\n layout.resizeParent = true;\n\n // Applies the size to children if parent size changes\n layout.fill = true;\n\n // Only update the size of swimlanes\n layout.isVertexIgnored = function(vertex) {\n return !graph.isSwimlane(vertex);\n };\n\n // Keeps the lanes and pools stacked\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (\n !model.isEdge(cell) &&\n graph.getModel().getChildCount(cell) > 0 &&\n (model.getParent(cell) == model.getRoot() || graph.isPool(cell))\n ) {\n layout.fill = graph.isPool(cell);\n\n return layout;\n }\n\n return null;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n model.beginUpdate();\n try {\n const pool1 = graph.insertVertex(parent, null, 'Pool 1', 0, 0, 640, 0);\n pool1.setConnectable(false);\n\n const lane1a = graph.insertVertex(pool1, null, 'Lane A', 0, 0, 640, 110);\n lane1a.setConnectable(false);\n\n const lane1b = graph.insertVertex(pool1, null, 'Lane B', 0, 0, 640, 110);\n lane1b.setConnectable(false);\n\n const pool2 = graph.insertVertex(parent, null, 'Pool 2', 0, 0, 640, 0);\n pool2.setConnectable(false);\n\n const lane2a = graph.insertVertex(pool2, null, 'Lane A', 0, 0, 640, 140);\n lane2a.setConnectable(false);\n\n const lane2b = graph.insertVertex(pool2, null, 'Lane B', 0, 0, 640, 110);\n lane2b.setConnectable(false);\n\n const start1 = graph.insertVertex(\n lane1a,\n null,\n null,\n 40,\n 40,\n 30,\n 30,\n 'state'\n );\n const end1 = graph.insertVertex(\n lane1a,\n null,\n 'A',\n 560,\n 40,\n 30,\n 30,\n 'end'\n );\n\n const step1 = graph.insertVertex(\n lane1a,\n null,\n 'Contact\\nProvider',\n 90,\n 30,\n 80,\n 50,\n 'process'\n );\n const step11 = graph.insertVertex(\n lane1a,\n null,\n 'Complete\\nAppropriate\\nRequest',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n const step111 = graph.insertVertex(\n lane1a,\n null,\n 'Receive and\\nAcknowledge',\n 385,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const start2 = graph.insertVertex(\n lane2b,\n null,\n null,\n 40,\n 40,\n 30,\n 30,\n 'state'\n );\n\n const step2 = graph.insertVertex(\n lane2b,\n null,\n 'Receive\\nRequest',\n 90,\n 30,\n 80,\n 50,\n 'process'\n );\n const step22 = graph.insertVertex(\n lane2b,\n null,\n 'Refer to Tap\\nSystems\\nCoordinator',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const step3 = graph.insertVertex(\n lane1b,\n null,\n 'Request 1st-\\nGate\\nInformation',\n 190,\n 30,\n 80,\n 50,\n 'process'\n );\n const step33 = graph.insertVertex(\n lane1b,\n null,\n 'Receive 1st-\\nGate\\nInformation',\n 290,\n 30,\n 80,\n 50,\n 'process'\n );\n\n const step4 = graph.insertVertex(\n lane2a,\n null,\n 'Receive and\\nAcknowledge',\n 290,\n 20,\n 80,\n 50,\n 'process'\n );\n const step44 = graph.insertVertex(\n lane2a,\n null,\n 'Contract\\nConstraints?',\n 400,\n 20,\n 50,\n 50,\n 'condition'\n );\n const step444 = graph.insertVertex(\n lane2a,\n null,\n 'Tap for gas\\ndelivery?',\n 480,\n 20,\n 50,\n 50,\n 'condition'\n );\n\n const end2 = graph.insertVertex(\n lane2a,\n null,\n 'B',\n 560,\n 30,\n 30,\n 30,\n 'end'\n );\n const end3 = graph.insertVertex(\n lane2a,\n null,\n 'C',\n 560,\n 84,\n 30,\n 30,\n 'end'\n );\n\n let e = null;\n\n graph.insertEdge(lane1a, null, null, start1, step1);\n graph.insertEdge(lane1a, null, null, step1, step11);\n graph.insertEdge(lane1a, null, null, step11, step111);\n\n graph.insertEdge(lane2b, null, null, start2, step2);\n graph.insertEdge(lane2b, null, null, step2, step22);\n graph.insertEdge(parent, null, null, step22, step3);\n\n graph.insertEdge(lane1b, null, null, step3, step33);\n graph.insertEdge(lane2a, null, null, step4, step44);\n graph.insertEdge(\n lane2a,\n null,\n 'No',\n step44,\n step444,\n 'verticalAlign=bottom'\n );\n graph.insertEdge(\n parent,\n null,\n 'Yes',\n step44,\n step111,\n 'verticalAlign=bottom;horizontal=0;labelBackgroundColor=white;'\n );\n\n graph.insertEdge(\n lane2a,\n null,\n 'Yes',\n step444,\n end2,\n 'verticalAlign=bottom'\n );\n e = graph.insertEdge(\n lane2a,\n null,\n 'No',\n step444,\n end3,\n 'verticalAlign=top'\n );\n e.geometry.points = [\n new mxPoint(\n step444.geometry.x + step444.geometry.width / 2,\n end3.geometry.y + end3.geometry.height / 2\n ),\n ];\n\n graph.insertEdge(parent, null, null, step1, step2, 'crossover');\n graph.insertEdge(parent, null, null, step3, step11, 'crossover');\n e = graph.insertEdge(lane1a, null, null, step11, step33, 'crossover');\n e.geometry.points = [\n new mxPoint(\n step33.geometry.x + step33.geometry.width / 2 + 20,\n step11.geometry.y + (step11.geometry.height * 4) / 5\n ),\n ];\n graph.insertEdge(parent, null, null, step33, step4);\n graph.insertEdge(lane1a, null, null, step111, end1);\n } finally {\n // Updates the display\n model.endUpdate();\n }\n }\n}\n\nexport default SwimLanes;\n", + "Previews": "import React, { useState } from 'react';\n\nimport SourceCodeDisplay from './SourceCodeDisplay';\nimport examplesListing from './examplesListing.json';\n\nfunction Preview({ sourceKey, content }) {\n const [sourceShown, setSourceShown] = useState(false);\n\n return (\n <>\n {content}\n\n {sourceShown ? (\n
\n setSourceShown(false)}\n style={{ float: 'right', color: 'blue', cursor: 'pointer' }}\n >\n hide source\n \n \n \n
\n \n ) : (\n
\n setSourceShown(true)}\n style={{ float: 'right', color: 'blue', cursor: 'pointer' }}\n >\n show source\n \n
\n )}\n \n );\n}\n\nexport default Preview;\n", + "Folding": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxStackLayout from '../mxgraph/layout/mxStackLayout';\n\nclass Folding extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Folding

\n This example demonstrates using a layout to implement a nested group\n structure.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Enables crisp rendering of rectangles in SVG\n mxConstants.ENTITY_SEGMENT = 20;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setDropEnabled(true);\n\n // Disables global features\n graph.collapseToPreferredSize = false;\n graph.constrainChildren = false;\n graph.cellsSelectable = false;\n graph.extendParentsOnAdd = false;\n graph.extendParents = false;\n graph.border = 10;\n\n // Sets global styles\n let style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';\n style[mxConstants.STYLE_SHAPE] = 'swimlane';\n style[mxConstants.STYLE_STARTSIZE] = 30;\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_STROKECOLOR] = 'none';\n style[mxConstants.STYLE_FILLCOLOR] = 'none';\n style[mxConstants.STYLE_FOLDABLE] = false;\n graph.getStylesheet().putCellStyle('column', style);\n\n // Installs auto layout for all levels\n const layout = new mxStackLayout(graph, true);\n layout.border = graph.border;\n const layoutMgr = new mxLayoutManager(graph);\n layoutMgr.getLayout = function(cell) {\n if (!cell.collapsed) {\n if (cell.parent !== graph.model.root) {\n layout.resizeParent = true;\n layout.horizontal = false;\n layout.spacing = 10;\n } else {\n layout.resizeParent = true;\n layout.horizontal = true;\n layout.spacing = 40;\n }\n\n return layout;\n }\n\n return null;\n };\n\n // Resizes the container\n graph.setResizeContainer(true);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const col1 = graph.insertVertex(parent, null, '', 0, 0, 120, 0, 'column');\n\n const v1 = graph.insertVertex(col1, null, '1', 0, 0, 100, 30);\n v1.collapsed = true;\n\n const v11 = graph.insertVertex(v1, null, '1.1', 0, 0, 80, 30);\n v11.collapsed = true;\n\n const v111 = graph.insertVertex(v11, null, '1.1.1', 0, 0, 60, 30);\n const v112 = graph.insertVertex(v11, null, '1.1.2', 0, 0, 60, 30);\n\n const v12 = graph.insertVertex(v1, null, '1.2', 0, 0, 80, 30);\n\n const col2 = graph.insertVertex(parent, null, '', 0, 0, 120, 0, 'column');\n\n const v2 = graph.insertVertex(col2, null, '2', 0, 0, 100, 30);\n v2.collapsed = true;\n\n const v21 = graph.insertVertex(v2, null, '2.1', 0, 0, 80, 30);\n v21.collapsed = true;\n\n const v211 = graph.insertVertex(v21, null, '2.1.1', 0, 0, 60, 30);\n const v212 = graph.insertVertex(v21, null, '2.1.2', 0, 0, 60, 30);\n\n const v22 = graph.insertVertex(v2, null, '2.2', 0, 0, 80, 30);\n\n const v3 = graph.insertVertex(col2, null, '3', 0, 0, 100, 30);\n v3.collapsed = true;\n\n const v31 = graph.insertVertex(v3, null, '3.1', 0, 0, 80, 30);\n v31.collapsed = true;\n\n const v311 = graph.insertVertex(v31, null, '3.1.1', 0, 0, 60, 30);\n const v312 = graph.insertVertex(v31, null, '3.1.2', 0, 0, 60, 30);\n\n const v32 = graph.insertVertex(v3, null, '3.2', 0, 0, 80, 30);\n\n graph.insertEdge(parent, null, '', v111, v211);\n graph.insertEdge(parent, null, '', v112, v212);\n graph.insertEdge(parent, null, '', v112, v22);\n\n graph.insertEdge(parent, null, '', v12, v311);\n graph.insertEdge(parent, null, '', v12, v312);\n graph.insertEdge(parent, null, '', v12, v32);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default Folding;\n", + "EdgeTolerance": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass EdgeTolerance extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Edge tolerance

\n This example demonstrates increasing the tolerance for hit detection on\n edges.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '481px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n const { el } = this;\n\n class MyCustomGraph extends mxGraph {\n fireMouseEvent(evtName, me, sender) {\n // Overrides the mouse event dispatching mechanism to update the\n // cell which is associated with the event in case the native hit\n // detection did not return anything.\n\n // Checks if native hit detection did not return anything\n if (me.getState() == null) {\n // Updates the graph coordinates in the event since we need\n // them here. Storing them in the event means the overridden\n // method doesn't have to do this again.\n if (me.graphX == null || me.graphY == null) {\n const pt = mxUtils.convertPoint(el, me.getX(), me.getY());\n\n me.graphX = pt.x;\n me.graphY = pt.y;\n }\n\n const cell = this.getCellAt(me.graphX, me.graphY);\n\n if (this.getModel().isEdge(cell)) {\n me.state = this.view.getState(cell);\n\n if (me.state != null && me.state.shape != null) {\n this.container.style.cursor = me.state.shape.node.style.cursor;\n }\n }\n }\n\n if (me.state == null) {\n this.container.style.cursor = 'default';\n }\n\n super.fireMouseEvent(evtName, me, sender);\n }\n\n dblClick(evt, cell) {\n // Overrides double click handling to use the tolerance\n if (cell == null) {\n const pt = mxUtils.convertPoint(\n el,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n cell = this.getCellAt(pt.x, pt.y);\n }\n\n super.dblClick(evt, cell);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setTolerance(20);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 120, 120, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 400, 250, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=orthogonalEdgeStyle;'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v2,\n v1,\n 'edgeStyle=orthogonalEdgeStyle;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default EdgeTolerance;\n", + "Events": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxParallelEdgeLayout from '../mxgraph/layout/mxParallelEdgeLayout';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Events extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Events

\n Events. This example demonstrates creating a graph container and using\n the mxDivResizer to update the size, interaction on the graph, including\n marquee selection, custom tooltips, context menu handling and changing\n the default menu opacity. It also demonstrates how to use an edgestyle\n in the default stylesheet, and handle the doubleclick on the adjustment\n point. See also: overlays.html for click event handling.\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n }\n\n componentDidMount() {\n // Program starts here. Creates a sample graph in the dynamically\n // created DOM node called container which is created below.\n\n class MyCustomConnectionHandler extends mxConnectionHandler {\n // Sets the image to be used for creating new connections\n connectImage = new mxImage('images/green-dot.gif', 14, 14);\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '0px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n // Disables built-in context menu\n mxEvent.disableContextMenu(container);\n this.el.appendChild(container);\n\n class MyCustomGraph extends mxGraph {\n alternateEdgeStyle = 'elbow=vertical';\n\n getTooltipForCell(cell) {\n // Installs a custom tooltip for cells\n return 'Doubleclick and right- or shiftclick';\n }\n\n createConnectionHandler() {\n return new MyCustomConnectionHandler(this);\n }\n }\n\n // Creates the graph inside the DOM node.\n // Optionally you can enable panning, tooltips and connections\n // using graph.setPanning(), setTooltips() & setConnectable().\n // To enable rubberband selection and basic keyboard events,\n // use new mxRubberband(graph) and new mxKeyHandler(graph).\n const graph = new MyCustomGraph(container);\n\n // Enables tooltips, new connections and panning\n graph.setPanning(true);\n graph.setTooltips(true);\n graph.setConnectable(true);\n\n // Automatically handle parallel edges\n const layout = new mxParallelEdgeLayout(graph);\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Enables rubberband (marquee) selection and a handler\n // for basic keystrokes (eg. return, escape during editing).\n const rubberband = new mxRubberband(graph);\n const keyHandler = new mxKeyHandler(graph);\n\n // Changes the default style for edges \"in-place\" and assigns\n // an alternate edge style which is applied in mxGraph.flip\n // when the user double clicks on the adjustment control point\n // of the edge. The ElbowConnector edge style switches to TopToBottom\n // if the horizontal style is true.\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n\n // Installs a popupmenu handler using local function (see below).\n graph.popupMenuHandler.factoryMethod = (menu, cell, evt) => {\n return this.createPopupMenu(graph, menu, cell, evt);\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Doubleclick',\n 20,\n 20,\n 80,\n 30\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Right-/Shiftclick',\n 200,\n 150,\n 120,\n 30\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Connect/Reconnect',\n 200,\n 20,\n 120,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n 'Control-Drag',\n 20,\n 150,\n 100,\n 30\n );\n const e1 = graph.insertEdge(parent, null, 'Tooltips', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v2, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n\n createPopupMenu(graph, menu, cell, evt) {\n // Function to create the entries in the popupmenu\n if (cell != null) {\n menu.addItem('Cell Item', 'editors/images/image.gif', () => {\n mxUtils.alert('MenuItem1');\n });\n } else {\n menu.addItem('No-Cell Item', 'editors/images/image.gif', () => {\n mxUtils.alert('MenuItem2');\n });\n }\n menu.addSeparator();\n menu.addItem('MenuItem3', '../src/images/warning.gif', () => {\n mxUtils.alert(`MenuItem3: ${graph.getSelectionCount()} selected`);\n });\n }\n}\n\nexport default Events;\n", + "Layers": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Layers extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Layers

\n This example demonstrates using multiple layers to contain cells.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container using a model\n // with a custom root and two layers. Layers can also be added\n // dynamically using let layer = model.add(root, new mxCell()).\n const root = new mxCell();\n const layer0 = root.insert(new mxCell());\n const layer1 = root.insert(new mxCell());\n const model = new mxGraphModel(root);\n\n const graph = new mxGraph(this.el, model);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n model.beginUpdate();\n try {\n const v1 = graph.insertVertex(\n layer1,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 30,\n 'fillColor=#C0C0C0'\n );\n const v2 = graph.insertVertex(\n layer1,\n null,\n 'Hello,',\n 200,\n 20,\n 80,\n 30,\n 'fillColor=#C0C0C0'\n );\n const v3 = graph.insertVertex(layer0, null, 'World!', 110, 150, 80, 30);\n const e1 = graph.insertEdge(\n layer1,\n null,\n '',\n v1,\n v3,\n 'strokeColor=#0C0C0C'\n );\n e1.geometry.points = [new mxPoint(60, 165)];\n const e2 = graph.insertEdge(layer0, null, '', v2, v3);\n e2.geometry.points = [new mxPoint(240, 165)];\n const e3 = graph.insertEdge(\n layer0,\n null,\n '',\n v1,\n v2,\n 'edgeStyle=topToBottomEdgeStyle'\n );\n e3.geometry.points = [new mxPoint(150, 30)];\n const e4 = graph.insertEdge(\n layer1,\n null,\n '',\n v2,\n v1,\n 'strokeColor=#0C0C0C;edgeStyle=topToBottomEdgeStyle'\n );\n e4.geometry.points = [new mxPoint(150, 40)];\n } finally {\n // Updates the display\n model.endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('Layer 0', function() {\n model.setVisible(layer0, !model.isVisible(layer0));\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Layer 1', function() {\n model.setVisible(layer1, !model.isVisible(layer1));\n })\n );\n }\n}\n\nexport default Layers;\n", + "Monitor": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\n\nclass Monitor extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

mxGraph Workflow Monitor

\n This example demonstrates using a graph to display the current state of\n a workflow.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '406px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxConstants.SHADOWCOLOR = '#e0e0e0';\n\n // Creates the graph inside the given container\n const graph = createGraph(this.el);\n\n // Creates a process display using the activity names as IDs to refer to the elements\n const xml =\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '' +\n '';\n const doc = mxUtils.parseXml(xml);\n const codec = new mxCodec(doc);\n codec.decode(doc.documentElement, graph.getModel());\n\n // Creates a button to invoke the refresh function\n this.el2.appendChild(\n mxUtils.button('Update', function(evt) {\n // XML is normally fetched from URL at server using mxUtils.get - this is a client-side\n // string with randomized states to demonstrate the idea of the workflow monitor\n const xml =\n `` +\n `` +\n ``;\n update(graph, xml);\n })\n );\n\n /**\n * Updates the display of the given graph using the XML data\n */\n function update(graph, xml) {\n if (xml != null && xml.length > 0) {\n const doc = mxUtils.parseXml(xml);\n\n if (doc != null && doc.documentElement != null) {\n const model = graph.getModel();\n const nodes = doc.documentElement.getElementsByTagName('update');\n\n if (nodes != null && nodes.length > 0) {\n model.beginUpdate();\n\n try {\n for (let i = 0; i < nodes.length; i++) {\n // Processes the activity nodes inside the process node\n const id = nodes[i].getAttribute('id');\n const state = nodes[i].getAttribute('state');\n\n // Gets the cell for the given activity name from the model\n const cell = model.getCell(id);\n\n // Updates the cell color and adds some tooltip information\n if (cell != null) {\n // Resets the fillcolor and the overlay\n graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, 'white', [\n cell,\n ]);\n graph.removeCellOverlays(cell);\n\n // Changes the cell color for the known states\n if (state == 'Running') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#f8cecc',\n [cell]\n );\n } else if (state == 'Waiting') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#fff2cc',\n [cell]\n );\n } else if (state == 'Completed') {\n graph.setCellStyles(\n mxConstants.STYLE_FILLCOLOR,\n '#d4e1f5',\n [cell]\n );\n }\n\n // Adds tooltip information using an overlay icon\n if (state != 'Init') {\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(\n cell,\n createOverlay(graph.warningImage, `State: ${state}`)\n );\n }\n }\n } // for\n } finally {\n model.endUpdate();\n }\n }\n }\n }\n }\n\n /**\n * Creates an overlay object using the given tooltip and text for the alert window\n * which is being displayed on click.\n */\n function createOverlay(image, tooltip) {\n const overlay = new mxCellOverlay(image, tooltip);\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, function(sender, evt) {\n mxUtils.alert(`${tooltip}\\nLast update: ${new Date()}`);\n });\n\n return overlay;\n }\n\n /**\n * Creates and returns an empty graph inside the given container.\n */\n function createGraph(container) {\n const graph = new mxGraph(container);\n graph.setTooltips(true);\n graph.setEnabled(false);\n\n // Disables folding\n graph.isCellFoldable = function(cell, collapse) {\n return false;\n };\n\n // Creates the stylesheet for the process display\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FONTSIZE] = 11;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKECOLOR] = '#808080';\n style[mxConstants.STYLE_FILLCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENT_DIRECTION] = mxConstants.DIRECTION_EAST;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_STROKECOLOR] = '#808080';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = '#a0a0a0';\n style[mxConstants.STYLE_FONTCOLOR] = '#606060';\n style[mxConstants.STYLE_FILLCOLOR] = '#E0E0DF';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_STARTSIZE] = 30;\n style[mxConstants.STYLE_ROUNDED] = false;\n style[mxConstants.STYLE_FONTSIZE] = 12;\n style[mxConstants.STYLE_FONTSTYLE] = 0;\n style[mxConstants.STYLE_HORIZONTAL] = false;\n // To improve text quality for vertical labels in some old IE versions...\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = '#efefef';\n\n graph.getStylesheet().putCellStyle('swimlane', style);\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RHOMBUS;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RhombusPerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = '#91BCC0';\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FILLCOLOR] = '#91BCC0';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = 16;\n graph.getStylesheet().putCellStyle('step', style);\n\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FILLCOLOR] = '#A0C88F';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_STROKECOLOR] = '#A0C88F';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = 16;\n graph.getStylesheet().putCellStyle('start', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_FILLCOLOR] = '#DACCBC';\n style[mxConstants.STYLE_STROKECOLOR] = '#AF7F73';\n graph.getStylesheet().putCellStyle('end', style);\n\n return graph;\n }\n\n /**\n * Returns a random state.\n */\n function getState() {\n let state = 'Init';\n const rnd = Math.random() * 4;\n\n if (rnd > 3) {\n state = 'Completed';\n } else if (rnd > 2) {\n state = 'Running';\n } else if (rnd > 1) {\n state = 'Waiting';\n }\n\n return state;\n }\n }\n}\n\nexport default Monitor;\n", + "Permissions": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nfunction Permission(locked, createEdges, editEdges, editVertices, cloneCells) {\n this.locked = locked != null ? locked : false;\n this.createEdges = createEdges != null ? createEdges : true;\n this.editEdges = editEdges != null ? editEdges : true;\n this.editVertices = editVertices != null ? editVertices : true;\n this.cloneCells = cloneCells != null ? cloneCells : true;\n}\n\nPermission.prototype.apply = function(graph) {\n graph.setConnectable(this.createEdges);\n graph.setCellsLocked(this.locked);\n};\n\nclass Permissions extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Permissions

\n This example demonstrates creating permissions to define the available\n operations a the graph.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300px',\n // background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '00px';\n container.style.top = '40px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n // Enable tooltips, disables mutligraphs, enable loops\n graph.setMultigraph(false);\n graph.setAllowLoops(true);\n\n // Enables rubberband selection and key handling\n const rubberband = new mxRubberband(graph);\n const keyHandler = new mxKeyHandler(graph);\n\n // Assigns the delete key\n keyHandler.bindKey(46, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells();\n }\n });\n\n // Shared variable between child function scopes\n // aka \"private\" variable\n let currentPermission = null;\n\n const apply = function(permission) {\n graph.clearSelection();\n permission.apply(graph);\n graph.setEnabled(true);\n graph.setTooltips(true);\n\n // Updates the icons on the shapes - rarely\n // needed and very slow for large graphs\n graph.refresh();\n currentPermission = permission;\n };\n\n apply(new Permission());\n\n let button = mxUtils.button('Allow All', function(evt) {\n apply(new Permission());\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Connect Only', function(evt) {\n apply(new Permission(false, true, false, false, true));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Edges Only', function(evt) {\n apply(new Permission(false, false, true, false, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Vertices Only', function(evt) {\n apply(new Permission(false, false, false, true, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Select Only', function(evt) {\n apply(new Permission(false, false, false, false, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Locked', function(evt) {\n apply(new Permission(true, false));\n });\n this.el.appendChild(button);\n\n button = mxUtils.button('Disabled', function(evt) {\n graph.clearSelection();\n graph.setEnabled(false);\n graph.setTooltips(false);\n });\n this.el.appendChild(button);\n\n // Extends hook functions to use permission object. This could\n // be done by assigning the respective switches (eg.\n // setMovable), but this approach is more flexible, doesn't\n // override any existing behaviour or settings, and allows for\n // dynamic conditions to be used in the functions. See the\n // specification for more functions to extend (eg.\n // isSelectable).\n const oldDisconnectable = graph.isCellDisconnectable;\n graph.isCellDisconnectable = function(cell, terminal, source) {\n return (\n oldDisconnectable.apply(this, arguments) && currentPermission.editEdges\n );\n };\n\n const oldTerminalPointMovable = graph.isTerminalPointMovable;\n graph.isTerminalPointMovable = function(cell) {\n return (\n oldTerminalPointMovable.apply(this, arguments) &&\n currentPermission.editEdges\n );\n };\n\n const oldBendable = graph.isCellBendable;\n graph.isCellBendable = function(cell) {\n return oldBendable.apply(this, arguments) && currentPermission.editEdges;\n };\n\n const oldLabelMovable = graph.isLabelMovable;\n graph.isLabelMovable = function(cell) {\n return (\n oldLabelMovable.apply(this, arguments) && currentPermission.editEdges\n );\n };\n\n const oldMovable = graph.isCellMovable;\n graph.isCellMovable = function(cell) {\n return (\n oldMovable.apply(this, arguments) && currentPermission.editVertices\n );\n };\n\n const oldResizable = graph.isCellResizable;\n graph.isCellResizable = function(cell) {\n return (\n oldResizable.apply(this, arguments) && currentPermission.editVertices\n );\n };\n\n const oldEditable = graph.isCellEditable;\n graph.isCellEditable = function(cell) {\n return (\n (oldEditable.apply(this, arguments) &&\n this.getModel().isVertex(cell) &&\n currentPermission.editVertices) ||\n (this.getModel().isEdge(cell) && currentPermission.editEdges)\n );\n };\n\n const oldDeletable = graph.isCellDeletable;\n graph.isCellDeletable = function(cell) {\n return (\n (oldDeletable.apply(this, arguments) &&\n this.getModel().isVertex(cell) &&\n currentPermission.editVertices) ||\n (this.getModel().isEdge(cell) && currentPermission.editEdges)\n );\n };\n\n const oldCloneable = graph.isCellCloneable;\n graph.isCellCloneable = function(cell) {\n return (\n oldCloneable.apply(this, arguments) && currentPermission.cloneCells\n );\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'Hello,', 200, 20, 80, 30);\n const v3 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, 'Connection', v1, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Permissions;\n", "index": "import Head from 'next/head';\nimport styles from '../styles/Home.module.css';\n\nimport HelloWorld from './HelloWorld';\nimport Anchors from './Anchors';\nimport AutoLayout from './AutoLayout';\nimport Animation from './Animation';\nimport Boundary from './Boundary';\nimport Clipboard from './Clipboard';\nimport DragSource from './DragSource';\nimport Control from './Control';\nimport ContextIcons from './ContextIcons';\nimport Collapse from './Collapse';\nimport Constituent from './Constituent';\nimport DynamicLoading from './DynamicLoading';\nimport Drop from './Drop';\nimport DynamicStyle from './DynamicStyle';\nimport DynamicToolbar from './DynamicToolbar';\nimport EdgeTolerance from './EdgeTolerance';\nimport Editing from './Editing';\nimport Tree from './Tree';\nimport Validation from './Validation';\nimport SwimLanes from './SwimLanes';\nimport Wrapping from './Wrapping';\n// import Windows from \"./Windows\";\nimport Visibility from './Visibility';\nimport UserObject from './UserObject';\nimport Toolbar from './Toolbar';\nimport Thread from './Thread';\n// import Template from \"./Template\";\nimport Stylesheet from './Stylesheet';\nimport Stencils from './Stencils';\nimport SecondLabel from './SecondLabel';\nimport Shape from './Shape';\nimport Resources from './Resources';\nimport RadialTreeLayout from './RadialTreeLayout';\nimport PortRefs from './PortRefs';\nimport Permissions from './Permissions';\nimport Perimeter from './Perimeter';\nimport PageBreaks from './PageBreaks';\nimport Overlays from './Overlays';\nimport Orthogonal from './Orthogonal';\nimport OrgChart from './OrgChart';\nimport OffPage from './OffPage';\nimport Morph from './Morph';\nimport Monitor from './Monitor';\nimport Merge from './Merge';\nimport Markers from './Markers';\nimport LOD from './LOD';\nimport Layers from './Layers';\nimport Labels from './Labels';\nimport LabelPosition from './LabelPosition';\nimport JsonData from './JsonData';\nimport Indicators from './Indicators';\nimport Images from './Images';\nimport HoverIcons from './HoverIcons';\nimport HoverStyle from './HoverStyle';\nimport HierarchicalLayout from './HierarchicalLayout';\nimport HelloPort from './HelloPort';\nimport Handles from './Handles';\nimport Guides from './Guides';\nimport Groups from './Groups';\nimport Grid from './Grid';\nimport Folding from './Folding';\nimport FixedPoints from './FixedPoints';\nimport FixedIcon from './FixedIcon';\nimport Preview from './Previews';\n\nexport default function Home() {\n return (\n \n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n {/* } /> */}\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n {/* } /> */}\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n {/* } /> */}\n } />\n } />\n } />\n } />\n } />\n } />\n } />\n {/* } /> */}\n } />\n } />\n {/* } /> */}\n } />\n } />\n } />\n\n } />\n } />\n } />\n {/* } /> */}\n } />\n \n );\n}\n", - "Boundary": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxGraphHandler from \"../mxgraph/handler/mxGraphHandler\";\nimport mxUtils from \"../mxgraph/util/mxUtils\";\n\nclass Boundary extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A this.el for the graph\n return (\n <>\n

Boundary

\n This example demonstrates\n implementing boundary events in BPMN diagrams.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default'\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n\n // Sets the base style for all vertices\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';\n style[mxConstants.STYLE_STROKECOLOR] = '#000000';\n style[mxConstants.STYLE_STROKEWIDTH] = '2';\n style[mxConstants.STYLE_FONTCOLOR] = '#000000';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n graph.getStylesheet().putDefaultVertexStyle(style);\n\n // Removes folding icon for relative children\n graph.isCellFoldable = function(cell, collapse) {\n const childCount = this.model.getChildCount(cell);\n\n for (let i = 0; i < childCount; i++) {\n const child = this.model.getChildAt(cell, i);\n const geo = this.getCellGeometry(child);\n\n if (geo != null && geo.relative) {\n return false;\n }\n }\n\n return childCount > 0;\n };\n\n // Returns the relative position of the given child\n function getRelativePosition(state, dx, dy) {\n if (state != null) {\n const model = graph.getModel();\n const geo = model.getGeometry(state.cell);\n\n if (geo != null && geo.relative && !model.isEdge(state.cell)) {\n const parent = model.getParent(state.cell);\n\n if (model.isVertex(parent)) {\n const pstate = graph.view.getState(parent);\n\n if (pstate != null) {\n const { scale } = graph.view;\n let x = state.x + dx;\n let y = state.y + dy;\n\n if (geo.offset != null) {\n x -= geo.offset.x * scale;\n y -= geo.offset.y * scale;\n }\n\n x = (x - pstate.x) / pstate.width;\n y = (y - pstate.y) / pstate.height;\n\n if (Math.abs(y - 0.5) <= Math.abs((x - 0.5) / 2)) {\n x = x > 0.5 ? 1 : 0;\n y = Math.min(1, Math.max(0, y));\n } else {\n x = Math.min(1, Math.max(0, x));\n y = y > 0.5 ? 1 : 0;\n }\n\n return new mxPoint(x, y);\n }\n }\n }\n }\n\n return null;\n }\n\n // Replaces translation for relative children\n graph.translateCell = function(cell, dx, dy) {\n const rel = getRelativePosition(\n this.view.getState(cell),\n dx * graph.view.scale,\n dy * graph.view.scale\n );\n\n if (rel != null) {\n let geo = this.model.getGeometry(cell);\n\n if (geo != null && geo.relative) {\n geo = geo.clone();\n geo.x = rel.x;\n geo.y = rel.y;\n\n this.model.setGeometry(cell, geo);\n }\n } else {\n mxGraph.prototype.translateCell.apply(this, arguments);\n }\n };\n\n // Replaces move preview for relative children\n graph.graphHandler.getDelta = function(me) {\n const point = mxUtils.convertPoint(\n this.graph.container,\n me.getX(),\n me.getY()\n );\n let delta = new mxPoint(point.x - this.first.x, point.y - this.first.y);\n\n if (\n this.cells != null &&\n this.cells.length > 0 &&\n this.cells[0] != null\n ) {\n const state = this.graph.view.getState(this.cells[0]);\n const rel = getRelativePosition(state, delta.x, delta.y);\n\n if (rel != null) {\n const pstate = this.graph.view.getState(\n this.graph.model.getParent(state.cell)\n );\n\n if (pstate != null) {\n delta = new mxPoint(\n pstate.x + pstate.width * rel.x - state.getCenterX(),\n pstate.y + pstate.height * rel.y - state.getCenterY()\n );\n }\n }\n }\n\n return delta;\n };\n\n // Relative children cannot be removed from parent\n graph.graphHandler.shouldRemoveCellsFromParent = function(\n parent,\n cells,\n evt\n ) {\n return (\n cells.length === 0 &&\n !cells[0].geometry.relative &&\n mxGraphHandler.prototype.shouldRemoveCellsFromParent.apply(\n this,\n arguments\n )\n );\n };\n\n // Enables moving of relative children\n graph.isCellLocked = function(cell) {\n return false;\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Process', 60, 60, 90, 40);\n const v2 = graph.insertVertex(\n v1,\n null,\n 'in',\n 0,\n 0.5,\n 20,\n 20,\n 'fontSize=9;shape=ellipse;resizable=0;'\n );\n v2.geometry.offset = new mxPoint(-10, -10);\n v2.geometry.relative = true;\n const v3 = graph.insertVertex(\n v1,\n null,\n 'out',\n 1,\n 0.5,\n 20,\n 20,\n 'fontSize=9;shape=ellipse;resizable=0;'\n );\n v3.geometry.offset = new mxPoint(-10, -10);\n v3.geometry.relative = true;\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default Boundary;\n", - "HoverStyle": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from \"../mxgraph/util/mxConstants\";\n\nclass HoverStyle extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hoverstyle

\n This example shows hot to change\n the style of a vertex on mouseover.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n function updateStyle(state, hover) {\n if (hover) {\n state.style[mxConstants.STYLE_FILLCOLOR] = '#ff0000';\n }\n\n // Sets rounded style for both cases since the rounded style\n // is not set in the default style and is therefore inherited\n // once it is set, whereas the above overrides the default value\n state.style[mxConstants.STYLE_ROUNDED] = hover ? '1' : '0';\n state.style[mxConstants.STYLE_STROKEWIDTH] = hover ? '4' : '1';\n state.style[mxConstants.STYLE_FONTSTYLE] = hover\n ? mxConstants.FONT_BOLD\n : '0';\n }\n\n // Changes fill color to red on mouseover\n graph.addMouseListener({\n currentState: null,\n previousStyle: null,\n mouseDown(sender, me) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n this.currentState = null;\n }\n },\n mouseMove(sender, me) {\n if (this.currentState != null && me.getState() == this.currentState) {\n return;\n }\n\n let tmp = graph.view.getState(me.getCell());\n\n // Ignores everything but vertices\n if (\n graph.isMouseDown ||\n (tmp != null && !graph.getModel().isVertex(tmp.cell))\n ) {\n tmp = null;\n }\n\n if (tmp != this.currentState) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n }\n\n this.currentState = tmp;\n\n if (this.currentState != null) {\n this.dragEnter(me.getEvent(), this.currentState);\n }\n }\n },\n mouseUp(sender, me) {},\n dragEnter(evt, state) {\n if (state != null) {\n this.previousStyle = state.style;\n state.style = mxUtils.clone(state.style);\n updateStyle(state, true);\n state.shape.apply(state);\n state.shape.redraw();\n\n if (state.text != null) {\n state.text.apply(state);\n state.text.redraw();\n }\n }\n },\n dragLeave(evt, state) {\n if (state != null) {\n state.style = this.previousStyle;\n updateStyle(state, false);\n state.shape.apply(state);\n state.shape.redraw();\n\n if (state.text != null) {\n state.text.apply(state);\n state.text.redraw();\n }\n }\n },\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HoverStyle;\n", - "HelloWorld": "/*\n * Copyright (c) 2006-2018, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\n\nclass HelloWorld extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph with a grid wallpaper\n return (\n <>\n

Hello, World!

\n This example demonstrates using\n a DOM node to create a graph and adding vertices and edges.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // FIXME!!\n const mxBasePath = '../src';\n\n // Create a sample graph in the DOM node with the specified ID.\n mxEvent.disableContextMenu(this.el); // Disable the built-in context menu\n const graph = new mxGraph(this.el); // Create the graph inside the given container\n new mxRubberband(graph); // Enable rubberband selection\n\n // Get the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n graph.batchUpdate(() => {\n // Add cells to the model in a single step\n const vertex1 = graph.insertVertex({\n parent,\n value: 'Hello',\n position: [20, 20],\n size: [80, 30],\n relative: false,\n });\n const vertex2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n relative: false,\n });\n const edge = graph.insertEdge({\n parent,\n // value: 'to the',\n source: vertex1,\n target: vertex2,\n });\n });\n };\n}\n\nexport default HelloWorld;\n", - "DynamicToolbar": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxToolbar from '../mxgraph/util/mxToolbar';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass DynamicToolbar extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Toolbar

\n This example demonstrates changing the state\n of the toolbar at runtime.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n position: \"relative\"\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the toolbar\n const tbContainer = document.createElement('div');\n tbContainer.style.position = 'absolute';\n tbContainer.style.overflow = 'hidden';\n tbContainer.style.padding = '2px';\n tbContainer.style.left = '0px';\n tbContainer.style.top = '0px';\n tbContainer.style.width = '24px';\n tbContainer.style.bottom = '0px';\n\n this.el.appendChild(tbContainer);\n\n // Creates new toolbar without event processing\n const toolbar = new mxToolbar(tbContainer);\n toolbar.enabled = false;\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '24px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the model and the graph inside the container\n // using the fastest rendering available on the browser\n const model = new mxGraphModel();\n const graph = new mxGraph(container, model);\n\n // Enables new connections in the graph\n graph.setConnectable(true);\n graph.setMultigraph(false);\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n const rubberband = new mxRubberband(graph);\n\n const addVertex = (icon, w, h, style) => {\n const vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);\n vertex.setVertex(true);\n\n const img = this.addToolbarItem(graph, toolbar, vertex, icon);\n img.enabled = true;\n\n graph.getSelectionModel().addListener(mxEvent.CHANGE, function() {\n const tmp = graph.isSelectionEmpty();\n mxUtils.setOpacity(img, tmp ? 100 : 20);\n img.enabled = tmp;\n });\n };\n\n addVertex('editors/images/rectangle.gif', 100, 40, '');\n addVertex('editors/images/rounded.gif', 100, 40, 'shape=rounded');\n addVertex('editors/images/ellipse.gif', 40, 40, 'shape=ellipse');\n addVertex('editors/images/rhombus.gif', 40, 40, 'shape=rhombus');\n addVertex('editors/images/triangle.gif', 40, 40, 'shape=triangle');\n addVertex('editors/images/cylinder.gif', 40, 40, 'shape=cylinder');\n addVertex('editors/images/actor.gif', 30, 40, 'shape=actor');\n }\n\n addToolbarItem(graph, toolbar, prototype, image) {\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = function(graph, evt, cell, x, y) {\n graph.stopEditing(false);\n\n const vertex = graph.getModel().cloneCell(prototype);\n vertex.geometry.x = x;\n vertex.geometry.y = y;\n\n graph.addCell(vertex);\n graph.setSelectionCell(vertex);\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(null, image, function(evt, cell) {\n const pt = this.graph.getPointForEvent(evt);\n funct(graph, evt, cell, pt.x, pt.y);\n });\n\n // Disables dragging if element is disabled. This is a workaround\n // for wrong event order in IE. Following is a dummy listener that\n // is invoked as the last listener in IE.\n mxEvent.addListener(img, 'mousedown', function(evt) {\n // do nothing\n });\n\n // This listener is always called first before any other listener\n // in all browsers.\n mxEvent.addListener(img, 'mousedown', function(evt) {\n if (img.enabled == false) {\n mxEvent.consume(evt);\n }\n });\n\n mxUtils.makeDraggable(img, graph, funct);\n\n return img;\n }\n}\n\nexport default DynamicToolbar;\n", + "Boundary": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Boundary extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Boundary

\n This example demonstrates implementing boundary events in BPMN diagrams.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n class MyCustomGraph extends mxGraph {\n // Enables moving of relative children\n isCellLocked(cell) {\n return false;\n }\n\n // Removes folding icon for relative children\n isCellFoldable(cell, collapse) {\n const childCount = this.model.getChildCount(cell);\n\n for (let i = 0; i < childCount; i++) {\n const child = this.model.getChildAt(cell, i);\n const geo = this.getCellGeometry(child);\n\n if (geo != null && geo.relative) {\n return false;\n }\n }\n\n return childCount > 0;\n }\n\n // Returns the relative position of the given child\n getRelativePosition(state, dx, dy) {\n if (state != null) {\n const model = graph.getModel();\n const geo = model.getGeometry(state.cell);\n\n if (geo != null && geo.relative && !model.isEdge(state.cell)) {\n const parent = model.getParent(state.cell);\n\n if (model.isVertex(parent)) {\n const pstate = graph.view.getState(parent);\n\n if (pstate != null) {\n const { scale } = graph.view;\n let x = state.x + dx;\n let y = state.y + dy;\n\n if (geo.offset != null) {\n x -= geo.offset.x * scale;\n y -= geo.offset.y * scale;\n }\n\n x = (x - pstate.x) / pstate.width;\n y = (y - pstate.y) / pstate.height;\n\n if (Math.abs(y - 0.5) <= Math.abs((x - 0.5) / 2)) {\n x = x > 0.5 ? 1 : 0;\n y = Math.min(1, Math.max(0, y));\n } else {\n x = Math.min(1, Math.max(0, x));\n y = y > 0.5 ? 1 : 0;\n }\n\n return new mxPoint(x, y);\n }\n }\n }\n }\n\n return null;\n }\n\n // Replaces translation for relative children\n translateCell(cell, dx, dy) {\n const rel = this.getRelativePosition(\n this.view.getState(cell),\n dx * graph.view.scale,\n dy * graph.view.scale\n );\n\n if (rel != null) {\n let geo = this.model.getGeometry(cell);\n\n if (geo != null && geo.relative) {\n geo = geo.clone();\n geo.x = rel.x;\n geo.y = rel.y;\n\n this.model.setGeometry(cell, geo);\n }\n } else {\n mxGraph.prototype.translateCell.apply(this, arguments);\n }\n }\n }\n\n // Creates the graph inside the given this.el\n const graph = new MyCustomGraph(this.el);\n\n // Sets the base style for all vertices\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';\n style[mxConstants.STYLE_STROKECOLOR] = '#000000';\n style[mxConstants.STYLE_STROKEWIDTH] = '2';\n style[mxConstants.STYLE_FONTCOLOR] = '#000000';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n graph.getStylesheet().putDefaultVertexStyle(style);\n\n // Replaces move preview for relative children\n graph.graphHandler.getDelta = function(me) {\n const point = mxUtils.convertPoint(\n this.graph.container,\n me.getX(),\n me.getY()\n );\n let delta = new mxPoint(point.x - this.first.x, point.y - this.first.y);\n\n if (\n this.cells != null &&\n this.cells.length > 0 &&\n this.cells[0] != null\n ) {\n const state = this.graph.view.getState(this.cells[0]);\n const rel = graph.getRelativePosition(state, delta.x, delta.y);\n\n if (rel != null) {\n const pstate = this.graph.view.getState(\n this.graph.model.getParent(state.cell)\n );\n\n if (pstate != null) {\n delta = new mxPoint(\n pstate.x + pstate.width * rel.x - state.getCenterX(),\n pstate.y + pstate.height * rel.y - state.getCenterY()\n );\n }\n }\n }\n\n return delta;\n };\n\n // Relative children cannot be removed from parent\n graph.graphHandler.shouldRemoveCellsFromParent = function(\n parent,\n cells,\n evt\n ) {\n return (\n cells.length === 0 &&\n !cells[0].geometry.relative &&\n mxGraphHandler.prototype.shouldRemoveCellsFromParent.apply(\n this,\n arguments\n )\n );\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Process',\n position: [60, 60],\n size: [90, 40],\n });\n\n const v2 = graph.insertVertex({\n parent: v1,\n value: 'in',\n position: [0, 0.5],\n size: [20, 20],\n style: 'fontSize=9;shape=ellipse;resizable=0;',\n });\n v2.geometry.offset = new mxPoint(-10, -10);\n v2.geometry.relative = true;\n\n const v3 = graph.insertVertex({\n parent: v1,\n value: 'out',\n position: [1, 0.5],\n size: [20, 20],\n style: 'fontSize=9;shape=ellipse;resizable=0;',\n });\n v3.geometry.offset = new mxPoint(-10, -10);\n v3.geometry.relative = true;\n });\n };\n}\n\nexport default Boundary;\n", + "HoverStyle": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass HoverStyle extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hoverstyle

\n This example shows hot to change the style of a vertex on mouseover.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n function updateStyle(state, hover) {\n if (hover) {\n state.style[mxConstants.STYLE_FILLCOLOR] = '#ff0000';\n }\n\n // Sets rounded style for both cases since the rounded style\n // is not set in the default style and is therefore inherited\n // once it is set, whereas the above overrides the default value\n state.style[mxConstants.STYLE_ROUNDED] = hover ? '1' : '0';\n state.style[mxConstants.STYLE_STROKEWIDTH] = hover ? '4' : '1';\n state.style[mxConstants.STYLE_FONTSTYLE] = hover\n ? mxConstants.FONT_BOLD\n : '0';\n }\n\n // Changes fill color to red on mouseover\n graph.addMouseListener({\n currentState: null,\n previousStyle: null,\n mouseDown(sender, me) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n this.currentState = null;\n }\n },\n mouseMove(sender, me) {\n if (this.currentState != null && me.getState() == this.currentState) {\n return;\n }\n\n let tmp = graph.view.getState(me.getCell());\n\n // Ignores everything but vertices\n if (\n graph.isMouseDown ||\n (tmp != null && !graph.getModel().isVertex(tmp.cell))\n ) {\n tmp = null;\n }\n\n if (tmp != this.currentState) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n }\n\n this.currentState = tmp;\n\n if (this.currentState != null) {\n this.dragEnter(me.getEvent(), this.currentState);\n }\n }\n },\n mouseUp(sender, me) {},\n dragEnter(evt, state) {\n if (state != null) {\n this.previousStyle = state.style;\n state.style = mxUtils.clone(state.style);\n updateStyle(state, true);\n state.shape.apply(state);\n state.shape.redraw();\n\n if (state.text != null) {\n state.text.apply(state);\n state.text.redraw();\n }\n }\n },\n dragLeave(evt, state) {\n if (state != null) {\n state.style = this.previousStyle;\n updateStyle(state, false);\n state.shape.apply(state);\n state.shape.redraw();\n\n if (state.text != null) {\n state.text.apply(state);\n state.text.redraw();\n }\n }\n },\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HoverStyle;\n", + "HelloWorld": "/*\n * Copyright (c) 2006-2018, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\n\nclass HelloWorld extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph with a grid wallpaper\n return (\n <>\n

Hello, World!

\n This example demonstrates using a DOM node to create a graph and adding\n vertices and edges.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Create a sample graph in the DOM node with the specified ID.\n mxEvent.disableContextMenu(this.el); // Disable the built-in context menu\n const graph = new mxGraph(this.el); // Create the graph inside the given container\n new mxRubberband(graph); // Enable rubberband selection\n\n // Get the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n graph.batchUpdate(() => {\n // Add cells to the model in a single step\n const vertex1 = graph.insertVertex({\n parent,\n value: 'Hello',\n position: [20, 20],\n size: [80, 30],\n relative: false,\n });\n const vertex2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n relative: false,\n });\n const edge = graph.insertEdge({\n parent,\n // value: 'to the',\n source: vertex1,\n target: vertex2,\n });\n });\n };\n}\n\nexport default HelloWorld;\n", + "DynamicToolbar": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxToolbar from '../mxgraph/util/mxToolbar';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass DynamicToolbar extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Toolbar

\n This example demonstrates changing the state of the toolbar at runtime.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n position: 'relative',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the toolbar\n const tbContainer = document.createElement('div');\n tbContainer.style.position = 'absolute';\n tbContainer.style.overflow = 'hidden';\n tbContainer.style.padding = '2px';\n tbContainer.style.left = '0px';\n tbContainer.style.top = '0px';\n tbContainer.style.width = '24px';\n tbContainer.style.bottom = '0px';\n\n this.el.appendChild(tbContainer);\n\n // Creates new toolbar without event processing\n const toolbar = new mxToolbar(tbContainer);\n toolbar.enabled = false;\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '24px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the model and the graph inside the container\n // using the fastest rendering available on the browser\n const model = new mxGraphModel();\n const graph = new mxGraph(container, model);\n\n // Enables new connections in the graph\n graph.setConnectable(true);\n graph.setMultigraph(false);\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n const rubberband = new mxRubberband(graph);\n\n const addVertex = (icon, w, h, style) => {\n const vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);\n vertex.setVertex(true);\n\n const img = this.addToolbarItem(graph, toolbar, vertex, icon);\n img.enabled = true;\n\n graph.getSelectionModel().addListener(mxEvent.CHANGE, function() {\n const tmp = graph.isSelectionEmpty();\n mxUtils.setOpacity(img, tmp ? 100 : 20);\n img.enabled = tmp;\n });\n };\n\n addVertex('editors/images/rectangle.gif', 100, 40, '');\n addVertex('editors/images/rounded.gif', 100, 40, 'shape=rounded');\n addVertex('editors/images/ellipse.gif', 40, 40, 'shape=ellipse');\n addVertex('editors/images/rhombus.gif', 40, 40, 'shape=rhombus');\n addVertex('editors/images/triangle.gif', 40, 40, 'shape=triangle');\n addVertex('editors/images/cylinder.gif', 40, 40, 'shape=cylinder');\n addVertex('editors/images/actor.gif', 30, 40, 'shape=actor');\n }\n\n addToolbarItem(graph, toolbar, prototype, image) {\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = function(graph, evt, cell, x, y) {\n graph.stopEditing(false);\n\n const vertex = graph.getModel().cloneCell(prototype);\n vertex.geometry.x = x;\n vertex.geometry.y = y;\n\n graph.addCell(vertex);\n graph.setSelectionCell(vertex);\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(null, image, function(evt, cell) {\n const pt = this.graph.getPointForEvent(evt);\n funct(graph, evt, cell, pt.x, pt.y);\n });\n\n // Disables dragging if element is disabled. This is a workaround\n // for wrong event order in IE. Following is a dummy listener that\n // is invoked as the last listener in IE.\n mxEvent.addListener(img, 'mousedown', function(evt) {\n // do nothing\n });\n\n // This listener is always called first before any other listener\n // in all browsers.\n mxEvent.addListener(img, 'mousedown', function(evt) {\n if (img.enabled == false) {\n mxEvent.consume(evt);\n }\n });\n\n mxUtils.makeDraggable(img, graph, funct);\n\n return img;\n }\n}\n\nexport default DynamicToolbar;\n", "SourceCodeDisplay": "import { Component } from 'react';\nimport Prism from 'prismjs';\nimport 'prismjs/themes/prism-okaidia.css';\nimport 'prismjs/components/prism-markup-templating';\nimport 'prismjs/components/prism-handlebars.min.js';\nimport 'prismjs/components/prism-lua.min.js';\nimport 'prismjs/components/prism-c.min.js';\nimport 'prismjs/components/prism-cpp.min.js';\nimport 'prismjs/components/prism-ruby.min.js';\nimport 'prismjs/components/prism-java.min.js';\nimport 'prismjs/components/prism-javascript.min.js';\nimport 'prismjs/components/prism-bash.min.js';\nimport 'prismjs/components/prism-csharp.min.js';\nimport 'prismjs/components/prism-css.min.js';\nimport 'prismjs/components/prism-typescript.min.js';\nimport 'prismjs/components/prism-yaml.min.js';\nimport 'prismjs/components/prism-json.min.js';\nimport 'prismjs/components/prism-swift.min.js';\nimport 'prismjs/components/prism-jsx.min.js';\nimport 'prismjs/components/prism-dart.min.js';\nimport 'prismjs/components/prism-sql.min.js';\nimport 'prismjs/components/prism-rust.min.js';\nimport 'prismjs/components/prism-php.min.js';\nimport 'prismjs/components/prism-perl.min.js';\nimport 'prismjs/components/prism-go.min.js';\nimport 'prismjs/components/prism-docker.min.js';\nimport 'prismjs/components/prism-python.min.js';\n\n// Adapted from\n// https://betterstack.dev/blog/code-highlighting-in-react-using-prismjs/\n\nexport class SourceCodeDisplay extends Component {\n /**\n *\n * @param code\n * @param plugins\n * @param language\n */\n constructor({ code, plugins, language, theme, style }) {\n if (plugins == null) {\n plugins = ['line-numbers', 'show-language'];\n }\n super({ code, plugins, language, theme, style });\n }\n\n render() {\n // TODO: Support theme!!!\n return (\n <>\n \n {\n this.el = el;\n }}\n className={`language-${this.props.language}`}\n >\n {(this.props.code || '').trim()}\n \n \n \n );\n }\n\n componentDidMount() {\n if (this.el) {\n Prism.highlightElement(this.el);\n }\n }\n\n componentDidUpdate() {\n if (this.el) {\n Prism.highlightElement(this.el);\n }\n }\n}\n\nexport default SourceCodeDisplay;\n", - "DynamicStyle": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass DynamicStyle extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dynamic Style

\n This example demonstrates changing the style of a cell\n dynamically by overriding mxGraphModel.getStyle.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables moving of edge labels in this examples\n graph.edgeLabelsMovable = false;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Needs to set a flag to check for dynamic style changes,\n // that is, changes to styles on cells where the style was\n // not explicitely changed using mxStyleChange\n graph.getView().updateStyle = true;\n\n // Overrides mxGraphModel.getStyle to return a specific style\n // for edges that reflects their target terminal (in this case\n // the strokeColor will be equal to the target's fillColor).\n const previous = graph.model.getStyle;\n\n graph.model.getStyle = function(cell) {\n if (cell != null) {\n let style = previous.apply(this, arguments);\n\n if (this.isEdge(cell)) {\n const target = this.getTerminal(cell, false);\n\n if (target != null) {\n const targetStyle = graph.getCurrentCellStyle(target);\n const fill = mxUtils.getValue(\n targetStyle,\n mxConstants.STYLE_FILLCOLOR\n );\n\n if (fill != null) {\n style += `;strokeColor=${fill}`;\n }\n }\n } else if (this.isVertex(cell)) {\n const geometry = this.getGeometry(cell);\n\n if (geometry != null && geometry.width > 80) {\n style += ';fillColor=green';\n }\n }\n\n return style;\n }\n\n return null;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 30,\n 'fillColor=green'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 200,\n 150,\n 80,\n 30,\n 'fillColor=blue'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 20,\n 150,\n 80,\n 30,\n 'fillColor=red'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n 'Connect',\n v1,\n v2,\n 'perimeterSpacing=4;strokeWidth=4;labelBackgroundColor=white;fontStyle=1'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default DynamicStyle;\n", - "PortRefs": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstraintHandler from '../mxgraph/handler/mxConstraintHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxShape from '../mxgraph/shape/mxShape';\nimport mxTriangle from '../mxgraph/shape/mxTriangle';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass PortRefs extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Port References Example

\n This example demonstrates referencing\n connection points by ID. The main difference to the implementation\n where the connection point is stored in the connecting edge is that\n changes to the original port will be reflected in all existing\n connections since they reference that port.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Replaces the port image\n mxConstraintHandler.prototype.pointImage = new mxImage(\n 'images/dot.gif',\n 10,\n 10\n );\n\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Disables automatic handling of ports. This disables the reset of the\n // respective style in mxGraph.cellConnected. Note that this feature may\n // be useful if floating and fixed connections are combined.\n graph.setPortsEnabled(false);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Ports are equal for all shapes...\n const ports = new Array();\n\n // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)\n ports.w = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };\n ports.e = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };\n ports.n = { x: 0.5, y: 0, perimeter: true, constraint: 'north' };\n ports.s = { x: 0.5, y: 1, perimeter: true, constraint: 'south' };\n ports.nw = { x: 0, y: 0, perimeter: true, constraint: 'north west' };\n ports.ne = { x: 1, y: 0, perimeter: true, constraint: 'north east' };\n ports.sw = { x: 0, y: 1, perimeter: true, constraint: 'south west' };\n ports.se = { x: 1, y: 1, perimeter: true, constraint: 'south east' };\n\n // ... except for triangles\n const ports2 = new Array();\n\n // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)\n ports2.in1 = { x: 0, y: 0, perimeter: true, constraint: 'west' };\n ports2.in2 = { x: 0, y: 0.25, perimeter: true, constraint: 'west' };\n ports2.in3 = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };\n ports2.in4 = { x: 0, y: 0.75, perimeter: true, constraint: 'west' };\n ports2.in5 = { x: 0, y: 1, perimeter: true, constraint: 'west' };\n\n ports2.out1 = {\n x: 0.5,\n y: 0,\n perimeter: true,\n constraint: 'north east',\n };\n ports2.out2 = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };\n ports2.out3 = {\n x: 0.5,\n y: 1,\n perimeter: true,\n constraint: 'south east',\n };\n\n // Extends shapes classes to return their ports\n mxShape.prototype.getPorts = function() {\n return ports;\n };\n\n mxTriangle.prototype.getPorts = function() {\n return ports2;\n };\n\n // Disables floating connections (only connections via ports allowed)\n graph.connectionHandler.isConnectableCell = function(cell) {\n return false;\n };\n mxEdgeHandler.prototype.isConnectableCell = function(cell) {\n return graph.connectionHandler.isConnectableCell(cell);\n };\n\n // Disables existing port functionality\n graph.view.getTerminalPort = function(state, terminal, source) {\n return terminal;\n };\n\n // Returns all possible ports for a given terminal\n graph.getAllConnectionConstraints = function(terminal, source) {\n if (\n terminal != null &&\n terminal.shape != null &&\n terminal.shape.stencil != null\n ) {\n // for stencils with existing constraints...\n if (terminal.shape.stencil != null) {\n return terminal.shape.stencil.constraints;\n }\n } else if (terminal != null && this.model.isVertex(terminal.cell)) {\n if (terminal.shape != null) {\n const ports = terminal.shape.getPorts();\n const cstrs = new Array();\n\n for (const id in ports) {\n const port = ports[id];\n\n const cstr = new mxConnectionConstraint(\n new mxPoint(port.x, port.y),\n port.perimeter\n );\n cstr.id = id;\n cstrs.push(cstr);\n }\n\n return cstrs;\n }\n }\n\n return null;\n };\n\n // Sets the port for the given connection\n graph.setConnectionConstraint = function(\n edge,\n terminal,\n source,\n constraint\n ) {\n if (constraint != null) {\n const key = source\n ? mxConstants.STYLE_SOURCE_PORT\n : mxConstants.STYLE_TARGET_PORT;\n\n if (constraint == null || constraint.id == null) {\n this.setCellStyles(key, null, [edge]);\n } else if (constraint.id != null) {\n this.setCellStyles(key, constraint.id, [edge]);\n }\n }\n };\n\n // Returns the port for the given connection\n graph.getConnectionConstraint = function(edge, terminal, source) {\n const key = source\n ? mxConstants.STYLE_SOURCE_PORT\n : mxConstants.STYLE_TARGET_PORT;\n const id = edge.style[key];\n\n if (id != null) {\n const c = new mxConnectionConstraint(null, null);\n c.id = id;\n\n return c;\n }\n\n return null;\n };\n\n // Returns the actual point for a port by redirecting the constraint to the port\n const graphGetConnectionPoint = graph.getConnectionPoint;\n graph.getConnectionPoint = function(vertex, constraint) {\n if (constraint.id != null && vertex != null && vertex.shape != null) {\n const port = vertex.shape.getPorts()[constraint.id];\n\n if (port != null) {\n constraint = new mxConnectionConstraint(\n new mxPoint(port.x, port.y),\n port.perimeter\n );\n }\n }\n\n return graphGetConnectionPoint.apply(this, arguments);\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'A', 20, 20, 100, 40);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'B',\n 80,\n 100,\n 100,\n 100,\n 'shape=ellipse;perimeter=ellipsePerimeter'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'C',\n 190,\n 30,\n 100,\n 60,\n 'shape=triangle;perimeter=trianglePerimeter;direction=south'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'sourcePort=s;targetPort=nw'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v3,\n 'sourcePort=e;targetPort=out3'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Comming soon... Integration with orthogonal edge style\n // Sets default edge style to use port constraints (needs to be moved up when uncommented)\n // graph.getStylesheet().getDefaultEdgeStyle()['edgeStyle'] = 'orthogonalEdgeStyle';\n /* let mxUtilsGetPortConstraints = mxUtils.getPortConstraints;\n mxUtils.getPortConstraints = function(terminal, edge, source, defaultValue)\n {\n let key = (source) ? mxConstants.STYLE_SOURCE_PORT : mxConstants.STYLE_TARGET_PORT;\n let id = edge.style[key];\n\n let port = terminal.shape.getPorts()[id];\n\n // TODO: Add support for rotation, direction\n if (port != null)\n {\n return port.constraint;\n }\n\n return mxUtilsGetPortConstraints.apply(this, arguments);\n };\n // Connect preview\n graph.connectionHandler.createEdgeState = function(me)\n {\n let edge = graph.createEdge(null, null, null, null, null);\n\n return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge));\n };\n */\n }\n}\n\nexport default PortRefs;\n", - "Groups": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from \"../mxgraph/handler/mxGraphHandler\";\nimport mxPopupMenuHandler from \"../mxgraph/handler/mxPopupMenuHandler\";\n\nclass Groups extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates using\n cells as parts of other cells.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Overrides check for valid roots\n mxGraph.prototype.isValidRoot = function() {\n return false;\n };\n\n // Don't clear selection if multiple cells selected\n const graphHandlerMouseDown = mxGraphHandler.prototype.mouseDown;\n mxGraphHandler.prototype.mouseDown = function(sender, me) {\n graphHandlerMouseDown.apply(this, arguments);\n\n if (\n this.graph.isCellSelected(me.getCell()) &&\n this.graph.getSelectionCount() > 1\n ) {\n this.delayedSelection = false;\n }\n };\n\n // Selects descendants before children selection mode\n const graphHandlerGetInitialCellForEvent =\n mxGraphHandler.prototype.getInitialCellForEvent;\n mxGraphHandler.prototype.getInitialCellForEvent = function(me) {\n const model = this.graph.getModel();\n const psel = model.getParent(this.graph.getSelectionCell());\n let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments);\n let parent = model.getParent(cell);\n\n if (psel == null || (psel != cell && psel != parent)) {\n while (\n !this.graph.isCellSelected(cell) &&\n !this.graph.isCellSelected(parent) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n cell = parent;\n parent = this.graph.getModel().getParent(cell);\n }\n }\n\n return cell;\n };\n\n // Selection is delayed to mouseup if child selected\n const graphHandlerIsDelayedSelection =\n mxGraphHandler.prototype.isDelayedSelection;\n mxGraphHandler.prototype.isDelayedSelection = function(cell) {\n let result = graphHandlerIsDelayedSelection.apply(this, arguments);\n const model = this.graph.getModel();\n const psel = model.getParent(this.graph.getSelectionCell());\n const parent = model.getParent(cell);\n\n if (psel == null || (psel != cell && psel != parent)) {\n if (\n !this.graph.isCellSelected(cell) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n result = true;\n }\n }\n\n return result;\n };\n\n // Delayed selection of parent group\n mxGraphHandler.prototype.selectDelayed = function(me) {\n let cell = me.getCell();\n\n if (cell == null) {\n cell = this.cell;\n }\n\n const model = this.graph.getModel();\n let parent = model.getParent(cell);\n\n while (\n this.graph.isCellSelected(cell) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n cell = parent;\n parent = model.getParent(cell);\n }\n\n this.graph.selectCellForEvent(cell, me.getEvent());\n };\n\n // Returns last selected ancestor\n mxPopupMenuHandler.prototype.getCellForPopupEvent = function(me) {\n let cell = me.getCell();\n const model = this.graph.getModel();\n let parent = model.getParent(cell);\n\n while (model.isVertex(parent) && !this.graph.isValidRoot(parent)) {\n if (this.graph.isCellSelected(parent)) {\n cell = parent;\n }\n\n parent = model.getParent(parent);\n }\n\n return cell;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.constrainChildren = false;\n graph.extendParents = false;\n graph.extendParentsOnAdd = false;\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 120, 60);\n const v2 = graph.insertVertex(v1, null, 'World!', 90, 20, 60, 20);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Groups;\n", - "ContextIcons": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxVertexHandler from '../mxgraph/handler/mxVertexHandler';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\n\nclass ContextIcons extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Context icons

\n This example demonstrates adding\n icons to selected vertices to carry out special operations.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Defines a subclass for mxVertexHandler that adds a set of clickable\n // icons to every selected vertex.\n function mxVertexToolHandler(state) {\n mxVertexHandler.apply(this, arguments);\n }\n\n mxVertexToolHandler.prototype = new mxVertexHandler();\n mxVertexToolHandler.prototype.constructor = mxVertexToolHandler;\n\n mxVertexToolHandler.prototype.domNode = null;\n\n mxVertexToolHandler.prototype.init = function() {\n mxVertexHandler.prototype.init.apply(this, arguments);\n\n // In this example we force the use of DIVs for images in IE. This\n // handles transparency in PNG images properly in IE and fixes the\n // problem that IE routes all mouse events for a gesture via the\n // initial IMG node, which means the target vertices\n this.domNode = document.createElement('div');\n this.domNode.style.position = 'absolute';\n this.domNode.style.whiteSpace = 'nowrap';\n\n // Workaround for event redirection via image tag in quirks and IE8\n function createImage(src) {\n return mxUtils.createImage(src);\n }\n\n // Delete\n let img = createImage('images/delete2.png');\n img.setAttribute('title', 'Delete');\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n mxEvent.addGestureListeners(\n img,\n mxUtils.bind(this, function(evt) {\n // Disables dragging the image\n mxEvent.consume(evt);\n })\n );\n mxEvent.addListener(\n img,\n 'click',\n mxUtils.bind(this, function(evt) {\n this.graph.removeCells([this.state.cell]);\n mxEvent.consume(evt);\n })\n );\n this.domNode.appendChild(img);\n\n // Size\n img = createImage('images/fit_to_size.png');\n img.setAttribute('title', 'Resize');\n img.style.cursor = 'se-resize';\n img.style.width = '16px';\n img.style.height = '16px';\n mxEvent.addGestureListeners(\n img,\n mxUtils.bind(this, function(evt) {\n this.start(mxEvent.getClientX(evt), mxEvent.getClientY(evt), 7);\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n })\n );\n this.domNode.appendChild(img);\n\n // Move\n img = createImage('images/plus.png');\n img.setAttribute('title', 'Move');\n img.style.cursor = 'move';\n img.style.width = '16px';\n img.style.height = '16px';\n mxEvent.addGestureListeners(\n img,\n mxUtils.bind(this, function(evt) {\n this.graph.graphHandler.start(\n this.state.cell,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n this.graph.graphHandler.cellWasClicked = true;\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n })\n );\n this.domNode.appendChild(img);\n\n // Connect\n img = createImage('images/check.png');\n img.setAttribute('title', 'Connect');\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n mxEvent.addGestureListeners(\n img,\n mxUtils.bind(this, function(evt) {\n const pt = mxUtils.convertPoint(\n this.graph.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n this.graph.connectionHandler.start(this.state, pt.x, pt.y);\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n })\n );\n this.domNode.appendChild(img);\n\n this.graph.container.appendChild(this.domNode);\n this.redrawTools();\n };\n\n mxVertexToolHandler.prototype.redraw = function() {\n mxVertexHandler.prototype.redraw.apply(this);\n this.redrawTools();\n };\n\n mxVertexToolHandler.prototype.redrawTools = function() {\n if (this.state != null && this.domNode != null) {\n const dy = 4;\n this.domNode.style.left = `${this.state.x + this.state.width - 56}px`;\n this.domNode.style.top = `${this.state.y + this.state.height + dy}px`;\n }\n };\n\n mxVertexToolHandler.prototype.destroy = function(sender, me) {\n mxVertexHandler.prototype.destroy.apply(this, arguments);\n\n if (this.domNode != null) {\n this.domNode.parentNode.removeChild(this.domNode);\n this.domNode = null;\n }\n };\n\n // Program starts here. Creates a sample graph in the\n // DOM node with the specified ID. This function is invoked\n // from the onLoad event handler of the document (see below).\n function main(container) {\n // Checks if the browser is supported\n if (!mxClient.isBrowserSupported()) {\n // Displays an error message if the browser is not supported.\n mxUtils.error('Browser is not supported!', 200, false);\n } else {\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n graph.setConnectable(true);\n graph.connectionHandler.createTarget = true;\n\n graph.createHandler = function(state) {\n if (state != null && this.model.isVertex(state.cell)) {\n return new mxVertexToolHandler(state);\n }\n\n return mxGraph.prototype.createHandler.apply(this, arguments);\n };\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 200,\n 150,\n 80,\n 30\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n }\n };\n}\n\nexport default ContextIcons;\n", - "RadialTreeLayout": "/**\n * Copyright (c) 2006-2014, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxRadialTreeLayout from '../mxgraph/layout/mxRadialTreeLayout';\n\nclass RadialTreeLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hierarchical Layout

\n This example demonstrates the\n use of the hierarchical and organic layouts. Note that the hierarchical\n layout requires another script tag in the head of the page.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '800px',\n borderTop: 'gray 1px solid',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection\n new mxRubberband(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 6;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxRadialTreeLayout(graph);\n\n const parent = graph.getDefaultParent();\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 500, 500, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2.1', 0, 0, 80, 30);\n const v3 = graph.insertVertex(parent, null, '2.2', 0, 0, 80, 30);\n const v4 = graph.insertVertex(parent, null, '3.1', 0, 0, 80, 30);\n const v4_1 = graph.insertVertex(parent, null, '3.2', 0, 0, 80, 30);\n const v4_2 = graph.insertVertex(parent, null, '3.3', 0, 0, 80, 30);\n const v4_3 = graph.insertVertex(parent, null, '3.6', 0, 0, 80, 30);\n const v4_4 = graph.insertVertex(parent, null, '3.7', 0, 0, 80, 30);\n const v5 = graph.insertVertex(parent, null, '3.4', 0, 0, 80, 30);\n const v6 = graph.insertVertex(parent, null, '2.3', 0, 0, 80, 30);\n const v7 = graph.insertVertex(parent, null, '4.1', 0, 0, 80, 30);\n const v7_1 = graph.insertVertex(parent, null, '4.2', 0, 0, 80, 30);\n const v7_2 = graph.insertVertex(parent, null, '4.3', 0, 0, 80, 30);\n const v7_3 = graph.insertVertex(parent, null, '4.4', 0, 0, 80, 30);\n const v7_4 = graph.insertVertex(parent, null, '4.5', 0, 0, 80, 30);\n const v7_5 = graph.insertVertex(parent, null, '4.6', 0, 0, 80, 30);\n const v7_6 = graph.insertVertex(parent, null, '4.7', 0, 0, 80, 30);\n\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v3, v4);\n const e3_1 = graph.insertEdge(parent, null, '', v3, v4_1);\n const e3_2 = graph.insertEdge(parent, null, '', v3, v4_2);\n const e3_3 = graph.insertEdge(parent, null, '', v3, v4_3);\n const e3_4 = graph.insertEdge(parent, null, '', v3, v4_4);\n const e4 = graph.insertEdge(parent, null, '', v2, v5);\n const e5 = graph.insertEdge(parent, null, '', v1, v6);\n const e6 = graph.insertEdge(parent, null, '', v4_3, v7);\n var e6_1 = graph.insertEdge(parent, null, '', v4_4, v7_4);\n var e6_2 = graph.insertEdge(parent, null, '', v4_4, v7_5);\n var e6_3 = graph.insertEdge(parent, null, '', v4_4, v7_6);\n var e6_1 = graph.insertEdge(parent, null, '', v4_3, v7_1);\n var e6_2 = graph.insertEdge(parent, null, '', v4_3, v7_2);\n var e6_3 = graph.insertEdge(parent, null, '', v4_3, v7_3);\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default RadialTreeLayout;\n", - "HelloPort": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass HelloPort extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates using\n the isPort hook for visually connecting to another cell.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n\n // Sets the default edge style\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n\n // Ports are not used as terminals for edges, they are\n // only used to compute the graphical connection point\n graph.isPort = function(cell) {\n const geo = this.getCellGeometry(cell);\n\n return geo != null ? geo.relative : false;\n };\n\n // Implements a tooltip that shows the actual\n // source and target of an edge\n graph.getTooltipForCell = function(cell) {\n if (this.model.isEdge(cell)) {\n return `${this.convertValueToString(\n this.model.getTerminal(cell, true)\n )} => ${this.convertValueToString(\n this.model.getTerminal(cell, false)\n )}`;\n }\n\n return mxGraph.prototype.getTooltipForCell.apply(this, arguments);\n };\n\n // Removes the folding icon and disables any folding\n graph.isCellFoldable = function(cell) {\n return false;\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello', 20, 80, 80, 30);\n v1.setConnectable(false);\n const v11 = graph.insertVertex(v1, null, '', 1, 1, 10, 10);\n v11.geometry.offset = new mxPoint(-5, -5);\n v11.geometry.relative = true;\n const v12 = graph.insertVertex(v1, null, '', 1, 0, 10, 10);\n v12.geometry.offset = new mxPoint(-5, -5);\n v12.geometry.relative = true;\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const v3 = graph.insertVertex(parent, null, 'World2', 200, 20, 80, 30);\n var e1 = graph.insertEdge(parent, null, '', v11, v2);\n var e1 = graph.insertEdge(parent, null, '', v12, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const button = mxUtils.button('View XML', function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getPrettyXml(node), true);\n });\n\n this.el2.appendChild(button);\n }\n}\n\nexport default HelloPort;\n", - "Clipboard": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClipboard from '../mxgraph/util/mxClipboard';\nimport mxClient from '../mxgraph/mxClient';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\n\nclass Clipboard extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A this.el for the graph\n return (\n <>\n

Clipboard

\n This example demonstrates using the clipboard\n for providing cross-tab and cross-browser copy and paste.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n\n // Public helper method for shared clipboard.\n mxClipboard.cellsToString = function(cells) {\n const codec = new mxCodec();\n const model = new mxGraphModel();\n const parent = model.getChildAt(model.getRoot(), 0);\n\n for (let i = 0; i < cells.length; i++) {\n model.add(parent, cells[i]);\n }\n\n return mxUtils.getXml(codec.encode(model));\n };\n\n // Focused but invisible textarea during control or meta key events\n const textInput = document.createElement('textarea');\n mxUtils.setOpacity(textInput, 0);\n textInput.style.width = '1px';\n textInput.style.height = '1px';\n let restoreFocus = false;\n const gs = graph.gridSize;\n let lastPaste = null;\n let dx = 0;\n let dy = 0;\n\n // Workaround for no copy event in IE/FF if empty\n textInput.value = ' ';\n\n // Shows a textare when control/cmd is pressed to handle native clipboard actions\n mxEvent.addListener(document, 'keydown', function(evt) {\n // No dialog visible\n const source = mxEvent.getSource(evt);\n\n if (\n graph.isEnabled() &&\n !graph.isMouseDown &&\n !graph.isEditing() &&\n source.nodeName !== 'INPUT'\n ) {\n if (\n evt.keyCode === 224 /* FF */ ||\n (!mxClient.IS_MAC && evt.keyCode === 17) /* Control */ ||\n (mxClient.IS_MAC &&\n (evt.keyCode === 91 || evt.keyCode === 93)) /* Left/Right Meta */\n ) {\n // Cannot use parentNode for check in IE\n if (!restoreFocus) {\n // Avoid autoscroll but allow handling of events\n textInput.style.position = 'absolute';\n textInput.style.left = `${graph.container.scrollLeft + 10}px`;\n textInput.style.top = `${graph.container.scrollTop + 10}px`;\n graph.container.appendChild(textInput);\n\n restoreFocus = true;\n textInput.focus();\n textInput.select();\n }\n }\n }\n });\n\n // Restores focus on graph this.el and removes text input from DOM\n mxEvent.addListener(document, 'keyup', function(evt) {\n if (\n restoreFocus &&\n (evt.keyCode === 224 /* FF */ ||\n evt.keyCode === 17 /* Control */ ||\n evt.keyCode === 91 ||\n evt.keyCode === 93) /* Meta */\n ) {\n restoreFocus = false;\n\n if (!graph.isEditing()) {\n graph.container.focus();\n }\n\n textInput.parentNode.removeChild(textInput);\n }\n });\n\n // Inserts the XML for the given cells into the text input for copy\n const copyCells = function(graph, cells) {\n if (cells.length > 0) {\n const clones = graph.cloneCells(cells);\n\n // Checks for orphaned relative children and makes absolute\n for (let i = 0; i < clones.length; i++) {\n const state = graph.view.getState(cells[i]);\n\n if (state != null) {\n const geo = graph.getCellGeometry(clones[i]);\n\n if (geo != null && geo.relative) {\n geo.relative = false;\n geo.x = state.x / state.view.scale - state.view.translate.x;\n geo.y = state.y / state.view.scale - state.view.translate.y;\n }\n }\n }\n\n textInput.value = mxClipboard.cellsToString(clones);\n }\n\n textInput.select();\n lastPaste = textInput.value;\n };\n\n // Handles copy event by putting XML for current selection into text input\n mxEvent.addListener(\n textInput,\n 'copy',\n mxUtils.bind(this, function(evt) {\n if (graph.isEnabled() && !graph.isSelectionEmpty()) {\n copyCells(\n graph,\n mxUtils.sortCells(\n graph.model.getTopmostCells(graph.getSelectionCells())\n )\n );\n dx = 0;\n dy = 0;\n }\n })\n );\n\n // Handles cut event by removing cells putting XML into text input\n mxEvent.addListener(\n textInput,\n 'cut',\n mxUtils.bind(this, function(evt) {\n if (graph.isEnabled() && !graph.isSelectionEmpty()) {\n copyCells(graph, graph.removeCells());\n dx = -gs;\n dy = -gs;\n }\n })\n );\n\n // Merges XML into existing graph and layers\n const importXml = function(xml, dx, dy) {\n dx = dx != null ? dx : 0;\n dy = dy != null ? dy : 0;\n let cells = [];\n\n try {\n const doc = mxUtils.parseXml(xml);\n const node = doc.documentElement;\n\n if (node != null) {\n const model = new mxGraphModel();\n const codec = new mxCodec(node.ownerDocument);\n codec.decode(node, model);\n\n const childCount = model.getChildCount(model.getRoot());\n const targetChildCount = graph.model.getChildCount(\n graph.model.getRoot()\n );\n\n // Merges existing layers and adds new layers\n graph.model.beginUpdate();\n try {\n for (let i = 0; i < childCount; i++) {\n let parent = model.getChildAt(model.getRoot(), i);\n\n // Adds cells to existing layers if not locked\n if (targetChildCount > i) {\n // Inserts into active layer if only one layer is being pasted\n const target =\n childCount === 1\n ? graph.getDefaultParent()\n : graph.model.getChildAt(graph.model.getRoot(), i);\n\n if (!graph.isCellLocked(target)) {\n const children = model.getChildren(parent);\n cells = cells.concat(\n graph.importCells(children, dx, dy, target)\n );\n }\n } else {\n // Delta is non cascading, needs separate move for layers\n parent = graph.importCells(\n [parent],\n 0,\n 0,\n graph.model.getRoot()\n )[0];\n const children = graph.model.getChildren(parent);\n graph.moveCells(children, dx, dy);\n cells = cells.concat(children);\n }\n }\n } finally {\n graph.model.endUpdate();\n }\n }\n } catch (e) {\n alert(e);\n throw e;\n }\n\n return cells;\n };\n\n // Parses and inserts XML into graph\n const pasteText = function(text) {\n const xml = mxUtils.trim(text);\n const x =\n graph.container.scrollLeft / graph.view.scale - graph.view.translate.x;\n const y =\n graph.container.scrollTop / graph.view.scale - graph.view.translate.y;\n\n if (xml.length > 0) {\n if (lastPaste !== xml) {\n lastPaste = xml;\n dx = 0;\n dy = 0;\n } else {\n dx += gs;\n dy += gs;\n }\n\n // Standard paste via control-v\n if (xml.substring(0, 14) === '') {\n graph.setSelectionCells(importXml(xml, dx, dy));\n graph.scrollCellToVisible(graph.getSelectionCell());\n }\n }\n };\n\n // Cross-browser function to fetch text from paste events\n const extractGraphModelFromEvent = function(evt) {\n let data = null;\n\n if (evt != null) {\n const provider =\n evt.dataTransfer != null ? evt.dataTransfer : evt.clipboardData;\n\n if (provider != null) {\n if (document.documentMode === 10 || document.documentMode === 11) {\n data = provider.getData('Text');\n } else {\n data =\n mxUtils.indexOf(provider.types, 'text/html') >= 0\n ? provider.getData('text/html')\n : null;\n\n if (\n mxUtils.indexOf(\n provider.types,\n 'text/plain' && (data == null || data.length === 0)\n )\n ) {\n data = provider.getData('text/plain');\n }\n }\n }\n }\n\n return data;\n };\n\n // Handles paste event by parsing and inserting XML\n mxEvent.addListener(textInput, 'paste', function(evt) {\n // Clears existing contents before paste - should not be needed\n // because all text is selected, but doesn't hurt since the\n // actual pasting of the new text is delayed in all cases.\n textInput.value = '';\n\n if (graph.isEnabled()) {\n const xml = extractGraphModelFromEvent(evt);\n\n if (xml != null && xml.length > 0) {\n pasteText(xml);\n } else {\n // Timeout for new value to appear\n window.setTimeout(\n mxUtils.bind(this, function() {\n pasteText(textInput.value);\n }),\n 0\n );\n }\n }\n\n textInput.select();\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default Clipboard;\n", - "__template": "import React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\n\nclass MYNAMEHERE extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

\n\n {\n this.el = el;\n }}\n style={{\n\n }}\n />\n \n );\n };\n\n componentDidMount() {\n\n };\n}\n\nexport default MYNAMEHERE;\n", - "Drop": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Drop extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A this.el for the graph\n return (\n <>\n

Drop

\n This example demonstrates handling native drag and\n drop of images (requires modern browser).\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: `url('editors/images/grid.gif')`,\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Checks if the browser is supported\n const fileSupport =\n window.File != null &&\n window.FileReader != null &&\n window.FileList != null;\n\n if (!fileSupport || !mxClient.isBrowserSupported()) {\n // Displays an error message if the browser is not supported.\n mxUtils.error('Browser is not supported!', 200, false);\n } else {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n mxEvent.addListener(this.el, 'dragover', function(evt) {\n if (graph.isEnabled()) {\n evt.stopPropagation();\n evt.preventDefault();\n }\n });\n\n mxEvent.addListener(this.el, 'drop', evt => {\n if (graph.isEnabled()) {\n evt.stopPropagation();\n evt.preventDefault();\n\n // Gets drop location point for vertex\n const pt = mxUtils.convertPoint(\n graph.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n const tr = graph.view.translate;\n const { scale } = graph.view;\n const x = pt.x / scale - tr.x;\n const y = pt.y / scale - tr.y;\n\n // Converts local images to data urls\n const filesArray = evt.dataTransfer.files;\n\n for (let i = 0; i < filesArray.length; i++) {\n this.handleDrop(graph, filesArray[i], x + i * 10, y + i * 10);\n }\n }\n });\n }\n }\n\n handleDrop(graph, file, x, y) {\n // Handles each file as a separate insert for simplicity.\n // Use barrier to handle multiple files as a single insert.\n\n if (file.type.substring(0, 5) === 'image') {\n const reader = new FileReader();\n\n reader.onload = function(e) {\n // Gets size of image for vertex\n let data = e.target.result;\n\n // SVG needs special handling to add viewbox if missing and\n // find initial size from SVG attributes (only for IE11)\n if (file.type.substring(0, 9) === 'image/svg') {\n const comma = data.indexOf(',');\n const svgText = atob(data.substring(comma + 1));\n const root = mxUtils.parseXml(svgText);\n\n // Parses SVG to find width and height\n if (root != null) {\n const svgs = root.getElementsByTagName('svg');\n\n if (svgs.length > 0) {\n const svgRoot = svgs[0];\n let w = parseFloat(svgRoot.getAttribute('width'));\n let h = parseFloat(svgRoot.getAttribute('height'));\n\n // Check if viewBox attribute already exists\n const vb = svgRoot.getAttribute('viewBox');\n\n if (vb == null || vb.length === 0) {\n svgRoot.setAttribute('viewBox', `0 0 ${w} ${h}`);\n }\n // Uses width and height from viewbox for\n // missing width and height attributes\n else if (Number.isNaN(w) || Number.isNaN(h)) {\n const tokens = vb.split(' ');\n\n if (tokens.length > 3) {\n w = parseFloat(tokens[2]);\n h = parseFloat(tokens[3]);\n }\n }\n\n w = Math.max(1, Math.round(w));\n h = Math.max(1, Math.round(h));\n\n data = `data:image/svg+xml,${btoa(\n mxUtils.getXml(svgs[0], '\\n')\n )}`;\n graph.insertVertex(\n null,\n null,\n '',\n x,\n y,\n w,\n h,\n `shape=image;image=${data};`\n );\n }\n }\n } else {\n const img = new Image();\n\n img.onload = function() {\n const w = Math.max(1, img.width);\n const h = Math.max(1, img.height);\n\n // Converts format of data url to cell style value for use in vertex\n const semi = data.indexOf(';');\n\n if (semi > 0) {\n data =\n data.substring(0, semi) +\n data.substring(data.indexOf(',', semi + 1));\n }\n\n graph.insertVertex(\n null,\n null,\n '',\n x,\n y,\n w,\n h,\n `shape=image;image=${data};`\n );\n };\n\n img.src = data;\n }\n };\n\n reader.readAsDataURL(file);\n }\n }\n}\n\nexport default Drop;\n", - "Markers": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxMarker from '../mxgraph/shape/mxMarker';\nimport mxArrow from '../mxgraph/shape/mxArrow';\n\nclass Markers extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Markers

\n This example demonstrates creating\n custom markers and customizing the built-in markers.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '381px',\n border: '1px solid gray',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Registers and defines the custom marker\n mxMarker.addMarker('dash', function(\n canvas,\n shape,\n type,\n pe,\n unitX,\n unitY,\n size,\n source,\n sw,\n filled\n ) {\n const nx = unitX * (size + sw + 1);\n const ny = unitY * (size + sw + 1);\n\n return function() {\n canvas.begin();\n canvas.moveTo(pe.x - nx / 2 - ny / 2, pe.y - ny / 2 + nx / 2);\n canvas.lineTo(\n pe.x + ny / 2 - (3 * nx) / 2,\n pe.y - (3 * ny) / 2 - nx / 2\n );\n canvas.stroke();\n };\n });\n\n // Defines custom message shape\n class MessageShape extends mxCylinder {\n redrawPath(path, x, y, w, h, isForeground) {\n if (isForeground) {\n path.moveTo(0, 0);\n path.lineTo(w / 2, h / 2);\n path.lineTo(w, 0);\n } else {\n path.moveTo(0, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h);\n path.lineTo(0, h);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('message', MessageShape);\n\n // Defines custom edge shape\n class LinkShape extends mxArrow {\n paintEdgeShape(c, pts) {\n const width = 10;\n\n // Base vector (between end points)\n const p0 = pts[0];\n const pe = pts[pts.length - 1];\n\n const dx = pe.x - p0.x;\n const dy = pe.y - p0.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n const length = dist;\n\n // Computes the norm and the inverse norm\n const nx = dx / dist;\n const ny = dy / dist;\n const basex = length * nx;\n const basey = length * ny;\n const floorx = (width * ny) / 3;\n const floory = (-width * nx) / 3;\n\n // Computes points\n const p0x = p0.x - floorx / 2;\n const p0y = p0.y - floory / 2;\n const p1x = p0x + floorx;\n const p1y = p0y + floory;\n const p2x = p1x + basex;\n const p2y = p1y + basey;\n const p3x = p2x + floorx;\n const p3y = p2y + floory;\n // p4 not necessary\n const p5x = p3x - 3 * floorx;\n const p5y = p3y - 3 * floory;\n\n c.begin();\n c.moveTo(p1x, p1y);\n c.lineTo(p2x, p2y);\n c.moveTo(p5x + floorx, p5y + floory);\n c.lineTo(p0x, p0y);\n c.stroke();\n }\n }\n mxCellRenderer.registerShape('link', LinkShape);\n\n // Creates the graph\n const graph = new mxGraph(this.el);\n\n // Sets default styles\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style.fillColor = '#FFFFFF';\n style.strokeColor = '#000000';\n style.fontColor = '#000000';\n style.fontStyle = '1';\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style.strokeColor = '#000000';\n style.fontColor = '#000000';\n style.fontStyle = '0';\n style.fontStyle = '0';\n style.startSize = '8';\n style.endSize = '8';\n\n // Populates the graph\n const parent = graph.getDefaultParent();\n\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'v1', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'v2', 440, 20, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'dashed=1;' +\n 'startArrow=oval;endArrow=block;sourcePerimeterSpacing=4;startFill=0;endFill=0;'\n );\n const e11 = graph.insertVertex(\n e1,\n null,\n 'Label',\n 0,\n 0,\n 20,\n 14,\n 'shape=message;labelBackgroundColor=#ffffff;labelPosition=left;spacingRight=2;align=right;fontStyle=0;'\n );\n e11.geometry.offset = new mxPoint(-10, -7);\n e11.geometry.relative = true;\n e11.connectable = false;\n\n const v3 = graph.insertVertex(parent, null, 'v3', 20, 120, 80, 30);\n const v4 = graph.insertVertex(parent, null, 'v4', 440, 120, 80, 30);\n const e2 = graph.insertEdge(\n parent,\n null,\n 'Label',\n v3,\n v4,\n 'startArrow=dash;startSize=12;endArrow=block;labelBackgroundColor=#FFFFFF;'\n );\n\n const v5 = graph.insertVertex(\n parent,\n null,\n 'v5',\n 40,\n 220,\n 40,\n 40,\n 'shape=ellipse;perimeter=ellipsePerimeter;'\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n 'v6',\n 460,\n 220,\n 40,\n 40,\n 'shape=doubleEllipse;perimeter=ellipsePerimeter;'\n );\n const e3 = graph.insertEdge(\n parent,\n null,\n 'Link',\n v5,\n v6,\n 'shape=link;labelBackgroundColor=#FFFFFF;'\n );\n } finally {\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Markers;\n", - "Overlays": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCellTracker from '../mxgraph/handler/mxCellTracker';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Overlays extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Overlays

\n This example demonstrates cell\n highlighting, overlays and handling click and double click\n events. See also: events.html for more event handling.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Highlights the vertices when the mouse enters\n const highlight = new mxCellTracker(graph, '#00FF00');\n\n // Enables tooltips for the overlays\n graph.setTooltips(true);\n\n // Installs a handler for click events in the graph\n // that toggles the overlay for the respective cell\n graph.addListener(mxEvent.CLICK, function(sender, evt) {\n const cell = evt.getProperty('cell');\n\n if (cell != null) {\n const overlays = graph.getCellOverlays(cell);\n\n if (overlays == null) {\n // Creates a new overlay with an image and a tooltip\n const overlay = new mxCellOverlay(\n new mxImage('editors/images/overlays/check.png', 16, 16),\n 'Overlay tooltip'\n );\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, function(sender, evt2) {\n mxUtils.alert('Overlay clicked');\n });\n\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(cell, overlay);\n } else {\n graph.removeCellOverlays(cell);\n }\n }\n });\n\n // Installs a handler for double click events in the graph\n // that shows an alert box\n graph.addListener(mxEvent.DOUBLE_CLICK, function(sender, evt) {\n const cell = evt.getProperty('cell');\n mxUtils.alert(`Doubleclick: ${cell != null ? 'Cell' : 'Graph'}`);\n evt.consume();\n });\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Click,', 20, 20, 60, 40);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Doubleclick',\n 200,\n 150,\n 100,\n 40\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Overlays;\n", - "Constituent": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from \"../mxgraph/handler/mxGraphHandler\";\n\nclass Constituent extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Constituent

\n This example demonstrates using\n cells as parts of other cells.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount() {\n class MyCustomGraphHandler extends mxGraphHandler {\n /**\n * Redirects start drag to parent.\n */\n getInitialCellForEvent(me) {\n let cell = super.getInitialCellForEvent(me);\n if (this.graph.isPart(cell)) {\n cell = this.graph.getModel().getParent(cell);\n }\n return cell;\n }\n }\n\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n class MyCustomGraph extends mxGraph {\n foldingEnabled = false;\n\n recursiveResize = true;\n\n isPart(cell) {\n // Helper method to mark parts with constituent=1 in the style\n return this.getCurrentCellStyle(cell).constituent == '1';\n }\n\n selectCellForEvent(cell, evt) {\n // Redirects selection to parent\n if (this.isPart(cell)) {\n cell = this.model.getParent(cell);\n }\n super.selectCellForEvent(cell, evt);\n }\n\n createGraphHandler() {\n return new MyCustomGraphHandler(this);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '', 20, 20, 120, 70);\n const v2 = graph.insertVertex(\n v1,\n null,\n 'Constituent',\n 20,\n 20,\n 80,\n 30,\n 'constituent=1;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Constituent;\n", - "Editing": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Editing extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Editing

\n This example demonstrates using the in-place\n editor trigger to specify the editing value and write the new value into\n a specific field of the user object. Wrapping and DOM nodes as labels are\n also demonstrated here.

\n\n Double-click the upper/lower half of the cell to edit different fields\n of the user object.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n };\n\n componentDidMount() {\n class MyCustomGraph extends mxGraph {\n getLabel(cell) {\n // Returns a HTML representation of the cell where the\n // upper half is the first value, lower half is second\n // value\n\n const table = document.createElement('table');\n table.style.height = '100%';\n table.style.width = '100%';\n\n const body = document.createElement('tbody');\n const tr1 = document.createElement('tr');\n const td1 = document.createElement('td');\n td1.style.textAlign = 'center';\n td1.style.fontSize = '12px';\n td1.style.color = '#774400';\n mxUtils.write(td1, cell.value.first);\n\n const tr2 = document.createElement('tr');\n const td2 = document.createElement('td');\n td2.style.textAlign = 'center';\n td2.style.fontSize = '12px';\n td2.style.color = '#774400';\n mxUtils.write(td2, cell.value.second);\n\n tr1.appendChild(td1);\n tr2.appendChild(td2);\n body.appendChild(tr1);\n body.appendChild(tr2);\n table.appendChild(body);\n\n return table;\n }\n\n getEditingValue(cell, evt) {\n // Returns the editing value for the given cell and event\n evt.fieldname = this.__getFieldnameForEvent(cell, evt);\n return cell.value[evt.fieldname] || '';\n }\n\n __getFieldnameForEvent(cell, evt) {\n // Helper method that returns the fieldname to be used for\n // a mouse event\n if (evt != null) {\n // Finds the relative coordinates inside the cell\n const point = mxUtils.convertPoint(\n this.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n const state = this.getView().getState(cell);\n\n if (state != null) {\n point.x -= state.x;\n point.y -= state.y;\n\n // Returns second if mouse in second half of cell\n if (point.y > state.height / 2) {\n return 'second';\n }\n }\n }\n return 'first';\n }\n\n labelChanged(cell, newValue, trigger) {\n // Sets the new value for the given cell and trigger\n const name = trigger != null ? trigger.fieldname : null;\n\n if (name != null) {\n // Clones the user object for correct undo and puts\n // the new value in the correct field.\n const value = mxUtils.clone(cell.value);\n value[name] = newValue;\n newValue = value;\n\n super.labelChanged(cell, newValue, trigger);\n }\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setHtmlLabels(true);\n\n // Adds handling of return and escape keystrokes for editing\n const keyHandler = new mxKeyHandler(graph);\n\n // Sample user objects with 2 fields\n const value = {};\n value.first = 'First value';\n value.second = 'Second value';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n value,\n 100,\n 60,\n 120,\n 80,\n 'overflow=fill;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Editing;\n", - "HierarchicalLayout": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxHierarchicalLayout from '../mxgraph/layout/hierarchical/mxHierarchicalLayout';\nimport mxFastOrganicLayout from '../mxgraph/layout/mxFastOrganicLayout';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\n\nclass HierarchicalLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hierarchical Layout

\n This example demonstrates the\n use of the hierarchical and organic layouts. Note that the hierarchical\n layout requires another script tag in the head of the page.\n\n {\n this.el = el;\n }}\n style={{\n position: 'absolute',\n overflow: 'auto',\n top: '36px',\n bottom: '0px',\n left: '0px',\n right: '0px',\n borderTop: 'gray 1px solid',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection\n new mxRubberband(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 6;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxHierarchicalLayout(graph);\n const organic = new mxFastOrganicLayout(graph);\n organic.forceConstant = 120;\n\n const parent = graph.getDefaultParent();\n\n // Adds a button to execute the layout\n let button = document.createElement('button');\n mxUtils.write(button, 'Hierarchical');\n mxEvent.addListener(button, 'click', function(evt) {\n layout.execute(parent);\n });\n this.el2.appendChild(button);\n\n // Adds a button to execute the layout\n button = document.createElement('button');\n mxUtils.write(button, 'Organic');\n\n mxEvent.addListener(button, 'click', function(evt) {\n organic.execute(parent);\n });\n\n this.el2.appendChild(button);\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 0, 0, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2', 0, 0, 80, 30);\n const v3 = graph.insertVertex(parent, null, '3', 0, 0, 80, 30);\n const v4 = graph.insertVertex(parent, null, '4', 0, 0, 80, 30);\n const v5 = graph.insertVertex(parent, null, '5', 0, 0, 80, 30);\n const v6 = graph.insertVertex(parent, null, '6', 0, 0, 80, 30);\n const v7 = graph.insertVertex(parent, null, '7', 0, 0, 80, 30);\n const v8 = graph.insertVertex(parent, null, '8', 0, 0, 80, 30);\n const v9 = graph.insertVertex(parent, null, '9', 0, 0, 80, 30);\n\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v3, v4);\n const e4 = graph.insertEdge(parent, null, '', v2, v5);\n const e5 = graph.insertEdge(parent, null, '', v1, v6);\n const e6 = graph.insertEdge(parent, null, '', v2, v3);\n const e7 = graph.insertEdge(parent, null, '', v6, v4);\n const e8 = graph.insertEdge(parent, null, '', v6, v1);\n const e9 = graph.insertEdge(parent, null, '', v6, v7);\n const e10 = graph.insertEdge(parent, null, '', v7, v8);\n const e11 = graph.insertEdge(parent, null, '', v7, v9);\n const e12 = graph.insertEdge(parent, null, '', v7, v6);\n const e13 = graph.insertEdge(parent, null, '', v7, v5);\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HierarchicalLayout;\n", - "OffPage": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCellTracker from \"../mxgraph/handler/mxCellTracker\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\n\nclass OffPage extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Offpage connector

\n This example demonstrates creating\n offpage connectors in a graph and loading a new diagram on a\n single click.\n\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n }\n\n componentDidMount() {\n // Use complete cell as highlight region\n mxConstants.ACTIVE_REGION = 1;\n\n const container = document.createElement('div');\n container.style.position = 'relative';\n container.style.overflow = 'hidden';\n container.style.height = '80vhpx';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n graph.setEnabled(false);\n\n // Highlights offpage connectors\n const highlight = new mxCellTracker(graph, null, function(me) {\n const cell = me.getCell();\n\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n return cell;\n }\n\n return null;\n });\n\n // Handles clicks on offpage connectors and\n // executes function in user object\n graph.addListener(mxEvent.CLICK, function(source, evt) {\n const cell = evt.getProperty('cell');\n\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n cell.value.create();\n }\n });\n\n // Handles clicks on offpage connectors and\n // executes function in user object\n graph.getCursorForCell = function(cell) {\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n return 'pointer';\n }\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n let first = null;\n let second = null;\n\n first = function() {\n const value = {\n toString() {\n return 'Next';\n },\n create: second,\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.getModel().setRoot(graph.getModel().createRoot());\n const parent = graph.getDefaultParent();\n\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Click',\n 30,\n 20,\n 80,\n 30,\n 'fillColor=#FFFF88;strokeColor=#FF1A00'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Next',\n 20,\n 150,\n 100,\n 30,\n 'fillColor=#FFFF88;strokeColor=#FF1A00'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n value,\n 200,\n 150,\n 40,\n 40,\n 'shape=triangle;align=left;fillColor=#C3D9FF;strokeColor=#4096EE'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n null,\n v1,\n v2,\n 'strokeColor=#FF1A00'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n\n second = function() {\n const value = {\n toString() {\n return 'Prev';\n },\n create: first,\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.getModel().setRoot(graph.getModel().createRoot());\n const parent = graph.getDefaultParent();\n\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Click',\n 30,\n 20,\n 80,\n 30,\n 'fillColor=#CDEB8B;strokeColor=#008C00'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Prev',\n 220,\n 20,\n 100,\n 30,\n 'fillColor=#CDEB8B;strokeColor=#008C00'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n value,\n 30,\n 150,\n 40,\n 40,\n 'shape=triangle;align=right;fillColor=#C3D9FF;strokeColor=#4096EE;direction=west'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n null,\n v1,\n v2,\n 'strokeColor=#008C00'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n\n first();\n }\n}\n\nexport default OffPage;\n", - "Resources": "/**\n * Copyright (c) 2006-2018, JGraph Ltd\n \n\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Resources extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Resources

\n This example demonstrates disabling the Synchronous\n XMLHttpRequest on main thread warning.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Async indirection to load resources asynchronously (see above)\n // Alternatively you can remove the line that sets mxLoadResources\n // anove and change the code to not use this callback.\n\n mxClient.loadResources(() => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n });\n }\n}\n\nexport default Resources;\n", - "Indicators": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Indicators extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Indicators

\n This example demonstrates the use of\n indicators, which are small subshapes inside a parent shape, typically\n an mxLabel.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300ph',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n new mxKeyHandler(graph);\n\n // Enables moving of vertex labels\n graph.vertexLabelsMovable = true;\n\n // Creates a style with an indicator\n let style = graph.getStylesheet().getDefaultVertexStyle();\n\n style[mxConstants.STYLE_SHAPE] = 'label';\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'bottom';\n style[mxConstants.STYLE_INDICATOR_SHAPE] = 'ellipse';\n style[mxConstants.STYLE_INDICATOR_WIDTH] = 34;\n style[mxConstants.STYLE_INDICATOR_HEIGHT] = 34;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = 'top'; // indicator v-alignment\n style[mxConstants.STYLE_IMAGE_ALIGN] = 'center';\n style[mxConstants.STYLE_INDICATOR_COLOR] = 'green';\n delete style[mxConstants.STYLE_STROKECOLOR]; // transparent\n delete style[mxConstants.STYLE_FILLCOLOR]; // transparent\n\n // Creates a style with an indicator\n style = graph.getStylesheet().getDefaultEdgeStyle();\n\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ELBOW] = mxConstants.ELBOW_VERTICAL;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.insertVertex(parent, null, 'Bottom Label', 80, 80, 80, 60);\n graph.insertVertex(\n parent,\n null,\n 'Top Label',\n 200,\n 80,\n 60,\n 60,\n 'indicatorShape=actor;indicatorWidth=28;indicatorColor=blue;imageVerticalAlign=bottom;verticalAlign=top'\n );\n graph.insertVertex(\n parent,\n null,\n 'Right Label',\n 300,\n 80,\n 120,\n 60,\n 'indicatorShape=cloud;indicatorWidth=40;indicatorColor=#00FFFF;imageVerticalAlign=center;verticalAlign=middle;imageAlign=left;align=left;spacingLeft=44'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Indicators;\n", - "HoverIcons": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from \"../mxgraph/util/mxRectangle\";\nimport mxImage from \"../mxgraph/util/mxImage\";\n\nclass HoverIcons extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hover icons

\n This example demonstrates showing\n icons on vertices as mouse hovers over them.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Defines a new class for all icons\n function mxIconSet(state) {\n this.images = [];\n const { graph } = state.view;\n\n // Icon1\n let img = mxUtils.createImage('images/copy.png');\n img.setAttribute('title', 'Duplicate');\n img.style.position = 'absolute';\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n img.style.left = `${state.x + state.width}px`;\n img.style.top = `${state.y + state.height}px`;\n\n mxEvent.addGestureListeners(img, evt => {\n const s = graph.gridSize;\n graph.setSelectionCells(graph.moveCells([state.cell], s, s, true));\n mxEvent.consume(evt);\n this.destroy();\n });\n\n state.view.graph.container.appendChild(img);\n this.images.push(img);\n\n // Delete\n img = mxUtils.createImage('images/delete2.png');\n img.setAttribute('title', 'Delete');\n img.style.position = 'absolute';\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n img.style.left = `${state.x + state.width}px`;\n img.style.top = `${state.y - 16}px`;\n\n mxEvent.addGestureListeners(img, evt => {\n // Disables dragging the image\n mxEvent.consume(evt);\n });\n\n mxEvent.addListener(img, 'click', evt => {\n graph.removeCells([state.cell]);\n mxEvent.consume(evt);\n this.destroy();\n });\n\n state.view.graph.container.appendChild(img);\n this.images.push(img);\n }\n\n mxIconSet.prototype.destroy = function() {\n if (this.images != null) {\n for (let i = 0; i < this.images.length; i++) {\n const img = this.images[i];\n img.parentNode.removeChild(img);\n }\n }\n\n this.images = null;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Defines the tolerance before removing the icons\n const iconTolerance = 20;\n\n // Shows icons if the mouse is over a cell\n graph.addMouseListener({\n currentState: null,\n currentIconSet: null,\n mouseDown(sender, me) {\n // Hides icons on mouse down\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n this.currentState = null;\n }\n },\n mouseMove(sender, me) {\n if (\n this.currentState != null &&\n (me.getState() == this.currentState || me.getState() == null)\n ) {\n const tol = iconTolerance;\n const tmp = new mxRectangle(\n me.getGraphX() - tol,\n me.getGraphY() - tol,\n 2 * tol,\n 2 * tol\n );\n\n if (mxUtils.intersects(tmp, this.currentState)) {\n return;\n }\n }\n\n let tmp = graph.view.getState(me.getCell());\n\n // Ignores everything but vertices\n if (\n graph.isMouseDown ||\n (tmp != null && !graph.getModel().isVertex(tmp.cell))\n ) {\n tmp = null;\n }\n\n if (tmp != this.currentState) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n }\n\n this.currentState = tmp;\n\n if (this.currentState != null) {\n this.dragEnter(me.getEvent(), this.currentState);\n }\n }\n },\n mouseUp(sender, me) {},\n dragEnter(evt, state) {\n if (this.currentIconSet == null) {\n this.currentIconSet = new mxIconSet(state);\n }\n },\n dragLeave(evt, state) {\n if (this.currentIconSet != null) {\n this.currentIconSet.destroy();\n this.currentIconSet = null;\n }\n },\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HoverIcons;\n", - "Collapse": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\n\nclass Collapse extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Collapse

\n This example demonstrates changing\n the style of a cell based on its collapsed state.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n const graph = new mxGraph(this.el);\n const parent = graph.getDefaultParent();\n\n // Extends mxGraphModel.getStyle to show an image when collapsed\n const modelGetStyle = graph.model.getStyle;\n graph.model.getStyle = function(cell) {\n if (cell != null) {\n let style = modelGetStyle.apply(this, arguments);\n\n if (this.isCollapsed(cell)) {\n style =\n `${style};shape=image;image=http://www.jgraph.com/images/mxgraph.gif;` +\n `noLabel=1;imageBackground=#C3D9FF;imageBorder=#6482B9`;\n }\n\n return style;\n }\n\n return null;\n };\n\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Container',\n 20,\n 20,\n 200,\n 200,\n 'shape=swimlane;startSize=20;'\n );\n v1.geometry.alternateBounds = new mxRectangle(0, 0, 110, 70);\n const v11 = graph.insertVertex(v1, null, 'Hello,', 10, 40, 120, 80);\n } finally {\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default Collapse;\n", - "LOD": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass LOD extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Level of detail

\n This example demonstrates\n implementing a level of detail per cell.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.centerZoom = false;\n\n // Links level of detail to zoom level but can be independent of zoom\n graph.isCellVisible = function(cell) {\n return cell.lod == null || cell.lod / 2 < this.view.scale;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 20, 20, 80, 30);\n v1.lod = 1;\n const v2 = graph.insertVertex(parent, null, '1', 200, 150, 80, 30);\n v2.lod = 1;\n const v3 = graph.insertVertex(parent, null, '2', 20, 150, 40, 20);\n v3.lod = 2;\n const v4 = graph.insertVertex(parent, null, '3', 200, 10, 20, 20);\n v4.lod = 3;\n const e1 = graph.insertEdge(parent, null, '2', v1, v2, 'strokeWidth=2');\n e1.lod = 2;\n var e2 = graph.insertEdge(parent, null, '2', v3, v4, 'strokeWidth=2');\n e2.lod = 2;\n var e2 = graph.insertEdge(parent, null, '3', v1, v4, 'strokeWidth=1');\n e2.lod = 3;\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default LOD;\n", - "Tree": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxCompactTreeLayout from '../mxgraph/layout/mxCompactTreeLayout';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\n\nclass Tree extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Tree

\n This example demonstrates folding\n of subtrees in a acyclic graph (tree).\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default'\n }}\n />\n \n );\n }\n\n componentDidMount() {\n /*\n Defines a custom shape for the tree node that includes the\n upper half of the outgoing edge(s).\n */\n class TreeNodeShape extends mxCylinder {\n // Defines the length of the upper edge segment.\n segment = 20;\n\n constructor(bounds, fill, stroke, strokewidth) {\n super(bounds, fill, stroke, strokewidth);\n }\n\n // Needs access to the cell state for rendering\n apply(state) {\n super.apply(state);\n this.state = state;\n }\n\n redrawPath(path, x, y, w, h, isForeground) {\n const { graph } = this.state.view;\n const hasChildren =\n graph.model.getOutgoingEdges(this.state.cell).length > 0;\n\n if (isForeground) {\n if (hasChildren) {\n // Painting outside of vertex bounds is used here\n path.moveTo(w / 2, h + this.segment);\n path.lineTo(w / 2, h);\n path.end();\n }\n } else {\n path.moveTo(0, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h);\n path.lineTo(0, h);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('treenode', TreeNodeShape);\n\n class MyCustomGraphView extends mxGraphView {\n updateFloatingTerminalPoint(edge, start, end, source) {\n // Defines a custom perimeter for the nodes in the tree\n let pt = null;\n\n if (source) {\n pt = new mxPoint(\n start.x + start.width / 2,\n start.y + start.height + TreeNodeShape.prototype.segment\n );\n } else {\n pt = new mxPoint(start.x + start.width / 2, start.y);\n }\n\n edge.setAbsoluteTerminalPoint(pt, source);\n }\n }\n\n class MyCustomCellRenderer extends mxCellRenderer {\n getControlBounds(state) {\n // Defines the position of the folding icon\n if (state.control != null) {\n const oldScale = state.control.scale;\n const w = state.control.bounds.width / oldScale;\n const h = state.control.bounds.height / oldScale;\n const s = state.view.scale;\n\n return new mxRectangle(\n state.x + state.width / 2 - (w / 2) * s,\n state.y +\n state.height +\n TreeNodeShape.prototype.segment * s -\n (h / 2) * s,\n w * s,\n h * s\n );\n }\n return null;\n }\n }\n\n // Make the layout instance accessible by MyCustomGraph\n let layout;\n\n class MyCustomGraph extends mxGraph {\n // Sets the collapse and expand icons. The values below are the default\n // values, but this is how to replace them if you need to.\n collapsedImage = new mxImage(\n `${mxClient.imageBasePath}/collapsed.gif`,\n 9,\n 9\n );\n\n expandedImage = new mxImage(\n `${mxClient.imageBasePath}/expanded.gif`,\n 9,\n 9\n );\n\n isCellFoldable(cell) {\n // Defines the condition for showing the folding icon\n return this.model.getOutgoingEdges(cell).length > 0;\n }\n\n createCellRenderer() {\n return new MyCustomCellRenderer();\n }\n\n createGraphView() {\n return new MyCustomGraphView(this);\n }\n\n foldCells(collapse, recurse, cells) {\n // Implements the click on a folding icon\n this.model.beginUpdate();\n try {\n this.toggleSubtree(this, cells[0], !collapse);\n this.model.setCollapsed(cells[0], collapse);\n\n // Executes the layout for the new graph since\n // changes to visiblity and collapsed state do\n // not trigger a layout in the current manager.\n layout.execute(this.getDefaultParent());\n } finally {\n this.model.endUpdate();\n }\n }\n\n toggleSubtree(cell, show) {\n // Updates the visible state of a given subtree taking into\n // account the collapsed state of the traversed branches\n show = show != null ? show : true;\n const cells = [];\n\n this.traverse(cell, true, function(vertex) {\n if (vertex !== cell) {\n cells.push(vertex);\n }\n\n // Stops recursion if a collapsed cell is seen\n return vertex === cell || !this.isCellCollapsed(vertex);\n });\n\n this.toggleCells(show, cells, true);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n\n // Disallow any selections\n graph.setCellsSelectable(false);\n\n // Avoids overlap of edges and collapse icons\n graph.keepEdgesInBackground = true;\n\n // Set some stylesheet options for the visual appearance\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'treenode';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Enables automatic sizing for vertices after editing and\n // panning by using the left mouse button.\n graph.setAutoSizeCells(true);\n graph.setPanning(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n\n // Enables automatic layout on the graph and installs\n // a tree layout for all groups who's children are\n // being changed, added or removed.\n layout = new mxCompactTreeLayout(graph, false);\n layout.useBoundingBox = false;\n layout.edgeRouting = false;\n layout.levelDistance = 30;\n layout.nodeDistance = 10;\n\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds the root vertex of the tree\n graph.getModel().beginUpdate();\n try {\n const w = graph.container.offsetWidth;\n const root = graph.insertVertex(\n parent,\n 'treeRoot',\n 'Root',\n w / 2 - 30,\n 20,\n 60,\n 40\n );\n\n const v1 = graph.insertVertex(parent, 'v1', 'Child 1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v1);\n\n const v2 = graph.insertVertex(parent, 'v2', 'Child 2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v2);\n\n const v3 = graph.insertVertex(parent, 'v3', 'Child 3', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v3);\n\n const v11 = graph.insertVertex(parent, 'v11', 'Child 1.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v1, v11);\n\n const v12 = graph.insertVertex(parent, 'v12', 'Child 1.2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v1, v12);\n\n const v21 = graph.insertVertex(parent, 'v21', 'Child 2.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v2, v21);\n\n const v22 = graph.insertVertex(parent, 'v22', 'Child 2.2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v2, v22);\n\n const v221 = graph.insertVertex(\n parent,\n 'v221',\n 'Child 2.2.1',\n 0,\n 0,\n 60,\n 40\n );\n graph.insertEdge(parent, null, '', v22, v221);\n\n const v222 = graph.insertVertex(\n parent,\n 'v222',\n 'Child 2.2.2',\n 0,\n 0,\n 60,\n 40\n );\n graph.insertEdge(parent, null, '', v22, v222);\n\n const v31 = graph.insertVertex(parent, 'v31', 'Child 3.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v3, v31);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Tree;\n", - "Labels": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxRectangle from \"../mxgraph/util/mxRectangle\";\n\nclass Labels extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates the use of wrapping\n and clipping for HTML labels of vertices, truncating labels to fit the\n size of a vertex, and manually placing vertex labels and relative children\n that act as \"sublabels\".\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setTooltips(true);\n graph.htmlLabels = true;\n graph.vertexLabelsMovable = true;\n new mxRubberband(graph);\n new mxKeyHandler(graph);\n\n // Do not allow removing labels from parents\n graph.graphHandler.removeCellsFromParent = false;\n\n // Autosize labels on insert where autosize=1\n graph.autoSizeCellsOnAdd = true;\n\n // Allows moving of relative cells\n graph.isCellLocked = function(cell) {\n return this.isCellsLocked();\n };\n\n graph.isCellResizable = function(cell) {\n const geo = this.model.getGeometry(cell);\n\n return geo == null || !geo.relative;\n };\n\n // Truncates the label to the size of the vertex\n graph.getLabel = function(cell) {\n const label = this.labelsVisible ? this.convertValueToString(cell) : '';\n const geometry = this.model.getGeometry(cell);\n\n if (\n !this.model.isCollapsed(cell) &&\n geometry != null &&\n (geometry.offset == null ||\n (geometry.offset.x == 0 && geometry.offset.y == 0)) &&\n this.model.isVertex(cell) &&\n geometry.width >= 2\n ) {\n const style = this.getCellStyle(cell);\n const fontSize =\n style[mxConstants.STYLE_FONTSIZE] || mxConstants.DEFAULT_FONTSIZE;\n const max = geometry.width / (fontSize * 0.625);\n\n if (max < label.length) {\n return `${label.substring(0, max)}...`;\n }\n }\n\n return label;\n };\n\n // Enables wrapping for vertex labels\n graph.isWrapping = function(cell) {\n return this.model.isCollapsed(cell);\n };\n\n // Enables clipping of vertex labels if no offset is defined\n graph.isLabelClipped = function(cell) {\n const geometry = this.model.getGeometry(cell);\n\n return (\n geometry != null &&\n !geometry.relative &&\n (geometry.offset == null ||\n (geometry.offset.x == 0 && geometry.offset.y == 0))\n );\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'vertexLabelsMovable',\n 20,\n 20,\n 80,\n 30\n );\n\n // Places sublabels inside the vertex\n const label11 = graph.insertVertex(\n v1,\n null,\n 'Label1',\n 0.5,\n 1,\n 0,\n 0,\n null,\n true\n );\n const label12 = graph.insertVertex(\n v1,\n null,\n 'Label2',\n 0.5,\n 0,\n 0,\n 0,\n null,\n true\n );\n\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Wrapping and clipping is enabled only if the cell is collapsed, otherwise the label is truncated if there is no manual offset.',\n 200,\n 150,\n 80,\n 30\n );\n v2.geometry.alternateBounds = new mxRectangle(0, 0, 80, 30);\n const e1 = graph.insertEdge(parent, null, 'edgeLabelsMovable', v1, v2);\n\n // Places sublabels inside the vertex\n const label21 = graph.insertVertex(\n v2,\n null,\n 'Label1',\n 0.5,\n 1,\n 0,\n 0,\n null,\n true\n );\n const label22 = graph.insertVertex(\n v2,\n null,\n 'Label2',\n 0.5,\n 0,\n 0,\n 0,\n null,\n true\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Labels;\n", - "Control": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxImageShape from '../mxgraph/shape/mxImageShape';\nimport mxImage from '../mxgraph/util/mxImage';\n\nclass Control extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Control

\n This example demonstrates adding controls to specific cells in a graph.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Specifies the URL and size of the new control\n const deleteImage = new mxImage(\n 'editors/images/overlays/forbidden.png',\n 16,\n 16\n );\n\n class MyCustomCellRenderer extends mxCellRenderer {\n createControl(state) {\n super.createControl(state);\n\n const { graph } = state.view;\n\n if (graph.getModel().isVertex(state.cell)) {\n if (state.deleteControl == null) {\n const b = new mxRectangle(\n 0,\n 0,\n deleteImage.width,\n deleteImage.height\n );\n state.deleteControl = new mxImageShape(b, deleteImage.src);\n state.deleteControl.dialect = graph.dialect;\n state.deleteControl.preserveImageAspect = false;\n\n this.initControl(state, state.deleteControl, false, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells([state.cell]);\n mxEvent.consume(evt);\n }\n });\n }\n } else if (state.deleteControl != null) {\n state.deleteControl.destroy();\n state.deleteControl = null;\n }\n }\n\n getDeleteControlBounds(state) {\n // Helper function to compute the bounds of the control\n if (state.deleteControl != null) {\n const oldScale = state.deleteControl.scale;\n const w = state.deleteControl.bounds.width / oldScale;\n const h = state.deleteControl.bounds.height / oldScale;\n const s = state.view.scale;\n\n return state.view.graph.getModel().isEdge(state.cell)\n ? new mxRectangle(\n state.x + state.width / 2 - (w / 2) * s,\n state.y + state.height / 2 - (h / 2) * s,\n w * s,\n h * s\n )\n : new mxRectangle(\n state.x + state.width - w * s,\n state.y,\n w * s,\n h * s\n );\n }\n return null;\n }\n\n redrawControl(state) {\n // Overridden to update the scale and bounds of the control\n super.redrawControl(state);\n\n if (state.deleteControl != null) {\n const bounds = this.getDeleteControlBounds(state);\n const s = state.view.scale;\n\n if (\n state.deleteControl.scale !== s ||\n !state.deleteControl.bounds.equals(bounds)\n ) {\n state.deleteControl.bounds = bounds;\n state.deleteControl.scale = s;\n state.deleteControl.redraw();\n }\n }\n }\n\n destroy(state) {\n // Overridden to remove the control if the state is destroyed\n super.destroy(state);\n\n if (state.deleteControl != null) {\n state.deleteControl.destroy();\n state.deleteControl = null;\n }\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createCellRenderer() {\n return new MyCustomCellRenderer();\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setPanning(true);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.centerZoom = false;\n\n this.el2.appendChild(\n mxUtils.button('Zoom In', function() {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom Out', function() {\n graph.zoomOut();\n })\n );\n };\n}\n\nexport default Control;\n", - "LabelPosition": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass LabelPosition extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Label Position

\n This example demonstrates the use of the\n label position styles to set the position of vertex labels.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '300px',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Defines the common part of all cell styles as a string-prefix\n const prefix = 'shape=image;image=images/icons48/keys.png;';\n\n // Adds cells to the model in a single step and set the vertex\n // label positions using the label position styles. Vertical\n // and horizontal label position styles can be combined.\n // Note: Alternatively, vertex labels can be set be overriding\n // mxCellRenderer.getLabelBounds.\n graph.getModel().beginUpdate();\n try {\n graph.insertVertex(\n parent,\n null,\n 'Bottom',\n 60,\n 60,\n 60,\n 60,\n `${prefix}verticalLabelPosition=bottom;verticalAlign=top`\n );\n graph.insertVertex(\n parent,\n null,\n 'Top',\n 140,\n 60,\n 60,\n 60,\n `${prefix}verticalLabelPosition=top;verticalAlign=bottom`\n );\n graph.insertVertex(\n parent,\n null,\n 'Left',\n 60,\n 160,\n 60,\n 60,\n `${prefix}labelPosition=left;align=right`\n );\n graph.insertVertex(\n parent,\n null,\n 'Right',\n 140,\n 160,\n 60,\n 60,\n `${prefix}labelPosition=right;align=left`\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default LabelPosition;\n", - "Validation": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxMultiplicity from '../mxgraph/view/mxMultiplicity';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Validation extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Validation

\n This example demonstrates using\n multiplicities for automatically validating a graph.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '281px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n const xmlDocument = mxUtils.createXmlDocument();\n const sourceNode = xmlDocument.createElement('Source');\n const targetNode = xmlDocument.createElement('Target');\n const subtargetNode = xmlDocument.createElement('Subtarget');\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n graph.setAllowDanglingEdges(false);\n graph.setMultigraph(false);\n\n // Source nodes needs 1..2 connected Targets\n graph.multiplicities.push(\n new mxMultiplicity(\n true,\n 'Source',\n null,\n null,\n 1,\n 2,\n ['Target'],\n 'Source Must Have 1 or 2 Targets',\n 'Source Must Connect to Target'\n )\n );\n\n // Source node does not want any incoming connections\n graph.multiplicities.push(\n new mxMultiplicity(\n false,\n 'Source',\n null,\n null,\n 0,\n 0,\n null,\n 'Source Must Have No Incoming Edge',\n null\n )\n ); // Type does not matter\n\n // Target needs exactly one incoming connection from Source\n graph.multiplicities.push(\n new mxMultiplicity(\n false,\n 'Target',\n null,\n null,\n 1,\n 1,\n ['Source'],\n 'Target Must Have 1 Source',\n 'Target Must Connect From Source'\n )\n );\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Removes cells when [DELETE] is pressed\n const keyHandler = new mxKeyHandler(graph);\n keyHandler.bindKey(46, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells();\n }\n });\n\n // Installs automatic validation (use editor.validation = true\n // if you are using an mxEditor instance)\n const listener = function(sender, evt) {\n graph.validateGraph();\n };\n\n graph.getModel().addListener(mxEvent.CHANGE, listener);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, sourceNode, 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, targetNode, 200, 20, 80, 30);\n const v3 = graph.insertVertex(\n parent,\n null,\n targetNode.cloneNode(true),\n 200,\n 80,\n 80,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n targetNode.cloneNode(true),\n 200,\n 140,\n 80,\n 30\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n subtargetNode,\n 200,\n 200,\n 80,\n 30\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n sourceNode.cloneNode(true),\n 20,\n 140,\n 80,\n 30\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v6, v4);\n // var e4 = graph.insertEdge(parent, null, '', v1, v4);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Validation;\n", - "Toolbar": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxDragSource from '../mxgraph/util/mxDragSource';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxToolbar from '../mxgraph/util/mxToolbar';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Toolbar extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Toolbar

\n This example demonstrates using\n existing cells as templates for creating new cells.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n border: 'gray dotted 1px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the toolbar\n const tbContainer = document.createElement('div');\n tbContainer.style.position = 'absolute';\n tbContainer.style.overflow = 'hidden';\n tbContainer.style.padding = '2px';\n tbContainer.style.left = '0px';\n tbContainer.style.top = '26px';\n tbContainer.style.width = '24px';\n tbContainer.style.bottom = '0px';\n\n this.el.appendChild(tbContainer);\n\n // Creates new toolbar without event processing\n const toolbar = new mxToolbar(tbContainer);\n toolbar.enabled = false;\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '24px';\n container.style.top = '26px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the model and the graph inside the container\n // using the fastest rendering available on the browser\n const model = new mxGraphModel();\n const graph = new mxGraph(container, model);\n graph.dropEnabled = true;\n\n // Matches DnD inside the graph\n mxDragSource.prototype.getDropTarget = function(graph, x, y) {\n let cell = graph.getCellAt(x, y);\n if (!graph.isValidDropTarget(cell)) {\n cell = null;\n }\n return cell;\n };\n\n // Enables new connections in the graph\n graph.setConnectable(true);\n graph.setMultigraph(false);\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n const rubberband = new mxRubberband(graph);\n\n const addVertex = (icon, w, h, style) => {\n const vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);\n vertex.setVertex(true);\n\n this.addToolbarItem(graph, toolbar, vertex, icon);\n };\n\n addVertex(\n 'editors/images/swimlane.gif',\n 120,\n 160,\n 'shape=swimlane;startSize=20;'\n );\n addVertex('editors/images/rectangle.gif', 100, 40, '');\n addVertex('editors/images/rounded.gif', 100, 40, 'shape=rounded');\n addVertex('editors/images/ellipse.gif', 40, 40, 'shape=ellipse');\n addVertex('editors/images/rhombus.gif', 40, 40, 'shape=rhombus');\n addVertex('editors/images/triangle.gif', 40, 40, 'shape=triangle');\n addVertex('editors/images/cylinder.gif', 40, 40, 'shape=cylinder');\n addVertex('editors/images/actor.gif', 30, 40, 'shape=actor');\n toolbar.addLine();\n\n const button = mxUtils.button(\n 'Create toolbar entry from selection',\n evt => {\n if (!graph.isSelectionEmpty()) {\n // Creates a copy of the selection array to preserve its state\n const cells = graph.getSelectionCells();\n const bounds = graph.getView().getBounds(cells);\n\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = (graph, evt, cell) => {\n graph.stopEditing(false);\n\n const pt = graph.getPointForEvent(evt);\n const dx = pt.x - bounds.x;\n const dy = pt.y - bounds.y;\n\n graph.setSelectionCells(graph.importCells(cells, dx, dy, cell));\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(\n null,\n 'editors/images/outline.gif',\n funct\n );\n mxUtils.makeDraggable(img, graph, funct);\n }\n }\n );\n\n this.el2.appendChild(button);\n }\n\n addToolbarItem(graph, toolbar, prototype, image) {\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = (graph, evt, cell) => {\n graph.stopEditing(false);\n\n const pt = graph.getPointForEvent(evt);\n const vertex = graph.getModel().cloneCell(prototype);\n vertex.geometry.x = pt.x;\n vertex.geometry.y = pt.y;\n\n graph.setSelectionCells(graph.importCells([vertex], 0, 0, cell));\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(null, image, funct);\n mxUtils.makeDraggable(img, graph, funct);\n }\n}\n\nexport default Toolbar;\n", - "Thread": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass Thread extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Thread

\n This example demonstrates setting\n overlays in mxGraph from within a timed function.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n let v1;\n let v2;\n let e1;\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Function to switch the overlay every 5 secs\n const f = () => {\n const overlays = graph.getCellOverlays(v1);\n\n if (overlays == null) {\n graph.removeCellOverlays(v2);\n graph.setCellWarning(v1, 'Tooltip');\n } else {\n graph.removeCellOverlays(v1);\n graph.setCellWarning(v2, 'Tooltip');\n }\n };\n\n window.setInterval(f, 1000);\n f();\n }\n}\n\nexport default Thread;\n", - "Animation": "/**\n * Copyright (c) 2006-2017, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from \"../mxgraph/util/mxPoint\";\n\nclass Animation extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Animation

\n This example demonstrates using\n SVG animations on edges to visualize the flow in a pipe.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n const graph = new mxGraph(this.el);\n graph.setEnabled(false);\n const parent = graph.getDefaultParent();\n\n const vertexStyle =\n 'shape=cylinder;strokeWidth=2;fillColor=#ffffff;strokeColor=black;' +\n 'gradientColor=#a0a0a0;fontColor=black;fontStyle=1;spacingTop=14;';\n\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Pump',\n 20,\n 20,\n 60,\n 60,\n vertexStyle\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Tank',\n 200,\n 150,\n 60,\n 60,\n vertexStyle\n );\n var e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'strokeWidth=3;endArrow=block;endSize=2;endFill=1;strokeColor=black;rounded=1;'\n );\n e1.geometry.points = [new mxPoint(230, 50)];\n graph.orderCells(true, [e1]);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Adds animation to edge shape and makes \"pipe\" visible\n const state = graph.view.getState(e1);\n state.shape.node\n .getElementsByTagName('path')[0]\n .removeAttribute('visibility');\n state.shape.node\n .getElementsByTagName('path')[0]\n .setAttribute('stroke-width', '6');\n state.shape.node\n .getElementsByTagName('path')[0]\n .setAttribute('stroke', 'lightGray');\n state.shape.node\n .getElementsByTagName('path')[1]\n .setAttribute('class', 'flow');\n };\n}\n\nexport default Animation;\n", - "Perimeter": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxGraphView from \"../mxgraph/view/mxGraphView\";\n\nclass Perimeter extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Perimeter

\n This example demonstrates how to\n avoid edge and label intersections.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Redirects the perimeter to the label bounds if intersection\n // between edge and label is found\n const mxGraphViewGetPerimeterPoint =\n mxGraphView.prototype.getPerimeterPoint;\n mxGraphView.prototype.getPerimeterPoint = function(\n terminal,\n next,\n orthogonal,\n border\n ) {\n let point = mxGraphViewGetPerimeterPoint.apply(this, arguments);\n\n if (point != null) {\n const perimeter = this.getPerimeterFunction(terminal);\n\n if (terminal.text != null && terminal.text.boundingBox != null) {\n // Adds a small border to the label bounds\n const b = terminal.text.boundingBox.clone();\n b.grow(3);\n\n if (mxUtils.rectangleIntersectsSegment(b, point, next)) {\n point = perimeter(b, terminal, next, orthogonal);\n }\n }\n }\n\n return point;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setVertexLabelsMovable(true);\n graph.setConnectable(true);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 20,\n 20,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 200,\n 20,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 20,\n 150,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n var e1 = graph.insertEdge(parent, null, '', v1, v2);\n var e1 = graph.insertEdge(parent, null, '', v1, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Perimeter;\n", - "JsonData": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCodecRegistry from '../mxgraph/io/mxCodecRegistry';\nimport mxObjectCodec from '../mxgraph/io/mxObjectCodec';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCodec from '../mxgraph/io/mxCodec';\n\nclass JsonData extends React.Component {\n // Adds an option to view the XML of the graph\n document;\n\n body;\n\n 'View XML';\n\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

JSON data

\n This example demonstrates using\n JSON to encode/decode parts of the graph model in mxCodec.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n v1.data = new CustomData('v1');\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n v2.data = new CustomData('v2');\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button(function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getXml(node), true);\n })\n );\n\n function CustomData(value) {\n this.value = value;\n }\n\n const codec = new mxObjectCodec(new CustomData());\n codec.encode = function(enc, obj) {\n const node = enc.document.createElement('CustomData');\n mxUtils.setTextContent(node, JSON.stringify(obj));\n\n return node;\n };\n codec.decode = function(dec, node, into) {\n const obj = JSON.parse(mxUtils.getTextContent(node));\n obj.constructor = CustomData;\n\n return obj;\n };\n mxCodecRegistry.register(codec);\n }\n}\n\nexport default JsonData;\n", - "Wrapping": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass Wrapping extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Wrapping

\n This example demonstrates using HTML markup and\n word-wrapping in vertex and edge labels.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables HTML labels as wrapping is only available for those\n graph.setHtmlLabels(true);\n\n // Disables in-place editing for edges\n graph.isCellEditable = function(cell) {\n return !this.model.isEdge(cell);\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n 20,\n 20,\n 100,\n 70,\n 'whiteSpace=wrap;'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n 220,\n 150,\n 80,\n 70,\n 'whiteSpace=wrap;'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n v1,\n v2,\n 'whiteSpace=wrap;'\n );\n e1.geometry.width = 100;\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Wrapping;\n", - "Stencils": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxPoint from \"../mxgraph/util/mxPoint\";\nimport mxStencilRegistry from \"../mxgraph/shape/mxStencilRegistry\";\nimport mxCellRenderer from \"../mxgraph/view/mxCellRenderer\";\nimport mxShape from \"../mxgraph/shape/mxShape\";\nimport mxVertexHandler from \"../mxgraph/handler/mxVertexHandler\";\nimport mxCellHighlight from \"../mxgraph/handler/mxCellHighlight\";\nimport mxEdgeHandler from \"../mxgraph/handler/mxEdgeHandler\";\nimport mxConnectionHandler from \"../mxgraph/handler/mxConnectionHandler\";\nimport mxStencil from \"../mxgraph/shape/mxStencil\";\n\nclass Stencils extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Stencils

\n This example demonstrates using\n an XML file to define new stencils to be used as shapes. See\n docs/stencils.xsd for the XML schema file.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '401px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n width: '601px',\n height: '150px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Sets the global shadow color\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n mxConstants.SHADOW_OPACITY = 0.5;\n mxConstants.SHADOW_OFFSET_X = 4;\n mxConstants.SHADOW_OFFSET_Y = 4;\n mxConstants.HANDLE_FILLCOLOR = '#99ccff';\n mxConstants.HANDLE_STROKECOLOR = '#0088cf';\n mxConstants.VERTEX_SELECTION_COLOR = '#00a8ff';\n\n // Enables connections along the outline\n mxConnectionHandler.prototype.outlineConnect = true;\n mxEdgeHandler.prototype.manageLabelHandle = true;\n mxEdgeHandler.prototype.outlineConnect = true;\n mxCellHighlight.prototype.keepOnTop = true;\n\n // Enable rotation handle\n mxVertexHandler.prototype.rotationEnabled = true;\n\n // Uses the shape for resize previews\n mxVertexHandler.prototype.createSelectionShape = function(bounds) {\n const key = this.state.style[mxConstants.STYLE_SHAPE];\n const stencil = mxStencilRegistry.getStencil(key);\n let shape = null;\n\n if (stencil != null) {\n shape = new mxShape(stencil);\n shape.apply(this.state);\n } else {\n shape = new this.state.shape.constructor();\n }\n\n shape.outline = true;\n shape.bounds = bounds;\n shape.stroke = mxConstants.HANDLE_STROKECOLOR;\n shape.strokewidth = this.getSelectionStrokeWidth();\n shape.isDashed = this.isSelectionDashed();\n shape.isShadow = false;\n\n return shape;\n };\n\n // Defines a custom stencil via the canvas API as defined here:\n // http://jgraph.github.io/mxgraph/docs/js-api/files/util/mxXmlCanvas2D-js.html\n\n class CustomShape extends mxShape {\n paintBackground(c, x, y, w, h) {\n c.translate(x, y);\n\n // Head\n c.ellipse(w / 4, 0, w / 2, h / 4);\n c.fillAndStroke();\n\n c.begin();\n c.moveTo(w / 2, h / 4);\n c.lineTo(w / 2, (2 * h) / 3);\n\n // Arms\n c.moveTo(w / 2, h / 3);\n c.lineTo(0, h / 3);\n c.moveTo(w / 2, h / 3);\n c.lineTo(w, h / 3);\n\n // Legs\n c.moveTo(w / 2, (2 * h) / 3);\n c.lineTo(0, h);\n c.moveTo(w / 2, (2 * h) / 3);\n c.lineTo(w, h);\n c.end();\n\n c.stroke();\n }\n }\n\n // Replaces existing actor shape\n mxCellRenderer.registerShape('customShape', CustomShape);\n\n // Loads the stencils into the registry\n const req = mxUtils.load('stencils.xml');\n const root = req.getDocumentElement();\n let shape = root.firstChild;\n\n while (shape != null) {\n if (shape.nodeType === mxConstants.NODETYPE_ELEMENT) {\n mxStencilRegistry.addStencil(\n shape.getAttribute('name'),\n new mxStencil(shape)\n );\n }\n\n shape = shape.nextSibling;\n }\n\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n graph.setPanning(true);\n\n graph.getTooltipForCell = function(cell) {\n if (cell != null) {\n return cell.style;\n }\n\n return null;\n };\n\n // Changes default styles\n let style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = 'orthogonalEdgeStyle';\n style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FILLCOLOR] = '#adc5ff';\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#7d85df';\n style[mxConstants.STYLE_SHADOW] = '1';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'A1',\n 20,\n 20,\n 40,\n 80,\n 'shape=and'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'A2',\n 20,\n 220,\n 40,\n 80,\n 'shape=and'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'X1',\n 160,\n 110,\n 80,\n 80,\n 'shape=xor'\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v3);\n e1.geometry.points = [new mxPoint(90, 60), new mxPoint(90, 130)];\n const e2 = graph.insertEdge(parent, null, '', v2, v3);\n e2.geometry.points = [new mxPoint(90, 260), new mxPoint(90, 170)];\n\n const v4 = graph.insertVertex(\n parent,\n null,\n 'A3',\n 520,\n 20,\n 40,\n 80,\n 'shape=customShape;flipH=1'\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n 'A4',\n 520,\n 220,\n 40,\n 80,\n 'shape=and;flipH=1'\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n 'X2',\n 340,\n 110,\n 80,\n 80,\n 'shape=xor;flipH=1'\n );\n const e3 = graph.insertEdge(parent, null, '', v4, v6);\n e3.geometry.points = [new mxPoint(490, 60), new mxPoint(130, 130)];\n const e4 = graph.insertEdge(parent, null, '', v5, v6);\n e4.geometry.points = [new mxPoint(490, 260), new mxPoint(130, 170)];\n\n const v7 = graph.insertVertex(\n parent,\n null,\n 'O1',\n 250,\n 260,\n 80,\n 60,\n 'shape=or;direction=south'\n );\n const e5 = graph.insertEdge(parent, null, '', v6, v7);\n e5.geometry.points = [new mxPoint(310, 150)];\n const e6 = graph.insertEdge(parent, null, '', v3, v7);\n e6.geometry.points = [new mxPoint(270, 150)];\n\n const e7 = graph.insertEdge(parent, null, '', v7, v5);\n e7.geometry.points = [new mxPoint(290, 370)];\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('FlipH', function() {\n graph.toggleCellStyles(mxConstants.STYLE_FLIPH);\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('FlipV', function() {\n graph.toggleCellStyles(mxConstants.STYLE_FLIPV);\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('Rotate', function() {\n const cell = graph.getSelectionCell();\n\n if (cell != null) {\n let geo = graph.getCellGeometry(cell);\n\n if (geo != null) {\n graph.getModel().beginUpdate();\n try {\n // Rotates the size and position in the geometry\n geo = geo.clone();\n geo.x += geo.width / 2 - geo.height / 2;\n geo.y += geo.height / 2 - geo.width / 2;\n const tmp = geo.width;\n geo.width = geo.height;\n geo.height = tmp;\n graph.getModel().setGeometry(cell, geo);\n\n // Reads the current direction and advances by 90 degrees\n const state = graph.view.getState(cell);\n\n if (state != null) {\n let dir =\n state.style[mxConstants.STYLE_DIRECTION] ||\n 'east'; /* default */\n\n if (dir === 'east') {\n dir = 'south';\n } else if (dir === 'south') {\n dir = 'west';\n } else if (dir === 'west') {\n dir = 'north';\n } else if (dir === 'north') {\n dir = 'east';\n }\n\n graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);\n }\n } finally {\n graph.getModel().endUpdate();\n }\n }\n }\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('And', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'and');\n })\n );\n this.el2.appendChild(\n mxUtils.button('Or', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'or');\n })\n );\n this.el2.appendChild(\n mxUtils.button('Xor', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'xor');\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('Style', function() {\n const cell = graph.getSelectionCell();\n\n if (cell != null) {\n const style = mxUtils.prompt(\n 'Style',\n graph.getModel().getStyle(cell)\n );\n\n if (style != null) {\n graph.getModel().setStyle(cell, style);\n }\n }\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Stencils;\n", - "UserObject": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxForm from \"../mxgraph/util/mxForm\";\nimport mxCellAttributeChange from \"../mxgraph/model/atomic_changes/mxCellAttributeChange\";\nimport mxKeyHandler from \"../mxgraph/handler/mxKeyHandler\";\nimport mxRectangle from \"../mxgraph/util/mxRectangle\";\nimport mxEdgeStyle from \"../mxgraph/view/mxEdgeStyle\";\n\nclass UserObject extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

User object

\n This example demonstrates using\n XML objects as values for cells.\n\n \n \n \n \n \n
\n {this.el = el;}}\n style={{\n border: 'solid 1px black',\n overflow: 'hidden',\n height: '241px',\n cursor: 'default'\n }}\n />\n \n {this.propertiesEl = el;}}\n style={{\n border: 'solid 1px black',\n padding: '10px'\n }}\n />\n
\n\n {this.el2 = el;}}\n />\n \n );\n }\n\n componentDidMount() {\n // Note that these XML nodes will be enclosing the\n // mxCell nodes for the model cells in the output\n const doc = mxUtils.createXmlDocument();\n\n const person1 = doc.createElement('Person');\n person1.setAttribute('firstName', 'Daffy');\n person1.setAttribute('lastName', 'Duck');\n\n const person2 = doc.createElement('Person');\n person2.setAttribute('firstName', 'Bugs');\n person2.setAttribute('lastName', 'Bunny');\n\n const relation = doc.createElement('Knows');\n relation.setAttribute('since', '1985');\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Optional disabling of sizing\n graph.setCellsResizable(false);\n\n // Configures the graph contains to resize and\n // add a border at the bottom, right\n graph.setResizeContainer(true);\n graph.minimumContainerSize = new mxRectangle(0, 0, 500, 380);\n graph.setBorder(60);\n\n // Stops editing on enter key, handles escape\n new mxKeyHandler(graph);\n\n // Overrides method to disallow edge label editing\n graph.isCellEditable = function(cell) {\n return !this.getModel().isEdge(cell);\n };\n\n // Overrides method to provide a cell label in the display\n graph.convertValueToString = function(cell) {\n if (mxUtils.isNode(cell.value)) {\n if (cell.value.nodeName.toLowerCase() == 'person') {\n const firstName = cell.getAttribute('firstName', '');\n const lastName = cell.getAttribute('lastName', '');\n\n if (lastName != null && lastName.length > 0) {\n return `${lastName}, ${firstName}`;\n }\n\n return firstName;\n }\n if (cell.value.nodeName.toLowerCase() == 'knows') {\n return `${cell.value.nodeName} (Since ${cell.getAttribute(\n 'since',\n ''\n )})`;\n }\n }\n\n return '';\n };\n\n // Overrides method to store a cell label in the model\n const { cellLabelChanged } = graph;\n graph.cellLabelChanged = function(cell, newValue, autoSize) {\n if (\n mxUtils.isNode(cell.value) &&\n cell.value.nodeName.toLowerCase() == 'person'\n ) {\n const pos = newValue.indexOf(' ');\n\n const firstName = pos > 0 ? newValue.substring(0, pos) : newValue;\n const lastName =\n pos > 0 ? newValue.substring(pos + 1, newValue.length) : '';\n\n // Clones the value for correct undo/redo\n const elt = cell.value.cloneNode(true);\n\n elt.setAttribute('firstName', firstName);\n elt.setAttribute('lastName', lastName);\n\n newValue = elt;\n autoSize = true;\n }\n\n cellLabelChanged.apply(this, arguments);\n };\n\n // Overrides method to create the editing value\n const { getEditingValue } = graph;\n graph.getEditingValue = function(cell) {\n if (\n mxUtils.isNode(cell.value) &&\n cell.value.nodeName.toLowerCase() == 'person'\n ) {\n const firstName = cell.getAttribute('firstName', '');\n const lastName = cell.getAttribute('lastName', '');\n\n return `${firstName} ${lastName}`;\n }\n };\n\n // Adds a special tooltip for edges\n graph.setTooltips(true);\n\n const { getTooltipForCell } = graph;\n graph.getTooltipForCell = function(cell) {\n // Adds some relation details for edges\n if (graph.getModel().isEdge(cell)) {\n const src = this.getLabel(this.getModel().getTerminal(cell, true));\n const trg = this.getLabel(this.getModel().getTerminal(cell, false));\n\n return `${src} ${cell.value.nodeName} ${trg}`;\n }\n\n return getTooltipForCell.apply(this, arguments);\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Adds an option to view the XML of the graph\n this.el2.appendChild(\n mxUtils.button('View XML', function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getPrettyXml(node), true);\n })\n );\n\n // Changes the style for match the markup\n // Creates the default style for vertices\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_STROKECOLOR] = 'gray';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#DFDFDF';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_SPACING] = 4;\n\n // Creates the default style for edges\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_STROKECOLOR] = '#0C0C0C';\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_FONTSIZE] = '10';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, person1, 40, 40, 80, 30);\n const v2 = graph.insertVertex(parent, null, person2, 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, relation, v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Implements a properties panel that uses\n // mxCellAttributeChange to change properties\n graph\n .getSelectionModel()\n .addListener(mxEvent.CHANGE, function(sender, evt) {\n this.selectionChanged(graph);\n });\n\n this.selectionChanged(graph);\n }\n\n /**\n * Updates the properties panel\n */\n selectionChanged(graph) {\n const div = this.propertiesEl;\n\n // Forces focusout in IE\n graph.container.focus();\n\n // Clears the DIV the non-DOM way\n div.innerHTML = '';\n\n // Gets the selection cell\n const cell = graph.getSelectionCell();\n\n if (cell == null) {\n mxUtils.writeln(div, 'Nothing selected.');\n } else {\n // Writes the title\n const center = document.createElement('center');\n mxUtils.writeln(center, `${cell.value.nodeName} (${cell.id})`);\n div.appendChild(center);\n mxUtils.br(div);\n\n // Creates the form from the attributes of the user object\n const form = new mxForm();\n\n const attrs = cell.value.attributes;\n\n for (let i = 0; i < attrs.length; i++) {\n this.createTextField(graph, form, cell, attrs[i]);\n }\n\n div.appendChild(form.getTable());\n mxUtils.br(div);\n }\n }\n\n /**\n * Creates the textfield for the given property.\n */\n createTextField(graph, form, cell, attribute) {\n const input = form.addText(`${attribute.nodeName}:`, attribute.nodeValue);\n\n const applyHandler = function() {\n const newValue = input.value || '';\n const oldValue = cell.getAttribute(attribute.nodeName, '');\n\n if (newValue != oldValue) {\n graph.getModel().beginUpdate();\n\n try {\n const edit = new mxCellAttributeChange(\n cell,\n attribute.nodeName,\n newValue\n );\n graph.getModel().execute(edit);\n graph.updateCellSize(cell);\n } finally {\n graph.getModel().endUpdate();\n }\n }\n };\n\n mxEvent.addListener(input, 'keypress', function(evt) {\n // Needs to take shift into account for textareas\n if (evt.keyCode == /* enter */ 13 && !mxEvent.isShiftDown(evt)) {\n input.blur();\n }\n });\n\n // Note: Known problem is the blurring of fields in\n // Firefox by changing the selection, in which case\n // no event is fired in FF and the change is lost.\n // As a workaround you should use a local variable\n // that stores the focused field and invoke blur\n // explicitely where we do the graph.focus above.\n mxEvent.addListener(input, 'blur', applyHandler);\n }\n}\n\nexport default UserObject;\n", - "Merge": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxPerimeter from \"../mxgraph/view/mxPerimeter\";\n\nclass Merge extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Merge

\n This example demonstrates using\n the mergeChildren function to merge two graphs.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '280px',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxConstants.SHADOWCOLOR = '#c0c0c0';\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // No size handles, please...\n graph.setCellsResizable(false);\n\n // Makes all cells round with a white, bold label\n let style = graph.stylesheet.getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_FONTCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;\n style[mxConstants.STYLE_FONTSIZE] = 14;\n style[mxConstants.STYLE_SHADOW] = true;\n\n // Makes all edge labels gray with a white background\n style = graph.stylesheet.getDefaultEdgeStyle();\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKEWIDTH] = 2;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the target model in a single step\n // using custom ids for the vertices and edges\n const w = 40;\n const h = 40;\n\n graph.getModel().beginUpdate();\n try {\n const a = graph.insertVertex(\n parent,\n 'a',\n 'A',\n 20,\n 20,\n w,\n h,\n 'fillColor=blue'\n );\n const b = graph.insertVertex(\n parent,\n 'b',\n 'B',\n 20,\n 200,\n w,\n h,\n 'fillColor=blue'\n );\n const c = graph.insertVertex(\n parent,\n 'c',\n 'C',\n 200,\n 20,\n w,\n h,\n 'fillColor=red'\n );\n const d = graph.insertVertex(\n parent,\n 'd',\n 'D',\n 200,\n 200,\n w,\n h,\n 'fillColor=red'\n );\n const ac = graph.insertEdge(\n parent,\n 'ac',\n 'ac',\n a,\n c,\n 'strokeColor=blue;verticalAlign=bottom'\n );\n const ad = graph.insertEdge(\n parent,\n 'ad',\n 'ad',\n a,\n d,\n 'strokeColor=blue;align=left;verticalAlign=bottom'\n );\n const bd = graph.insertEdge(\n parent,\n 'bd',\n 'bd',\n b,\n d,\n 'strokeColor=blue;verticalAlign=bottom'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Creates the second graph model (without a container)\n const graph2 = new mxGraph();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent2 = graph2.getDefaultParent();\n\n // Adds cells to the target model in a single step\n // using custom ids for the vertices\n graph2.getModel().beginUpdate();\n try {\n const c = graph2.insertVertex(\n parent2,\n 'c',\n 'C',\n 200,\n 20,\n w,\n h,\n 'fillColor=green'\n );\n const d = graph2.insertVertex(\n parent2,\n 'd',\n 'D',\n 200,\n 200,\n w,\n h,\n 'fillColor=green'\n );\n const e = graph2.insertVertex(\n parent2,\n 'e',\n 'E',\n 400,\n 20,\n w,\n h,\n 'fillColor=green'\n );\n const f = graph2.insertVertex(\n parent2,\n 'f',\n 'F',\n 400,\n 200,\n w,\n h,\n 'fillColor=green'\n );\n const ce = graph2.insertEdge(\n parent2,\n 'ce',\n 'ce',\n c,\n e,\n 'strokeColor=green;verticalAlign=bottom'\n );\n const ed = graph2.insertEdge(\n parent2,\n 'ed',\n 'ed',\n e,\n d,\n 'strokeColor=green;align=right;verticalAlign=bottom'\n );\n const fd = graph2.insertEdge(\n parent2,\n 'bd',\n 'fd',\n f,\n d,\n 'strokeColor=green;verticalAlign=bottom'\n );\n } finally {\n // Updates the display\n graph2.getModel().endUpdate();\n }\n\n // Merges the model from the second graph into the model of\n // the first graph. Note: If you add a false to the parameter\n // list then _not_ all edges will be cloned, that is, the\n // edges are assumed to have an identity, and hence the edge\n // \"bd\" will be changed to point from f to d, as specified in\n // the edge for the same id in the second graph.\n graph.getModel().mergeChildren(parent2, parent /* , false */);\n }\n}\n\nexport default Merge;\n", - "OrgChart": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n\n Orgchart. This example demonstrates using\n automatic layouts, fit to page zoom and poster print (across\n multiple pages).\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPrintPreview from '../mxgraph/view/mxPrintPreview';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxWindow from \"../mxgraph/util/mxWindow\";\nimport mxToolbar from \"../mxgraph/util/mxToolbar\";\nimport mxLayoutManager from \"../mxgraph/view/mxLayoutManager\";\nimport mxEdgeStyle from \"../mxgraph/view/mxEdgeStyle\";\nimport mxCompactTreeLayout from \"../mxgraph/layout/mxCompactTreeLayout\";\nimport mxKeyHandler from \"../mxgraph/handler/mxKeyHandler\";\nimport mxClient from \"../mxgraph/mxClient\";\nimport mxOutline from \"../mxgraph/view/mxOutline\";\n\nclass OrgChart extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Orgchart

\n {\n this.el = el;\n }}\n style={{\n zIndex: 1,\n position: 'relative',\n overflow: 'hidden',\n height: '50vh',\n background: 'transparent',\n borderStyle: 'solid',\n borderColor: 'lightgray',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Makes the shadow brighter\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n\n // Workaround for Internet Explorer ignoring certain styles\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '0px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n\n const outline = document.getElementById('outlineContainer');\n\n mxEvent.disableContextMenu(container);\n\n // Sets a gradient background\n if (mxClient.IS_GC || mxClient.IS_SF) {\n container.style.background =\n '-webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFFFFF), to(#E7E7E7))';\n } else if (mxClient.IS_NS) {\n container.style.background =\n '-moz-linear-gradient(top, #FFFFFF, #E7E7E7)';\n }\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n // Enables automatic sizing for vertices after editing and\n // panning by using the left mouse button.\n graph.setCellsMovable(false);\n graph.setAutoSizeCells(true);\n graph.setPanning(true);\n graph.centerZoom = false;\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Displays a popupmenu when the user clicks\n // on a cell (using the left mouse button) but\n // do not select the cell when the popup menu\n // is displayed\n graph.panningHandler.popupMenuHandler = false;\n\n // Creates the outline (navigator, overview) for moving\n // around the graph in the top, right corner of the window.\n const outln = new mxOutline(graph, outline);\n\n // Disables tooltips on touch devices\n graph.setTooltips(!mxClient.IS_TOUCH);\n\n // Set some stylesheet options for the visual appearance of vertices\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'label';\n\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_SPACING_LEFT] = 54;\n\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#7d85df';\n style[mxConstants.STYLE_STROKECOLOR] = '#5d65df';\n style[mxConstants.STYLE_FILLCOLOR] = '#adc5ff';\n\n style[mxConstants.STYLE_FONTCOLOR] = '#1d258f';\n style[mxConstants.STYLE_FONTFAMILY] = 'Verdana';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = '1';\n\n style[mxConstants.STYLE_SHADOW] = '1';\n style[mxConstants.STYLE_ROUNDED] = '1';\n style[mxConstants.STYLE_GLASS] = '1';\n\n style[mxConstants.STYLE_IMAGE] = 'editors/images/dude3.png';\n style[mxConstants.STYLE_IMAGE_WIDTH] = '48';\n style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';\n style[mxConstants.STYLE_SPACING] = 8;\n\n // Sets the default style for edges\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_STROKEWIDTH] = 3;\n style[mxConstants.STYLE_EXIT_X] = 0.5; // center\n style[mxConstants.STYLE_EXIT_Y] = 1.0; // bottom\n style[mxConstants.STYLE_EXIT_PERIMETER] = 0; // disabled\n style[mxConstants.STYLE_ENTRY_X] = 0.5; // center\n style[mxConstants.STYLE_ENTRY_Y] = 0; // top\n style[mxConstants.STYLE_ENTRY_PERIMETER] = 0; // disabled\n\n // Disable the following for straight lines\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n\n // Enables automatic layout on the graph and installs\n // a tree layout for all groups who's children are\n // being changed, added or removed.\n const layout = new mxCompactTreeLayout(graph, false);\n layout.useBoundingBox = false;\n layout.edgeRouting = false;\n layout.levelDistance = 60;\n layout.nodeDistance = 16;\n\n // Allows the layout to move cells even though cells\n // aren't movable in the graph\n layout.isVertexMovable = function(cell) {\n return true;\n };\n\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Installs a popupmenu handler using local function (see below).\n graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {\n return createPopupMenu(graph, menu, cell, evt);\n };\n\n // Fix for wrong preferred size\n const oldGetPreferredSizeForCell = graph.getPreferredSizeForCell;\n graph.getPreferredSizeForCell = function(cell) {\n const result = oldGetPreferredSizeForCell.apply(this, arguments);\n\n if (result != null) {\n result.width = Math.max(120, result.width - 40);\n }\n\n return result;\n };\n\n // Sets the maximum text scale to 1\n graph.cellRenderer.getTextScale = function(state) {\n return Math.min(1, state.view.scale);\n };\n\n // Dynamically adds text to the label as we zoom in\n // (without affecting the preferred size for new cells)\n graph.cellRenderer.getLabelValue = function(state) {\n let result = state.cell.value;\n\n if (state.view.graph.getModel().isVertex(state.cell)) {\n if (state.view.scale > 1) {\n result += '\\nDetails 1';\n }\n\n if (state.view.scale > 1.3) {\n result += '\\nDetails 2';\n }\n }\n\n return result;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds the root vertex of the tree\n graph.getModel().beginUpdate();\n try {\n const w = graph.container.offsetWidth;\n const v1 = graph.insertVertex(\n parent,\n 'treeRoot',\n 'Organization',\n w / 2 - 30,\n 20,\n 140,\n 60,\n 'image=editors/images/house.png'\n );\n graph.updateCellSize(v1);\n addOverlays(graph, v1, false);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const content = document.createElement('div');\n content.style.padding = '4px';\n\n const tb = new mxToolbar(content);\n\n tb.addItem('Zoom In', 'images/zoom_in32.png', function(evt) {\n graph.zoomIn();\n });\n\n tb.addItem('Zoom Out', 'images/zoom_out32.png', function(evt) {\n graph.zoomOut();\n });\n\n tb.addItem('Actual Size', 'images/view_1_132.png', function(evt) {\n graph.zoomActual();\n });\n\n tb.addItem('Print', 'images/print32.png', function(evt) {\n const preview = new mxPrintPreview(graph, 1);\n preview.open();\n });\n\n tb.addItem('Poster Print', 'images/press32.png', function(evt) {\n const pageCount = mxUtils.prompt('Enter maximum page count', '1');\n\n if (pageCount != null) {\n const scale = mxUtils.getScaleForPageCount(pageCount, graph);\n const preview = new mxPrintPreview(graph, scale);\n preview.open();\n }\n });\n\n let wnd = new mxWindow('Tools', content, 0, 0, 200, 66, false);\n wnd.setMaximizable(false);\n wnd.setScrollable(false);\n wnd.setResizable(false);\n wnd.setVisible(true);\n\n // Function to create the entries in the popupmenu\n function createPopupMenu(graph, menu, cell, evt) {\n const model = graph.getModel();\n\n if (cell != null) {\n if (model.isVertex(cell)) {\n menu.addItem(\n 'Add child',\n 'editors/images/overlays/check.png',\n function() {\n addChild(graph, cell);\n }\n );\n }\n\n menu.addItem('Edit label', 'editors/images/text.gif', function() {\n graph.startEditingAtCell(cell);\n });\n\n if (cell.id != 'treeRoot' && model.isVertex(cell)) {\n menu.addItem('Delete', 'editors/images/delete.gif', function() {\n deleteSubtree(graph, cell);\n });\n }\n\n menu.addSeparator();\n }\n\n menu.addItem('Fit', 'editors/images/zoom.gif', function() {\n graph.fit();\n });\n\n menu.addItem('Actual', 'editors/images/zoomactual.gif', function() {\n graph.zoomActual();\n });\n\n menu.addSeparator();\n\n menu.addItem('Print', 'editors/images/print.gif', function() {\n const preview = new mxPrintPreview(graph, 1);\n preview.open();\n });\n\n menu.addItem('Poster Print', 'editors/images/print.gif', function() {\n const pageCount = mxUtils.prompt('Enter maximum page count', '1');\n\n if (pageCount != null) {\n const scale = mxUtils.getScaleForPageCount(pageCount, graph);\n const preview = new mxPrintPreview(graph, scale);\n preview.open();\n }\n });\n }\n\n function addOverlays(graph, cell, addDeleteIcon) {\n let overlay = new mxCellOverlay(\n new mxImage('images/add.png', 24, 24),\n 'Add child'\n );\n overlay.cursor = 'hand';\n overlay.align = mxConstants.ALIGN_CENTER;\n overlay.addListener(\n mxEvent.CLICK,\n mxUtils.bind(this, function(sender, evt) {\n addChild(graph, cell);\n })\n );\n\n graph.addCellOverlay(cell, overlay);\n\n if (addDeleteIcon) {\n overlay = new mxCellOverlay(\n new mxImage('images/close.png', 30, 30),\n 'Delete'\n );\n overlay.cursor = 'hand';\n overlay.offset = new mxPoint(-4, 8);\n overlay.align = mxConstants.ALIGN_RIGHT;\n overlay.verticalAlign = mxConstants.ALIGN_TOP;\n overlay.addListener(\n mxEvent.CLICK,\n mxUtils.bind(this, function(sender, evt) {\n deleteSubtree(graph, cell);\n })\n );\n\n graph.addCellOverlay(cell, overlay);\n }\n }\n\n function addChild(graph, cell) {\n const model = graph.getModel();\n const parent = graph.getDefaultParent();\n let vertex;\n\n model.beginUpdate();\n try {\n vertex = graph.insertVertex(parent, null, 'Double click to set name');\n const geometry = model.getGeometry(vertex);\n\n // Updates the geometry of the vertex with the\n // preferred size computed in the graph\n const size = graph.getPreferredSizeForCell(vertex);\n geometry.width = size.width;\n geometry.height = size.height;\n\n // Adds the edge between the existing cell\n // and the new vertex and executes the\n // automatic layout on the parent\n const edge = graph.insertEdge(parent, null, '', cell, vertex);\n\n // Configures the edge label \"in-place\" to reside\n // at the end of the edge (x = 1) and with an offset\n // of 20 pixels in negative, vertical direction.\n edge.geometry.x = 1;\n edge.geometry.y = 0;\n edge.geometry.offset = new mxPoint(0, -20);\n\n addOverlays(graph, vertex, true);\n } finally {\n model.endUpdate();\n }\n\n return vertex;\n }\n\n function deleteSubtree(graph, cell) {\n // Gets the subtree from cell downwards\n const cells = [];\n graph.traverse(cell, true, function(vertex) {\n cells.push(vertex);\n\n return true;\n });\n\n graph.removeCells(cells);\n }\n }\n}\n\nexport default OrgChart;\n", - "Visibility": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Visibility extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Visibility

\n This example demonstrates using\n various solutions for hiding and showing cells.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n let showOne = true;\n let showTwo = true;\n let showThree = true;\n\n // Overridden to implement dynamic conditions\n graph.isCellVisible = function(cell) {\n let result = mxGraph.prototype.isCellVisible.apply(this, arguments);\n\n if (result && cell.value != null) {\n result =\n (showOne && cell.value == '1') ||\n (showTwo && cell.value == '2') ||\n (showThree && cell.value == '3');\n }\n\n return result;\n };\n\n // Adds cells to the model in a single step\n let v1;\n graph.getModel().beginUpdate();\n try {\n v1 = graph.insertVertex(parent, null, '1', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '3', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Dynamic conditions (requires refresh)\n this.el2.appendChild(\n mxUtils.button('Cond 1', function() {\n showOne = !showOne;\n graph.refresh();\n })\n );\n this.el2.appendChild(\n mxUtils.button('Cond 2', function() {\n showTwo = !showTwo;\n graph.refresh();\n })\n );\n this.el2.appendChild(\n mxUtils.button('Cond 3', function() {\n showThree = !showThree;\n graph.refresh();\n })\n );\n\n // Explicit show/hide\n this.el2.appendChild(\n mxUtils.button('Toggle cell', function() {\n graph.toggleCells(!graph.getModel().isVisible(v1), [v1], true);\n })\n );\n\n // Explicit remove/add\n let removed = null;\n\n this.el2.appendChild(\n mxUtils.button('Add/remove cell', function() {\n if (removed != null) {\n graph.addCells(removed);\n removed = null;\n } else {\n removed = graph.removeCells([v1]);\n }\n })\n );\n }\n}\n\nexport default Visibility;\n", - "Shape": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxCellRenderer from \"../mxgraph/view/mxCellRenderer\";\n\nclass Shape extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Shape

\n This example demonstrates how to\n implement and use a custom shape.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n /*\n The example shape is a \"3D box\" that looks like this:\n ____\n / /|\n /___/ |\n | | /\n |___|/\n\n The code below defines the shape. The BoxShape function\n it the constructor which creates a new object instance.\n \n The next lines use an mxCylinder instance to augment the\n prototype of the shape (\"inheritance\") and reset the\n constructor to the topmost function of the c'tor chain.\n */\n\n class BoxShape extends mxCylinder {\n // Defines the extrusion of the box as a \"static class variable\"\n extrude = 10;\n\n /*\n Next, the mxCylinder's redrawPath method is \"overridden\".\n This method has a isForeground argument to separate two\n paths, one for the background (which must be closed and\n might be filled) and one for the foreground, which is\n just a stroke.\n\n Foreground: /\n _____/\n |\n |\n ____\n Background: / |\n / |\n | /\n |____/\n */\n redrawPath(path, x, y, w, h, isForeground) {\n const dy = this.extrude * this.scale;\n const dx = this.extrude * this.scale;\n\n if (isForeground) {\n path.moveTo(0, dy);\n path.lineTo(w - dx, dy);\n path.lineTo(w, 0);\n path.moveTo(w - dx, dy);\n path.lineTo(w - dx, h);\n } else {\n path.moveTo(0, dy);\n path.lineTo(dx, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h - dy);\n path.lineTo(w - dx, h);\n path.lineTo(0, h);\n path.lineTo(0, dy);\n path.lineTo(dx, 0);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('box', BoxShape);\n\n // Creates the graph inside the DOM node.\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Changes the default style for vertices \"in-place\"\n // to use the custom shape.\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'box';\n\n // Adds a spacing for the label that matches the\n // extrusion size\n style[mxConstants.STYLE_SPACING_TOP] = BoxShape.prototype.extrude;\n style[mxConstants.STYLE_SPACING_RIGHT] = BoxShape.prototype.extrude;\n\n // Adds a gradient and shadow to improve the user experience\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#FFFFFF';\n style[mxConstants.STYLE_SHADOW] = true;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Custom', 20, 20, 80, 60);\n const v2 = graph.insertVertex(parent, null, 'Shape', 200, 150, 80, 60);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Shape;\n", - "Images": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxPerimeter from \"../mxgraph/view/mxPerimeter\";\n\nclass Images extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Images

\n This example demonstrates using\n background images and images for for the label- and image-shape.\n \n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '200px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Sets a background image and restricts child movement to its bounds\n graph.setBackgroundImage(\n new mxImage('images/gradient_background.jpg', 360, 200)\n );\n graph.maximumGraphBounds = new mxRectangle(0, 0, 360, 200);\n\n // Resizes the container but never make it bigger than the background\n graph.minimumContainerSize = new mxRectangle(0, 0, 360, 200);\n graph.setResizeContainer(true);\n\n // Disables basic selection and cell handling\n // graph.setEnabled(false);\n configureStylesheet(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n var v1 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 20,\n 10,\n 80,\n 100,\n 'bottom'\n );\n var v1 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 130,\n 10,\n 80,\n 100,\n 'top'\n );\n var v1 = graph.insertVertex(parent, null, '', 230, 10, 100, 100, 'image');\n var v2 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 20,\n 130,\n 140,\n 60,\n 'right'\n );\n var v2 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 180,\n 130,\n 140,\n 60,\n 'left'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n function configureStylesheet(graph) {\n let style = {};\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/keys.png';\n style[mxConstants.STYLE_FONTCOLOR] = '#FFFFFF';\n graph.getStylesheet().putCellStyle('image', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL;\n style[mxConstants.STYLE_STROKECOLOR] = '#000000';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/gear.png';\n style[mxConstants.STYLE_IMAGE_WIDTH] = '48';\n style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';\n style[mxConstants.STYLE_SPACING_TOP] = '56';\n style[mxConstants.STYLE_SPACING] = '8';\n graph.getStylesheet().putCellStyle('bottom', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_BOTTOM;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/server.png';\n delete style[mxConstants.STYLE_SPACING_TOP];\n graph.getStylesheet().putCellStyle('top', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/earth.png';\n style[mxConstants.STYLE_SPACING_LEFT] = '55';\n style[mxConstants.STYLE_SPACING] = '4';\n graph.getStylesheet().putCellStyle('right', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_RIGHT;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_RIGHT;\n delete style[mxConstants.STYLE_SPACING_LEFT];\n style[mxConstants.STYLE_SPACING_RIGHT] = '55';\n graph.getStylesheet().putCellStyle('left', style);\n }\n }\n}\n\nexport default Images;\n", - "Stylesheet": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxPerimeter from \"../mxgraph/view/mxPerimeter\";\n\nclass Stylesheet extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Stylesheet

\n This example demonstrates using\n a custom stylesheet and control points in edges, as well as\n overriding the getLabel and getTooltip function to return\n dynamic information, and making a supercall in JavaScript.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '311px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the DOM node.\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Returns a special label for edges. Note: This does\n // a supercall to use the default implementation.\n graph.getLabel = function(cell) {\n const label = mxGraph.prototype.getLabel.apply(this, arguments);\n\n if (this.getModel().isEdge(cell)) {\n return `Transfer ${label}`;\n }\n return label;\n };\n\n // Installs a custom global tooltip\n graph.setTooltips(true);\n graph.getTooltip = function(state) {\n const { cell } = state;\n const model = this.getModel();\n\n if (model.isEdge(cell)) {\n const source = this.getLabel(model.getTerminal(cell, true));\n const target = this.getLabel(model.getTerminal(cell, false));\n\n return `${source} -> ${target}`;\n }\n return this.getLabel(cell);\n };\n\n // Creates the default style for vertices\n let style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = 'gray';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#EEEEEE';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTCOLOR] = '#774400';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n graph.getStylesheet().putDefaultVertexStyle(style);\n\n // Creates the default style for edges\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_CONNECTOR;\n style[mxConstants.STYLE_STROKECOLOR] = '#6482B9';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;\n style[mxConstants.STYLE_FONTSIZE] = '10';\n graph.getStylesheet().putDefaultEdgeStyle(style);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Interval 1',\n 20,\n 20,\n 180,\n 30\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Interval 2',\n 140,\n 80,\n 280,\n 30\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Interval 3',\n 200,\n 140,\n 360,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n 'Interval 4',\n 480,\n 200,\n 120,\n 30\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n 'Interval 5',\n 60,\n 260,\n 400,\n 30\n );\n const e1 = graph.insertEdge(parent, null, '1', v1, v2);\n e1.getGeometry().points = [{ x: 160, y: 60 }];\n const e2 = graph.insertEdge(parent, null, '2', v1, v5);\n e2.getGeometry().points = [{ x: 80, y: 60 }];\n const e3 = graph.insertEdge(parent, null, '3', v2, v3);\n e3.getGeometry().points = [{ x: 280, y: 120 }];\n const e4 = graph.insertEdge(parent, null, '4', v3, v4);\n e4.getGeometry().points = [{ x: 500, y: 180 }];\n const e5 = graph.insertEdge(parent, null, '5', v3, v5);\n e5.getGeometry().points = [{ x: 380, y: 180 }];\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Stylesheet;\n", - "ExtendCanvas": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxPoint from '../mxgraph/util/mxPoint';\n\nclass ExtendCanvas extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Extend canvas

\n This example demonstrates implementing\n an infinite canvas with scrollbars.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.panningHandler.ignoreCell = true;\n graph.setPanning(true);\n\n /**\n * Specifies the size of the size for \"tiles\" to be used for a graph with\n * scrollbars but no visible background page. A good value is large\n * enough to reduce the number of repaints that is caused for auto-\n * translation, which depends on this value, and small enough to give\n * a small empty buffer around the graph. Default is 400x400.\n */\n graph.scrollTileSize = new mxRectangle(0, 0, 400, 400);\n\n /**\n * Returns the padding for pages in page view with scrollbars.\n */\n graph.getPagePadding = function() {\n return new mxPoint(\n Math.max(0, Math.round(graph.container.offsetWidth - 34)),\n Math.max(0, Math.round(graph.container.offsetHeight - 34))\n );\n };\n\n /**\n * Returns the size of the page format scaled with the page size.\n */\n graph.getPageSize = function() {\n return this.pageVisible\n ? new mxRectangle(\n 0,\n 0,\n this.pageFormat.width * this.pageScale,\n this.pageFormat.height * this.pageScale\n )\n : this.scrollTileSize;\n };\n\n /**\n * Returns a rectangle describing the position and count of the\n * background pages, where x and y are the position of the top,\n * left page and width and height are the vertical and horizontal\n * page count.\n */\n graph.getPageLayout = function() {\n const size = this.pageVisible ? this.getPageSize() : this.scrollTileSize;\n const bounds = this.getGraphBounds();\n\n if (bounds.width === 0 || bounds.height === 0) {\n return new mxRectangle(0, 0, 1, 1);\n }\n\n // Computes untransformed graph bounds\n const x = Math.ceil(bounds.x / this.view.scale - this.view.translate.x);\n const y = Math.ceil(bounds.y / this.view.scale - this.view.translate.y);\n const w = Math.floor(bounds.width / this.view.scale);\n const h = Math.floor(bounds.height / this.view.scale);\n\n const x0 = Math.floor(x / size.width);\n const y0 = Math.floor(y / size.height);\n const w0 = Math.ceil((x + w) / size.width) - x0;\n const h0 = Math.ceil((y + h) / size.height) - y0;\n\n return new mxRectangle(x0, y0, w0, h0);\n };\n\n // Fits the number of background pages to the graph\n graph.view.getBackgroundPageBounds = function() {\n const layout = this.graph.getPageLayout();\n const page = this.graph.getPageSize();\n\n return new mxRectangle(\n this.scale * (this.translate.x + layout.x * page.width),\n this.scale * (this.translate.y + layout.y * page.height),\n this.scale * layout.width * page.width,\n this.scale * layout.height * page.height\n );\n };\n\n graph.getPreferredPageSize = function(bounds, width, height) {\n const pages = this.getPageLayout();\n const size = this.getPageSize();\n\n return new mxRectangle(\n 0,\n 0,\n pages.width * size.width,\n pages.height * size.height\n );\n };\n\n /**\n * Guesses autoTranslate to avoid another repaint (see below).\n * Works if only the scale of the graph changes or if pages\n * are visible and the visible pages do not change.\n */\n const graphViewValidate = graph.view.validate;\n graph.view.validate = function() {\n if (\n this.graph.container != null &&\n mxUtils.hasScrollbars(this.graph.container)\n ) {\n const pad = this.graph.getPagePadding();\n const size = this.graph.getPageSize();\n\n // Updating scrollbars here causes flickering in quirks and is not needed\n // if zoom method is always used to set the current scale on the graph.\n const tx = this.translate.x;\n const ty = this.translate.y;\n this.translate.x = pad.x / this.scale - (this.x0 || 0) * size.width;\n this.translate.y = pad.y / this.scale - (this.y0 || 0) * size.height;\n }\n\n graphViewValidate.apply(this, arguments);\n };\n\n const graphSizeDidChange = graph.sizeDidChange;\n graph.sizeDidChange = function() {\n if (this.container != null && mxUtils.hasScrollbars(this.container)) {\n const pages = this.getPageLayout();\n const pad = this.getPagePadding();\n const size = this.getPageSize();\n\n // Updates the minimum graph size\n const minw = Math.ceil(\n (2 * pad.x) / this.view.scale + pages.width * size.width\n );\n const minh = Math.ceil(\n (2 * pad.y) / this.view.scale + pages.height * size.height\n );\n\n const min = graph.minimumGraphSize;\n\n // LATER: Fix flicker of scrollbar size in IE quirks mode\n // after delayed call in window.resize event handler\n if (min == null || min.width !== minw || min.height !== minh) {\n graph.minimumGraphSize = new mxRectangle(0, 0, minw, minh);\n }\n\n // Updates auto-translate to include padding and graph size\n const dx = pad.x / this.view.scale - pages.x * size.width;\n const dy = pad.y / this.view.scale - pages.y * size.height;\n\n if (\n !this.autoTranslate &&\n (this.view.translate.x !== dx || this.view.translate.y !== dy)\n ) {\n this.autoTranslate = true;\n this.view.x0 = pages.x;\n this.view.y0 = pages.y;\n\n // NOTE: THIS INVOKES THIS METHOD AGAIN. UNFORTUNATELY THERE IS NO WAY AROUND THIS SINCE THE\n // BOUNDS ARE KNOWN AFTER THE VALIDATION AND SETTING THE TRANSLATE TRIGGERS A REVALIDATION.\n // SHOULD MOVE TRANSLATE/SCALE TO VIEW.\n const tx = graph.view.translate.x;\n const ty = graph.view.translate.y;\n\n graph.view.setTranslate(dx, dy);\n graph.container.scrollLeft += (dx - tx) * graph.view.scale;\n graph.container.scrollTop += (dy - ty) * graph.view.scale;\n\n this.autoTranslate = false;\n return;\n }\n\n graphSizeDidChange.apply(this, arguments);\n }\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Sets initial scrollbar positions\n window.setTimeout(function() {\n const bounds = graph.getGraphBounds();\n const width = Math.max(\n bounds.width,\n graph.scrollTileSize.width * graph.view.scale\n );\n const height = Math.max(\n bounds.height,\n graph.scrollTileSize.height * graph.view.scale\n );\n graph.container.scrollTop = Math.floor(\n Math.max(\n 0,\n bounds.y - Math.max(20, (graph.container.clientHeight - height) / 4)\n )\n );\n graph.container.scrollLeft = Math.floor(\n Math.max(\n 0,\n bounds.x - Math.max(0, (graph.container.clientWidth - width) / 2)\n )\n );\n }, 0);\n };\n}\n\nexport default ExtendCanvas;\n", - "DynamicLoading": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxText from '../mxgraph/shape/mxText';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxEffects from '../mxgraph/util/mxEffects';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\n\nclass DynamicLoading extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dynamic loading

\n This example demonstrates loading graph model data\n dynamically to limit the number of cells in the model.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'visible',\n position: 'absolute',\n height: '100%',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n let requestId = 0;\n\n // Speedup the animation\n mxText.prototype.enableBoundingBox = false;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables all built-in interactions\n graph.setEnabled(false);\n\n // Handles clicks on cells\n graph.addListener(mxEvent.CLICK, function(sender, evt) {\n const cell = evt.getProperty('cell');\n\n if (cell != null) {\n load(graph, cell);\n }\n });\n\n // Changes the default vertex style in-place\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const cx = graph.container.clientWidth / 2;\n const cy = graph.container.clientHeight / 2;\n\n const cell = graph.insertVertex(\n parent,\n '0-0',\n '0-0',\n cx - 20,\n cy - 15,\n 60,\n 40\n );\n\n // Animates the changes in the graph model\n graph.getModel().addListener(mxEvent.CHANGE, function(sender, evt) {\n const { changes } = evt.getProperty('edit');\n mxEffects.animateChanges(graph, changes);\n });\n\n // Loads the links for the given cell into the given graph\n // by requesting the respective data in the server-side\n // (implemented for this demo using the server-function)\n function load(graph, cell) {\n if (graph.getModel().isVertex(cell)) {\n const cx = graph.container.clientWidth / 2;\n const cy = graph.container.clientHeight / 2;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const xml = server(cell.id);\n const doc = mxUtils.parseXml(xml);\n const dec = new mxCodec(doc);\n const model = dec.decode(doc.documentElement);\n\n // Removes all cells which are not in the response\n for (var key in graph.getModel().cells) {\n const tmp = graph.getModel().getCell(key);\n\n if (tmp != cell && graph.getModel().isVertex(tmp)) {\n graph.removeCells([tmp]);\n }\n }\n\n // Merges the response model with the client model\n graph.getModel().mergeChildren(model.getRoot().getChildAt(0), parent);\n\n // Moves the given cell to the center\n let geo = graph.getModel().getGeometry(cell);\n\n if (geo != null) {\n geo = geo.clone();\n geo.x = cx - geo.width / 2;\n geo.y = cy - geo.height / 2;\n\n graph.getModel().setGeometry(cell, geo);\n }\n\n // Creates a list of the new vertices, if there is more\n // than the center vertex which might have existed\n // previously, then this needs to be changed to analyze\n // the target model before calling mergeChildren above\n const vertices = [];\n\n for (var key in graph.getModel().cells) {\n const tmp = graph.getModel().getCell(key);\n\n if (tmp != cell && model.isVertex(tmp)) {\n vertices.push(tmp);\n\n // Changes the initial location \"in-place\"\n // to get a nice animation effect from the\n // center to the radius of the circle\n const geo = model.getGeometry(tmp);\n\n if (geo != null) {\n geo.x = cx - geo.width / 2;\n geo.y = cy - geo.height / 2;\n }\n }\n }\n\n // Arranges the response in a circle\n const cellCount = vertices.length;\n const phi = (2 * Math.PI) / cellCount;\n const r = Math.min(\n graph.container.clientWidth / 4,\n graph.container.clientHeight / 4\n );\n\n for (let i = 0; i < cellCount; i++) {\n let geo = graph.getModel().getGeometry(vertices[i]);\n\n if (geo != null) {\n geo = geo.clone();\n geo.x += r * Math.sin(i * phi);\n geo.y += r * Math.cos(i * phi);\n\n graph.getModel().setGeometry(vertices[i], geo);\n }\n }\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n }\n\n // Simulates the existence of a server that can crawl the\n // big graph with a certain depth and create a graph model\n // for the traversed cells, which is then sent to the client\n function server(cellId) {\n // Increments the request ID as a prefix for the cell IDs\n requestId++;\n\n // Creates a local graph with no display\n const graph = new mxGraph();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v0 = graph.insertVertex(parent, cellId, 'Dummy', 0, 0, 60, 40);\n const cellCount = parseInt(Math.random() * 16) + 4;\n\n // Creates the random links and cells for the response\n for (let i = 0; i < cellCount; i++) {\n const id = `${requestId}-${i}`;\n const v = graph.insertVertex(parent, id, id, 0, 0, 60, 40);\n const e = graph.insertEdge(parent, null, `Link ${i}`, v0, v);\n }\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const enc = new mxCodec();\n const node = enc.encode(graph.getModel());\n\n return mxUtils.getXml(node);\n }\n\n load(graph, cell);\n };\n}\n\nexport default DynamicLoading;\n", - "AutoLayout": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\nimport mxMorphing from '../mxgraph/util/mxMorphing';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxHierarchicalLayout from '../mxgraph/layout/hierarchical/mxHierarchicalLayout';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxEventObject from '../mxgraph/util/mxEventObject';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\n\nclass AutoLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A this.el for the graph\n return (\n <>\n

Auto layout

\n This example demonstrates running\n and animating a layout algorithm after every change to a graph.\n\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '641px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n mxEvent.disableContextMenu(this.el);\n\n const mxCellRendererInstallCellOverlayListeners =\n mxCellRenderer.prototype.installCellOverlayListeners;\n mxCellRenderer.prototype.installCellOverlayListeners = function(\n state,\n overlay,\n shape\n ) {\n mxCellRendererInstallCellOverlayListeners.apply(this, arguments);\n\n mxEvent.addListener(\n shape.node,\n mxClient.IS_POINTER ? 'pointerdown' : 'mousedown',\n function(evt) {\n overlay.fireEvent(\n new mxEventObject('pointerdown', 'event', evt, 'state', state)\n );\n }\n );\n\n if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {\n mxEvent.addListener(shape.node, 'touchstart', function(evt) {\n overlay.fireEvent(\n new mxEventObject('pointerdown', 'event', evt, 'state', state)\n );\n });\n }\n };\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n graph.setPanning(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n graph.setAllowDanglingEdges(false);\n graph.connectionHandler.select = false;\n graph.view.setTranslate(20, 20);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);\n const executeLayout = function(change, post) {\n graph.getModel().beginUpdate();\n try {\n if (change != null) {\n change();\n }\n layout.execute(graph.getDefaultParent(), v1);\n } catch (e) {\n throw e;\n } finally {\n // New API for animating graph layout results asynchronously\n const morph = new mxMorphing(graph);\n morph.addListener(\n mxEvent.DONE,\n mxUtils.bind(this, function() {\n graph.getModel().endUpdate();\n if (post != null) {\n post();\n }\n })\n );\n morph.startAnimation();\n }\n };\n\n const addOverlay = function(cell) {\n // Creates a new overlay with an image and a tooltip\n const overlay = new mxCellOverlay(\n new mxImage('images/add.png', 24, 24),\n 'Add outgoing'\n );\n overlay.cursor = 'hand';\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, function(sender, evt2) {\n graph.clearSelection();\n const geo = graph.getCellGeometry(cell);\n\n let v2;\n\n executeLayout(\n function() {\n v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n geo.x,\n geo.y,\n 80,\n 30\n );\n addOverlay(v2);\n graph.view.refresh(v2);\n const e1 = graph.insertEdge(parent, null, '', cell, v2);\n },\n function() {\n graph.scrollCellToVisible(v2);\n }\n );\n });\n\n // Special CMS event\n overlay.addListener('pointerdown', function(sender, eo) {\n const evt2 = eo.getProperty('event');\n const state = eo.getProperty('state');\n\n graph.popupMenuHandler.hideMenu();\n graph.stopEditing(false);\n\n const pt = mxUtils.convertPoint(\n graph.container,\n mxEvent.getClientX(evt2),\n mxEvent.getClientY(evt2)\n );\n graph.connectionHandler.start(state, pt.x, pt.y);\n graph.isMouseDown = true;\n graph.isMouseTrigger = mxEvent.isMouseEvent(evt2);\n mxEvent.consume(evt2);\n });\n\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(cell, overlay);\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 0, 0, 80, 30);\n addOverlay(v1);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const edgeHandleConnect = mxEdgeHandler.prototype.connect;\n mxEdgeHandler.prototype.connect = function(\n edge,\n terminal,\n isSource,\n isClone,\n me\n ) {\n edgeHandleConnect.apply(this, arguments);\n executeLayout();\n };\n\n graph.resizeCell = function() {\n mxGraph.prototype.resizeCell.apply(this, arguments);\n executeLayout();\n };\n\n graph.connectionHandler.addListener(mxEvent.CONNECT, function() {\n executeLayout();\n });\n };\n}\n\nexport default AutoLayout;\n", - "FixedIcon": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from \"../mxgraph/util/mxUtils\";\nimport mxConstants from \"../mxgraph/util/mxConstants\";\nimport mxLabel from \"../mxgraph/shape/mxLabel\";\nimport mxRectangle from \"../mxgraph/util/mxRectangle\";\n\nclass FixedIcon extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Fixed icon

\n This example demonstrates\n customizing the icon position in the mxLabel shape.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Overrides the image bounds code to change the position\n mxLabel.prototype.getImageBounds = function(x, y, w, h) {\n const iw = mxUtils.getValue(\n this.style,\n mxConstants.STYLE_IMAGE_WIDTH,\n mxConstants.DEFAULT_IMAGESIZE\n );\n const ih = mxUtils.getValue(\n this.style,\n mxConstants.STYLE_IMAGE_HEIGHT,\n mxConstants.DEFAULT_IMAGESIZE\n );\n\n // Places the icon\n const ix = (w - iw) / 2;\n const iy = h - ih;\n\n return new mxRectangle(x + ix, y + iy, iw, ih);\n };\n\n // Makes the shadow brighter\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Fixed icon',\n 20,\n 20,\n 80,\n 50,\n 'shape=label;image=images/plus.png;imageWidth=16;imageHeight=16;spacingBottom=10;' +\n 'fillColor=#adc5ff;gradientColor=#7d85df;glass=1;rounded=1;shadow=1;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default FixedIcon;\n", - "_app": "import '../styles/globals.css';\nimport '../public/css/common.css';\nimport \"./Animation.css\";\n\nfunction MyApp({ Component, pageProps }) {\n return ;\n}\n\nexport default MyApp;\n", - "Guides": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Guides extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Guides

\n This example demonstrates the guides\n feature which aligns the current selection to the existing vertices\n in the graph. This feature is in RFC state. Creating a grid using\n a canvas and installing a key handler for cursor keys is also\n demonstrated here, as well as snapping waypoints to terminals.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '601px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n\n // Alt disables guides\n mxGraphHandler.prototype.useGuidesForEvent = function(me) {\n return !mxEvent.isAltDown(me.getEvent());\n };\n\n // Defines the guides to be red (default)\n mxConstants.GUIDE_COLOR = '#FF0000';\n\n // Defines the guides to be 1 pixel (default)\n mxConstants.GUIDE_STROKEWIDTH = 1;\n\n // Enables snapping waypoints to terminals\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.gridSize = 30;\n\n // Changes the default style for edges \"in-place\" and assigns\n // an alternate edge style which is applied in mxGraph.flip\n // when the user double clicks on the adjustment control point\n // of the edge. The ElbowConnector edge style switches to TopToBottom\n // if the horizontal style is true.\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n graph.alternateEdgeStyle = 'elbow=vertical';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 40, 80, 70);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 140, 80, 40);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Handles cursor keys\n const nudge = function(keyCode) {\n if (!graph.isSelectionEmpty()) {\n let dx = 0;\n let dy = 0;\n\n if (keyCode === 37) {\n dx = -1;\n } else if (keyCode === 38) {\n dy = -1;\n } else if (keyCode === 39) {\n dx = 1;\n } else if (keyCode === 40) {\n dy = 1;\n }\n\n graph.moveCells(graph.getSelectionCells(), dx, dy);\n }\n\n // Transfer initial focus to graph container for keystroke handling\n graph.container.focus();\n\n // Handles keystroke events\n const keyHandler = new mxKeyHandler(graph);\n\n // Ignores enter keystroke. Remove this line if you want the\n // enter keystroke to stop editing\n keyHandler.enter = function() {};\n\n keyHandler.bindKey(37, function() {\n nudge(37);\n });\n\n keyHandler.bindKey(38, function() {\n nudge(38);\n });\n\n keyHandler.bindKey(39, function() {\n nudge(39);\n });\n\n keyHandler.bindKey(40, function() {\n nudge(40);\n });\n };\n }\n}\n\nexport default Guides;\n", - "DragSource": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxDragSource from '../mxgraph/util/mxDragSource';\nimport mxGraphHandler from \"../mxgraph/handler/mxGraphHandler\";\nimport mxGuide from \"../mxgraph/util/mxGuide\";\nimport mxEdgeHandler from \"../mxgraph/handler/mxEdgeHandler\";\n\nclass DragSource extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dragsource

\n This example demonstrates using one drag source\n for multiple graphs and changing the drag icon.\n\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n\n // Alt disables guides\n mxGuide.prototype.isEnabledForEvent = function(evt) {\n return !mxEvent.isAltDown(evt);\n };\n\n // Enables snapping waypoints to terminals\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n const graphs = [];\n\n // Creates the graph inside the given container\n for (let i = 0; i < 2; i++) {\n const container = document.createElement('div');\n container.style.overflow = 'hidden';\n container.style.position = 'relative';\n container.style.width = '321px';\n container.style.height = '241px';\n container.style.background = \"url('editors/images/grid.gif')\";\n container.style.cursor = 'default';\n\n this.el.appendChild(container);\n\n var graph = new mxGraph(container);\n graph.gridSize = 30;\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graphs.push(graph);\n }\n\n // Returns the graph under the mouse\n const graphF = function(evt) {\n const x = mxEvent.getClientX(evt);\n const y = mxEvent.getClientY(evt);\n const elt = document.elementFromPoint(x, y);\n\n for (let i = 0; i < graphs.length; i++) {\n if (mxUtils.isAncestorNode(graphs[i].container, elt)) {\n return graphs[i];\n }\n }\n\n return null;\n };\n\n // Inserts a cell at the given location\n const funct = function(graph, evt, target, x, y) {\n const cell = new mxCell('Test', new mxGeometry(0, 0, 120, 40));\n cell.vertex = true;\n const cells = graph.importCells([cell], x, y, target);\n\n if (cells != null && cells.length > 0) {\n graph.scrollCellToVisible(cells[0]);\n graph.setSelectionCells(cells);\n }\n };\n\n // Creates a DOM node that acts as the drag source\n const img = mxUtils.createImage('images/icons48/gear.png');\n img.style.width = '48px';\n img.style.height = '48px';\n this.el.appendChild(img);\n\n // Creates the element that is being for the actual preview.\n const dragElt = document.createElement('div');\n dragElt.style.border = 'dashed black 1px';\n dragElt.style.width = '120px';\n dragElt.style.height = '40px';\n\n // Drag source is configured to use dragElt for preview and as drag icon\n // if scalePreview (last) argument is true. Dx and dy are null to force\n // the use of the defaults. Note that dx and dy are only used for the\n // drag icon but not for the preview.\n const ds = mxUtils.makeDraggable(\n img,\n graphF,\n funct,\n dragElt,\n null,\n null,\n graph.autoscroll,\n true\n );\n\n // Redirects feature to global switch. Note that this feature should only be used\n // if the the x and y arguments are used in funct to insert the cell.\n ds.isGuidesEnabled = function() {\n return graph.graphHandler.guidesEnabled;\n };\n\n // Restores original drag icon while outside of graph\n ds.createDragElement = mxDragSource.prototype.createDragElement;\n };\n\n // NOTE: To enable cross-document DnD (eg. between frames),\n // the following methods need to be overridden:\n /* mxDragSourceMouseUp = mxDragSource.prototype.mouseUp;\nmxDragSource.prototype.mouseUp = function(evt)\n{\n let doc = this.element.ownerDocument;\n\n if (doc != document)\n {\n let mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';\n\n if (this.mouseUpHandler != null)\n {\n mxEvent.removeListener(doc, mu, this.mouseUpHandler);\n }\n }\n\n mxDragSourceMouseUp.apply(this, arguments);\n}; */\n\n /* mxDragSourceMouseDown = mxDragSource.prototype.mouseDown;\nmxDragSource.prototype.mouseDown = function(evt)\n{\n if (this.enabled && !mxEvent.isConsumed(evt))\n {\n mxDragSourceMouseDown.apply(this, arguments);\n let doc = this.element.ownerDocument;\n\n if (doc != document)\n {\n let mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';\n mxEvent.addListener(doc, mu, this.mouseUpHandler);\n }\n }\n}; */\n}\n\nexport default DragSource;\n", - "Orthogonal": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from \"../mxgraph/handler/mxGraphHandler\";\nimport mxGuide from \"../mxgraph/util/mxGuide\";\nimport mxEdgeHandler from \"../mxgraph/handler/mxEdgeHandler\";\nimport mxConnectionHandler from \"../mxgraph/handler/mxConnectionHandler\";\nimport mxGraphView from \"../mxgraph/view/mxGraphView\";\nimport mxPoint from \"../mxgraph/util/mxPoint\";\nimport mxCellState from \"../mxgraph/view/mxCellState\";\n\nclass Orthogonal extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Orthogonal

\n This example demonstrates the use\n of port constraints and orthogonal edge styles and handlers.\n\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n\n // Alt disables guides\n mxGuide.prototype.isEnabledForEvent = function(evt) {\n return !mxEvent.isAltDown(evt);\n };\n\n // Enables snapping waypoints to terminals\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Enables orthogonal connect preview in IE\n mxConnectionHandler.prototype.movePreviewAway = false;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.disconnectOnMove = false;\n graph.foldingEnabled = false;\n graph.cellsResizable = false;\n graph.extendParents = false;\n graph.setConnectable(true);\n\n // Implements perimeter-less connection points as fixed points (computed before the edge style).\n graph.view.updateFixedTerminalPoint = function(\n edge,\n terminal,\n source,\n constraint\n ) {\n mxGraphView.prototype.updateFixedTerminalPoint.apply(this, arguments);\n\n const pts = edge.absolutePoints;\n const pt = pts[source ? 0 : pts.length - 1];\n\n if (\n terminal != null &&\n pt == null &&\n this.getPerimeterFunction(terminal) == null\n ) {\n edge.setAbsoluteTerminalPoint(\n new mxPoint(\n this.getRoutingCenterX(terminal),\n this.getRoutingCenterY(terminal)\n ),\n source\n );\n }\n };\n\n // Changes the default edge style\n graph.getStylesheet().getDefaultEdgeStyle().edgeStyle =\n 'orthogonalEdgeStyle';\n delete graph.getStylesheet().getDefaultEdgeStyle().endArrow;\n\n // Implements the connect preview\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(null, null, null, null, null);\n\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '', 40, 40, 40, 30);\n v1.setConnectable(false);\n const v11 = graph.insertVertex(\n v1,\n null,\n '',\n 0.5,\n 0,\n 10,\n 40,\n 'portConstraint=northsouth;',\n true\n );\n v11.geometry.offset = new mxPoint(-5, -5);\n const v12 = graph.insertVertex(\n v1,\n null,\n '',\n 0,\n 0.5,\n 10,\n 10,\n 'portConstraint=west;shape=triangle;direction=west;perimeter=none;' +\n 'routingCenterX=-0.5;routingCenterY=0;',\n true\n );\n v12.geometry.offset = new mxPoint(-10, -5);\n const v13 = graph.insertVertex(\n v1,\n null,\n '',\n 1,\n 0.5,\n 10,\n 10,\n 'portConstraint=east;shape=triangle;direction=east;perimeter=none;' +\n 'routingCenterX=0.5;routingCenterY=0;',\n true\n );\n v13.geometry.offset = new mxPoint(0, -5);\n\n const v2 = graph.addCell(graph.getModel().cloneCell(v1));\n v2.geometry.x = 200;\n v2.geometry.y = 60;\n\n const v3 = graph.addCell(graph.getModel().cloneCell(v1));\n v3.geometry.x = 40;\n v3.geometry.y = 150;\n\n const v4 = graph.addCell(graph.getModel().cloneCell(v1));\n v4.geometry.x = 200;\n v4.geometry.y = 170;\n\n graph.insertEdge(parent, null, '', v1.getChildAt(2), v2.getChildAt(1));\n graph.insertEdge(parent, null, '', v2.getChildAt(2), v3.getChildAt(1));\n graph.insertEdge(parent, null, '', v3.getChildAt(2), v4.getChildAt(1));\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Orthogonal;\n" + "DynamicStyle": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass DynamicStyle extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dynamic Style

\n This example demonstrates changing the style of a cell dynamically by\n overriding mxGraphModel.getStyle.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables moving of edge labels in this examples\n graph.edgeLabelsMovable = false;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Needs to set a flag to check for dynamic style changes,\n // that is, changes to styles on cells where the style was\n // not explicitely changed using mxStyleChange\n graph.getView().updateStyle = true;\n\n // Overrides mxGraphModel.getStyle to return a specific style\n // for edges that reflects their target terminal (in this case\n // the strokeColor will be equal to the target's fillColor).\n const previous = graph.model.getStyle;\n\n graph.model.getStyle = function(cell) {\n if (cell != null) {\n let style = previous.apply(this, arguments);\n\n if (this.isEdge(cell)) {\n const target = this.getTerminal(cell, false);\n\n if (target != null) {\n const targetStyle = graph.getCurrentCellStyle(target);\n const fill = mxUtils.getValue(\n targetStyle,\n mxConstants.STYLE_FILLCOLOR\n );\n\n if (fill != null) {\n style += `;strokeColor=${fill}`;\n }\n }\n } else if (this.isVertex(cell)) {\n const geometry = this.getGeometry(cell);\n\n if (geometry != null && geometry.width > 80) {\n style += ';fillColor=green';\n }\n }\n\n return style;\n }\n\n return null;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Hello,',\n 20,\n 20,\n 80,\n 30,\n 'fillColor=green'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 200,\n 150,\n 80,\n 30,\n 'fillColor=blue'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'World!',\n 20,\n 150,\n 80,\n 30,\n 'fillColor=red'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n 'Connect',\n v1,\n v2,\n 'perimeterSpacing=4;strokeWidth=4;labelBackgroundColor=white;fontStyle=1'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default DynamicStyle;\n", + "PortRefs": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstraintHandler from '../mxgraph/handler/mxConstraintHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxShape from '../mxgraph/shape/mxShape';\nimport mxTriangle from '../mxgraph/shape/mxTriangle';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionConstraint from '../mxgraph/view/mxConnectionConstraint';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass PortRefs extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Port References Example

\n This example demonstrates referencing connection points by ID. The main\n difference to the implementation where the connection point is stored in\n the connecting edge is that changes to the original port will be\n reflected in all existing connections since they reference that port.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Replaces the port image\n mxConstraintHandler.prototype.pointImage = new mxImage(\n 'images/dot.gif',\n 10,\n 10\n );\n\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Disables automatic handling of ports. This disables the reset of the\n // respective style in mxGraph.cellConnected. Note that this feature may\n // be useful if floating and fixed connections are combined.\n graph.setPortsEnabled(false);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Ports are equal for all shapes...\n const ports = new Array();\n\n // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)\n ports.w = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };\n ports.e = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };\n ports.n = { x: 0.5, y: 0, perimeter: true, constraint: 'north' };\n ports.s = { x: 0.5, y: 1, perimeter: true, constraint: 'south' };\n ports.nw = { x: 0, y: 0, perimeter: true, constraint: 'north west' };\n ports.ne = { x: 1, y: 0, perimeter: true, constraint: 'north east' };\n ports.sw = { x: 0, y: 1, perimeter: true, constraint: 'south west' };\n ports.se = { x: 1, y: 1, perimeter: true, constraint: 'south east' };\n\n // ... except for triangles\n const ports2 = new Array();\n\n // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)\n ports2.in1 = { x: 0, y: 0, perimeter: true, constraint: 'west' };\n ports2.in2 = { x: 0, y: 0.25, perimeter: true, constraint: 'west' };\n ports2.in3 = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };\n ports2.in4 = { x: 0, y: 0.75, perimeter: true, constraint: 'west' };\n ports2.in5 = { x: 0, y: 1, perimeter: true, constraint: 'west' };\n\n ports2.out1 = {\n x: 0.5,\n y: 0,\n perimeter: true,\n constraint: 'north east',\n };\n ports2.out2 = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };\n ports2.out3 = {\n x: 0.5,\n y: 1,\n perimeter: true,\n constraint: 'south east',\n };\n\n // Extends shapes classes to return their ports\n mxShape.prototype.getPorts = function() {\n return ports;\n };\n\n mxTriangle.prototype.getPorts = function() {\n return ports2;\n };\n\n // Disables floating connections (only connections via ports allowed)\n graph.connectionHandler.isConnectableCell = function(cell) {\n return false;\n };\n mxEdgeHandler.prototype.isConnectableCell = function(cell) {\n return graph.connectionHandler.isConnectableCell(cell);\n };\n\n // Disables existing port functionality\n graph.view.getTerminalPort = function(state, terminal, source) {\n return terminal;\n };\n\n // Returns all possible ports for a given terminal\n graph.getAllConnectionConstraints = function(terminal, source) {\n if (\n terminal != null &&\n terminal.shape != null &&\n terminal.shape.stencil != null\n ) {\n // for stencils with existing constraints...\n if (terminal.shape.stencil != null) {\n return terminal.shape.stencil.constraints;\n }\n } else if (terminal != null && this.model.isVertex(terminal.cell)) {\n if (terminal.shape != null) {\n const ports = terminal.shape.getPorts();\n const cstrs = new Array();\n\n for (const id in ports) {\n const port = ports[id];\n\n const cstr = new mxConnectionConstraint(\n new mxPoint(port.x, port.y),\n port.perimeter\n );\n cstr.id = id;\n cstrs.push(cstr);\n }\n\n return cstrs;\n }\n }\n\n return null;\n };\n\n // Sets the port for the given connection\n graph.setConnectionConstraint = function(\n edge,\n terminal,\n source,\n constraint\n ) {\n if (constraint != null) {\n const key = source\n ? mxConstants.STYLE_SOURCE_PORT\n : mxConstants.STYLE_TARGET_PORT;\n\n if (constraint == null || constraint.id == null) {\n this.setCellStyles(key, null, [edge]);\n } else if (constraint.id != null) {\n this.setCellStyles(key, constraint.id, [edge]);\n }\n }\n };\n\n // Returns the port for the given connection\n graph.getConnectionConstraint = function(edge, terminal, source) {\n const key = source\n ? mxConstants.STYLE_SOURCE_PORT\n : mxConstants.STYLE_TARGET_PORT;\n const id = edge.style[key];\n\n if (id != null) {\n const c = new mxConnectionConstraint(null, null);\n c.id = id;\n\n return c;\n }\n\n return null;\n };\n\n // Returns the actual point for a port by redirecting the constraint to the port\n const graphGetConnectionPoint = graph.getConnectionPoint;\n graph.getConnectionPoint = function(vertex, constraint) {\n if (constraint.id != null && vertex != null && vertex.shape != null) {\n const port = vertex.shape.getPorts()[constraint.id];\n\n if (port != null) {\n constraint = new mxConnectionConstraint(\n new mxPoint(port.x, port.y),\n port.perimeter\n );\n }\n }\n\n return graphGetConnectionPoint.apply(this, arguments);\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'A', 20, 20, 100, 40);\n const v2 = graph.insertVertex(\n parent,\n null,\n 'B',\n 80,\n 100,\n 100,\n 100,\n 'shape=ellipse;perimeter=ellipsePerimeter'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'C',\n 190,\n 30,\n 100,\n 60,\n 'shape=triangle;perimeter=trianglePerimeter;direction=south'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'sourcePort=s;targetPort=nw'\n );\n const e2 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v3,\n 'sourcePort=e;targetPort=out3'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Comming soon... Integration with orthogonal edge style\n // Sets default edge style to use port constraints (needs to be moved up when uncommented)\n // graph.getStylesheet().getDefaultEdgeStyle()['edgeStyle'] = 'orthogonalEdgeStyle';\n /* let mxUtilsGetPortConstraints = mxUtils.getPortConstraints;\n mxUtils.getPortConstraints = function(terminal, edge, source, defaultValue)\n {\n let key = (source) ? mxConstants.STYLE_SOURCE_PORT : mxConstants.STYLE_TARGET_PORT;\n let id = edge.style[key];\n\n let port = terminal.shape.getPorts()[id];\n\n // TODO: Add support for rotation, direction\n if (port != null)\n {\n return port.constraint;\n }\n\n return mxUtilsGetPortConstraints.apply(this, arguments);\n };\n // Connect preview\n graph.connectionHandler.createEdgeState = function(me)\n {\n let edge = graph.createEdge(null, null, null, null, null);\n\n return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge));\n };\n */\n }\n}\n\nexport default PortRefs;\n", + "Groups": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxPopupMenuHandler from '../mxgraph/handler/mxPopupMenuHandler';\n\nclass Groups extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates using cells as parts of other cells.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Overrides check for valid roots\n mxGraph.prototype.isValidRoot = function() {\n return false;\n };\n\n // Don't clear selection if multiple cells selected\n const graphHandlerMouseDown = mxGraphHandler.prototype.mouseDown;\n mxGraphHandler.prototype.mouseDown = function(sender, me) {\n graphHandlerMouseDown.apply(this, arguments);\n\n if (\n this.graph.isCellSelected(me.getCell()) &&\n this.graph.getSelectionCount() > 1\n ) {\n this.delayedSelection = false;\n }\n };\n\n // Selects descendants before children selection mode\n const graphHandlerGetInitialCellForEvent =\n mxGraphHandler.prototype.getInitialCellForEvent;\n mxGraphHandler.prototype.getInitialCellForEvent = function(me) {\n const model = this.graph.getModel();\n const psel = model.getParent(this.graph.getSelectionCell());\n let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments);\n let parent = model.getParent(cell);\n\n if (psel == null || (psel != cell && psel != parent)) {\n while (\n !this.graph.isCellSelected(cell) &&\n !this.graph.isCellSelected(parent) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n cell = parent;\n parent = this.graph.getModel().getParent(cell);\n }\n }\n\n return cell;\n };\n\n // Selection is delayed to mouseup if child selected\n const graphHandlerIsDelayedSelection =\n mxGraphHandler.prototype.isDelayedSelection;\n mxGraphHandler.prototype.isDelayedSelection = function(cell) {\n let result = graphHandlerIsDelayedSelection.apply(this, arguments);\n const model = this.graph.getModel();\n const psel = model.getParent(this.graph.getSelectionCell());\n const parent = model.getParent(cell);\n\n if (psel == null || (psel != cell && psel != parent)) {\n if (\n !this.graph.isCellSelected(cell) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n result = true;\n }\n }\n\n return result;\n };\n\n // Delayed selection of parent group\n mxGraphHandler.prototype.selectDelayed = function(me) {\n let cell = me.getCell();\n\n if (cell == null) {\n cell = this.cell;\n }\n\n const model = this.graph.getModel();\n let parent = model.getParent(cell);\n\n while (\n this.graph.isCellSelected(cell) &&\n model.isVertex(parent) &&\n !this.graph.isValidRoot(parent)\n ) {\n cell = parent;\n parent = model.getParent(cell);\n }\n\n this.graph.selectCellForEvent(cell, me.getEvent());\n };\n\n // Returns last selected ancestor\n mxPopupMenuHandler.prototype.getCellForPopupEvent = function(me) {\n let cell = me.getCell();\n const model = this.graph.getModel();\n let parent = model.getParent(cell);\n\n while (model.isVertex(parent) && !this.graph.isValidRoot(parent)) {\n if (this.graph.isCellSelected(parent)) {\n cell = parent;\n }\n\n parent = model.getParent(parent);\n }\n\n return cell;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.constrainChildren = false;\n graph.extendParents = false;\n graph.extendParentsOnAdd = false;\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 120, 60);\n const v2 = graph.insertVertex(v1, null, 'World!', 90, 20, 60, 20);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Groups;\n", + "ContextIcons": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxVertexHandler from '../mxgraph/handler/mxVertexHandler';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\n\nclass ContextIcons extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Context icons

\n This example demonstrates adding icons to selected vertices to carry out\n special operations.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n class mxVertexToolHandler extends mxVertexHandler {\n // Defines a subclass for mxVertexHandler that adds a set of clickable\n // icons to every selected vertex.\n\n domNode = null;\n\n init() {\n super.init();\n\n // In this example we force the use of DIVs for images in IE. This\n // handles transparency in PNG images properly in IE and fixes the\n // problem that IE routes all mouse events for a gesture via the\n // initial IMG node, which means the target vertices\n this.domNode = document.createElement('div');\n this.domNode.style.position = 'absolute';\n this.domNode.style.whiteSpace = 'nowrap';\n\n // Workaround for event redirection via image tag in quirks and IE8\n const createImage = src => {\n return mxUtils.createImage(src);\n };\n\n // Delete\n let img = createImage('images/delete2.png');\n img.setAttribute('title', 'Delete');\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n mxEvent.addGestureListeners(img, evt => {\n // Disables dragging the image\n mxEvent.consume(evt);\n });\n mxEvent.addListener(img, 'click', evt => {\n this.graph.removeCells([this.state.cell]);\n mxEvent.consume(evt);\n });\n this.domNode.appendChild(img);\n\n // Size\n img = createImage('images/fit_to_size.png');\n img.setAttribute('title', 'Resize');\n img.style.cursor = 'se-resize';\n img.style.width = '16px';\n img.style.height = '16px';\n\n mxEvent.addGestureListeners(img, evt => {\n this.start(mxEvent.getClientX(evt), mxEvent.getClientY(evt), 7);\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n });\n this.domNode.appendChild(img);\n\n // Move\n img = createImage('images/plus.png');\n img.setAttribute('title', 'Move');\n img.style.cursor = 'move';\n img.style.width = '16px';\n img.style.height = '16px';\n\n mxEvent.addGestureListeners(img, evt => {\n this.graph.graphHandler.start(\n this.state.cell,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n this.graph.graphHandler.cellWasClicked = true;\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n });\n this.domNode.appendChild(img);\n\n // Connect\n img = createImage('images/check.png');\n img.setAttribute('title', 'Connect');\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n\n mxEvent.addGestureListeners(img, evt => {\n const pt = mxUtils.convertPoint(\n this.graph.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n this.graph.connectionHandler.start(this.state, pt.x, pt.y);\n this.graph.isMouseDown = true;\n this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);\n mxEvent.consume(evt);\n });\n this.domNode.appendChild(img);\n\n this.graph.container.appendChild(this.domNode);\n this.redrawTools();\n }\n\n redraw() {\n super.redraw();\n this.redrawTools();\n }\n\n redrawTools() {\n if (this.state != null && this.domNode != null) {\n const dy = 4;\n this.domNode.style.left = `${this.state.x + this.state.width - 56}px`;\n this.domNode.style.top = `${this.state.y + this.state.height + dy}px`;\n }\n }\n\n destroy(sender, me) {\n super.destroy(sender, me);\n\n if (this.domNode != null) {\n this.domNode.parentNode.removeChild(this.domNode);\n this.domNode = null;\n }\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createHandler(state) {\n if (state != null && this.model.isVertex(state.cell)) {\n return new mxVertexToolHandler(state);\n }\n return super.createHandler(state);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setConnectable(true);\n graph.connectionHandler.createTarget = true;\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n });\n });\n };\n}\n\nexport default ContextIcons;\n", + "RadialTreeLayout": "/**\n * Copyright (c) 2006-2014, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxRadialTreeLayout from '../mxgraph/layout/mxRadialTreeLayout';\n\nclass RadialTreeLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hierarchical Layout

\n This example demonstrates the use of the hierarchical and organic\n layouts. Note that the hierarchical layout requires another script tag\n in the head of the page.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '800px',\n borderTop: 'gray 1px solid',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection\n new mxRubberband(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 6;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxRadialTreeLayout(graph);\n\n const parent = graph.getDefaultParent();\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 500, 500, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2.1', 0, 0, 80, 30);\n const v3 = graph.insertVertex(parent, null, '2.2', 0, 0, 80, 30);\n const v4 = graph.insertVertex(parent, null, '3.1', 0, 0, 80, 30);\n const v4_1 = graph.insertVertex(parent, null, '3.2', 0, 0, 80, 30);\n const v4_2 = graph.insertVertex(parent, null, '3.3', 0, 0, 80, 30);\n const v4_3 = graph.insertVertex(parent, null, '3.6', 0, 0, 80, 30);\n const v4_4 = graph.insertVertex(parent, null, '3.7', 0, 0, 80, 30);\n const v5 = graph.insertVertex(parent, null, '3.4', 0, 0, 80, 30);\n const v6 = graph.insertVertex(parent, null, '2.3', 0, 0, 80, 30);\n const v7 = graph.insertVertex(parent, null, '4.1', 0, 0, 80, 30);\n const v7_1 = graph.insertVertex(parent, null, '4.2', 0, 0, 80, 30);\n const v7_2 = graph.insertVertex(parent, null, '4.3', 0, 0, 80, 30);\n const v7_3 = graph.insertVertex(parent, null, '4.4', 0, 0, 80, 30);\n const v7_4 = graph.insertVertex(parent, null, '4.5', 0, 0, 80, 30);\n const v7_5 = graph.insertVertex(parent, null, '4.6', 0, 0, 80, 30);\n const v7_6 = graph.insertVertex(parent, null, '4.7', 0, 0, 80, 30);\n\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v3, v4);\n const e3_1 = graph.insertEdge(parent, null, '', v3, v4_1);\n const e3_2 = graph.insertEdge(parent, null, '', v3, v4_2);\n const e3_3 = graph.insertEdge(parent, null, '', v3, v4_3);\n const e3_4 = graph.insertEdge(parent, null, '', v3, v4_4);\n const e4 = graph.insertEdge(parent, null, '', v2, v5);\n const e5 = graph.insertEdge(parent, null, '', v1, v6);\n const e6 = graph.insertEdge(parent, null, '', v4_3, v7);\n var e6_1 = graph.insertEdge(parent, null, '', v4_4, v7_4);\n var e6_2 = graph.insertEdge(parent, null, '', v4_4, v7_5);\n var e6_3 = graph.insertEdge(parent, null, '', v4_4, v7_6);\n var e6_1 = graph.insertEdge(parent, null, '', v4_3, v7_1);\n var e6_2 = graph.insertEdge(parent, null, '', v4_3, v7_2);\n var e6_3 = graph.insertEdge(parent, null, '', v4_3, v7_3);\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default RadialTreeLayout;\n", + "HelloPort": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass HelloPort extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates using the isPort hook for visually connecting\n to another cell.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n\n // Sets the default edge style\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n\n // Ports are not used as terminals for edges, they are\n // only used to compute the graphical connection point\n graph.isPort = function(cell) {\n const geo = this.getCellGeometry(cell);\n\n return geo != null ? geo.relative : false;\n };\n\n // Implements a tooltip that shows the actual\n // source and target of an edge\n graph.getTooltipForCell = function(cell) {\n if (this.model.isEdge(cell)) {\n return `${this.convertValueToString(\n this.model.getTerminal(cell, true)\n )} => ${this.convertValueToString(\n this.model.getTerminal(cell, false)\n )}`;\n }\n\n return mxGraph.prototype.getTooltipForCell.apply(this, arguments);\n };\n\n // Removes the folding icon and disables any folding\n graph.isCellFoldable = function(cell) {\n return false;\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello', 20, 80, 80, 30);\n v1.setConnectable(false);\n const v11 = graph.insertVertex(v1, null, '', 1, 1, 10, 10);\n v11.geometry.offset = new mxPoint(-5, -5);\n v11.geometry.relative = true;\n const v12 = graph.insertVertex(v1, null, '', 1, 0, 10, 10);\n v12.geometry.offset = new mxPoint(-5, -5);\n v12.geometry.relative = true;\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const v3 = graph.insertVertex(parent, null, 'World2', 200, 20, 80, 30);\n var e1 = graph.insertEdge(parent, null, '', v11, v2);\n var e1 = graph.insertEdge(parent, null, '', v12, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const button = mxUtils.button('View XML', function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getPrettyXml(node), true);\n });\n\n this.el2.appendChild(button);\n }\n}\n\nexport default HelloPort;\n", + "Clipboard": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClipboard from '../mxgraph/util/mxClipboard';\nimport mxClient from '../mxgraph/mxClient';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\n\nclass Clipboard extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Clipboard

\n This example demonstrates using the clipboard for providing cross-tab\n and cross-browser copy and paste.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n\n // Public helper method for shared clipboard.\n mxClipboard.cellsToString = function(cells) {\n const codec = new mxCodec();\n const model = new mxGraphModel();\n const parent = model.getChildAt(model.getRoot(), 0);\n\n for (let i = 0; i < cells.length; i++) {\n model.add(parent, cells[i]);\n }\n\n return mxUtils.getXml(codec.encode(model));\n };\n\n // Focused but invisible textarea during control or meta key events\n const textInput = document.createElement('textarea');\n mxUtils.setOpacity(textInput, 0);\n textInput.style.width = '1px';\n textInput.style.height = '1px';\n let restoreFocus = false;\n const gs = graph.gridSize;\n let lastPaste = null;\n let dx = 0;\n let dy = 0;\n\n // Workaround for no copy event in IE/FF if empty\n textInput.value = ' ';\n\n // Shows a textare when control/cmd is pressed to handle native clipboard actions\n mxEvent.addListener(document, 'keydown', function(evt) {\n // No dialog visible\n const source = mxEvent.getSource(evt);\n\n if (\n graph.isEnabled() &&\n !graph.isMouseDown &&\n !graph.isEditing() &&\n source.nodeName !== 'INPUT'\n ) {\n if (\n evt.keyCode === 224 /* FF */ ||\n (!mxClient.IS_MAC && evt.keyCode === 17) /* Control */ ||\n (mxClient.IS_MAC &&\n (evt.keyCode === 91 || evt.keyCode === 93)) /* Left/Right Meta */\n ) {\n // Cannot use parentNode for check in IE\n if (!restoreFocus) {\n // Avoid autoscroll but allow handling of events\n textInput.style.position = 'absolute';\n textInput.style.left = `${graph.container.scrollLeft + 10}px`;\n textInput.style.top = `${graph.container.scrollTop + 10}px`;\n graph.container.appendChild(textInput);\n\n restoreFocus = true;\n textInput.focus();\n textInput.select();\n }\n }\n }\n });\n\n // Restores focus on graph this.el and removes text input from DOM\n mxEvent.addListener(document, 'keyup', function(evt) {\n if (\n restoreFocus &&\n (evt.keyCode === 224 /* FF */ ||\n evt.keyCode === 17 /* Control */ ||\n evt.keyCode === 91 ||\n evt.keyCode === 93) /* Meta */\n ) {\n restoreFocus = false;\n\n if (!graph.isEditing()) {\n graph.container.focus();\n }\n\n textInput.parentNode.removeChild(textInput);\n }\n });\n\n // Inserts the XML for the given cells into the text input for copy\n const copyCells = function(graph, cells) {\n if (cells.length > 0) {\n const clones = graph.cloneCells(cells);\n\n // Checks for orphaned relative children and makes absolute\n for (let i = 0; i < clones.length; i++) {\n const state = graph.view.getState(cells[i]);\n\n if (state != null) {\n const geo = graph.getCellGeometry(clones[i]);\n\n if (geo != null && geo.relative) {\n geo.relative = false;\n geo.x = state.x / state.view.scale - state.view.translate.x;\n geo.y = state.y / state.view.scale - state.view.translate.y;\n }\n }\n }\n\n textInput.value = mxClipboard.cellsToString(clones);\n }\n\n textInput.select();\n lastPaste = textInput.value;\n };\n\n // Handles copy event by putting XML for current selection into text input\n mxEvent.addListener(\n textInput,\n 'copy',\n mxUtils.bind(this, function(evt) {\n if (graph.isEnabled() && !graph.isSelectionEmpty()) {\n copyCells(\n graph,\n mxUtils.sortCells(\n graph.model.getTopmostCells(graph.getSelectionCells())\n )\n );\n dx = 0;\n dy = 0;\n }\n })\n );\n\n // Handles cut event by removing cells putting XML into text input\n mxEvent.addListener(\n textInput,\n 'cut',\n mxUtils.bind(this, function(evt) {\n if (graph.isEnabled() && !graph.isSelectionEmpty()) {\n copyCells(graph, graph.removeCells());\n dx = -gs;\n dy = -gs;\n }\n })\n );\n\n // Merges XML into existing graph and layers\n const importXml = function(xml, dx, dy) {\n dx = dx != null ? dx : 0;\n dy = dy != null ? dy : 0;\n let cells = [];\n\n try {\n const doc = mxUtils.parseXml(xml);\n const node = doc.documentElement;\n\n if (node != null) {\n const model = new mxGraphModel();\n const codec = new mxCodec(node.ownerDocument);\n codec.decode(node, model);\n\n const childCount = model.getChildCount(model.getRoot());\n const targetChildCount = graph.model.getChildCount(\n graph.model.getRoot()\n );\n\n // Merges existing layers and adds new layers\n graph.model.beginUpdate();\n try {\n for (let i = 0; i < childCount; i++) {\n let parent = model.getChildAt(model.getRoot(), i);\n\n // Adds cells to existing layers if not locked\n if (targetChildCount > i) {\n // Inserts into active layer if only one layer is being pasted\n const target =\n childCount === 1\n ? graph.getDefaultParent()\n : graph.model.getChildAt(graph.model.getRoot(), i);\n\n if (!graph.isCellLocked(target)) {\n const children = model.getChildren(parent);\n cells = cells.concat(\n graph.importCells(children, dx, dy, target)\n );\n }\n } else {\n // Delta is non cascading, needs separate move for layers\n parent = graph.importCells(\n [parent],\n 0,\n 0,\n graph.model.getRoot()\n )[0];\n const children = graph.model.getChildren(parent);\n graph.moveCells(children, dx, dy);\n cells = cells.concat(children);\n }\n }\n } finally {\n graph.model.endUpdate();\n }\n }\n } catch (e) {\n alert(e);\n throw e;\n }\n\n return cells;\n };\n\n // Parses and inserts XML into graph\n const pasteText = function(text) {\n const xml = mxUtils.trim(text);\n const x =\n graph.container.scrollLeft / graph.view.scale - graph.view.translate.x;\n const y =\n graph.container.scrollTop / graph.view.scale - graph.view.translate.y;\n\n if (xml.length > 0) {\n if (lastPaste !== xml) {\n lastPaste = xml;\n dx = 0;\n dy = 0;\n } else {\n dx += gs;\n dy += gs;\n }\n\n // Standard paste via control-v\n if (xml.substring(0, 14) === '') {\n graph.setSelectionCells(importXml(xml, dx, dy));\n graph.scrollCellToVisible(graph.getSelectionCell());\n }\n }\n };\n\n // Function to fetch text from paste events\n const extractGraphModelFromEvent = function(evt) {\n let data = null;\n\n if (evt != null) {\n const provider =\n evt.dataTransfer != null ? evt.dataTransfer : evt.clipboardData;\n\n if (provider != null) {\n data =\n mxUtils.indexOf(provider.types, 'text/html') >= 0\n ? provider.getData('text/html')\n : null;\n\n if (\n mxUtils.indexOf(\n provider.types,\n 'text/plain' && (data == null || data.length === 0)\n )\n ) {\n data = provider.getData('text/plain');\n }\n }\n }\n\n return data;\n };\n\n // Handles paste event by parsing and inserting XML\n mxEvent.addListener(textInput, 'paste', function(evt) {\n // Clears existing contents before paste - should not be needed\n // because all text is selected, but doesn't hurt since the\n // actual pasting of the new text is delayed in all cases.\n textInput.value = '';\n\n if (graph.isEnabled()) {\n const xml = extractGraphModelFromEvent(evt);\n\n if (xml != null && xml.length > 0) {\n pasteText(xml);\n } else {\n // Timeout for new value to appear\n window.setTimeout(\n mxUtils.bind(this, function() {\n pasteText(textInput.value);\n }),\n 0\n );\n }\n }\n\n textInput.select();\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({ parent, source: v1, target: v2 });\n });\n };\n}\n\nexport default Clipboard;\n", + "__template": "import React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\n\nclass MYNAMEHERE extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

\n\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n }\n\n componentDidMount() {}\n}\n\nexport default MYNAMEHERE;\n", + "Drop": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Drop extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Drop

\n This example demonstrates handling native drag and drop of images\n (requires modern browser).\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: `url('editors/images/grid.gif')`,\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Checks if the browser is supported\n const fileSupport =\n window.File != null &&\n window.FileReader != null &&\n window.FileList != null;\n\n if (!fileSupport || !mxClient.isBrowserSupported()) {\n // Displays an error message if the browser is not supported.\n mxUtils.error('Browser is not supported!', 200, false);\n } else {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given this.el\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n mxEvent.addListener(this.el, 'dragover', function(evt) {\n if (graph.isEnabled()) {\n evt.stopPropagation();\n evt.preventDefault();\n }\n });\n\n mxEvent.addListener(this.el, 'drop', evt => {\n if (graph.isEnabled()) {\n evt.stopPropagation();\n evt.preventDefault();\n\n // Gets drop location point for vertex\n const pt = mxUtils.convertPoint(\n graph.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n const tr = graph.view.translate;\n const { scale } = graph.view;\n const x = pt.x / scale - tr.x;\n const y = pt.y / scale - tr.y;\n\n // Converts local images to data urls\n const filesArray = evt.dataTransfer.files;\n\n for (let i = 0; i < filesArray.length; i++) {\n this.handleDrop(graph, filesArray[i], x + i * 10, y + i * 10);\n }\n }\n });\n }\n }\n\n handleDrop(graph, file, x, y) {\n // Handles each file as a separate insert for simplicity.\n // Use barrier to handle multiple files as a single insert.\n\n if (file.type.substring(0, 5) === 'image') {\n const reader = new FileReader();\n\n reader.onload = function(e) {\n // Gets size of image for vertex\n let data = e.target.result;\n\n // SVG needs special handling to add viewbox if missing and\n // find initial size from SVG attributes (only for IE11)\n if (file.type.substring(0, 9) === 'image/svg') {\n const comma = data.indexOf(',');\n const svgText = atob(data.substring(comma + 1));\n const root = mxUtils.parseXml(svgText);\n\n // Parses SVG to find width and height\n if (root != null) {\n const svgs = root.getElementsByTagName('svg');\n\n if (svgs.length > 0) {\n const svgRoot = svgs[0];\n let w = parseFloat(svgRoot.getAttribute('width'));\n let h = parseFloat(svgRoot.getAttribute('height'));\n\n // Check if viewBox attribute already exists\n const vb = svgRoot.getAttribute('viewBox');\n\n if (vb == null || vb.length === 0) {\n svgRoot.setAttribute('viewBox', `0 0 ${w} ${h}`);\n }\n // Uses width and height from viewbox for\n // missing width and height attributes\n else if (Number.isNaN(w) || Number.isNaN(h)) {\n const tokens = vb.split(' ');\n\n if (tokens.length > 3) {\n w = parseFloat(tokens[2]);\n h = parseFloat(tokens[3]);\n }\n }\n\n w = Math.max(1, Math.round(w));\n h = Math.max(1, Math.round(h));\n\n data = `data:image/svg+xml,${btoa(\n mxUtils.getXml(svgs[0], '\\n')\n )}`;\n graph.insertVertex(\n null,\n null,\n '',\n x,\n y,\n w,\n h,\n `shape=image;image=${data};`\n );\n }\n }\n } else {\n const img = new Image();\n\n img.onload = function() {\n const w = Math.max(1, img.width);\n const h = Math.max(1, img.height);\n\n // Converts format of data url to cell style value for use in vertex\n const semi = data.indexOf(';');\n\n if (semi > 0) {\n data =\n data.substring(0, semi) +\n data.substring(data.indexOf(',', semi + 1));\n }\n\n graph.insertVertex(\n null,\n null,\n '',\n x,\n y,\n w,\n h,\n `shape=image;image=${data};`\n );\n };\n\n img.src = data;\n }\n };\n\n reader.readAsDataURL(file);\n }\n }\n}\n\nexport default Drop;\n", + "Markers": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxMarker from '../mxgraph/shape/mxMarker';\nimport mxArrow from '../mxgraph/shape/mxArrow';\n\nclass Markers extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Markers

\n This example demonstrates creating custom markers and customizing the\n built-in markers.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '381px',\n border: '1px solid gray',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Registers and defines the custom marker\n mxMarker.addMarker('dash', function(\n canvas,\n shape,\n type,\n pe,\n unitX,\n unitY,\n size,\n source,\n sw,\n filled\n ) {\n const nx = unitX * (size + sw + 1);\n const ny = unitY * (size + sw + 1);\n\n return function() {\n canvas.begin();\n canvas.moveTo(pe.x - nx / 2 - ny / 2, pe.y - ny / 2 + nx / 2);\n canvas.lineTo(\n pe.x + ny / 2 - (3 * nx) / 2,\n pe.y - (3 * ny) / 2 - nx / 2\n );\n canvas.stroke();\n };\n });\n\n // Defines custom message shape\n class MessageShape extends mxCylinder {\n redrawPath(path, x, y, w, h, isForeground) {\n if (isForeground) {\n path.moveTo(0, 0);\n path.lineTo(w / 2, h / 2);\n path.lineTo(w, 0);\n } else {\n path.moveTo(0, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h);\n path.lineTo(0, h);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('message', MessageShape);\n\n // Defines custom edge shape\n class LinkShape extends mxArrow {\n paintEdgeShape(c, pts) {\n const width = 10;\n\n // Base vector (between end points)\n const p0 = pts[0];\n const pe = pts[pts.length - 1];\n\n const dx = pe.x - p0.x;\n const dy = pe.y - p0.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n const length = dist;\n\n // Computes the norm and the inverse norm\n const nx = dx / dist;\n const ny = dy / dist;\n const basex = length * nx;\n const basey = length * ny;\n const floorx = (width * ny) / 3;\n const floory = (-width * nx) / 3;\n\n // Computes points\n const p0x = p0.x - floorx / 2;\n const p0y = p0.y - floory / 2;\n const p1x = p0x + floorx;\n const p1y = p0y + floory;\n const p2x = p1x + basex;\n const p2y = p1y + basey;\n const p3x = p2x + floorx;\n const p3y = p2y + floory;\n // p4 not necessary\n const p5x = p3x - 3 * floorx;\n const p5y = p3y - 3 * floory;\n\n c.begin();\n c.moveTo(p1x, p1y);\n c.lineTo(p2x, p2y);\n c.moveTo(p5x + floorx, p5y + floory);\n c.lineTo(p0x, p0y);\n c.stroke();\n }\n }\n mxCellRenderer.registerShape('link', LinkShape);\n\n // Creates the graph\n const graph = new mxGraph(this.el);\n\n // Sets default styles\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style.fillColor = '#FFFFFF';\n style.strokeColor = '#000000';\n style.fontColor = '#000000';\n style.fontStyle = '1';\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style.strokeColor = '#000000';\n style.fontColor = '#000000';\n style.fontStyle = '0';\n style.fontStyle = '0';\n style.startSize = '8';\n style.endSize = '8';\n\n // Populates the graph\n const parent = graph.getDefaultParent();\n\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'v1', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'v2', 440, 20, 80, 30);\n const e1 = graph.insertEdge(\n parent,\n null,\n '',\n v1,\n v2,\n 'dashed=1;' +\n 'startArrow=oval;endArrow=block;sourcePerimeterSpacing=4;startFill=0;endFill=0;'\n );\n const e11 = graph.insertVertex(\n e1,\n null,\n 'Label',\n 0,\n 0,\n 20,\n 14,\n 'shape=message;labelBackgroundColor=#ffffff;labelPosition=left;spacingRight=2;align=right;fontStyle=0;'\n );\n e11.geometry.offset = new mxPoint(-10, -7);\n e11.geometry.relative = true;\n e11.connectable = false;\n\n const v3 = graph.insertVertex(parent, null, 'v3', 20, 120, 80, 30);\n const v4 = graph.insertVertex(parent, null, 'v4', 440, 120, 80, 30);\n const e2 = graph.insertEdge(\n parent,\n null,\n 'Label',\n v3,\n v4,\n 'startArrow=dash;startSize=12;endArrow=block;labelBackgroundColor=#FFFFFF;'\n );\n\n const v5 = graph.insertVertex(\n parent,\n null,\n 'v5',\n 40,\n 220,\n 40,\n 40,\n 'shape=ellipse;perimeter=ellipsePerimeter;'\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n 'v6',\n 460,\n 220,\n 40,\n 40,\n 'shape=doubleEllipse;perimeter=ellipsePerimeter;'\n );\n const e3 = graph.insertEdge(\n parent,\n null,\n 'Link',\n v5,\n v6,\n 'shape=link;labelBackgroundColor=#FFFFFF;'\n );\n } finally {\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Markers;\n", + "Overlays": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxCellTracker from '../mxgraph/handler/mxCellTracker';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Overlays extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Overlays

\n This example demonstrates cell highlighting, overlays and handling click\n and double click events. See also: events.html for more event handling.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Highlights the vertices when the mouse enters\n const highlight = new mxCellTracker(graph, '#00FF00');\n\n // Enables tooltips for the overlays\n graph.setTooltips(true);\n\n // Installs a handler for click events in the graph\n // that toggles the overlay for the respective cell\n graph.addListener(mxEvent.CLICK, (sender, evt) => {\n const cell = evt.getProperty('cell');\n\n if (cell != null) {\n const overlays = graph.getCellOverlays(cell);\n\n if (overlays == null) {\n // Creates a new overlay with an image and a tooltip\n const overlay = new mxCellOverlay(\n new mxImage('editors/images/overlays/check.png', 16, 16),\n 'Overlay tooltip'\n );\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, (sender, evt2) => {\n mxUtils.alert('Overlay clicked');\n });\n\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(cell, overlay);\n } else {\n graph.removeCellOverlays(cell);\n }\n }\n });\n\n // Installs a handler for double click events in the graph\n // that shows an alert box\n graph.addListener(mxEvent.DOUBLE_CLICK, (sender, evt) => {\n const cell = evt.getProperty('cell');\n mxUtils.alert(`Doubleclick: ${cell != null ? 'Cell' : 'Graph'}`);\n evt.consume();\n });\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Click,',\n position: [20, 20],\n size: [60, 40],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'Doubleclick',\n position: [200, 150],\n size: [100, 40],\n });\n const e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n });\n });\n }\n}\n\nexport default Overlays;\n", + "Constituent": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\n\nclass Constituent extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Constituent

\n This example demonstrates using cells as parts of other cells.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount() {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n class MyCustomGraphHandler extends mxGraphHandler {\n /**\n * Redirects start drag to parent.\n */\n getInitialCellForEvent(me) {\n let cell = super.getInitialCellForEvent(me);\n if (this.graph.isPart(cell)) {\n cell = this.graph.getModel().getParent(cell);\n }\n return cell;\n }\n }\n\n class MyCustomGraph extends mxGraph {\n foldingEnabled = false;\n\n recursiveResize = true;\n\n isPart(cell) {\n // Helper method to mark parts with constituent=1 in the style\n return this.getCurrentCellStyle(cell).constituent == '1';\n }\n\n selectCellForEvent(cell, evt) {\n // Redirects selection to parent\n if (this.isPart(cell)) {\n cell = this.model.getParent(cell);\n }\n super.selectCellForEvent(cell, evt);\n }\n\n createGraphHandler() {\n return new MyCustomGraphHandler(this);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n position: [20, 20],\n size: [120, 70],\n });\n const v2 = graph.insertVertex({\n parent: v1,\n value: 'Constituent',\n position: [20, 20],\n size: [80, 30],\n style: 'constituent=1;',\n });\n });\n }\n}\n\nexport default Constituent;\n", + "Editing": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Editing extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Editing

\n This example demonstrates using the in-place editor trigger to specify\n the editing value and write the new value into a specific field of the\n user object. Wrapping and DOM nodes as labels are also demonstrated\n here.\n
\n
\n Double-click the upper/lower half of the cell to edit different fields\n of the user object.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n class MyCustomGraph extends mxGraph {\n getLabel(cell) {\n // Returns a HTML representation of the cell where the\n // upper half is the first value, lower half is second\n // value\n\n const table = document.createElement('table');\n table.style.height = '100%';\n table.style.width = '100%';\n\n const body = document.createElement('tbody');\n const tr1 = document.createElement('tr');\n const td1 = document.createElement('td');\n td1.style.textAlign = 'center';\n td1.style.fontSize = '12px';\n td1.style.color = '#774400';\n mxUtils.write(td1, cell.value.first);\n\n const tr2 = document.createElement('tr');\n const td2 = document.createElement('td');\n td2.style.textAlign = 'center';\n td2.style.fontSize = '12px';\n td2.style.color = '#774400';\n mxUtils.write(td2, cell.value.second);\n\n tr1.appendChild(td1);\n tr2.appendChild(td2);\n body.appendChild(tr1);\n body.appendChild(tr2);\n table.appendChild(body);\n\n return table;\n }\n\n getEditingValue(cell, evt) {\n // Returns the editing value for the given cell and event\n evt.fieldname = this.__getFieldnameForEvent(cell, evt);\n return cell.value[evt.fieldname] || '';\n }\n\n __getFieldnameForEvent(cell, evt) {\n // Helper method that returns the fieldname to be used for\n // a mouse event\n if (evt != null) {\n // Finds the relative coordinates inside the cell\n const point = mxUtils.convertPoint(\n this.container,\n mxEvent.getClientX(evt),\n mxEvent.getClientY(evt)\n );\n const state = this.getView().getState(cell);\n\n if (state != null) {\n point.x -= state.x;\n point.y -= state.y;\n\n // Returns second if mouse in second half of cell\n if (point.y > state.height / 2) {\n return 'second';\n }\n }\n }\n return 'first';\n }\n\n labelChanged(cell, newValue, trigger) {\n // Sets the new value for the given cell and trigger\n const name = trigger != null ? trigger.fieldname : null;\n\n if (name != null) {\n // Clones the user object for correct undo and puts\n // the new value in the correct field.\n const value = mxUtils.clone(cell.value);\n value[name] = newValue;\n newValue = value;\n\n super.labelChanged(cell, newValue, trigger);\n }\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setHtmlLabels(true);\n\n // Adds handling of return and escape keystrokes for editing\n const keyHandler = new mxKeyHandler(graph);\n\n // Sample user objects with 2 fields\n const value = {};\n value.first = 'First value';\n value.second = 'Second value';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n value,\n 100,\n 60,\n 120,\n 80,\n 'overflow=fill;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Editing;\n", + "HierarchicalLayout": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxHierarchicalLayout from '../mxgraph/layout/hierarchical/mxHierarchicalLayout';\nimport mxFastOrganicLayout from '../mxgraph/layout/mxFastOrganicLayout';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass HierarchicalLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hierarchical Layout

\n This example demonstrates the use of the hierarchical and organic\n layouts. Note that the hierarchical layout requires another script tag\n in the head of the page.\n {\n this.el = el;\n }}\n style={{\n position: 'absolute',\n overflow: 'auto',\n top: '36px',\n bottom: '0px',\n left: '0px',\n right: '0px',\n borderTop: 'gray 1px solid',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Adds rubberband selection\n new mxRubberband(graph);\n\n // Changes the default vertex style in-place\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_PERIMETER_SPACING] = 6;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Creates a layout algorithm to be used\n // with the graph\n const layout = new mxHierarchicalLayout(graph);\n const organic = new mxFastOrganicLayout(graph);\n organic.forceConstant = 120;\n\n const parent = graph.getDefaultParent();\n\n // Adds a button to execute the layout\n let button = document.createElement('button');\n mxUtils.write(button, 'Hierarchical');\n mxEvent.addListener(button, 'click', function(evt) {\n layout.execute(parent);\n });\n this.el2.appendChild(button);\n\n // Adds a button to execute the layout\n button = document.createElement('button');\n mxUtils.write(button, 'Organic');\n\n mxEvent.addListener(button, 'click', function(evt) {\n organic.execute(parent);\n });\n\n this.el2.appendChild(button);\n\n // Load cells and layouts the graph\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 0, 0, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2', 0, 0, 80, 30);\n const v3 = graph.insertVertex(parent, null, '3', 0, 0, 80, 30);\n const v4 = graph.insertVertex(parent, null, '4', 0, 0, 80, 30);\n const v5 = graph.insertVertex(parent, null, '5', 0, 0, 80, 30);\n const v6 = graph.insertVertex(parent, null, '6', 0, 0, 80, 30);\n const v7 = graph.insertVertex(parent, null, '7', 0, 0, 80, 30);\n const v8 = graph.insertVertex(parent, null, '8', 0, 0, 80, 30);\n const v9 = graph.insertVertex(parent, null, '9', 0, 0, 80, 30);\n\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v3, v4);\n const e4 = graph.insertEdge(parent, null, '', v2, v5);\n const e5 = graph.insertEdge(parent, null, '', v1, v6);\n const e6 = graph.insertEdge(parent, null, '', v2, v3);\n const e7 = graph.insertEdge(parent, null, '', v6, v4);\n const e8 = graph.insertEdge(parent, null, '', v6, v1);\n const e9 = graph.insertEdge(parent, null, '', v6, v7);\n const e10 = graph.insertEdge(parent, null, '', v7, v8);\n const e11 = graph.insertEdge(parent, null, '', v7, v9);\n const e12 = graph.insertEdge(parent, null, '', v7, v6);\n const e13 = graph.insertEdge(parent, null, '', v7, v5);\n\n // Executes the layout\n layout.execute(parent);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HierarchicalLayout;\n", + "OffPage": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCellTracker from '../mxgraph/handler/mxCellTracker';\nimport mxConstants from '../mxgraph/util/mxConstants';\n\nclass OffPage extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Offpage connector

\n This example demonstrates creating offpage connectors in a graph and\n loading a new diagram on a single click.\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n }\n\n componentDidMount() {\n // Use complete cell as highlight region\n mxConstants.ACTIVE_REGION = 1;\n\n const container = document.createElement('div');\n container.style.position = 'relative';\n container.style.overflow = 'hidden';\n container.style.height = '80vhpx';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n graph.setEnabled(false);\n\n // Highlights offpage connectors\n const highlight = new mxCellTracker(graph, null, function(me) {\n const cell = me.getCell();\n\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n return cell;\n }\n\n return null;\n });\n\n // Handles clicks on offpage connectors and\n // executes function in user object\n graph.addListener(mxEvent.CLICK, function(source, evt) {\n const cell = evt.getProperty('cell');\n\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n cell.value.create();\n }\n });\n\n // Handles clicks on offpage connectors and\n // executes function in user object\n graph.getCursorForCell = function(cell) {\n if (\n cell != null &&\n cell.value != null &&\n typeof cell.value.create === 'function'\n ) {\n return 'pointer';\n }\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n let first = null;\n let second = null;\n\n first = function() {\n const value = {\n toString() {\n return 'Next';\n },\n create: second,\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.getModel().setRoot(graph.getModel().createRoot());\n const parent = graph.getDefaultParent();\n\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Click',\n 30,\n 20,\n 80,\n 30,\n 'fillColor=#FFFF88;strokeColor=#FF1A00'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Next',\n 20,\n 150,\n 100,\n 30,\n 'fillColor=#FFFF88;strokeColor=#FF1A00'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n value,\n 200,\n 150,\n 40,\n 40,\n 'shape=triangle;align=left;fillColor=#C3D9FF;strokeColor=#4096EE'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n null,\n v1,\n v2,\n 'strokeColor=#FF1A00'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n\n second = function() {\n const value = {\n toString() {\n return 'Prev';\n },\n create: first,\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.getModel().setRoot(graph.getModel().createRoot());\n const parent = graph.getDefaultParent();\n\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Click',\n 30,\n 20,\n 80,\n 30,\n 'fillColor=#CDEB8B;strokeColor=#008C00'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Prev',\n 220,\n 20,\n 100,\n 30,\n 'fillColor=#CDEB8B;strokeColor=#008C00'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n value,\n 30,\n 150,\n 40,\n 40,\n 'shape=triangle;align=right;fillColor=#C3D9FF;strokeColor=#4096EE;direction=west'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n null,\n v1,\n v2,\n 'strokeColor=#008C00'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n\n first();\n }\n}\n\nexport default OffPage;\n", + "Resources": "/**\n * Copyright (c) 2006-2018, JGraph Ltd\n \n\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\n\nclass Resources extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Resources

\n This example demonstrates disabling the Synchronous XMLHttpRequest on\n main thread warning.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Async indirection to load resources asynchronously (see above)\n // Alternatively you can remove the line that sets mxLoadResources\n // anove and change the code to not use this callback.\n\n mxClient.loadResources(() => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n });\n }\n}\n\nexport default Resources;\n", + "Indicators": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Indicators extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Indicators

\n This example demonstrates the use of indicators, which are small\n subshapes inside a parent shape, typically an mxLabel.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300ph',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n new mxKeyHandler(graph);\n\n // Enables moving of vertex labels\n graph.vertexLabelsMovable = true;\n\n // Creates a style with an indicator\n let style = graph.getStylesheet().getDefaultVertexStyle();\n\n style[mxConstants.STYLE_SHAPE] = 'label';\n style[mxConstants.STYLE_VERTICAL_ALIGN] = 'bottom';\n style[mxConstants.STYLE_INDICATOR_SHAPE] = 'ellipse';\n style[mxConstants.STYLE_INDICATOR_WIDTH] = 34;\n style[mxConstants.STYLE_INDICATOR_HEIGHT] = 34;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = 'top'; // indicator v-alignment\n style[mxConstants.STYLE_IMAGE_ALIGN] = 'center';\n style[mxConstants.STYLE_INDICATOR_COLOR] = 'green';\n delete style[mxConstants.STYLE_STROKECOLOR]; // transparent\n delete style[mxConstants.STYLE_FILLCOLOR]; // transparent\n\n // Creates a style with an indicator\n style = graph.getStylesheet().getDefaultEdgeStyle();\n\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ELBOW] = mxConstants.ELBOW_VERTICAL;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n graph.insertVertex(parent, null, 'Bottom Label', 80, 80, 80, 60);\n graph.insertVertex(\n parent,\n null,\n 'Top Label',\n 200,\n 80,\n 60,\n 60,\n 'indicatorShape=actor;indicatorWidth=28;indicatorColor=blue;imageVerticalAlign=bottom;verticalAlign=top'\n );\n graph.insertVertex(\n parent,\n null,\n 'Right Label',\n 300,\n 80,\n 120,\n 60,\n 'indicatorShape=cloud;indicatorWidth=40;indicatorColor=#00FFFF;imageVerticalAlign=center;verticalAlign=middle;imageAlign=left;align=left;spacingLeft=44'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Indicators;\n", + "HoverIcons": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxImage from '../mxgraph/util/mxImage';\n\nclass HoverIcons extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hover icons

\n This example demonstrates showing icons on vertices as mouse hovers over\n them.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Defines a new class for all icons\n function mxIconSet(state) {\n this.images = [];\n const { graph } = state.view;\n\n // Icon1\n let img = mxUtils.createImage('images/copy.png');\n img.setAttribute('title', 'Duplicate');\n img.style.position = 'absolute';\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n img.style.left = `${state.x + state.width}px`;\n img.style.top = `${state.y + state.height}px`;\n\n mxEvent.addGestureListeners(img, evt => {\n const s = graph.gridSize;\n graph.setSelectionCells(graph.moveCells([state.cell], s, s, true));\n mxEvent.consume(evt);\n this.destroy();\n });\n\n state.view.graph.container.appendChild(img);\n this.images.push(img);\n\n // Delete\n img = mxUtils.createImage('images/delete2.png');\n img.setAttribute('title', 'Delete');\n img.style.position = 'absolute';\n img.style.cursor = 'pointer';\n img.style.width = '16px';\n img.style.height = '16px';\n img.style.left = `${state.x + state.width}px`;\n img.style.top = `${state.y - 16}px`;\n\n mxEvent.addGestureListeners(img, evt => {\n // Disables dragging the image\n mxEvent.consume(evt);\n });\n\n mxEvent.addListener(img, 'click', evt => {\n graph.removeCells([state.cell]);\n mxEvent.consume(evt);\n this.destroy();\n });\n\n state.view.graph.container.appendChild(img);\n this.images.push(img);\n }\n\n mxIconSet.prototype.destroy = function() {\n if (this.images != null) {\n for (let i = 0; i < this.images.length; i++) {\n const img = this.images[i];\n img.parentNode.removeChild(img);\n }\n }\n\n this.images = null;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n\n // Defines the tolerance before removing the icons\n const iconTolerance = 20;\n\n // Shows icons if the mouse is over a cell\n graph.addMouseListener({\n currentState: null,\n currentIconSet: null,\n mouseDown(sender, me) {\n // Hides icons on mouse down\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n this.currentState = null;\n }\n },\n mouseMove(sender, me) {\n if (\n this.currentState != null &&\n (me.getState() == this.currentState || me.getState() == null)\n ) {\n const tol = iconTolerance;\n const tmp = new mxRectangle(\n me.getGraphX() - tol,\n me.getGraphY() - tol,\n 2 * tol,\n 2 * tol\n );\n\n if (mxUtils.intersects(tmp, this.currentState)) {\n return;\n }\n }\n\n let tmp = graph.view.getState(me.getCell());\n\n // Ignores everything but vertices\n if (\n graph.isMouseDown ||\n (tmp != null && !graph.getModel().isVertex(tmp.cell))\n ) {\n tmp = null;\n }\n\n if (tmp != this.currentState) {\n if (this.currentState != null) {\n this.dragLeave(me.getEvent(), this.currentState);\n }\n\n this.currentState = tmp;\n\n if (this.currentState != null) {\n this.dragEnter(me.getEvent(), this.currentState);\n }\n }\n },\n mouseUp(sender, me) {},\n dragEnter(evt, state) {\n if (this.currentIconSet == null) {\n this.currentIconSet = new mxIconSet(state);\n }\n },\n dragLeave(evt, state) {\n if (this.currentIconSet != null) {\n this.currentIconSet.destroy();\n this.currentIconSet = null;\n }\n },\n });\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default HoverIcons;\n", + "Collapse": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\n\nclass Collapse extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Collapse

\n This example demonstrates changing the style of a cell based on its\n collapsed state.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n class MyCustomModel extends mxGraphModel {\n getStyle(cell) {\n // Extends mxGraphModel.getStyle to show an image when collapsed\n if (cell != null) {\n let style = super.getStyle(cell);\n if (this.isCollapsed(cell)) {\n style =\n `${style};shape=image;image=http://www.jgraph.com/images/mxgraph.gif;` +\n `noLabel=1;imageBackground=#C3D9FF;imageBorder=#6482B9`;\n }\n return style;\n }\n return null;\n }\n }\n\n const graph = new mxGraph(this.el, new MyCustomModel());\n const parent = graph.getDefaultParent();\n\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Container',\n position: [20, 20],\n size: [200, 200],\n style: 'shape=swimlane;startSize=20;',\n });\n v1.geometry.alternateBounds = new mxRectangle(0, 0, 110, 70);\n\n const v11 = graph.insertVertex({\n parent: v1,\n value: 'Hello,',\n position: [10, 40],\n size: [120, 80],\n });\n });\n };\n}\n\nexport default Collapse;\n", + "LOD": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass LOD extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Level of detail

\n This example demonstrates implementing a level of detail per cell.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.centerZoom = false;\n\n // Links level of detail to zoom level but can be independent of zoom\n graph.isCellVisible = function(cell) {\n return cell.lod == null || cell.lod / 2 < this.view.scale;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '1', 20, 20, 80, 30);\n v1.lod = 1;\n const v2 = graph.insertVertex(parent, null, '1', 200, 150, 80, 30);\n v2.lod = 1;\n const v3 = graph.insertVertex(parent, null, '2', 20, 150, 40, 20);\n v3.lod = 2;\n const v4 = graph.insertVertex(parent, null, '3', 200, 10, 20, 20);\n v4.lod = 3;\n const e1 = graph.insertEdge(parent, null, '2', v1, v2, 'strokeWidth=2');\n e1.lod = 2;\n var e2 = graph.insertEdge(parent, null, '2', v3, v4, 'strokeWidth=2');\n e2.lod = 2;\n var e2 = graph.insertEdge(parent, null, '3', v1, v4, 'strokeWidth=1');\n e2.lod = 3;\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default LOD;\n", + "Tree": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxCompactTreeLayout from '../mxgraph/layout/mxCompactTreeLayout';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxClient from '../mxgraph/mxClient';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\n\nclass Tree extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Tree

\n This example demonstrates folding of subtrees in a acyclic graph (tree).\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n /*\n Defines a custom shape for the tree node that includes the\n upper half of the outgoing edge(s).\n */\n class TreeNodeShape extends mxCylinder {\n // Defines the length of the upper edge segment.\n segment = 20;\n\n constructor(bounds, fill, stroke, strokewidth) {\n super(bounds, fill, stroke, strokewidth);\n }\n\n // Needs access to the cell state for rendering\n apply(state) {\n super.apply(state);\n this.state = state;\n }\n\n redrawPath(path, x, y, w, h, isForeground) {\n const { graph } = this.state.view;\n const hasChildren =\n graph.model.getOutgoingEdges(this.state.cell).length > 0;\n\n if (isForeground) {\n if (hasChildren) {\n // Painting outside of vertex bounds is used here\n path.moveTo(w / 2, h + this.segment);\n path.lineTo(w / 2, h);\n path.end();\n }\n } else {\n path.moveTo(0, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h);\n path.lineTo(0, h);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('treenode', TreeNodeShape);\n\n class MyCustomGraphView extends mxGraphView {\n updateFloatingTerminalPoint(edge, start, end, source) {\n // Defines a custom perimeter for the nodes in the tree\n let pt = null;\n\n if (source) {\n pt = new mxPoint(\n start.x + start.width / 2,\n start.y + start.height + TreeNodeShape.prototype.segment\n );\n } else {\n pt = new mxPoint(start.x + start.width / 2, start.y);\n }\n\n edge.setAbsoluteTerminalPoint(pt, source);\n }\n }\n\n class MyCustomCellRenderer extends mxCellRenderer {\n getControlBounds(state) {\n // Defines the position of the folding icon\n if (state.control != null) {\n const oldScale = state.control.scale;\n const w = state.control.bounds.width / oldScale;\n const h = state.control.bounds.height / oldScale;\n const s = state.view.scale;\n\n return new mxRectangle(\n state.x + state.width / 2 - (w / 2) * s,\n state.y +\n state.height +\n TreeNodeShape.prototype.segment * s -\n (h / 2) * s,\n w * s,\n h * s\n );\n }\n return null;\n }\n }\n\n // Make the layout instance accessible by MyCustomGraph\n let layout;\n\n class MyCustomGraph extends mxGraph {\n // Sets the collapse and expand icons. The values below are the default\n // values, but this is how to replace them if you need to.\n collapsedImage = new mxImage(\n `${mxClient.imageBasePath}/collapsed.gif`,\n 9,\n 9\n );\n\n expandedImage = new mxImage(\n `${mxClient.imageBasePath}/expanded.gif`,\n 9,\n 9\n );\n\n isCellFoldable(cell) {\n // Defines the condition for showing the folding icon\n return this.model.getOutgoingEdges(cell).length > 0;\n }\n\n createCellRenderer() {\n return new MyCustomCellRenderer();\n }\n\n createGraphView() {\n return new MyCustomGraphView(this);\n }\n\n foldCells(collapse, recurse, cells) {\n // Implements the click on a folding icon\n this.model.beginUpdate();\n try {\n this.toggleSubtree(this, cells[0], !collapse);\n this.model.setCollapsed(cells[0], collapse);\n\n // Executes the layout for the new graph since\n // changes to visiblity and collapsed state do\n // not trigger a layout in the current manager.\n layout.execute(this.getDefaultParent());\n } finally {\n this.model.endUpdate();\n }\n }\n\n toggleSubtree(cell, show) {\n // Updates the visible state of a given subtree taking into\n // account the collapsed state of the traversed branches\n show = show != null ? show : true;\n const cells = [];\n\n this.traverse(cell, true, function(vertex) {\n if (vertex !== cell) {\n cells.push(vertex);\n }\n\n // Stops recursion if a collapsed cell is seen\n return vertex === cell || !this.isCellCollapsed(vertex);\n });\n\n this.toggleCells(show, cells, true);\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n\n // Disallow any selections\n graph.setCellsSelectable(false);\n\n // Avoids overlap of edges and collapse icons\n graph.keepEdgesInBackground = true;\n\n // Set some stylesheet options for the visual appearance\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'treenode';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_SHADOW] = true;\n\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;\n style[mxConstants.STYLE_ROUNDED] = true;\n\n // Enables automatic sizing for vertices after editing and\n // panning by using the left mouse button.\n graph.setAutoSizeCells(true);\n graph.setPanning(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n\n // Enables automatic layout on the graph and installs\n // a tree layout for all groups who's children are\n // being changed, added or removed.\n layout = new mxCompactTreeLayout(graph, false);\n layout.useBoundingBox = false;\n layout.edgeRouting = false;\n layout.levelDistance = 30;\n layout.nodeDistance = 10;\n\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds the root vertex of the tree\n graph.getModel().beginUpdate();\n try {\n const w = graph.container.offsetWidth;\n const root = graph.insertVertex(\n parent,\n 'treeRoot',\n 'Root',\n w / 2 - 30,\n 20,\n 60,\n 40\n );\n\n const v1 = graph.insertVertex(parent, 'v1', 'Child 1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v1);\n\n const v2 = graph.insertVertex(parent, 'v2', 'Child 2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v2);\n\n const v3 = graph.insertVertex(parent, 'v3', 'Child 3', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', root, v3);\n\n const v11 = graph.insertVertex(parent, 'v11', 'Child 1.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v1, v11);\n\n const v12 = graph.insertVertex(parent, 'v12', 'Child 1.2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v1, v12);\n\n const v21 = graph.insertVertex(parent, 'v21', 'Child 2.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v2, v21);\n\n const v22 = graph.insertVertex(parent, 'v22', 'Child 2.2', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v2, v22);\n\n const v221 = graph.insertVertex(\n parent,\n 'v221',\n 'Child 2.2.1',\n 0,\n 0,\n 60,\n 40\n );\n graph.insertEdge(parent, null, '', v22, v221);\n\n const v222 = graph.insertVertex(\n parent,\n 'v222',\n 'Child 2.2.2',\n 0,\n 0,\n 60,\n 40\n );\n graph.insertEdge(parent, null, '', v22, v222);\n\n const v31 = graph.insertVertex(parent, 'v31', 'Child 3.1', 0, 0, 60, 40);\n graph.insertEdge(parent, null, '', v3, v31);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Tree;\n", + "Labels": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\n\nclass Labels extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Hello, World!

\n This example demonstrates the use of wrapping and clipping for HTML\n labels of vertices, truncating labels to fit the size of a vertex, and\n manually placing vertex labels and relative children that act as\n \"sublabels\".\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '300px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setTooltips(true);\n graph.htmlLabels = true;\n graph.vertexLabelsMovable = true;\n new mxRubberband(graph);\n new mxKeyHandler(graph);\n\n // Do not allow removing labels from parents\n graph.graphHandler.removeCellsFromParent = false;\n\n // Autosize labels on insert where autosize=1\n graph.autoSizeCellsOnAdd = true;\n\n // Allows moving of relative cells\n graph.isCellLocked = function(cell) {\n return this.isCellsLocked();\n };\n\n graph.isCellResizable = function(cell) {\n const geo = this.model.getGeometry(cell);\n\n return geo == null || !geo.relative;\n };\n\n // Truncates the label to the size of the vertex\n graph.getLabel = function(cell) {\n const label = this.labelsVisible ? this.convertValueToString(cell) : '';\n const geometry = this.model.getGeometry(cell);\n\n if (\n !this.model.isCollapsed(cell) &&\n geometry != null &&\n (geometry.offset == null ||\n (geometry.offset.x == 0 && geometry.offset.y == 0)) &&\n this.model.isVertex(cell) &&\n geometry.width >= 2\n ) {\n const style = this.getCellStyle(cell);\n const fontSize =\n style[mxConstants.STYLE_FONTSIZE] || mxConstants.DEFAULT_FONTSIZE;\n const max = geometry.width / (fontSize * 0.625);\n\n if (max < label.length) {\n return `${label.substring(0, max)}...`;\n }\n }\n\n return label;\n };\n\n // Enables wrapping for vertex labels\n graph.isWrapping = function(cell) {\n return this.model.isCollapsed(cell);\n };\n\n // Enables clipping of vertex labels if no offset is defined\n graph.isLabelClipped = function(cell) {\n const geometry = this.model.getGeometry(cell);\n\n return (\n geometry != null &&\n !geometry.relative &&\n (geometry.offset == null ||\n (geometry.offset.x == 0 && geometry.offset.y == 0))\n );\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'vertexLabelsMovable',\n 20,\n 20,\n 80,\n 30\n );\n\n // Places sublabels inside the vertex\n const label11 = graph.insertVertex(\n v1,\n null,\n 'Label1',\n 0.5,\n 1,\n 0,\n 0,\n null,\n true\n );\n const label12 = graph.insertVertex(\n v1,\n null,\n 'Label2',\n 0.5,\n 0,\n 0,\n 0,\n null,\n true\n );\n\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Wrapping and clipping is enabled only if the cell is collapsed, otherwise the label is truncated if there is no manual offset.',\n 200,\n 150,\n 80,\n 30\n );\n v2.geometry.alternateBounds = new mxRectangle(0, 0, 80, 30);\n const e1 = graph.insertEdge(parent, null, 'edgeLabelsMovable', v1, v2);\n\n // Places sublabels inside the vertex\n const label21 = graph.insertVertex(\n v2,\n null,\n 'Label1',\n 0.5,\n 1,\n 0,\n 0,\n null,\n true\n );\n const label22 = graph.insertVertex(\n v2,\n null,\n 'Label2',\n 0.5,\n 0,\n 0,\n 0,\n null,\n true\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Labels;\n", + "Control": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxImageShape from '../mxgraph/shape/mxImageShape';\nimport mxImage from '../mxgraph/util/mxImage';\n\nclass Control extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Control

\n This example demonstrates adding controls to specific cells in a graph.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '441px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Specifies the URL and size of the new control\n const deleteImage = new mxImage(\n 'editors/images/overlays/forbidden.png',\n 16,\n 16\n );\n\n class MyCustomCellRenderer extends mxCellRenderer {\n createControl(state) {\n super.createControl(state);\n\n const { graph } = state.view;\n\n if (graph.getModel().isVertex(state.cell)) {\n if (state.deleteControl == null) {\n const b = new mxRectangle(\n 0,\n 0,\n deleteImage.width,\n deleteImage.height\n );\n state.deleteControl = new mxImageShape(b, deleteImage.src);\n state.deleteControl.dialect = graph.dialect;\n state.deleteControl.preserveImageAspect = false;\n\n this.initControl(state, state.deleteControl, false, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells([state.cell]);\n mxEvent.consume(evt);\n }\n });\n }\n } else if (state.deleteControl != null) {\n state.deleteControl.destroy();\n state.deleteControl = null;\n }\n }\n\n getDeleteControlBounds(state) {\n // Helper function to compute the bounds of the control\n if (state.deleteControl != null) {\n const oldScale = state.deleteControl.scale;\n const w = state.deleteControl.bounds.width / oldScale;\n const h = state.deleteControl.bounds.height / oldScale;\n const s = state.view.scale;\n\n return state.view.graph.getModel().isEdge(state.cell)\n ? new mxRectangle(\n state.x + state.width / 2 - (w / 2) * s,\n state.y + state.height / 2 - (h / 2) * s,\n w * s,\n h * s\n )\n : new mxRectangle(\n state.x + state.width - w * s,\n state.y,\n w * s,\n h * s\n );\n }\n return null;\n }\n\n redrawControl(state) {\n // Overridden to update the scale and bounds of the control\n super.redrawControl(state);\n\n if (state.deleteControl != null) {\n const bounds = this.getDeleteControlBounds(state);\n const s = state.view.scale;\n\n if (\n state.deleteControl.scale !== s ||\n !state.deleteControl.bounds.equals(bounds)\n ) {\n state.deleteControl.bounds = bounds;\n state.deleteControl.scale = s;\n state.deleteControl.redraw();\n }\n }\n }\n\n destroy(state) {\n // Overridden to remove the control if the state is destroyed\n super.destroy(state);\n\n if (state.deleteControl != null) {\n state.deleteControl.destroy();\n state.deleteControl = null;\n }\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createCellRenderer() {\n return new MyCustomCellRenderer();\n }\n }\n\n // Creates the graph inside the given container\n const graph = new MyCustomGraph(this.el);\n graph.setPanning(true);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n });\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.centerZoom = false;\n\n this.el2.appendChild(\n mxUtils.button('Zoom In', () => {\n graph.zoomIn();\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('Zoom Out', () => {\n graph.zoomOut();\n })\n );\n };\n}\n\nexport default Control;\n", + "LabelPosition": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass LabelPosition extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Label Position

\n This example demonstrates the use of the label position styles to set\n the position of vertex labels.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '300px',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Defines the common part of all cell styles as a string-prefix\n const prefix = 'shape=image;image=images/icons48/keys.png;';\n\n // Adds cells to the model in a single step and set the vertex\n // label positions using the label position styles. Vertical\n // and horizontal label position styles can be combined.\n // Note: Alternatively, vertex labels can be set be overriding\n // mxCellRenderer.getLabelBounds.\n graph.getModel().beginUpdate();\n try {\n graph.insertVertex(\n parent,\n null,\n 'Bottom',\n 60,\n 60,\n 60,\n 60,\n `${prefix}verticalLabelPosition=bottom;verticalAlign=top`\n );\n graph.insertVertex(\n parent,\n null,\n 'Top',\n 140,\n 60,\n 60,\n 60,\n `${prefix}verticalLabelPosition=top;verticalAlign=bottom`\n );\n graph.insertVertex(\n parent,\n null,\n 'Left',\n 60,\n 160,\n 60,\n 60,\n `${prefix}labelPosition=left;align=right`\n );\n graph.insertVertex(\n parent,\n null,\n 'Right',\n 140,\n 160,\n 60,\n 60,\n `${prefix}labelPosition=right;align=left`\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default LabelPosition;\n", + "Validation": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxMultiplicity from '../mxgraph/view/mxMultiplicity';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Validation extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Validation

\n This example demonstrates using multiplicities for automatically\n validating a graph.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '281px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n const xmlDocument = mxUtils.createXmlDocument();\n const sourceNode = xmlDocument.createElement('Source');\n const targetNode = xmlDocument.createElement('Target');\n const subtargetNode = xmlDocument.createElement('Subtarget');\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n graph.setAllowDanglingEdges(false);\n graph.setMultigraph(false);\n\n // Source nodes needs 1..2 connected Targets\n graph.multiplicities.push(\n new mxMultiplicity(\n true,\n 'Source',\n null,\n null,\n 1,\n 2,\n ['Target'],\n 'Source Must Have 1 or 2 Targets',\n 'Source Must Connect to Target'\n )\n );\n\n // Source node does not want any incoming connections\n graph.multiplicities.push(\n new mxMultiplicity(\n false,\n 'Source',\n null,\n null,\n 0,\n 0,\n null,\n 'Source Must Have No Incoming Edge',\n null\n )\n ); // Type does not matter\n\n // Target needs exactly one incoming connection from Source\n graph.multiplicities.push(\n new mxMultiplicity(\n false,\n 'Target',\n null,\n null,\n 1,\n 1,\n ['Source'],\n 'Target Must Have 1 Source',\n 'Target Must Connect From Source'\n )\n );\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Removes cells when [DELETE] is pressed\n const keyHandler = new mxKeyHandler(graph);\n keyHandler.bindKey(46, function(evt) {\n if (graph.isEnabled()) {\n graph.removeCells();\n }\n });\n\n // Installs automatic validation (use editor.validation = true\n // if you are using an mxEditor instance)\n const listener = function(sender, evt) {\n graph.validateGraph();\n };\n\n graph.getModel().addListener(mxEvent.CHANGE, listener);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, sourceNode, 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, targetNode, 200, 20, 80, 30);\n const v3 = graph.insertVertex(\n parent,\n null,\n targetNode.cloneNode(true),\n 200,\n 80,\n 80,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n targetNode.cloneNode(true),\n 200,\n 140,\n 80,\n 30\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n subtargetNode,\n 200,\n 200,\n 80,\n 30\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n sourceNode.cloneNode(true),\n 20,\n 140,\n 80,\n 30\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n const e2 = graph.insertEdge(parent, null, '', v1, v3);\n const e3 = graph.insertEdge(parent, null, '', v6, v4);\n // var e4 = graph.insertEdge(parent, null, '', v1, v4);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Validation;\n", + "Toolbar": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxDragSource from '../mxgraph/util/mxDragSource';\nimport mxGraphModel from '../mxgraph/model/mxGraphModel';\nimport mxToolbar from '../mxgraph/util/mxToolbar';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Toolbar extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Toolbar

\n This example demonstrates using existing cells as templates for creating\n new cells.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '400px',\n border: 'gray dotted 1px',\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Defines an icon for creating new connections in the connection handler.\n // This will automatically disable the highlighting of the source vertex.\n mxConnectionHandler.prototype.connectImage = new mxImage(\n 'images/connector.gif',\n 16,\n 16\n );\n\n // Creates the div for the toolbar\n const tbContainer = document.createElement('div');\n tbContainer.style.position = 'absolute';\n tbContainer.style.overflow = 'hidden';\n tbContainer.style.padding = '2px';\n tbContainer.style.left = '0px';\n tbContainer.style.top = '26px';\n tbContainer.style.width = '24px';\n tbContainer.style.bottom = '0px';\n\n this.el.appendChild(tbContainer);\n\n // Creates new toolbar without event processing\n const toolbar = new mxToolbar(tbContainer);\n toolbar.enabled = false;\n\n // Creates the div for the graph\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '24px';\n container.style.top = '26px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n container.style.background = 'url(\"editors/images/grid.gif\")';\n\n this.el.appendChild(container);\n\n // Creates the model and the graph inside the container\n // using the fastest rendering available on the browser\n const model = new mxGraphModel();\n const graph = new mxGraph(container, model);\n graph.dropEnabled = true;\n\n // Matches DnD inside the graph\n mxDragSource.prototype.getDropTarget = function(graph, x, y) {\n let cell = graph.getCellAt(x, y);\n if (!graph.isValidDropTarget(cell)) {\n cell = null;\n }\n return cell;\n };\n\n // Enables new connections in the graph\n graph.setConnectable(true);\n graph.setMultigraph(false);\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n const rubberband = new mxRubberband(graph);\n\n const addVertex = (icon, w, h, style) => {\n const vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);\n vertex.setVertex(true);\n\n this.addToolbarItem(graph, toolbar, vertex, icon);\n };\n\n addVertex(\n 'editors/images/swimlane.gif',\n 120,\n 160,\n 'shape=swimlane;startSize=20;'\n );\n addVertex('editors/images/rectangle.gif', 100, 40, '');\n addVertex('editors/images/rounded.gif', 100, 40, 'shape=rounded');\n addVertex('editors/images/ellipse.gif', 40, 40, 'shape=ellipse');\n addVertex('editors/images/rhombus.gif', 40, 40, 'shape=rhombus');\n addVertex('editors/images/triangle.gif', 40, 40, 'shape=triangle');\n addVertex('editors/images/cylinder.gif', 40, 40, 'shape=cylinder');\n addVertex('editors/images/actor.gif', 30, 40, 'shape=actor');\n toolbar.addLine();\n\n const button = mxUtils.button(\n 'Create toolbar entry from selection',\n evt => {\n if (!graph.isSelectionEmpty()) {\n // Creates a copy of the selection array to preserve its state\n const cells = graph.getSelectionCells();\n const bounds = graph.getView().getBounds(cells);\n\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = (graph, evt, cell) => {\n graph.stopEditing(false);\n\n const pt = graph.getPointForEvent(evt);\n const dx = pt.x - bounds.x;\n const dy = pt.y - bounds.y;\n\n graph.setSelectionCells(graph.importCells(cells, dx, dy, cell));\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(\n null,\n 'editors/images/outline.gif',\n funct\n );\n mxUtils.makeDraggable(img, graph, funct);\n }\n }\n );\n\n this.el2.appendChild(button);\n }\n\n addToolbarItem(graph, toolbar, prototype, image) {\n // Function that is executed when the image is dropped on\n // the graph. The cell argument points to the cell under\n // the mousepointer if there is one.\n const funct = (graph, evt, cell) => {\n graph.stopEditing(false);\n\n const pt = graph.getPointForEvent(evt);\n const vertex = graph.getModel().cloneCell(prototype);\n vertex.geometry.x = pt.x;\n vertex.geometry.y = pt.y;\n\n graph.setSelectionCells(graph.importCells([vertex], 0, 0, cell));\n };\n\n // Creates the image which is used as the drag icon (preview)\n const img = toolbar.addMode(null, image, funct);\n mxUtils.makeDraggable(img, graph, funct);\n }\n}\n\nexport default Toolbar;\n", + "Thread": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass Thread extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Thread

\n This example demonstrates setting overlays in mxGraph from within a\n timed function.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n let v1;\n let v2;\n let e1;\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Function to switch the overlay every 5 secs\n const f = () => {\n const overlays = graph.getCellOverlays(v1);\n\n if (overlays == null) {\n graph.removeCellOverlays(v2);\n graph.setCellWarning(v1, 'Tooltip');\n } else {\n graph.removeCellOverlays(v1);\n graph.setCellWarning(v2, 'Tooltip');\n }\n };\n\n window.setInterval(f, 1000);\n f();\n }\n}\n\nexport default Thread;\n", + "Animation": "/**\n * Copyright (c) 2006-2017, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxPoint from '../mxgraph/util/mxPoint';\n\nclass Animation extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Animation

\n This example demonstrates using SVG animations on edges to visualize the\n flow in a pipe.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n const graph = new mxGraph(this.el);\n graph.setEnabled(false);\n const parent = graph.getDefaultParent();\n\n const vertexStyle =\n 'shape=cylinder;strokeWidth=2;fillColor=#ffffff;strokeColor=black;' +\n 'gradientColor=#a0a0a0;fontColor=black;fontStyle=1;spacingTop=14;';\n\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex({\n parent,\n value: 'Pump',\n position: [20, 20],\n size: [60, 60],\n style: vertexStyle,\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'Tank',\n position: [200, 150],\n size: [60, 60],\n style: vertexStyle,\n });\n var e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n style:\n 'strokeWidth=3;endArrow=block;endSize=2;endFill=1;strokeColor=black;rounded=1;',\n });\n e1.geometry.points = [new mxPoint(230, 50)];\n graph.orderCells(true, [e1]);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Adds animation to edge shape and makes \"pipe\" visible\n const state = graph.view.getState(e1);\n state.shape.node\n .getElementsByTagName('path')[0]\n .removeAttribute('visibility');\n state.shape.node\n .getElementsByTagName('path')[0]\n .setAttribute('stroke-width', '6');\n state.shape.node\n .getElementsByTagName('path')[0]\n .setAttribute('stroke', 'lightGray');\n state.shape.node\n .getElementsByTagName('path')[1]\n .setAttribute('class', 'flow');\n };\n}\n\nexport default Animation;\n", + "Perimeter": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\n\nclass Perimeter extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Perimeter

\n This example demonstrates how to avoid edge and label intersections.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Redirects the perimeter to the label bounds if intersection\n // between edge and label is found\n const mxGraphViewGetPerimeterPoint =\n mxGraphView.prototype.getPerimeterPoint;\n mxGraphView.prototype.getPerimeterPoint = function(\n terminal,\n next,\n orthogonal,\n border\n ) {\n let point = mxGraphViewGetPerimeterPoint.apply(this, arguments);\n\n if (point != null) {\n const perimeter = this.getPerimeterFunction(terminal);\n\n if (terminal.text != null && terminal.text.boundingBox != null) {\n // Adds a small border to the label bounds\n const b = terminal.text.boundingBox.clone();\n b.grow(3);\n\n if (mxUtils.rectangleIntersectsSegment(b, point, next)) {\n point = perimeter(b, terminal, next, orthogonal);\n }\n }\n }\n\n return point;\n };\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setVertexLabelsMovable(true);\n graph.setConnectable(true);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 20,\n 20,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 200,\n 20,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Label',\n 20,\n 150,\n 80,\n 30,\n 'verticalLabelPosition=bottom'\n );\n var e1 = graph.insertEdge(parent, null, '', v1, v2);\n var e1 = graph.insertEdge(parent, null, '', v1, v3);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Perimeter;\n", + "JsonData": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCodecRegistry from '../mxgraph/io/mxCodecRegistry';\nimport mxObjectCodec from '../mxgraph/io/mxObjectCodec';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCodec from '../mxgraph/io/mxCodec';\n\nclass JsonData extends React.Component {\n // Adds an option to view the XML of the graph\n document;\n\n body;\n\n 'View XML';\n\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

JSON data

\n This example demonstrates using JSON to encode/decode parts of the graph\n model in mxCodec.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n v1.data = new CustomData('v1');\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n v2.data = new CustomData('v2');\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button(function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getXml(node), true);\n })\n );\n\n function CustomData(value) {\n this.value = value;\n }\n\n const codec = new mxObjectCodec(new CustomData());\n codec.encode = function(enc, obj) {\n const node = enc.document.createElement('CustomData');\n mxUtils.setTextContent(node, JSON.stringify(obj));\n\n return node;\n };\n codec.decode = function(dec, node, into) {\n const obj = JSON.parse(mxUtils.getTextContent(node));\n obj.constructor = CustomData;\n\n return obj;\n };\n mxCodecRegistry.register(codec);\n }\n}\n\nexport default JsonData;\n", + "Wrapping": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\n\nclass Wrapping extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Wrapping

\n This example demonstrates using HTML markup and word-wrapping in vertex\n and edge labels.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables HTML labels as wrapping is only available for those\n graph.setHtmlLabels(true);\n\n // Disables in-place editing for edges\n graph.isCellEditable = function(cell) {\n return !this.model.isEdge(cell);\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n 20,\n 20,\n 100,\n 70,\n 'whiteSpace=wrap;'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n 220,\n 150,\n 80,\n 70,\n 'whiteSpace=wrap;'\n );\n const e1 = graph.insertEdge(\n parent,\n null,\n 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n v1,\n v2,\n 'whiteSpace=wrap;'\n );\n e1.geometry.width = 100;\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Wrapping;\n", + "Stencils": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxStencilRegistry from '../mxgraph/shape/mxStencilRegistry';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\nimport mxShape from '../mxgraph/shape/mxShape';\nimport mxVertexHandler from '../mxgraph/handler/mxVertexHandler';\nimport mxCellHighlight from '../mxgraph/handler/mxCellHighlight';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxStencil from '../mxgraph/shape/mxStencil';\n\nclass Stencils extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Stencils

\n This example demonstrates using an XML file to define new stencils to be\n used as shapes. See docs/stencils.xsd for the XML schema file.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '401px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n width: '601px',\n height: '150px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Sets the global shadow color\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n mxConstants.SHADOW_OPACITY = 0.5;\n mxConstants.SHADOW_OFFSET_X = 4;\n mxConstants.SHADOW_OFFSET_Y = 4;\n mxConstants.HANDLE_FILLCOLOR = '#99ccff';\n mxConstants.HANDLE_STROKECOLOR = '#0088cf';\n mxConstants.VERTEX_SELECTION_COLOR = '#00a8ff';\n\n // Enables connections along the outline\n mxConnectionHandler.prototype.outlineConnect = true;\n mxEdgeHandler.prototype.manageLabelHandle = true;\n mxEdgeHandler.prototype.outlineConnect = true;\n mxCellHighlight.prototype.keepOnTop = true;\n\n // Enable rotation handle\n mxVertexHandler.prototype.rotationEnabled = true;\n\n // Uses the shape for resize previews\n mxVertexHandler.prototype.createSelectionShape = function(bounds) {\n const key = this.state.style[mxConstants.STYLE_SHAPE];\n const stencil = mxStencilRegistry.getStencil(key);\n let shape = null;\n\n if (stencil != null) {\n shape = new mxShape(stencil);\n shape.apply(this.state);\n } else {\n shape = new this.state.shape.constructor();\n }\n\n shape.outline = true;\n shape.bounds = bounds;\n shape.stroke = mxConstants.HANDLE_STROKECOLOR;\n shape.strokewidth = this.getSelectionStrokeWidth();\n shape.isDashed = this.isSelectionDashed();\n shape.isShadow = false;\n\n return shape;\n };\n\n // Defines a custom stencil via the canvas API as defined here:\n // http://jgraph.github.io/mxgraph/docs/js-api/files/util/mxXmlCanvas2D-js.html\n\n class CustomShape extends mxShape {\n paintBackground(c, x, y, w, h) {\n c.translate(x, y);\n\n // Head\n c.ellipse(w / 4, 0, w / 2, h / 4);\n c.fillAndStroke();\n\n c.begin();\n c.moveTo(w / 2, h / 4);\n c.lineTo(w / 2, (2 * h) / 3);\n\n // Arms\n c.moveTo(w / 2, h / 3);\n c.lineTo(0, h / 3);\n c.moveTo(w / 2, h / 3);\n c.lineTo(w, h / 3);\n\n // Legs\n c.moveTo(w / 2, (2 * h) / 3);\n c.lineTo(0, h);\n c.moveTo(w / 2, (2 * h) / 3);\n c.lineTo(w, h);\n c.end();\n\n c.stroke();\n }\n }\n\n // Replaces existing actor shape\n mxCellRenderer.registerShape('customShape', CustomShape);\n\n // Loads the stencils into the registry\n const req = mxUtils.load('stencils.xml');\n const root = req.getDocumentElement();\n let shape = root.firstChild;\n\n while (shape != null) {\n if (shape.nodeType === mxConstants.NODETYPE_ELEMENT) {\n mxStencilRegistry.addStencil(\n shape.getAttribute('name'),\n new mxStencil(shape)\n );\n }\n\n shape = shape.nextSibling;\n }\n\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.setTooltips(true);\n graph.setPanning(true);\n\n graph.getTooltipForCell = function(cell) {\n if (cell != null) {\n return cell.style;\n }\n\n return null;\n };\n\n // Changes default styles\n let style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_EDGE] = 'orthogonalEdgeStyle';\n style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_FILLCOLOR] = '#adc5ff';\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#7d85df';\n style[mxConstants.STYLE_SHADOW] = '1';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'A1',\n 20,\n 20,\n 40,\n 80,\n 'shape=and'\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'A2',\n 20,\n 220,\n 40,\n 80,\n 'shape=and'\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'X1',\n 160,\n 110,\n 80,\n 80,\n 'shape=xor'\n );\n const e1 = graph.insertEdge(parent, null, '', v1, v3);\n e1.geometry.points = [new mxPoint(90, 60), new mxPoint(90, 130)];\n const e2 = graph.insertEdge(parent, null, '', v2, v3);\n e2.geometry.points = [new mxPoint(90, 260), new mxPoint(90, 170)];\n\n const v4 = graph.insertVertex(\n parent,\n null,\n 'A3',\n 520,\n 20,\n 40,\n 80,\n 'shape=customShape;flipH=1'\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n 'A4',\n 520,\n 220,\n 40,\n 80,\n 'shape=and;flipH=1'\n );\n const v6 = graph.insertVertex(\n parent,\n null,\n 'X2',\n 340,\n 110,\n 80,\n 80,\n 'shape=xor;flipH=1'\n );\n const e3 = graph.insertEdge(parent, null, '', v4, v6);\n e3.geometry.points = [new mxPoint(490, 60), new mxPoint(130, 130)];\n const e4 = graph.insertEdge(parent, null, '', v5, v6);\n e4.geometry.points = [new mxPoint(490, 260), new mxPoint(130, 170)];\n\n const v7 = graph.insertVertex(\n parent,\n null,\n 'O1',\n 250,\n 260,\n 80,\n 60,\n 'shape=or;direction=south'\n );\n const e5 = graph.insertEdge(parent, null, '', v6, v7);\n e5.geometry.points = [new mxPoint(310, 150)];\n const e6 = graph.insertEdge(parent, null, '', v3, v7);\n e6.geometry.points = [new mxPoint(270, 150)];\n\n const e7 = graph.insertEdge(parent, null, '', v7, v5);\n e7.geometry.points = [new mxPoint(290, 370)];\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n this.el2.appendChild(\n mxUtils.button('FlipH', function() {\n graph.toggleCellStyles(mxConstants.STYLE_FLIPH);\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('FlipV', function() {\n graph.toggleCellStyles(mxConstants.STYLE_FLIPV);\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('Rotate', function() {\n const cell = graph.getSelectionCell();\n\n if (cell != null) {\n let geo = graph.getCellGeometry(cell);\n\n if (geo != null) {\n graph.getModel().beginUpdate();\n try {\n // Rotates the size and position in the geometry\n geo = geo.clone();\n geo.x += geo.width / 2 - geo.height / 2;\n geo.y += geo.height / 2 - geo.width / 2;\n const tmp = geo.width;\n geo.width = geo.height;\n geo.height = tmp;\n graph.getModel().setGeometry(cell, geo);\n\n // Reads the current direction and advances by 90 degrees\n const state = graph.view.getState(cell);\n\n if (state != null) {\n let dir =\n state.style[mxConstants.STYLE_DIRECTION] ||\n 'east'; /* default */\n\n if (dir === 'east') {\n dir = 'south';\n } else if (dir === 'south') {\n dir = 'west';\n } else if (dir === 'west') {\n dir = 'north';\n } else if (dir === 'north') {\n dir = 'east';\n }\n\n graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);\n }\n } finally {\n graph.getModel().endUpdate();\n }\n }\n }\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('And', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'and');\n })\n );\n this.el2.appendChild(\n mxUtils.button('Or', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'or');\n })\n );\n this.el2.appendChild(\n mxUtils.button('Xor', function() {\n graph.setCellStyles(mxConstants.STYLE_SHAPE, 'xor');\n })\n );\n\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n this.el2.appendChild(document.createTextNode('\\u00a0'));\n\n this.el2.appendChild(\n mxUtils.button('Style', function() {\n const cell = graph.getSelectionCell();\n\n if (cell != null) {\n const style = mxUtils.prompt(\n 'Style',\n graph.getModel().getStyle(cell)\n );\n\n if (style != null) {\n graph.getModel().setStyle(cell, style);\n }\n }\n })\n );\n\n this.el2.appendChild(\n mxUtils.button('+', function() {\n graph.zoomIn();\n })\n );\n this.el2.appendChild(\n mxUtils.button('-', function() {\n graph.zoomOut();\n })\n );\n }\n}\n\nexport default Stencils;\n", + "UserObject": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxForm from '../mxgraph/util/mxForm';\nimport mxCellAttributeChange from '../mxgraph/model/atomic_changes/mxCellAttributeChange';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\n\nclass UserObject extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

User object

\n This example demonstrates using XML objects as values for cells.\n \n \n \n {\n this.el = el;\n }}\n style={{\n border: 'solid 1px black',\n overflow: 'hidden',\n height: '241px',\n cursor: 'default',\n }}\n />\n \n \n {\n this.propertiesEl = el;\n }}\n style={{\n border: 'solid 1px black',\n padding: '10px',\n }}\n />\n \n \n \n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Note that these XML nodes will be enclosing the\n // mxCell nodes for the model cells in the output\n const doc = mxUtils.createXmlDocument();\n\n const person1 = doc.createElement('Person');\n person1.setAttribute('firstName', 'Daffy');\n person1.setAttribute('lastName', 'Duck');\n\n const person2 = doc.createElement('Person');\n person2.setAttribute('firstName', 'Bugs');\n person2.setAttribute('lastName', 'Bunny');\n\n const relation = doc.createElement('Knows');\n relation.setAttribute('since', '1985');\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Optional disabling of sizing\n graph.setCellsResizable(false);\n\n // Configures the graph contains to resize and\n // add a border at the bottom, right\n graph.setResizeContainer(true);\n graph.minimumContainerSize = new mxRectangle(0, 0, 500, 380);\n graph.setBorder(60);\n\n // Stops editing on enter key, handles escape\n new mxKeyHandler(graph);\n\n // Overrides method to disallow edge label editing\n graph.isCellEditable = function(cell) {\n return !this.getModel().isEdge(cell);\n };\n\n // Overrides method to provide a cell label in the display\n graph.convertValueToString = function(cell) {\n if (mxUtils.isNode(cell.value)) {\n if (cell.value.nodeName.toLowerCase() == 'person') {\n const firstName = cell.getAttribute('firstName', '');\n const lastName = cell.getAttribute('lastName', '');\n\n if (lastName != null && lastName.length > 0) {\n return `${lastName}, ${firstName}`;\n }\n\n return firstName;\n }\n if (cell.value.nodeName.toLowerCase() == 'knows') {\n return `${cell.value.nodeName} (Since ${cell.getAttribute(\n 'since',\n ''\n )})`;\n }\n }\n\n return '';\n };\n\n // Overrides method to store a cell label in the model\n const { cellLabelChanged } = graph;\n graph.cellLabelChanged = function(cell, newValue, autoSize) {\n if (\n mxUtils.isNode(cell.value) &&\n cell.value.nodeName.toLowerCase() == 'person'\n ) {\n const pos = newValue.indexOf(' ');\n\n const firstName = pos > 0 ? newValue.substring(0, pos) : newValue;\n const lastName =\n pos > 0 ? newValue.substring(pos + 1, newValue.length) : '';\n\n // Clones the value for correct undo/redo\n const elt = cell.value.cloneNode(true);\n\n elt.setAttribute('firstName', firstName);\n elt.setAttribute('lastName', lastName);\n\n newValue = elt;\n autoSize = true;\n }\n\n cellLabelChanged.apply(this, arguments);\n };\n\n // Overrides method to create the editing value\n const { getEditingValue } = graph;\n graph.getEditingValue = function(cell) {\n if (\n mxUtils.isNode(cell.value) &&\n cell.value.nodeName.toLowerCase() == 'person'\n ) {\n const firstName = cell.getAttribute('firstName', '');\n const lastName = cell.getAttribute('lastName', '');\n\n return `${firstName} ${lastName}`;\n }\n };\n\n // Adds a special tooltip for edges\n graph.setTooltips(true);\n\n const { getTooltipForCell } = graph;\n graph.getTooltipForCell = function(cell) {\n // Adds some relation details for edges\n if (graph.getModel().isEdge(cell)) {\n const src = this.getLabel(this.getModel().getTerminal(cell, true));\n const trg = this.getLabel(this.getModel().getTerminal(cell, false));\n\n return `${src} ${cell.value.nodeName} ${trg}`;\n }\n\n return getTooltipForCell.apply(this, arguments);\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Adds an option to view the XML of the graph\n this.el2.appendChild(\n mxUtils.button('View XML', function() {\n const encoder = new mxCodec();\n const node = encoder.encode(graph.getModel());\n mxUtils.popup(mxUtils.getPrettyXml(node), true);\n })\n );\n\n // Changes the style for match the markup\n // Creates the default style for vertices\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_STROKECOLOR] = 'gray';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_SHADOW] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#DFDFDF';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_SPACING] = 4;\n\n // Creates the default style for edges\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_STROKECOLOR] = '#0C0C0C';\n style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = 'white';\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_FONTSIZE] = '10';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, person1, 40, 40, 80, 30);\n const v2 = graph.insertVertex(parent, null, person2, 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, relation, v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Implements a properties panel that uses\n // mxCellAttributeChange to change properties\n graph\n .getSelectionModel()\n .addListener(mxEvent.CHANGE, function(sender, evt) {\n this.selectionChanged(graph);\n });\n\n this.selectionChanged(graph);\n }\n\n /**\n * Updates the properties panel\n */\n selectionChanged(graph) {\n const div = this.propertiesEl;\n\n // Forces focusout in IE\n graph.container.focus();\n\n // Clears the DIV the non-DOM way\n div.innerHTML = '';\n\n // Gets the selection cell\n const cell = graph.getSelectionCell();\n\n if (cell == null) {\n mxUtils.writeln(div, 'Nothing selected.');\n } else {\n // Writes the title\n const center = document.createElement('center');\n mxUtils.writeln(center, `${cell.value.nodeName} (${cell.id})`);\n div.appendChild(center);\n mxUtils.br(div);\n\n // Creates the form from the attributes of the user object\n const form = new mxForm();\n\n const attrs = cell.value.attributes;\n\n for (let i = 0; i < attrs.length; i++) {\n this.createTextField(graph, form, cell, attrs[i]);\n }\n\n div.appendChild(form.getTable());\n mxUtils.br(div);\n }\n }\n\n /**\n * Creates the textfield for the given property.\n */\n createTextField(graph, form, cell, attribute) {\n const input = form.addText(`${attribute.nodeName}:`, attribute.nodeValue);\n\n const applyHandler = function() {\n const newValue = input.value || '';\n const oldValue = cell.getAttribute(attribute.nodeName, '');\n\n if (newValue != oldValue) {\n graph.getModel().beginUpdate();\n\n try {\n const edit = new mxCellAttributeChange(\n cell,\n attribute.nodeName,\n newValue\n );\n graph.getModel().execute(edit);\n graph.updateCellSize(cell);\n } finally {\n graph.getModel().endUpdate();\n }\n }\n };\n\n mxEvent.addListener(input, 'keypress', function(evt) {\n // Needs to take shift into account for textareas\n if (evt.keyCode == /* enter */ 13 && !mxEvent.isShiftDown(evt)) {\n input.blur();\n }\n });\n\n // Note: Known problem is the blurring of fields in\n // Firefox by changing the selection, in which case\n // no event is fired in FF and the change is lost.\n // As a workaround you should use a local variable\n // that stores the focused field and invoke blur\n // explicitely where we do the graph.focus above.\n mxEvent.addListener(input, 'blur', applyHandler);\n }\n}\n\nexport default UserObject;\n", + "Merge": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\n\nclass Merge extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Merge

\n This example demonstrates using the mergeChildren function to merge two\n graphs.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '280px',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n mxConstants.SHADOWCOLOR = '#c0c0c0';\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // No size handles, please...\n graph.setCellsResizable(false);\n\n // Makes all cells round with a white, bold label\n let style = graph.stylesheet.getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_FONTCOLOR] = 'white';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;\n style[mxConstants.STYLE_FONTSIZE] = 14;\n style[mxConstants.STYLE_SHADOW] = true;\n\n // Makes all edge labels gray with a white background\n style = graph.stylesheet.getDefaultEdgeStyle();\n style[mxConstants.STYLE_FONTCOLOR] = 'gray';\n style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;\n style[mxConstants.STYLE_FONTCOLOR] = 'black';\n style[mxConstants.STYLE_STROKEWIDTH] = 2;\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the target model in a single step\n // using custom ids for the vertices and edges\n const w = 40;\n const h = 40;\n\n graph.getModel().beginUpdate();\n try {\n const a = graph.insertVertex(\n parent,\n 'a',\n 'A',\n 20,\n 20,\n w,\n h,\n 'fillColor=blue'\n );\n const b = graph.insertVertex(\n parent,\n 'b',\n 'B',\n 20,\n 200,\n w,\n h,\n 'fillColor=blue'\n );\n const c = graph.insertVertex(\n parent,\n 'c',\n 'C',\n 200,\n 20,\n w,\n h,\n 'fillColor=red'\n );\n const d = graph.insertVertex(\n parent,\n 'd',\n 'D',\n 200,\n 200,\n w,\n h,\n 'fillColor=red'\n );\n const ac = graph.insertEdge(\n parent,\n 'ac',\n 'ac',\n a,\n c,\n 'strokeColor=blue;verticalAlign=bottom'\n );\n const ad = graph.insertEdge(\n parent,\n 'ad',\n 'ad',\n a,\n d,\n 'strokeColor=blue;align=left;verticalAlign=bottom'\n );\n const bd = graph.insertEdge(\n parent,\n 'bd',\n 'bd',\n b,\n d,\n 'strokeColor=blue;verticalAlign=bottom'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Creates the second graph model (without a container)\n const graph2 = new mxGraph();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent2 = graph2.getDefaultParent();\n\n // Adds cells to the target model in a single step\n // using custom ids for the vertices\n graph2.getModel().beginUpdate();\n try {\n const c = graph2.insertVertex(\n parent2,\n 'c',\n 'C',\n 200,\n 20,\n w,\n h,\n 'fillColor=green'\n );\n const d = graph2.insertVertex(\n parent2,\n 'd',\n 'D',\n 200,\n 200,\n w,\n h,\n 'fillColor=green'\n );\n const e = graph2.insertVertex(\n parent2,\n 'e',\n 'E',\n 400,\n 20,\n w,\n h,\n 'fillColor=green'\n );\n const f = graph2.insertVertex(\n parent2,\n 'f',\n 'F',\n 400,\n 200,\n w,\n h,\n 'fillColor=green'\n );\n const ce = graph2.insertEdge(\n parent2,\n 'ce',\n 'ce',\n c,\n e,\n 'strokeColor=green;verticalAlign=bottom'\n );\n const ed = graph2.insertEdge(\n parent2,\n 'ed',\n 'ed',\n e,\n d,\n 'strokeColor=green;align=right;verticalAlign=bottom'\n );\n const fd = graph2.insertEdge(\n parent2,\n 'bd',\n 'fd',\n f,\n d,\n 'strokeColor=green;verticalAlign=bottom'\n );\n } finally {\n // Updates the display\n graph2.getModel().endUpdate();\n }\n\n // Merges the model from the second graph into the model of\n // the first graph. Note: If you add a false to the parameter\n // list then _not_ all edges will be cloned, that is, the\n // edges are assumed to have an identity, and hence the edge\n // \"bd\" will be changed to point from f to d, as specified in\n // the edge for the same id in the second graph.\n graph.getModel().mergeChildren(parent2, parent /* , false */);\n }\n}\n\nexport default Merge;\n", + "OrgChart": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n\n Orgchart. This example demonstrates using\n automatic layouts, fit to page zoom and poster print (across\n multiple pages).\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxPrintPreview from '../mxgraph/view/mxPrintPreview';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxWindow from '../mxgraph/util/mxWindow';\nimport mxToolbar from '../mxgraph/util/mxToolbar';\nimport mxLayoutManager from '../mxgraph/view/mxLayoutManager';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxCompactTreeLayout from '../mxgraph/layout/mxCompactTreeLayout';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\nimport mxClient from '../mxgraph/mxClient';\nimport mxOutline from '../mxgraph/view/mxOutline';\n\nclass OrgChart extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Orgchart

\n {\n this.el = el;\n }}\n style={{\n zIndex: 1,\n position: 'relative',\n overflow: 'hidden',\n height: '50vh',\n background: 'transparent',\n borderStyle: 'solid',\n borderColor: 'lightgray',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Makes the shadow brighter\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n\n // Workaround for Internet Explorer ignoring certain styles\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.overflow = 'hidden';\n container.style.left = '0px';\n container.style.top = '0px';\n container.style.right = '0px';\n container.style.bottom = '0px';\n\n const outline = document.getElementById('outlineContainer');\n\n mxEvent.disableContextMenu(container);\n\n // Sets a gradient background\n if (mxClient.IS_GC || mxClient.IS_SF) {\n container.style.background =\n '-webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFFFFF), to(#E7E7E7))';\n } else if (mxClient.IS_NS) {\n container.style.background =\n '-moz-linear-gradient(top, #FFFFFF, #E7E7E7)';\n }\n\n this.el.appendChild(container);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(container);\n\n // Enables automatic sizing for vertices after editing and\n // panning by using the left mouse button.\n graph.setCellsMovable(false);\n graph.setAutoSizeCells(true);\n graph.setPanning(true);\n graph.centerZoom = false;\n graph.panningHandler.useLeftButtonForPanning = true;\n\n // Displays a popupmenu when the user clicks\n // on a cell (using the left mouse button) but\n // do not select the cell when the popup menu\n // is displayed\n graph.panningHandler.popupMenuHandler = false;\n\n // Creates the outline (navigator, overview) for moving\n // around the graph in the top, right corner of the window.\n const outln = new mxOutline(graph, outline);\n\n // Disables tooltips on touch devices\n graph.setTooltips(!mxClient.IS_TOUCH);\n\n // Set some stylesheet options for the visual appearance of vertices\n let style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'label';\n\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_SPACING_LEFT] = 54;\n\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#7d85df';\n style[mxConstants.STYLE_STROKECOLOR] = '#5d65df';\n style[mxConstants.STYLE_FILLCOLOR] = '#adc5ff';\n\n style[mxConstants.STYLE_FONTCOLOR] = '#1d258f';\n style[mxConstants.STYLE_FONTFAMILY] = 'Verdana';\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = '1';\n\n style[mxConstants.STYLE_SHADOW] = '1';\n style[mxConstants.STYLE_ROUNDED] = '1';\n style[mxConstants.STYLE_GLASS] = '1';\n\n style[mxConstants.STYLE_IMAGE] = 'editors/images/dude3.png';\n style[mxConstants.STYLE_IMAGE_WIDTH] = '48';\n style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';\n style[mxConstants.STYLE_SPACING] = 8;\n\n // Sets the default style for edges\n style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_STROKEWIDTH] = 3;\n style[mxConstants.STYLE_EXIT_X] = 0.5; // center\n style[mxConstants.STYLE_EXIT_Y] = 1.0; // bottom\n style[mxConstants.STYLE_EXIT_PERIMETER] = 0; // disabled\n style[mxConstants.STYLE_ENTRY_X] = 0.5; // center\n style[mxConstants.STYLE_ENTRY_Y] = 0; // top\n style[mxConstants.STYLE_ENTRY_PERIMETER] = 0; // disabled\n\n // Disable the following for straight lines\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;\n\n // Stops editing on enter or escape keypress\n const keyHandler = new mxKeyHandler(graph);\n\n // Enables automatic layout on the graph and installs\n // a tree layout for all groups who's children are\n // being changed, added or removed.\n const layout = new mxCompactTreeLayout(graph, false);\n layout.useBoundingBox = false;\n layout.edgeRouting = false;\n layout.levelDistance = 60;\n layout.nodeDistance = 16;\n\n // Allows the layout to move cells even though cells\n // aren't movable in the graph\n layout.isVertexMovable = function(cell) {\n return true;\n };\n\n const layoutMgr = new mxLayoutManager(graph);\n\n layoutMgr.getLayout = function(cell) {\n if (cell.getChildCount() > 0) {\n return layout;\n }\n };\n\n // Installs a popupmenu handler using local function (see below).\n graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {\n return createPopupMenu(graph, menu, cell, evt);\n };\n\n // Fix for wrong preferred size\n const oldGetPreferredSizeForCell = graph.getPreferredSizeForCell;\n graph.getPreferredSizeForCell = function(cell) {\n const result = oldGetPreferredSizeForCell.apply(this, arguments);\n\n if (result != null) {\n result.width = Math.max(120, result.width - 40);\n }\n\n return result;\n };\n\n // Sets the maximum text scale to 1\n graph.cellRenderer.getTextScale = function(state) {\n return Math.min(1, state.view.scale);\n };\n\n // Dynamically adds text to the label as we zoom in\n // (without affecting the preferred size for new cells)\n graph.cellRenderer.getLabelValue = function(state) {\n let result = state.cell.value;\n\n if (state.view.graph.getModel().isVertex(state.cell)) {\n if (state.view.scale > 1) {\n result += '\\nDetails 1';\n }\n\n if (state.view.scale > 1.3) {\n result += '\\nDetails 2';\n }\n }\n\n return result;\n };\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds the root vertex of the tree\n graph.getModel().beginUpdate();\n try {\n const w = graph.container.offsetWidth;\n const v1 = graph.insertVertex(\n parent,\n 'treeRoot',\n 'Organization',\n w / 2 - 30,\n 20,\n 140,\n 60,\n 'image=editors/images/house.png'\n );\n graph.updateCellSize(v1);\n addOverlays(graph, v1, false);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const content = document.createElement('div');\n content.style.padding = '4px';\n this.el2.appendChild(content);\n const tb = new mxToolbar(content);\n\n tb.addItem('Zoom In', 'images/zoom_in32.png', function(evt) {\n graph.zoomIn();\n });\n\n tb.addItem('Zoom Out', 'images/zoom_out32.png', function(evt) {\n graph.zoomOut();\n });\n\n tb.addItem('Actual Size', 'images/view_1_132.png', function(evt) {\n graph.zoomActual();\n });\n\n tb.addItem('Print', 'images/print32.png', function(evt) {\n const preview = new mxPrintPreview(graph, 1);\n preview.open();\n });\n\n tb.addItem('Poster Print', 'images/press32.png', function(evt) {\n const pageCount = mxUtils.prompt('Enter maximum page count', '1');\n\n if (pageCount != null) {\n const scale = mxUtils.getScaleForPageCount(pageCount, graph);\n const preview = new mxPrintPreview(graph, scale);\n preview.open();\n }\n });\n\n // Function to create the entries in the popupmenu\n function createPopupMenu(graph, menu, cell, evt) {\n const model = graph.getModel();\n\n if (cell != null) {\n if (model.isVertex(cell)) {\n menu.addItem(\n 'Add child',\n 'editors/images/overlays/check.png',\n function() {\n addChild(graph, cell);\n }\n );\n }\n\n menu.addItem('Edit label', 'editors/images/text.gif', function() {\n graph.startEditingAtCell(cell);\n });\n\n if (cell.id != 'treeRoot' && model.isVertex(cell)) {\n menu.addItem('Delete', 'editors/images/delete.gif', function() {\n deleteSubtree(graph, cell);\n });\n }\n\n menu.addSeparator();\n }\n\n menu.addItem('Fit', 'editors/images/zoom.gif', function() {\n graph.fit();\n });\n\n menu.addItem('Actual', 'editors/images/zoomactual.gif', function() {\n graph.zoomActual();\n });\n\n menu.addSeparator();\n\n menu.addItem('Print', 'editors/images/print.gif', function() {\n const preview = new mxPrintPreview(graph, 1);\n preview.open();\n });\n\n menu.addItem('Poster Print', 'editors/images/print.gif', function() {\n const pageCount = mxUtils.prompt('Enter maximum page count', '1');\n\n if (pageCount != null) {\n const scale = mxUtils.getScaleForPageCount(pageCount, graph);\n const preview = new mxPrintPreview(graph, scale);\n preview.open();\n }\n });\n }\n\n function addOverlays(graph, cell, addDeleteIcon) {\n let overlay = new mxCellOverlay(\n new mxImage('images/add.png', 24, 24),\n 'Add child'\n );\n overlay.cursor = 'hand';\n overlay.align = mxConstants.ALIGN_CENTER;\n overlay.addListener(\n mxEvent.CLICK,\n mxUtils.bind(this, function(sender, evt) {\n addChild(graph, cell);\n })\n );\n\n graph.addCellOverlay(cell, overlay);\n\n if (addDeleteIcon) {\n overlay = new mxCellOverlay(\n new mxImage('images/close.png', 30, 30),\n 'Delete'\n );\n overlay.cursor = 'hand';\n overlay.offset = new mxPoint(-4, 8);\n overlay.align = mxConstants.ALIGN_RIGHT;\n overlay.verticalAlign = mxConstants.ALIGN_TOP;\n overlay.addListener(\n mxEvent.CLICK,\n mxUtils.bind(this, function(sender, evt) {\n deleteSubtree(graph, cell);\n })\n );\n\n graph.addCellOverlay(cell, overlay);\n }\n }\n\n function addChild(graph, cell) {\n const model = graph.getModel();\n const parent = graph.getDefaultParent();\n let vertex;\n\n model.beginUpdate();\n try {\n vertex = graph.insertVertex(parent, null, 'Double click to set name');\n const geometry = model.getGeometry(vertex);\n\n // Updates the geometry of the vertex with the\n // preferred size computed in the graph\n const size = graph.getPreferredSizeForCell(vertex);\n geometry.width = size.width;\n geometry.height = size.height;\n\n // Adds the edge between the existing cell\n // and the new vertex and executes the\n // automatic layout on the parent\n const edge = graph.insertEdge(parent, null, '', cell, vertex);\n\n // Configures the edge label \"in-place\" to reside\n // at the end of the edge (x = 1) and with an offset\n // of 20 pixels in negative, vertical direction.\n edge.geometry.x = 1;\n edge.geometry.y = 0;\n edge.geometry.offset = new mxPoint(0, -20);\n\n addOverlays(graph, vertex, true);\n } finally {\n model.endUpdate();\n }\n\n return vertex;\n }\n\n function deleteSubtree(graph, cell) {\n // Gets the subtree from cell downwards\n const cells = [];\n graph.traverse(cell, true, function(vertex) {\n cells.push(vertex);\n\n return true;\n });\n\n graph.removeCells(cells);\n }\n }\n}\n\nexport default OrgChart;\n", + "Visibility": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\n\nclass Visibility extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Visibility

\n This example demonstrates using various solutions for hiding and showing\n cells.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n {\n this.el2 = el;\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n let showOne = true;\n let showTwo = true;\n let showThree = true;\n\n // Overridden to implement dynamic conditions\n graph.isCellVisible = function(cell) {\n let result = mxGraph.prototype.isCellVisible.apply(this, arguments);\n\n if (result && cell.value != null) {\n result =\n (showOne && cell.value == '1') ||\n (showTwo && cell.value == '2') ||\n (showThree && cell.value == '3');\n }\n\n return result;\n };\n\n // Adds cells to the model in a single step\n let v1;\n graph.getModel().beginUpdate();\n try {\n v1 = graph.insertVertex(parent, null, '1', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, '2', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '3', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Dynamic conditions (requires refresh)\n this.el2.appendChild(\n mxUtils.button('Cond 1', function() {\n showOne = !showOne;\n graph.refresh();\n })\n );\n this.el2.appendChild(\n mxUtils.button('Cond 2', function() {\n showTwo = !showTwo;\n graph.refresh();\n })\n );\n this.el2.appendChild(\n mxUtils.button('Cond 3', function() {\n showThree = !showThree;\n graph.refresh();\n })\n );\n\n // Explicit show/hide\n this.el2.appendChild(\n mxUtils.button('Toggle cell', function() {\n graph.toggleCells(!graph.getModel().isVisible(v1), [v1], true);\n })\n );\n\n // Explicit remove/add\n let removed = null;\n\n this.el2.appendChild(\n mxUtils.button('Add/remove cell', function() {\n if (removed != null) {\n graph.addCells(removed);\n removed = null;\n } else {\n removed = graph.removeCells([v1]);\n }\n })\n );\n }\n}\n\nexport default Visibility;\n", + "Shape": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCylinder from '../mxgraph/shape/mxCylinder';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\n\nclass Shape extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Shape

\n This example demonstrates how to implement and use a custom shape.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n }}\n />\n \n );\n }\n\n componentDidMount() {\n /*\n The example shape is a \"3D box\" that looks like this:\n ____\n / /|\n /___/ |\n | | /\n |___|/\n\n The code below defines the shape. The BoxShape function\n it the constructor which creates a new object instance.\n \n The next lines use an mxCylinder instance to augment the\n prototype of the shape (\"inheritance\") and reset the\n constructor to the topmost function of the c'tor chain.\n */\n\n class BoxShape extends mxCylinder {\n // Defines the extrusion of the box as a \"static class variable\"\n extrude = 10;\n\n /*\n Next, the mxCylinder's redrawPath method is \"overridden\".\n This method has a isForeground argument to separate two\n paths, one for the background (which must be closed and\n might be filled) and one for the foreground, which is\n just a stroke.\n\n Foreground: /\n _____/\n |\n |\n ____\n Background: / |\n / |\n | /\n |____/\n */\n redrawPath(path, x, y, w, h, isForeground) {\n const dy = this.extrude * this.scale;\n const dx = this.extrude * this.scale;\n\n if (isForeground) {\n path.moveTo(0, dy);\n path.lineTo(w - dx, dy);\n path.lineTo(w, 0);\n path.moveTo(w - dx, dy);\n path.lineTo(w - dx, h);\n } else {\n path.moveTo(0, dy);\n path.lineTo(dx, 0);\n path.lineTo(w, 0);\n path.lineTo(w, h - dy);\n path.lineTo(w - dx, h);\n path.lineTo(0, h);\n path.lineTo(0, dy);\n path.lineTo(dx, 0);\n path.close();\n }\n }\n }\n mxCellRenderer.registerShape('box', BoxShape);\n\n // Creates the graph inside the DOM node.\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Changes the default style for vertices \"in-place\"\n // to use the custom shape.\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = 'box';\n\n // Adds a spacing for the label that matches the\n // extrusion size\n style[mxConstants.STYLE_SPACING_TOP] = BoxShape.prototype.extrude;\n style[mxConstants.STYLE_SPACING_RIGHT] = BoxShape.prototype.extrude;\n\n // Adds a gradient and shadow to improve the user experience\n style[mxConstants.STYLE_GRADIENTCOLOR] = '#FFFFFF';\n style[mxConstants.STYLE_SHADOW] = true;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Custom', 20, 20, 80, 60);\n const v2 = graph.insertVertex(parent, null, 'Shape', 200, 150, 80, 60);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Shape;\n", + "Images": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\n\nclass Images extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Images

\n This example demonstrates using background images and images for for the\n label- and image-shape.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '200px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Sets a background image and restricts child movement to its bounds\n graph.setBackgroundImage(\n new mxImage('images/gradient_background.jpg', 360, 200)\n );\n graph.maximumGraphBounds = new mxRectangle(0, 0, 360, 200);\n\n // Resizes the container but never make it bigger than the background\n graph.minimumContainerSize = new mxRectangle(0, 0, 360, 200);\n graph.setResizeContainer(true);\n\n // Disables basic selection and cell handling\n // graph.setEnabled(false);\n configureStylesheet(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n var v1 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 20,\n 10,\n 80,\n 100,\n 'bottom'\n );\n var v1 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 130,\n 10,\n 80,\n 100,\n 'top'\n );\n var v1 = graph.insertVertex(parent, null, '', 230, 10, 100, 100, 'image');\n var v2 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 20,\n 130,\n 140,\n 60,\n 'right'\n );\n var v2 = graph.insertVertex(\n parent,\n null,\n 'First Line\\nSecond Line',\n 180,\n 130,\n 140,\n 60,\n 'left'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n function configureStylesheet(graph) {\n let style = {};\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/keys.png';\n style[mxConstants.STYLE_FONTCOLOR] = '#FFFFFF';\n graph.getStylesheet().putCellStyle('image', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL;\n style[mxConstants.STYLE_STROKECOLOR] = '#000000';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/gear.png';\n style[mxConstants.STYLE_IMAGE_WIDTH] = '48';\n style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';\n style[mxConstants.STYLE_SPACING_TOP] = '56';\n style[mxConstants.STYLE_SPACING] = '8';\n graph.getStylesheet().putCellStyle('bottom', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_BOTTOM;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/server.png';\n delete style[mxConstants.STYLE_SPACING_TOP];\n graph.getStylesheet().putCellStyle('top', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_LEFT;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_IMAGE] = 'images/icons48/earth.png';\n style[mxConstants.STYLE_SPACING_LEFT] = '55';\n style[mxConstants.STYLE_SPACING] = '4';\n graph.getStylesheet().putCellStyle('right', style);\n\n style = mxUtils.clone(style);\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_RIGHT;\n style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_RIGHT;\n delete style[mxConstants.STYLE_SPACING_LEFT];\n style[mxConstants.STYLE_SPACING_RIGHT] = '55';\n graph.getStylesheet().putCellStyle('left', style);\n }\n }\n}\n\nexport default Images;\n", + "Stylesheet": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\n\nclass Stylesheet extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Stylesheet

\n This example demonstrates using a custom stylesheet and control points\n in edges, as well as overriding the getLabel and getTooltip function to\n return dynamic information, and making a supercall in JavaScript.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '311px',\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Creates the graph inside the DOM node.\n const graph = new mxGraph(this.el);\n\n // Disables basic selection and cell handling\n graph.setEnabled(false);\n\n // Returns a special label for edges. Note: This does\n // a supercall to use the default implementation.\n graph.getLabel = function(cell) {\n const label = mxGraph.prototype.getLabel.apply(this, arguments);\n\n if (this.getModel().isEdge(cell)) {\n return `Transfer ${label}`;\n }\n return label;\n };\n\n // Installs a custom global tooltip\n graph.setTooltips(true);\n graph.getTooltip = function(state) {\n const { cell } = state;\n const model = this.getModel();\n\n if (model.isEdge(cell)) {\n const source = this.getLabel(model.getTerminal(cell, true));\n const target = this.getLabel(model.getTerminal(cell, false));\n\n return `${source} -> ${target}`;\n }\n return this.getLabel(cell);\n };\n\n // Creates the default style for vertices\n let style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;\n style[mxConstants.STYLE_STROKECOLOR] = 'gray';\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_FILLCOLOR] = '#EEEEEE';\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n style[mxConstants.STYLE_FONTCOLOR] = '#774400';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_FONTSIZE] = '12';\n style[mxConstants.STYLE_FONTSTYLE] = 1;\n graph.getStylesheet().putDefaultVertexStyle(style);\n\n // Creates the default style for edges\n style = [];\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_CONNECTOR;\n style[mxConstants.STYLE_STROKECOLOR] = '#6482B9';\n style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;\n style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;\n style[mxConstants.STYLE_FONTSIZE] = '10';\n graph.getStylesheet().putDefaultEdgeStyle(style);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Interval 1',\n 20,\n 20,\n 180,\n 30\n );\n const v2 = graph.insertVertex(\n parent,\n null,\n 'Interval 2',\n 140,\n 80,\n 280,\n 30\n );\n const v3 = graph.insertVertex(\n parent,\n null,\n 'Interval 3',\n 200,\n 140,\n 360,\n 30\n );\n const v4 = graph.insertVertex(\n parent,\n null,\n 'Interval 4',\n 480,\n 200,\n 120,\n 30\n );\n const v5 = graph.insertVertex(\n parent,\n null,\n 'Interval 5',\n 60,\n 260,\n 400,\n 30\n );\n const e1 = graph.insertEdge(parent, null, '1', v1, v2);\n e1.getGeometry().points = [{ x: 160, y: 60 }];\n const e2 = graph.insertEdge(parent, null, '2', v1, v5);\n e2.getGeometry().points = [{ x: 80, y: 60 }];\n const e3 = graph.insertEdge(parent, null, '3', v2, v3);\n e3.getGeometry().points = [{ x: 280, y: 120 }];\n const e4 = graph.insertEdge(parent, null, '4', v3, v4);\n e4.getGeometry().points = [{ x: 500, y: 180 }];\n const e5 = graph.insertEdge(parent, null, '5', v3, v5);\n e5.getGeometry().points = [{ x: 380, y: 180 }];\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Stylesheet;\n", + "ExtendCanvas": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxPoint from '../mxgraph/util/mxPoint';\n\nclass ExtendCanvas extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Extend canvas

\n This example demonstrates implementing an infinite canvas with\n scrollbars.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'auto',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Disables the built-in context menu\n mxEvent.disableContextMenu(this.el);\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.panningHandler.ignoreCell = true;\n graph.setPanning(true);\n\n /**\n * Specifies the size of the size for \"tiles\" to be used for a graph with\n * scrollbars but no visible background page. A good value is large\n * enough to reduce the number of repaints that is caused for auto-\n * translation, which depends on this value, and small enough to give\n * a small empty buffer around the graph. Default is 400x400.\n */\n graph.scrollTileSize = new mxRectangle(0, 0, 400, 400);\n\n /**\n * Returns the padding for pages in page view with scrollbars.\n */\n graph.getPagePadding = function() {\n return new mxPoint(\n Math.max(0, Math.round(graph.container.offsetWidth - 34)),\n Math.max(0, Math.round(graph.container.offsetHeight - 34))\n );\n };\n\n /**\n * Returns the size of the page format scaled with the page size.\n */\n graph.getPageSize = function() {\n return this.pageVisible\n ? new mxRectangle(\n 0,\n 0,\n this.pageFormat.width * this.pageScale,\n this.pageFormat.height * this.pageScale\n )\n : this.scrollTileSize;\n };\n\n /**\n * Returns a rectangle describing the position and count of the\n * background pages, where x and y are the position of the top,\n * left page and width and height are the vertical and horizontal\n * page count.\n */\n graph.getPageLayout = function() {\n const size = this.pageVisible ? this.getPageSize() : this.scrollTileSize;\n const bounds = this.getGraphBounds();\n\n if (bounds.width === 0 || bounds.height === 0) {\n return new mxRectangle(0, 0, 1, 1);\n }\n\n // Computes untransformed graph bounds\n const x = Math.ceil(bounds.x / this.view.scale - this.view.translate.x);\n const y = Math.ceil(bounds.y / this.view.scale - this.view.translate.y);\n const w = Math.floor(bounds.width / this.view.scale);\n const h = Math.floor(bounds.height / this.view.scale);\n\n const x0 = Math.floor(x / size.width);\n const y0 = Math.floor(y / size.height);\n const w0 = Math.ceil((x + w) / size.width) - x0;\n const h0 = Math.ceil((y + h) / size.height) - y0;\n\n return new mxRectangle(x0, y0, w0, h0);\n };\n\n // Fits the number of background pages to the graph\n graph.view.getBackgroundPageBounds = function() {\n const layout = this.graph.getPageLayout();\n const page = this.graph.getPageSize();\n\n return new mxRectangle(\n this.scale * (this.translate.x + layout.x * page.width),\n this.scale * (this.translate.y + layout.y * page.height),\n this.scale * layout.width * page.width,\n this.scale * layout.height * page.height\n );\n };\n\n graph.getPreferredPageSize = function(bounds, width, height) {\n const pages = this.getPageLayout();\n const size = this.getPageSize();\n\n return new mxRectangle(\n 0,\n 0,\n pages.width * size.width,\n pages.height * size.height\n );\n };\n\n /**\n * Guesses autoTranslate to avoid another repaint (see below).\n * Works if only the scale of the graph changes or if pages\n * are visible and the visible pages do not change.\n */\n const graphViewValidate = graph.view.validate;\n graph.view.validate = function() {\n if (\n this.graph.container != null &&\n mxUtils.hasScrollbars(this.graph.container)\n ) {\n const pad = this.graph.getPagePadding();\n const size = this.graph.getPageSize();\n\n // Updating scrollbars here causes flickering in quirks and is not needed\n // if zoom method is always used to set the current scale on the graph.\n const tx = this.translate.x;\n const ty = this.translate.y;\n this.translate.x = pad.x / this.scale - (this.x0 || 0) * size.width;\n this.translate.y = pad.y / this.scale - (this.y0 || 0) * size.height;\n }\n\n graphViewValidate.apply(this, arguments);\n };\n\n const graphSizeDidChange = graph.sizeDidChange;\n graph.sizeDidChange = function() {\n if (this.container != null && mxUtils.hasScrollbars(this.container)) {\n const pages = this.getPageLayout();\n const pad = this.getPagePadding();\n const size = this.getPageSize();\n\n // Updates the minimum graph size\n const minw = Math.ceil(\n (2 * pad.x) / this.view.scale + pages.width * size.width\n );\n const minh = Math.ceil(\n (2 * pad.y) / this.view.scale + pages.height * size.height\n );\n\n const min = graph.minimumGraphSize;\n\n // LATER: Fix flicker of scrollbar size in IE quirks mode\n // after delayed call in window.resize event handler\n if (min == null || min.width !== minw || min.height !== minh) {\n graph.minimumGraphSize = new mxRectangle(0, 0, minw, minh);\n }\n\n // Updates auto-translate to include padding and graph size\n const dx = pad.x / this.view.scale - pages.x * size.width;\n const dy = pad.y / this.view.scale - pages.y * size.height;\n\n if (\n !this.autoTranslate &&\n (this.view.translate.x !== dx || this.view.translate.y !== dy)\n ) {\n this.autoTranslate = true;\n this.view.x0 = pages.x;\n this.view.y0 = pages.y;\n\n // NOTE: THIS INVOKES THIS METHOD AGAIN. UNFORTUNATELY THERE IS NO WAY AROUND THIS SINCE THE\n // BOUNDS ARE KNOWN AFTER THE VALIDATION AND SETTING THE TRANSLATE TRIGGERS A REVALIDATION.\n // SHOULD MOVE TRANSLATE/SCALE TO VIEW.\n const tx = graph.view.translate.x;\n const ty = graph.view.translate.y;\n\n graph.view.setTranslate(dx, dy);\n graph.container.scrollLeft += (dx - tx) * graph.view.scale;\n graph.container.scrollTop += (dy - ty) * graph.view.scale;\n\n this.autoTranslate = false;\n return;\n }\n\n graphSizeDidChange.apply(this, arguments);\n }\n };\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Sets initial scrollbar positions\n window.setTimeout(function() {\n const bounds = graph.getGraphBounds();\n const width = Math.max(\n bounds.width,\n graph.scrollTileSize.width * graph.view.scale\n );\n const height = Math.max(\n bounds.height,\n graph.scrollTileSize.height * graph.view.scale\n );\n graph.container.scrollTop = Math.floor(\n Math.max(\n 0,\n bounds.y - Math.max(20, (graph.container.clientHeight - height) / 4)\n )\n );\n graph.container.scrollLeft = Math.floor(\n Math.max(\n 0,\n bounds.x - Math.max(0, (graph.container.clientWidth - width) / 2)\n )\n );\n }, 0);\n };\n}\n\nexport default ExtendCanvas;\n", + "DynamicLoading": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxText from '../mxgraph/shape/mxText';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxCodec from '../mxgraph/io/mxCodec';\nimport mxEffects from '../mxgraph/util/mxEffects';\nimport mxPerimeter from '../mxgraph/view/mxPerimeter';\n\nclass DynamicLoading extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dynamic loading

\n This example demonstrates loading graph model data dynamically to limit\n the number of cells in the model.\n {\n this.el = el;\n }}\n style={{\n overflow: 'visible',\n position: 'absolute',\n height: '100%',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n let requestId = 0;\n\n // Speedup the animation\n mxText.prototype.enableBoundingBox = false;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Disables all built-in interactions\n graph.setEnabled(false);\n\n // Handles clicks on cells\n graph.addListener(mxEvent.CLICK, function(sender, evt) {\n const cell = evt.getProperty('cell');\n\n if (cell != null) {\n load(graph, cell);\n }\n });\n\n // Changes the default vertex style in-place\n const style = graph.getStylesheet().getDefaultVertexStyle();\n style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;\n style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;\n style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const cx = graph.container.clientWidth / 2;\n const cy = graph.container.clientHeight / 2;\n\n const cell = graph.insertVertex(\n parent,\n '0-0',\n '0-0',\n cx - 20,\n cy - 15,\n 60,\n 40\n );\n\n // Animates the changes in the graph model\n graph.getModel().addListener(mxEvent.CHANGE, function(sender, evt) {\n const { changes } = evt.getProperty('edit');\n mxEffects.animateChanges(graph, changes);\n });\n\n // Loads the links for the given cell into the given graph\n // by requesting the respective data in the server-side\n // (implemented for this demo using the server-function)\n function load(graph, cell) {\n if (graph.getModel().isVertex(cell)) {\n const cx = graph.container.clientWidth / 2;\n const cy = graph.container.clientHeight / 2;\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const xml = server(cell.id);\n const doc = mxUtils.parseXml(xml);\n const dec = new mxCodec(doc);\n const model = dec.decode(doc.documentElement);\n\n // Removes all cells which are not in the response\n for (var key in graph.getModel().cells) {\n const tmp = graph.getModel().getCell(key);\n\n if (tmp != cell && graph.getModel().isVertex(tmp)) {\n graph.removeCells([tmp]);\n }\n }\n\n // Merges the response model with the client model\n graph.getModel().mergeChildren(model.getRoot().getChildAt(0), parent);\n\n // Moves the given cell to the center\n let geo = graph.getModel().getGeometry(cell);\n\n if (geo != null) {\n geo = geo.clone();\n geo.x = cx - geo.width / 2;\n geo.y = cy - geo.height / 2;\n\n graph.getModel().setGeometry(cell, geo);\n }\n\n // Creates a list of the new vertices, if there is more\n // than the center vertex which might have existed\n // previously, then this needs to be changed to analyze\n // the target model before calling mergeChildren above\n const vertices = [];\n\n for (var key in graph.getModel().cells) {\n const tmp = graph.getModel().getCell(key);\n\n if (tmp != cell && model.isVertex(tmp)) {\n vertices.push(tmp);\n\n // Changes the initial location \"in-place\"\n // to get a nice animation effect from the\n // center to the radius of the circle\n const geo = model.getGeometry(tmp);\n\n if (geo != null) {\n geo.x = cx - geo.width / 2;\n geo.y = cy - geo.height / 2;\n }\n }\n }\n\n // Arranges the response in a circle\n const cellCount = vertices.length;\n const phi = (2 * Math.PI) / cellCount;\n const r = Math.min(\n graph.container.clientWidth / 4,\n graph.container.clientHeight / 4\n );\n\n for (let i = 0; i < cellCount; i++) {\n let geo = graph.getModel().getGeometry(vertices[i]);\n\n if (geo != null) {\n geo = geo.clone();\n geo.x += r * Math.sin(i * phi);\n geo.y += r * Math.cos(i * phi);\n\n graph.getModel().setGeometry(vertices[i], geo);\n }\n }\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n }\n\n // Simulates the existence of a server that can crawl the\n // big graph with a certain depth and create a graph model\n // for the traversed cells, which is then sent to the client\n function server(cellId) {\n // Increments the request ID as a prefix for the cell IDs\n requestId++;\n\n // Creates a local graph with no display\n const graph = new mxGraph();\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v0 = graph.insertVertex(parent, cellId, 'Dummy', 0, 0, 60, 40);\n const cellCount = parseInt(Math.random() * 16) + 4;\n\n // Creates the random links and cells for the response\n for (let i = 0; i < cellCount; i++) {\n const id = `${requestId}-${i}`;\n const v = graph.insertVertex(parent, id, id, 0, 0, 60, 40);\n const e = graph.insertEdge(parent, null, `Link ${i}`, v0, v);\n }\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n const enc = new mxCodec();\n const node = enc.encode(graph.getModel());\n\n return mxUtils.getXml(node);\n }\n\n load(graph, cell);\n };\n}\n\nexport default DynamicLoading;\n", + "AutoLayout": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxClient from '../mxgraph/mxClient';\nimport mxMorphing from '../mxgraph/util/mxMorphing';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxHierarchicalLayout from '../mxgraph/layout/hierarchical/mxHierarchicalLayout';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxCellOverlay from '../mxgraph/view/mxCellOverlay';\nimport mxImage from '../mxgraph/util/mxImage';\nimport mxEventObject from '../mxgraph/util/mxEventObject';\nimport mxCellRenderer from '../mxgraph/view/mxCellRenderer';\n\nclass AutoLayout extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Auto layout

\n This example demonstrates running and animating a layout algorithm after\n every change to a graph.\n {\n this.el = el;\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n height: '641px',\n background: 'url(\"editors/images/grid.gif\")',\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n mxEvent.disableContextMenu(this.el);\n\n class MyCustomCellRenderer extends mxCellRenderer {\n installCellOverlayListeners(state, overlay, shape) {\n super.installCellOverlayListeners(state, overlay, shape);\n\n mxEvent.addListener(\n shape.node,\n mxClient.IS_POINTER ? 'pointerdown' : 'mousedown',\n function(evt) {\n overlay.fireEvent(\n new mxEventObject('pointerdown', 'event', evt, 'state', state)\n );\n }\n );\n\n if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {\n mxEvent.addListener(shape.node, 'touchstart', function(evt) {\n overlay.fireEvent(\n new mxEventObject('pointerdown', 'event', evt, 'state', state)\n );\n });\n }\n }\n }\n\n class MyCustomEdgeHandler extends mxEdgeHandler {\n connect(edge, terminal, isSource, isClone, me) {\n super.connect(edge, terminal, isSource, isClone, me);\n executeLayout();\n }\n }\n\n class MyCustomGraph extends mxGraph {\n createEdgeHandler(state, edgeStyle) {\n return new MyCustomEdgeHandler(state, edgeStyle);\n }\n\n createCellRenderer() {\n return new MyCustomCellRenderer();\n }\n }\n\n // Creates the graph inside the given this.el\n const graph = new MyCustomGraph(this.el);\n graph.setPanning(true);\n graph.panningHandler.useLeftButtonForPanning = true;\n graph.setAllowDanglingEdges(false);\n graph.connectionHandler.select = false;\n graph.view.setTranslate(20, 20);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n const layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);\n const executeLayout = (change, post) => {\n graph.getModel().beginUpdate();\n try {\n if (change != null) {\n change();\n }\n layout.execute(graph.getDefaultParent(), v1);\n } catch (e) {\n throw e;\n } finally {\n // New API for animating graph layout results asynchronously\n const morph = new mxMorphing(graph);\n morph.addListener(mxEvent.DONE, () => {\n graph.getModel().endUpdate();\n if (post != null) {\n post();\n }\n });\n morph.startAnimation();\n }\n };\n\n const addOverlay = function(cell) {\n // Creates a new overlay with an image and a tooltip\n const overlay = new mxCellOverlay(\n new mxImage('images/add.png', 24, 24),\n 'Add outgoing'\n );\n overlay.cursor = 'hand';\n\n // Installs a handler for clicks on the overlay\n overlay.addListener(mxEvent.CLICK, function(sender, evt2) {\n graph.clearSelection();\n const geo = graph.getCellGeometry(cell);\n\n let v2;\n\n executeLayout(\n function() {\n v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [geo.x, geo.y],\n size: [80, 30],\n });\n addOverlay(v2);\n graph.view.refresh(v2);\n const e1 = graph.insertEdge({\n parent,\n source: cell,\n target: v2,\n });\n },\n function() {\n graph.scrollCellToVisible(v2);\n }\n );\n });\n\n // Special CMS event\n overlay.addListener('pointerdown', function(sender, eo) {\n const evt2 = eo.getProperty('event');\n const state = eo.getProperty('state');\n\n graph.popupMenuHandler.hideMenu();\n graph.stopEditing(false);\n\n const pt = mxUtils.convertPoint(\n graph.container,\n mxEvent.getClientX(evt2),\n mxEvent.getClientY(evt2)\n );\n graph.connectionHandler.start(state, pt.x, pt.y);\n graph.isMouseDown = true;\n graph.isMouseTrigger = mxEvent.isMouseEvent(evt2);\n mxEvent.consume(evt2);\n });\n\n // Sets the overlay for the cell in the graph\n graph.addCellOverlay(cell, overlay);\n };\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n try {\n v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [0, 0],\n size: [80, 30],\n });\n addOverlay(v1);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n graph.resizeCell = function() {\n mxGraph.prototype.resizeCell.apply(this, arguments);\n executeLayout();\n };\n\n graph.connectionHandler.addListener(mxEvent.CONNECT, function() {\n executeLayout();\n });\n };\n}\n\nexport default AutoLayout;\n", + "FixedIcon": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxLabel from '../mxgraph/shape/mxLabel';\nimport mxRectangle from '../mxgraph/util/mxRectangle';\n\nclass FixedIcon extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Fixed icon

\n This example demonstrates customizing the icon position in the mxLabel\n shape.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n };\n\n componentDidMount = () => {\n // Overrides the image bounds code to change the position\n mxLabel.prototype.getImageBounds = function(x, y, w, h) {\n const iw = mxUtils.getValue(\n this.style,\n mxConstants.STYLE_IMAGE_WIDTH,\n mxConstants.DEFAULT_IMAGESIZE\n );\n const ih = mxUtils.getValue(\n this.style,\n mxConstants.STYLE_IMAGE_HEIGHT,\n mxConstants.DEFAULT_IMAGESIZE\n );\n\n // Places the icon\n const ix = (w - iw) / 2;\n const iy = h - ih;\n\n return new mxRectangle(x + ix, y + iy, iw, ih);\n };\n\n // Makes the shadow brighter\n mxConstants.SHADOWCOLOR = '#C0C0C0';\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(\n parent,\n null,\n 'Fixed icon',\n 20,\n 20,\n 80,\n 50,\n 'shape=label;image=images/plus.png;imageWidth=16;imageHeight=16;spacingBottom=10;' +\n 'fillColor=#adc5ff;gradientColor=#7d85df;glass=1;rounded=1;shadow=1;'\n );\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n };\n}\n\nexport default FixedIcon;\n", + "_app": "import '../styles/globals.css';\nimport '../public/css/common.css';\nimport './Animation.css';\n\nfunction MyApp({ Component, pageProps }) {\n return ;\n}\n\nexport default MyApp;\n", + "Guides": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConstants from '../mxgraph/util/mxConstants';\nimport mxEdgeStyle from '../mxgraph/view/mxEdgeStyle';\nimport mxKeyHandler from '../mxgraph/handler/mxKeyHandler';\n\nclass Guides extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Guides

\n This example demonstrates the guides feature which aligns the current\n selection to the existing vertices in the graph. This feature is in RFC\n state. Creating a grid using a canvas and installing a key handler for\n cursor keys is also demonstrated here, as well as snapping waypoints to\n terminals.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n height: '601px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n\n // Alt disables guides\n mxGraphHandler.prototype.useGuidesForEvent = function(me) {\n return !mxEvent.isAltDown(me.getEvent());\n };\n\n // Defines the guides to be red (default)\n mxConstants.GUIDE_COLOR = '#FF0000';\n\n // Defines the guides to be 1 pixel (default)\n mxConstants.GUIDE_STROKEWIDTH = 1;\n\n // Enables snapping waypoints to terminals\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.setConnectable(true);\n graph.gridSize = 30;\n\n // Changes the default style for edges \"in-place\" and assigns\n // an alternate edge style which is applied in mxGraph.flip\n // when the user double clicks on the adjustment control point\n // of the edge. The ElbowConnector edge style switches to TopToBottom\n // if the horizontal style is true.\n const style = graph.getStylesheet().getDefaultEdgeStyle();\n style[mxConstants.STYLE_ROUNDED] = true;\n style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;\n graph.alternateEdgeStyle = 'elbow=vertical';\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n let v1;\n try {\n v1 = graph.insertVertex(parent, null, 'Hello,', 20, 40, 80, 70);\n const v2 = graph.insertVertex(parent, null, 'World!', 200, 140, 80, 40);\n const e1 = graph.insertEdge(parent, null, '', v1, v2);\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n\n // Handles cursor keys\n const nudge = function(keyCode) {\n if (!graph.isSelectionEmpty()) {\n let dx = 0;\n let dy = 0;\n\n if (keyCode === 37) {\n dx = -1;\n } else if (keyCode === 38) {\n dy = -1;\n } else if (keyCode === 39) {\n dx = 1;\n } else if (keyCode === 40) {\n dy = 1;\n }\n\n graph.moveCells(graph.getSelectionCells(), dx, dy);\n }\n\n // Transfer initial focus to graph container for keystroke handling\n graph.container.focus();\n\n // Handles keystroke events\n const keyHandler = new mxKeyHandler(graph);\n\n // Ignores enter keystroke. Remove this line if you want the\n // enter keystroke to stop editing\n keyHandler.enter = function() {};\n\n keyHandler.bindKey(37, function() {\n nudge(37);\n });\n\n keyHandler.bindKey(38, function() {\n nudge(38);\n });\n\n keyHandler.bindKey(39, function() {\n nudge(39);\n });\n\n keyHandler.bindKey(40, function() {\n nudge(40);\n });\n };\n }\n}\n\nexport default Guides;\n", + "DragSource": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxCell from '../mxgraph/model/mxCell';\nimport mxGeometry from '../mxgraph/model/mxGeometry';\nimport mxUtils from '../mxgraph/util/mxUtils';\nimport mxDragSource from '../mxgraph/util/mxDragSource';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxGuide from '../mxgraph/util/mxGuide';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\n\nclass DragSource extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render = () => {\n // A container for the graph\n return (\n <>\n

Dragsource

\n This example demonstrates using one drag source for multiple graphs and\n changing the drag icon.\n {\n this.el = el;\n }}\n style={{}}\n />\n \n );\n };\n\n componentDidMount = () => {\n class MyCustomGuide extends mxGuide {\n isEnabledForEvent(evt) {\n // Alt disables guides\n return !mxEvent.isAltDown(evt);\n }\n }\n\n class MyCustomGraphHandler extends mxGraphHandler {\n // Enables guides\n guidesEnabled = true;\n\n createGuide() {\n return new MyCustomGuide(this.graph, this.getGuideStates());\n }\n }\n\n class MyCustomEdgeHandler extends mxEdgeHandler {\n // Enables snapping waypoints to terminals\n snapToTerminals = true;\n }\n\n class MyCustomGraph extends mxGraph {\n createGraphHandler() {\n return new MyCustomGraphHandler(this);\n }\n\n createEdgeHandler(state, edgeStyle) {\n return new MyCustomEdgeHandler(state, edgeStyle);\n }\n }\n\n const graphs = [];\n\n // Creates the graph inside the given container\n for (let i = 0; i < 2; i++) {\n const container = document.createElement('div');\n container.style.overflow = 'hidden';\n container.style.position = 'relative';\n container.style.width = '321px';\n container.style.height = '241px';\n container.style.background = \"url('editors/images/grid.gif')\";\n container.style.cursor = 'default';\n\n this.el.appendChild(container);\n\n const graph = new MyCustomGraph(container);\n graph.gridSize = 30;\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n });\n });\n\n graphs.push(graph);\n }\n\n // Returns the graph under the mouse\n const graphF = evt => {\n const x = mxEvent.getClientX(evt);\n const y = mxEvent.getClientY(evt);\n const elt = document.elementFromPoint(x, y);\n\n for (const graph of graphs) {\n if (mxUtils.isAncestorNode(graph.container, elt)) {\n return graph;\n }\n }\n\n return null;\n };\n\n // Inserts a cell at the given location\n const funct = (graph, evt, target, x, y) => {\n const cell = new mxCell('Test', new mxGeometry(0, 0, 120, 40));\n cell.vertex = true;\n const cells = graph.importCells([cell], x, y, target);\n\n if (cells != null && cells.length > 0) {\n graph.scrollCellToVisible(cells[0]);\n graph.setSelectionCells(cells);\n }\n };\n\n // Creates a DOM node that acts as the drag source\n const img = mxUtils.createImage('images/icons48/gear.png');\n img.style.width = '48px';\n img.style.height = '48px';\n this.el.appendChild(img);\n\n // Creates the element that is being for the actual preview.\n const dragElt = document.createElement('div');\n dragElt.style.border = 'dashed black 1px';\n dragElt.style.width = '120px';\n dragElt.style.height = '40px';\n\n // Drag source is configured to use dragElt for preview and as drag icon\n // if scalePreview (last) argument is true. Dx and dy are null to force\n // the use of the defaults. Note that dx and dy are only used for the\n // drag icon but not for the preview.\n const ds = mxUtils.makeDraggable(\n img,\n graphF,\n funct,\n dragElt,\n null,\n null,\n graphs[0].autoscroll,\n true\n );\n\n // Redirects feature to global switch. Note that this feature should only be used\n // if the the x and y arguments are used in funct to insert the cell.\n ds.isGuidesEnabled = () => {\n return graphs[0].graphHandler.guidesEnabled;\n };\n\n // Restores original drag icon while outside of graph\n ds.createDragElement = mxDragSource.prototype.createDragElement;\n };\n\n // NOTE: To enable cross-document DnD (eg. between frames),\n // the following methods need to be overridden:\n /* mxDragSourceMouseUp = mxDragSource.prototype.mouseUp;\nmxDragSource.prototype.mouseUp = function(evt)\n{\n let doc = this.element.ownerDocument;\n\n if (doc != document)\n {\n let mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';\n\n if (this.mouseUpHandler != null)\n {\n mxEvent.removeListener(doc, mu, this.mouseUpHandler);\n }\n }\n\n mxDragSourceMouseUp.apply(this, arguments);\n}; */\n\n /* mxDragSourceMouseDown = mxDragSource.prototype.mouseDown;\nmxDragSource.prototype.mouseDown = function(evt)\n{\n if (this.enabled && !mxEvent.isConsumed(evt))\n {\n mxDragSourceMouseDown.apply(this, arguments);\n let doc = this.element.ownerDocument;\n\n if (doc != document)\n {\n let mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';\n mxEvent.addListener(doc, mu, this.mouseUpHandler);\n }\n }\n}; */\n}\n\nexport default DragSource;\n", + "Orthogonal": "/**\n * Copyright (c) 2006-2013, JGraph Ltd\n * Converted to ES9 syntax/React by David Morrissey 2021\n */\n\nimport React from 'react';\nimport mxEvent from '../mxgraph/util/mxEvent';\nimport mxGraph from '../mxgraph/view/mxGraph';\nimport mxRubberband from '../mxgraph/handler/mxRubberband';\nimport mxGraphHandler from '../mxgraph/handler/mxGraphHandler';\nimport mxGuide from '../mxgraph/util/mxGuide';\nimport mxEdgeHandler from '../mxgraph/handler/mxEdgeHandler';\nimport mxConnectionHandler from '../mxgraph/handler/mxConnectionHandler';\nimport mxGraphView from '../mxgraph/view/mxGraphView';\nimport mxPoint from '../mxgraph/util/mxPoint';\nimport mxCellState from '../mxgraph/view/mxCellState';\n\nclass Orthogonal extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n // A container for the graph\n return (\n <>\n

Orthogonal

\n This example demonstrates the use of port constraints and orthogonal\n edge styles and handlers.\n {\n this.el = el;\n }}\n style={{\n overflow: 'hidden',\n position: 'relative',\n height: '241px',\n background: \"url('editors/images/grid.gif')\",\n cursor: 'default',\n }}\n />\n \n );\n }\n\n componentDidMount() {\n // Enables guides\n mxGraphHandler.prototype.guidesEnabled = true;\n\n // Alt disables guides\n mxGuide.prototype.isEnabledForEvent = function(evt) {\n return !mxEvent.isAltDown(evt);\n };\n\n // Enables snapping waypoints to terminals\n mxEdgeHandler.prototype.snapToTerminals = true;\n\n // Enables orthogonal connect preview in IE\n mxConnectionHandler.prototype.movePreviewAway = false;\n\n // Creates the graph inside the given container\n const graph = new mxGraph(this.el);\n graph.disconnectOnMove = false;\n graph.foldingEnabled = false;\n graph.cellsResizable = false;\n graph.extendParents = false;\n graph.setConnectable(true);\n\n // Implements perimeter-less connection points as fixed points (computed before the edge style).\n graph.view.updateFixedTerminalPoint = function(\n edge,\n terminal,\n source,\n constraint\n ) {\n mxGraphView.prototype.updateFixedTerminalPoint.apply(this, arguments);\n\n const pts = edge.absolutePoints;\n const pt = pts[source ? 0 : pts.length - 1];\n\n if (\n terminal != null &&\n pt == null &&\n this.getPerimeterFunction(terminal) == null\n ) {\n edge.setAbsoluteTerminalPoint(\n new mxPoint(\n this.getRoutingCenterX(terminal),\n this.getRoutingCenterY(terminal)\n ),\n source\n );\n }\n };\n\n // Changes the default edge style\n graph.getStylesheet().getDefaultEdgeStyle().edgeStyle =\n 'orthogonalEdgeStyle';\n delete graph.getStylesheet().getDefaultEdgeStyle().endArrow;\n\n // Implements the connect preview\n graph.connectionHandler.createEdgeState = function(me) {\n const edge = graph.createEdge(null, null, null, null, null);\n\n return new mxCellState(\n this.graph.view,\n edge,\n this.graph.getCellStyle(edge)\n );\n };\n\n // Uncomment the following if you want the container\n // to fit the size of the graph\n // graph.setResizeContainer(true);\n\n // Enables rubberband selection\n new mxRubberband(graph);\n\n // Gets the default parent for inserting new cells. This\n // is normally the first child of the root (ie. layer 0).\n const parent = graph.getDefaultParent();\n\n // Adds cells to the model in a single step\n graph.getModel().beginUpdate();\n try {\n const v1 = graph.insertVertex(parent, null, '', 40, 40, 40, 30);\n v1.setConnectable(false);\n const v11 = graph.insertVertex(\n v1,\n null,\n '',\n 0.5,\n 0,\n 10,\n 40,\n 'portConstraint=northsouth;',\n true\n );\n v11.geometry.offset = new mxPoint(-5, -5);\n const v12 = graph.insertVertex(\n v1,\n null,\n '',\n 0,\n 0.5,\n 10,\n 10,\n 'portConstraint=west;shape=triangle;direction=west;perimeter=none;' +\n 'routingCenterX=-0.5;routingCenterY=0;',\n true\n );\n v12.geometry.offset = new mxPoint(-10, -5);\n const v13 = graph.insertVertex(\n v1,\n null,\n '',\n 1,\n 0.5,\n 10,\n 10,\n 'portConstraint=east;shape=triangle;direction=east;perimeter=none;' +\n 'routingCenterX=0.5;routingCenterY=0;',\n true\n );\n v13.geometry.offset = new mxPoint(0, -5);\n\n const v2 = graph.addCell(graph.getModel().cloneCell(v1));\n v2.geometry.x = 200;\n v2.geometry.y = 60;\n\n const v3 = graph.addCell(graph.getModel().cloneCell(v1));\n v3.geometry.x = 40;\n v3.geometry.y = 150;\n\n const v4 = graph.addCell(graph.getModel().cloneCell(v1));\n v4.geometry.x = 200;\n v4.geometry.y = 170;\n\n graph.insertEdge(parent, null, '', v1.getChildAt(2), v2.getChildAt(1));\n graph.insertEdge(parent, null, '', v2.getChildAt(2), v3.getChildAt(1));\n graph.insertEdge(parent, null, '', v3.getChildAt(2), v4.getChildAt(1));\n } finally {\n // Updates the display\n graph.getModel().endUpdate();\n }\n }\n}\n\nexport default Orthogonal;\n" } \ No newline at end of file