- )}
- >
- );
-}
-
-export default Preview;
diff --git a/src/pages/README.md b/src/pages/README.md
deleted file mode 100644
index 902e70ee8..000000000
--- a/src/pages/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# mxGraph Examples
-
-This directory contains modified examples for mxGraph.
-The original examples can be found at
-https://jgraph.github.io/mxgraph/javascript/index.html.
-
-The main ways in which it differs from the original
-samples are that the examples have been refactored and
-converted to React with templates+logic code separated.
-
-The JavaScript prototypes of mxGraph classes have also been
-replaced with subclasses to not make configuration
-global for other mxGraph configurations on the same page.
-
-## How to View/Run Examples
-
-The examples are grouped by category tabs in the React
-application, which you can view live at
-https://mxgraph-mcyph.vercel.app/ or run locally by
-typing the following:
-
- cd src
- npm install
- npm run dev
-
-From this project's root directory on the command line.
-Note that this next application has a different `package.json`
-and dependencies to the core mxGraph library, whose
-`package.json` is located in the root directory of this
-project.
-
-## Development Status+Plans
-
-Some of the examples are yet to be converted: these can
-be found in the `/docs/stashed` folder.
-
-To add new tabs, go to `PageTabs.js` and add the route
-and text of the tab to the list. Note that the examples
-are served by next.js and the routes correspond to the
-subdirectories, e.g. "/effects" will include
-`/src/pages/effects/index.js`.
-
-To update the source code previews displayed in `Previews.js`
-after modifying the examples, run `python3 copy_examples_to_json.py`.
-
-There are plans to remove the react+next example
-dependencies: see also https://github.com/jsGraph/mxgraph/issues/8
-for the full discussion.
-
diff --git a/src/pages/SourceCodeDisplay.js b/src/pages/SourceCodeDisplay.js
deleted file mode 100644
index eabb9c4cb..000000000
--- a/src/pages/SourceCodeDisplay.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { Component } from 'react';
-import Prism from 'prismjs';
-import 'prismjs/themes/prism-okaidia.css';
-import 'prismjs/components/prism-markup-templating';
-import 'prismjs/components/prism-handlebars.min';
-import 'prismjs/components/prism-jsx.min';
-import 'prismjs/components/prism-javascript.min';
-
-// Adapted from
-// https://betterstack.dev/blog/code-highlighting-in-react-using-prismjs/
-
-export class SourceCodeDisplay extends Component {
- /**
- *
- * @param code
- * @param plugins
- * @param language
- */
- constructor({ code, plugins, language, theme, style }) {
- if (plugins == null) {
- plugins = ['line-numbers', 'show-language'];
- }
- super({ code, plugins, language, theme, style });
- }
-
- render() {
- // TODO: Support theme!!!
- return (
- <>
-
{
- this.el2 = el;
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
- graph.setConnectable(true);
- graph.setTooltips(true);
-
- // Sets the default edge style
- const style = graph.getStylesheet().getDefaultEdgeStyle();
- style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;
-
- // Ports are not used as terminals for edges, they are
- // only used to compute the graphical connection point
- graph.isPort = function(cell) {
- const geo = this.getCellGeometry(cell);
-
- return geo != null ? geo.relative : false;
- };
-
- // Implements a tooltip that shows the actual
- // source and target of an edge
- graph.getTooltipForCell = function(cell) {
- if (cell.isEdge()) {
- return `${this.convertValueToString(
- cell.getTerminal(true)
- )} => ${this.convertValueToString(
- cell.getTerminal(false)
- )}`;
- }
-
- return mxGraph.prototype.getTooltipForCell.apply(this, arguments);
- };
-
- // Removes the folding icon and disables any folding
- graph.isCellFoldable = function(cell) {
- return false;
- };
-
- // 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, 80, 80, 30);
- v1.setConnectable(false);
- const v11 = graph.insertVertex(v1, null, '', 1, 1, 10, 10);
- v11.geometry.offset = new mxPoint(-5, -5);
- v11.geometry.relative = true;
- const v12 = graph.insertVertex(v1, null, '', 1, 0, 10, 10);
- v12.geometry.offset = new mxPoint(-5, -5);
- v12.geometry.relative = true;
- const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
- const v3 = graph.insertVertex(parent, null, 'World2', 200, 20, 80, 30);
- var e1 = graph.insertEdge(parent, null, '', v11, v2);
- var e1 = graph.insertEdge(parent, null, '', v12, v3);
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- const button = mxUtils.button('View XML', function() {
- const encoder = new mxCodec();
- const node = encoder.encode(graph.getModel());
- mxUtils.popup(mxUtils.getPrettyXml(node), true);
- });
-
- this.el2.appendChild(button);
- }
-}
-
-export default HelloPort;
diff --git a/src/pages/connections/PortRefs.js b/src/pages/connections/PortRefs.js
deleted file mode 100644
index 750b5f587..000000000
--- a/src/pages/connections/PortRefs.js
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxConstraintHandler from '../../mxgraph/handler/mxConstraintHandler';
-import mxImage from '../../mxgraph/util/image/mxImage';
-import mxShape from '../../mxgraph/shape/mxShape';
-import mxTriangle from '../../mxgraph/shape/mxTriangle';
-import mxEdgeHandler from '../../mxgraph/handler/mxEdgeHandler';
-import mxConnectionConstraint from '../../mxgraph/view/connection/mxConnectionConstraint';
-import mxPoint from '../../mxgraph/util/datatypes/mxPoint';
-import mxConstants from '../../mxgraph/util/mxConstants';
-
-class PortRefs extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Port References Example
- This example demonstrates referencing connection points by ID. The main
- difference to the implementation where the connection point is stored in
- the connecting edge is that changes to the original port will be
- reflected in all existing connections since they reference that port.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'hidden',
- position: 'relative',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Replaces the port image
- mxConstraintHandler.prototype.pointImage = new mxImage(
- 'images/dot.gif',
- 10,
- 10
- );
-
- const graph = new mxGraph(this.el);
- graph.setConnectable(true);
-
- // Disables automatic handling of ports. This disables the reset of the
- // respective style in mxGraph.cellConnected. Note that this feature may
- // be useful if floating and fixed connections are combined.
- graph.setPortsEnabled(false);
-
- // 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();
-
- // Ports are equal for all shapes...
- const ports = new Array();
-
- // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)
- ports.w = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };
- ports.e = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };
- ports.n = { x: 0.5, y: 0, perimeter: true, constraint: 'north' };
- ports.s = { x: 0.5, y: 1, perimeter: true, constraint: 'south' };
- ports.nw = { x: 0, y: 0, perimeter: true, constraint: 'north west' };
- ports.ne = { x: 1, y: 0, perimeter: true, constraint: 'north east' };
- ports.sw = { x: 0, y: 1, perimeter: true, constraint: 'south west' };
- ports.se = { x: 1, y: 1, perimeter: true, constraint: 'south east' };
-
- // ... except for triangles
- const ports2 = new Array();
-
- // NOTE: Constraint is used later for orthogonal edge routing (currently ignored)
- ports2.in1 = { x: 0, y: 0, perimeter: true, constraint: 'west' };
- ports2.in2 = { x: 0, y: 0.25, perimeter: true, constraint: 'west' };
- ports2.in3 = { x: 0, y: 0.5, perimeter: true, constraint: 'west' };
- ports2.in4 = { x: 0, y: 0.75, perimeter: true, constraint: 'west' };
- ports2.in5 = { x: 0, y: 1, perimeter: true, constraint: 'west' };
-
- ports2.out1 = {
- x: 0.5,
- y: 0,
- perimeter: true,
- constraint: 'north east',
- };
- ports2.out2 = { x: 1, y: 0.5, perimeter: true, constraint: 'east' };
- ports2.out3 = {
- x: 0.5,
- y: 1,
- perimeter: true,
- constraint: 'south east',
- };
-
- // Extends shapes classes to return their ports
- mxShape.prototype.getPorts = function() {
- return ports;
- };
-
- mxTriangle.prototype.getPorts = function() {
- return ports2;
- };
-
- // Disables floating connections (only connections via ports allowed)
- graph.connectionHandler.isConnectableCell = function(cell) {
- return false;
- };
- mxEdgeHandler.prototype.isConnectableCell = function(cell) {
- return graph.connectionHandler.isConnectableCell(cell);
- };
-
- // Disables existing port functionality
- graph.view.getTerminalPort = function(state, terminal, source) {
- return terminal;
- };
-
- // Returns all possible ports for a given terminal
- graph.getAllConnectionConstraints = function(terminal, source) {
- if (
- terminal != null &&
- terminal.shape != null &&
- terminal.shape.stencil != null
- ) {
- // for stencils with existing constraints...
- if (terminal.shape.stencil != null) {
- return terminal.shape.stencil.constraints;
- }
- } else if (terminal != null && terminal.cell.isVertex()) {
- if (terminal.shape != null) {
- const ports = terminal.shape.getPorts();
- const cstrs = new Array();
-
- for (const id in ports) {
- const port = ports[id];
-
- const cstr = new mxConnectionConstraint(
- new mxPoint(port.x, port.y),
- port.perimeter
- );
- cstr.id = id;
- cstrs.push(cstr);
- }
-
- return cstrs;
- }
- }
-
- return null;
- };
-
- // Sets the port for the given connection
- graph.setConnectionConstraint = function(
- edge,
- terminal,
- source,
- constraint
- ) {
- if (constraint != null) {
- const key = source
- ? mxConstants.STYLE_SOURCE_PORT
- : mxConstants.STYLE_TARGET_PORT;
-
- if (constraint == null || constraint.id == null) {
- this.setCellStyles(key, null, [edge]);
- } else if (constraint.id != null) {
- this.setCellStyles(key, constraint.id, [edge]);
- }
- }
- };
-
- // Returns the port for the given connection
- graph.getConnectionConstraint = function(edge, terminal, source) {
- const key = source
- ? mxConstants.STYLE_SOURCE_PORT
- : mxConstants.STYLE_TARGET_PORT;
- const id = edge.style[key];
-
- if (id != null) {
- const c = new mxConnectionConstraint(null, null);
- c.id = id;
-
- return c;
- }
-
- return null;
- };
-
- // Returns the actual point for a port by redirecting the constraint to the port
- const graphGetConnectionPoint = graph.getConnectionPoint;
- graph.getConnectionPoint = function(vertex, constraint) {
- if (constraint.id != null && vertex != null && vertex.shape != null) {
- const port = vertex.shape.getPorts()[constraint.id];
-
- if (port != null) {
- constraint = new mxConnectionConstraint(
- new mxPoint(port.x, port.y),
- port.perimeter
- );
- }
- }
-
- return graphGetConnectionPoint.apply(this, arguments);
- };
-
- // Adds cells to the model in a single step
- graph.getModel().beginUpdate();
- try {
- const v1 = graph.insertVertex(parent, null, 'A', 20, 20, 100, 40);
- const v2 = graph.insertVertex(
- parent,
- null,
- 'B',
- 80,
- 100,
- 100,
- 100,
- 'shape=ellipse;perimeter=ellipsePerimeter'
- );
- const v3 = graph.insertVertex(
- parent,
- null,
- 'C',
- 190,
- 30,
- 100,
- 60,
- 'shape=triangle;perimeter=trianglePerimeter;direction=south'
- );
- const e1 = graph.insertEdge(
- parent,
- null,
- '',
- v1,
- v2,
- 'sourcePort=s;targetPort=nw'
- );
- const e2 = graph.insertEdge(
- parent,
- null,
- '',
- v1,
- v3,
- 'sourcePort=e;targetPort=out3'
- );
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- // Comming soon... Integration with orthogonal edge style
- // Sets default edge style to use port constraints (needs to be moved up when uncommented)
- // graph.getStylesheet().getDefaultEdgeStyle()['edgeStyle'] = 'orthogonalEdgeStyle';
- /* let mxUtilsGetPortConstraints = mxUtils.getPortConstraints;
- mxUtils.getPortConstraints = function(terminal, edge, source, defaultValue)
- {
- let key = (source) ? mxConstants.STYLE_SOURCE_PORT : mxConstants.STYLE_TARGET_PORT;
- let id = edge.style[key];
-
- let port = terminal.shape.getPorts()[id];
-
- // TODO: Add support for rotation, direction
- if (port != null)
- {
- return port.constraint;
- }
-
- return mxUtilsGetPortConstraints.apply(this, arguments);
- };
- // Connect preview
- graph.connectionHandler.createEdgeState = function(me)
- {
- let edge = graph.createEdge(null, null, null, null, null);
-
- return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge));
- };
- */
- }
-}
-
-export default PortRefs;
diff --git a/src/pages/copy_examples_to_json.py b/src/pages/copy_examples_to_json.py
deleted file mode 100644
index dbb0f03dc..000000000
--- a/src/pages/copy_examples_to_json.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import json
-import pathlib
-
-out = {}
-for js_path in pathlib.Path('').rglob('*.js'):
- print(js_path)
- out[js_path.name.rpartition('.')[0]] = js_path.read_text(encoding='utf-8')
-
-with open("examplesListing.json", "w", encoding="utf-8") as f:
- f.write(json.dumps(out, ensure_ascii=False, indent=2))
diff --git a/src/pages/dnd_copypaste/Clipboard.js b/src/pages/dnd_copypaste/Clipboard.js
deleted file mode 100644
index cc2524dc1..000000000
--- a/src/pages/dnd_copypaste/Clipboard.js
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxClipboard from '../../mxgraph/util/storage/mxClipboard';
-import mxClient from '../../mxgraph/mxClient';
-import mxCodec from '../../mxgraph/serialization/mxCodec';
-import mxGraphModel from '../../mxgraph/view/graph/mxGraphModel';
-
-class Clipboard extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Clipboard
- This example demonstrates using the clipboard for providing cross-tab
- and cross-browser copy and paste.
-
{
- this.el = el;
- }}
- style={{
- position: 'relative',
- overflow: 'hidden',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- };
-
- componentDidMount() {
- // Disables the built-in context menu
- mxEvent.disableContextMenu(this.el);
-
- // Creates the graph inside the given this.el
- const graph = new mxGraph(this.el);
-
- // Public helper method for shared clipboard.
- mxClipboard.cellsToString = function(cells) {
- const codec = new mxCodec();
- const model = new mxGraphModel();
- const parent = model.getRoot().getChildAt(0);
-
- for (let i = 0; i < cells.length; i++) {
- model.add(parent, cells[i]);
- }
-
- return mxUtils.getXml(codec.encode(model));
- };
-
- // Focused but invisible textarea during control or meta key events
- const textInput = document.createElement('textarea');
- mxUtils.setOpacity(textInput, 0);
- textInput.style.width = '1px';
- textInput.style.height = '1px';
- let restoreFocus = false;
- const gs = graph.gridSize;
- let lastPaste = null;
- let dx = 0;
- let dy = 0;
-
- // Workaround for no copy event in IE/FF if empty
- textInput.value = ' ';
-
- // Shows a textare when control/cmd is pressed to handle native clipboard actions
- mxEvent.addListener(document, 'keydown', function(evt) {
- // No dialog visible
- const source = mxEvent.getSource(evt);
-
- if (
- graph.isEnabled() &&
- !graph.isMouseDown &&
- !graph.isEditing() &&
- source.nodeName !== 'INPUT'
- ) {
- if (
- evt.keyCode === 224 /* FF */ ||
- (!mxClient.IS_MAC && evt.keyCode === 17) /* Control */ ||
- (mxClient.IS_MAC &&
- (evt.keyCode === 91 || evt.keyCode === 93)) /* Left/Right Meta */
- ) {
- // Cannot use parentNode for check in IE
- if (!restoreFocus) {
- // Avoid autoscroll but allow handling of events
- textInput.style.position = 'absolute';
- textInput.style.left = `${graph.container.scrollLeft + 10}px`;
- textInput.style.top = `${graph.container.scrollTop + 10}px`;
- graph.container.appendChild(textInput);
-
- restoreFocus = true;
- textInput.focus();
- textInput.select();
- }
- }
- }
- });
-
- // Restores focus on graph this.el and removes text input from DOM
- mxEvent.addListener(document, 'keyup', function(evt) {
- if (
- restoreFocus &&
- (evt.keyCode === 224 /* FF */ ||
- evt.keyCode === 17 /* Control */ ||
- evt.keyCode === 91 ||
- evt.keyCode === 93) /* Meta */
- ) {
- restoreFocus = false;
-
- if (!graph.isEditing()) {
- graph.container.focus();
- }
-
- textInput.parentNode.removeChild(textInput);
- }
- });
-
- // Inserts the XML for the given cells into the text input for copy
- const copyCells = function(graph, cells) {
- if (cells.length > 0) {
- const clones = graph.cloneCells(cells);
-
- // Checks for orphaned relative children and makes absolute
- for (let i = 0; i < clones.length; i++) {
- const state = graph.view.getState(cells[i]);
-
- if (state != null) {
- const geo = graph.getCellGeometry(clones[i]);
-
- if (geo != null && geo.relative) {
- geo.relative = false;
- geo.x = state.x / state.view.scale - state.view.translate.x;
- geo.y = state.y / state.view.scale - state.view.translate.y;
- }
- }
- }
-
- textInput.value = mxClipboard.cellsToString(clones);
- }
-
- textInput.select();
- lastPaste = textInput.value;
- };
-
- // Handles copy event by putting XML for current selection into text input
- mxEvent.addListener(
- textInput,
- 'copy',
- mxUtils.bind(this, function(evt) {
- if (graph.isEnabled() && !graph.isSelectionEmpty()) {
- copyCells(
- graph,
- mxUtils.sortCells(
- graph.model.getTopmostCells(graph.getSelectionCells())
- )
- );
- dx = 0;
- dy = 0;
- }
- })
- );
-
- // Handles cut event by removing cells putting XML into text input
- mxEvent.addListener(
- textInput,
- 'cut',
- mxUtils.bind(this, function(evt) {
- if (graph.isEnabled() && !graph.isSelectionEmpty()) {
- copyCells(graph, graph.removeCells());
- dx = -gs;
- dy = -gs;
- }
- })
- );
-
- // Merges XML into existing graph and layers
- const importXml = function(xml, dx, dy) {
- dx = dx != null ? dx : 0;
- dy = dy != null ? dy : 0;
- let cells = [];
-
- try {
- const doc = mxUtils.parseXml(xml);
- const node = doc.documentElement;
-
- if (node != null) {
- const model = new mxGraphModel();
- const codec = new mxCodec(node.ownerDocument);
- codec.decode(node, model);
-
- const childCount = model.getRoot().getChildCount();
- const targetChildCount = graph.model.getRoot().getChildCount();
-
- // Merges existing layers and adds new layers
- graph.model.beginUpdate();
- try {
- for (let i = 0; i < childCount; i++) {
- let parent = model.getRoot().getChildAt(i);
-
- // Adds cells to existing layers if not locked
- if (targetChildCount > i) {
- // Inserts into active layer if only one layer is being pasted
- const target =
- childCount === 1
- ? graph.getDefaultParent()
- : graph.model.getRoot().getChildAt(i);
-
- if (!graph.isCellLocked(target)) {
- const children = parent.getChildren();
- cells = cells.concat(
- graph.importCells(children, dx, dy, target)
- );
- }
- } else {
- // Delta is non cascading, needs separate move for layers
- parent = graph.importCells(
- [parent],
- 0,
- 0,
- graph.model.getRoot()
- )[0];
- const children = parent.getChildren();
- graph.moveCells(children, dx, dy);
- cells = cells.concat(children);
- }
- }
- } finally {
- graph.model.endUpdate();
- }
- }
- } catch (e) {
- alert(e);
- throw e;
- }
-
- return cells;
- };
-
- // Parses and inserts XML into graph
- const pasteText = function(text) {
- const xml = mxUtils.trim(text);
- const x =
- graph.container.scrollLeft / graph.view.scale - graph.view.translate.x;
- const y =
- graph.container.scrollTop / graph.view.scale - graph.view.translate.y;
-
- if (xml.length > 0) {
- if (lastPaste !== xml) {
- lastPaste = xml;
- dx = 0;
- dy = 0;
- } else {
- dx += gs;
- dy += gs;
- }
-
- // Standard paste via control-v
- if (xml.substring(0, 14) === '') {
- graph.setSelectionCells(importXml(xml, dx, dy));
- graph.scrollCellToVisible(graph.getSelectionCell());
- }
- }
- };
-
- // Function to fetch text from paste events
- const extractGraphModelFromEvent = function(evt) {
- let data = null;
-
- if (evt != null) {
- const provider =
- evt.dataTransfer != null ? evt.dataTransfer : evt.clipboardData;
-
- if (provider != null) {
- data =
- mxUtils.indexOf(provider.types, 'text/html') >= 0
- ? provider.getData('text/html')
- : null;
-
- if (
- mxUtils.indexOf(
- provider.types,
- 'text/plain' && (data == null || data.length === 0)
- )
- ) {
- data = provider.getData('text/plain');
- }
- }
- }
-
- return data;
- };
-
- // Handles paste event by parsing and inserting XML
- mxEvent.addListener(textInput, 'paste', function(evt) {
- // Clears existing contents before paste - should not be needed
- // because all text is selected, but doesn't hurt since the
- // actual pasting of the new text is delayed in all cases.
- textInput.value = '';
-
- if (graph.isEnabled()) {
- const xml = extractGraphModelFromEvent(evt);
-
- if (xml != null && xml.length > 0) {
- pasteText(xml);
- } else {
- // Timeout for new value to appear
- window.setTimeout(
- mxUtils.bind(this, function() {
- pasteText(textInput.value);
- }),
- 0
- );
- }
- }
-
- textInput.select();
- });
-
- // 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 });
- });
- };
-}
-
-export default Clipboard;
diff --git a/src/pages/events/Boundary.js b/src/pages/events/Boundary.js
deleted file mode 100644
index a44a06413..000000000
--- a/src/pages/events/Boundary.js
+++ /dev/null
@@ -1,237 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxPoint from '../../mxgraph/util/datatypes/mxPoint';
-import mxGraphHandler from '../../mxgraph/handler/mxGraphHandler';
-import mxUtils from '../../mxgraph/util/mxUtils';
-
-class Boundary extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Boundary
- This example demonstrates implementing boundary events in BPMN diagrams.
-
{
- this.el = el;
- }}
- style={{
- position: 'relative',
- overflow: 'hidden',
- height: '241px',
- background: 'url("editors/images/grid.gif")',
- cursor: 'default',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Disables the built-in context menu
- mxEvent.disableContextMenu(this.el);
-
- class MyCustomGraph extends mxGraph {
- // Enables moving of relative children
- isCellLocked(cell) {
- return false;
- }
-
- // Removes folding icon for relative children
- isCellFoldable(cell, collapse) {
- const childCount = cell.getChildCount();
-
- for (let i = 0; i < childCount; i++) {
- const child = cell.getChildAt(i);
- const geo = this.getCellGeometry(child);
-
- if (geo != null && geo.relative) {
- return false;
- }
- }
-
- return childCount > 0;
- }
-
- // Returns the relative position of the given child
- getRelativePosition(state, dx, dy) {
- if (state != null) {
- const model = graph.getModel();
- const geo = state.cell.getGeometry();
-
- if (geo != null && geo.relative && !state.cell.isEdge()) {
- const parent = state.cell.getParent();
-
- if (parent.isVertex()) {
- const pstate = graph.view.getState(parent);
-
- if (pstate != null) {
- const { scale } = graph.view;
- let x = state.x + dx;
- let y = state.y + dy;
-
- if (geo.offset != null) {
- x -= geo.offset.x * scale;
- y -= geo.offset.y * scale;
- }
-
- x = (x - pstate.x) / pstate.width;
- y = (y - pstate.y) / pstate.height;
-
- if (Math.abs(y - 0.5) <= Math.abs((x - 0.5) / 2)) {
- x = x > 0.5 ? 1 : 0;
- y = Math.min(1, Math.max(0, y));
- } else {
- x = Math.min(1, Math.max(0, x));
- y = y > 0.5 ? 1 : 0;
- }
-
- return new mxPoint(x, y);
- }
- }
- }
- }
-
- return null;
- }
-
- // Replaces translation for relative children
- translateCell(cell, dx, dy) {
- const rel = this.getRelativePosition(
- this.view.getState(cell),
- dx * graph.view.scale,
- dy * graph.view.scale
- );
-
- if (rel != null) {
- let geo = cell.getGeometry();
-
- if (geo != null && geo.relative) {
- geo = geo.clone();
- geo.x = rel.x;
- geo.y = rel.y;
-
- this.model.setGeometry(cell, geo);
- }
- } else {
- mxGraph.prototype.translateCell.apply(this, arguments);
- }
- }
- }
-
- // Creates the graph inside the given this.el
- const graph = new MyCustomGraph(this.el);
-
- // Sets the base style for all vertices
- const style = graph.getStylesheet().getDefaultVertexStyle();
- style[mxConstants.STYLE_ROUNDED] = true;
- style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';
- style[mxConstants.STYLE_STROKECOLOR] = '#000000';
- style[mxConstants.STYLE_STROKEWIDTH] = '2';
- style[mxConstants.STYLE_FONTCOLOR] = '#000000';
- style[mxConstants.STYLE_FONTSIZE] = '12';
- style[mxConstants.STYLE_FONTSTYLE] = 1;
- graph.getStylesheet().putDefaultVertexStyle(style);
-
- // Replaces move preview for relative children
- graph.graphHandler.getDelta = function(me) {
- const point = mxUtils.convertPoint(
- this.graph.container,
- me.getX(),
- me.getY()
- );
- let delta = new mxPoint(point.x - this.first.x, point.y - this.first.y);
-
- if (
- this.cells != null &&
- this.cells.length > 0 &&
- this.cells[0] != null
- ) {
- const state = this.graph.view.getState(this.cells[0]);
- const rel = graph.getRelativePosition(state, delta.x, delta.y);
-
- if (rel != null) {
- const pstate = this.graph.view.getState(
- state.cell.getParent()
- );
-
- if (pstate != null) {
- delta = new mxPoint(
- pstate.x + pstate.width * rel.x - state.getCenterX(),
- pstate.y + pstate.height * rel.y - state.getCenterY()
- );
- }
- }
- }
-
- return delta;
- };
-
- // Relative children cannot be removed from parent
- graph.graphHandler.shouldRemoveCellsFromParent = function(
- parent,
- cells,
- evt
- ) {
- return (
- cells.length === 0 &&
- !cells[0].geometry.relative &&
- mxGraphHandler.prototype.shouldRemoveCellsFromParent.apply(
- this,
- arguments
- )
- );
- };
-
- // 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: 'Process',
- position: [60, 60],
- size: [90, 40],
- });
-
- const v2 = graph.insertVertex({
- parent: v1,
- value: 'in',
- position: [0, 0.5],
- size: [20, 20],
- style: 'fontSize=9;shape=ellipse;resizable=0;',
- });
- v2.geometry.offset = new mxPoint(-10, -10);
- v2.geometry.relative = true;
-
- const v3 = graph.insertVertex({
- parent: v1,
- value: 'out',
- position: [1, 0.5],
- size: [20, 20],
- style: 'fontSize=9;shape=ellipse;resizable=0;',
- });
- v3.geometry.offset = new mxPoint(-10, -10);
- v3.geometry.relative = true;
- });
- }
-}
-
-export default Boundary;
diff --git a/src/pages/examplesListing.json b/src/pages/examplesListing.json
deleted file mode 100644
index 9323be2be..000000000
--- a/src/pages/examplesListing.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "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.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.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 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 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 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.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [120, 120],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [400, 250],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n source: v1,\n target: v2,\n style: 'edgeStyle=orthogonalEdgeStyle;',\n });\n const e2 = graph.insertEdge({\n parent,\n source: v2,\n target: v1,\n style: 'edgeStyle=orthogonalEdgeStyle;',\n });\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 );\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 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
Dynamic 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 = (this.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 = (this.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 this.addVertex('editors/images/rectangle.gif', 100, 40, '');\n this.addVertex('editors/images/rounded.gif', 100, 40, 'shape=rounded');\n this.addVertex('editors/images/ellipse.gif', 40, 40, 'shape=ellipse');\n this.addVertex('editors/images/rhombus.gif', 40, 40, 'shape=rhombus');\n this.addVertex('editors/images/triangle.gif', 40, 40, 'shape=triangle');\n this.addVertex('editors/images/cylinder.gif', 40, 40, 'shape=cylinder');\n this.addVertex('editors/images/actor.gif', 30, 40, 'shape=actor');\n }\n\n 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(this.graph, this.toolbar, vertex, icon);\n img.enabled = true;\n\n this.graph.getSelectionModel().addListener(mxEvent.CHANGE, () => {\n const tmp = this.graph.isSelectionEmpty();\n mxUtils.setOpacity(img, tmp ? 100 : 20);\n img.enabled = tmp;\n });\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, 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, (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', 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', evt => {\n if (img.enabled == false) {\n mxEvent.consume(evt);\n }\n });\n\n mxUtils.makeDraggable(img, graph, funct);\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 );\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 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.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Hello,',\n position: [20, 20],\n size: [80, 30],\n style: 'fillColor=green',\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [200, 150],\n size: [80, 30],\n style: 'fillColor=blue',\n });\n const v3 = graph.insertVertex({\n parent,\n value: 'World!',\n position: [20, 150],\n size: [80, 30],\n style: 'fillColor=red',\n });\n const e1 = graph.insertEdge({\n parent,\n value: 'Connect',\n source: v1,\n target: v2,\n style: 'perimeterSpacing=4;strokeWidth=4;labelBackgroundColor=white;fontStyle=1',\n });\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
Groups
\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.cell.getParent();\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
Radial Tree (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 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.cell.getParent();\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 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.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
Labels
\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.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 value: targetNode.cloneNode(true),\n position: [200, 80],\n size: [80, 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.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.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.batchUpdate(() => {\n const v1 = graph.insertVertex({\n parent,\n value: 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n position: [20, 20],\n size: [100, 70],\n style: 'whiteSpace=wrap;',\n });\n const v2 = graph.insertVertex({\n parent,\n value: 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n position: [220, 150],\n size: [80, 70],\n style: 'whiteSpace=wrap;',\n });\n const e1 = graph.insertEdge({\n parent,\n value: 'Cum Caesar vidisset, portum plenum esse, iuxta navigavit.',\n source: v1,\n target: v2,\n style: 'whiteSpace=wrap;',\n });\n e1.geometry.width = 100;\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.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
{\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.batchUpdate(() => {\n v1 = graph.insertVertex({\n parent,\n value: '1',\n position: [20, 20],\n size: [80, 30],\n });\n const v2 = graph.insertVertex({\n parent,\n value: '2',\n position: [200, 150],\n size: [80, 30],\n });\n const e1 = graph.insertEdge({\n parent,\n value: '3',\n source: v1,\n target: v2,\n });\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 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', 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 = 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, (sender, evt2) => {\n graph.clearSelection();\n const geo = graph.getCellGeometry(cell);\n\n let v2;\n\n executeLayout(\n () => {\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 () => {\n graph.scrollCellToVisible(v2);\n }\n );\n });\n\n // Special CMS event\n overlay.addListener('pointerdown', (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
diff --git a/src/pages/icons_images/ContextIcons.js b/src/pages/icons_images/ContextIcons.js
deleted file mode 100644
index 01c9ba2d1..000000000
--- a/src/pages/icons_images/ContextIcons.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxVertexHandler from '../../mxgraph/handler/mxVertexHandler';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxClient from '../../mxgraph/mxClient';
-
-class ContextIcons extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Context icons
- This example demonstrates adding icons to selected vertices to carry out
- special operations.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'hidden',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- };
-
- componentDidMount() {
- class mxVertexToolHandler extends mxVertexHandler {
- // Defines a subclass for mxVertexHandler that adds a set of clickable
- // icons to every selected vertex.
-
- domNode = null;
-
- init() {
- super.init();
-
- // 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);
- };
-
- // 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', evt => {
- this.graph.removeCells([this.state.cell]);
- mxEvent.consume(evt);
- });
- 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, 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);
-
- // 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),
- mxEvent.getClientY(evt)
- );
- this.graph.graphHandler.cellWasClicked = true;
- this.graph.isMouseDown = true;
- this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);
- mxEvent.consume(evt);
- });
- 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, evt => {
- const pt = mxUtils.convertPoint(
- this.graph.container,
- mxEvent.getClientX(evt),
- mxEvent.getClientY(evt)
- );
- this.graph.connectionHandler.start(this.state, pt.x, pt.y);
- this.graph.isMouseDown = true;
- this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt);
- mxEvent.consume(evt);
- });
- this.domNode.appendChild(img);
-
- this.graph.container.appendChild(this.domNode);
- this.redrawTools();
- }
-
- redraw() {
- super.redraw();
- this.redrawTools();
- }
-
- 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`;
- }
- }
-
- destroy(sender, me) {
- super.destroy(sender, me);
-
- if (this.domNode != null) {
- this.domNode.parentNode.removeChild(this.domNode);
- this.domNode = null;
- }
- }
- }
-
- class MyCustomGraph extends mxGraph {
- createHandler(state) {
- if (state != null && state.cell.isVertex()) {
- 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,
- });
- });
- };
-}
-
-export default ContextIcons;
diff --git a/src/pages/icons_images/Control.js b/src/pages/icons_images/Control.js
deleted file mode 100644
index 9a42bb5ec..000000000
--- a/src/pages/icons_images/Control.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxRectangle from '../../mxgraph/util/datatypes/mxRectangle';
-import mxCellRenderer from '../../mxgraph/view/cell/mxCellRenderer';
-import mxImageShape from '../../mxgraph/shape/node/mxImageShape';
-import mxImage from '../../mxgraph/util/image/mxImage';
-
-class Control extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Control
- This example demonstrates adding controls to specific cells in a graph.
-
{
- this.el2 = el;
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Specifies the URL and size of the new control
- const deleteImage = new mxImage(
- 'editors/images/overlays/forbidden.png',
- 16,
- 16
- );
-
- class MyCustomCellRenderer extends mxCellRenderer {
- createControl(state) {
- super.createControl(state);
-
- const { graph } = state.view;
-
- if (state.cell.isVertex()) {
- if (state.deleteControl == null) {
- const b = new mxRectangle(
- 0,
- 0,
- deleteImage.width,
- deleteImage.height
- );
- state.deleteControl = new mxImageShape(b, deleteImage.src);
- state.deleteControl.dialect = graph.dialect;
- state.deleteControl.preserveImageAspect = false;
-
- this.initControl(state, state.deleteControl, false, function(evt) {
- if (graph.isEnabled()) {
- graph.removeCells([state.cell]);
- mxEvent.consume(evt);
- }
- });
- }
- } else if (state.deleteControl != null) {
- state.deleteControl.destroy();
- state.deleteControl = null;
- }
- }
-
- getDeleteControlBounds(state) {
- // Helper function to compute the bounds of the control
- if (state.deleteControl != null) {
- const oldScale = state.deleteControl.scale;
- const w = state.deleteControl.bounds.width / oldScale;
- const h = state.deleteControl.bounds.height / oldScale;
- const s = state.view.scale;
-
- return state.cell.isEdge()
- ? new mxRectangle(
- state.x + state.width / 2 - (w / 2) * s,
- state.y + state.height / 2 - (h / 2) * s,
- w * s,
- h * s
- )
- : new mxRectangle(
- state.x + state.width - w * s,
- state.y,
- w * s,
- h * s
- );
- }
- return null;
- }
-
- redrawControl(state) {
- // Overridden to update the scale and bounds of the control
- super.redrawControl(state);
-
- if (state.deleteControl != null) {
- const bounds = this.getDeleteControlBounds(state);
- const s = state.view.scale;
-
- if (
- state.deleteControl.scale !== s ||
- !state.deleteControl.bounds.equals(bounds)
- ) {
- state.deleteControl.bounds = bounds;
- state.deleteControl.scale = s;
- state.deleteControl.redraw();
- }
- }
- }
-
- destroy(state) {
- // Overridden to remove the control if the state is destroyed
- super.destroy(state);
-
- if (state.deleteControl != null) {
- state.deleteControl.destroy();
- state.deleteControl = null;
- }
- }
- }
-
- class MyCustomGraph extends mxGraph {
- createCellRenderer() {
- return new MyCustomCellRenderer();
- }
- }
-
- // Creates the graph inside the given container
- const graph = new MyCustomGraph(this.el);
- graph.setPanning(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.getModel().beginUpdate();
- try {
- 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();
- }
-
- graph.centerZoom = false;
-
- this.el2.appendChild(
- mxUtils.button('Zoom In', () => {
- graph.zoomIn();
- })
- );
-
- this.el2.appendChild(
- mxUtils.button('Zoom Out', () => {
- graph.zoomOut();
- })
- );
- }
-}
-
-export default Control;
diff --git a/src/pages/icons_images/HoverIcons.js b/src/pages/icons_images/HoverIcons.js
deleted file mode 100644
index 14ee55e42..000000000
--- a/src/pages/icons_images/HoverIcons.js
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxConnectionHandler from '../../mxgraph/handler/mxConnectionHandler';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxRectangle from '../../mxgraph/util/datatypes/mxRectangle';
-import mxImage from '../../mxgraph/util/image/mxImage';
-
-class HoverIcons extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Hover icons
- This example demonstrates showing icons on vertices as mouse hovers over
- them.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'hidden',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Defines an icon for creating new connections in the connection handler.
- // This will automatically disable the highlighting of the source vertex.
- mxConnectionHandler.prototype.connectImage = new mxImage(
- 'images/connector.gif',
- 16,
- 16
- );
-
- // Defines a new class for all icons
- class mxIconSet {
- constructor(state) {
- this.images = [];
- const { graph } = state.view;
-
- // Icon1
- let img = mxUtils.createImage('images/copy.png');
- img.setAttribute('title', 'Duplicate');
- Object.assign(img.style, {
- cursor: 'pointer',
- width: '16px',
- height: '16px',
- position: 'absolute',
- left: `${state.x + state.width}px`,
- top: `${state.y + state.height}px`,
- });
-
- mxEvent.addGestureListeners(img, evt => {
- const s = graph.gridSize;
- graph.setSelectionCells(graph.moveCells([state.cell], s, s, true));
- mxEvent.consume(evt);
- this.destroy();
- });
-
- state.view.graph.container.appendChild(img);
- this.images.push(img);
-
- // Delete
- img = mxUtils.createImage('images/delete2.png');
- img.setAttribute('title', 'Delete');
- Object.assign(img.style, {
- cursor: 'pointer',
- width: '16px',
- height: '16px',
- position: 'absolute',
- left: `${state.x + state.width}px`,
- top: `${state.y - 16}px`,
- });
-
- mxEvent.addGestureListeners(img, evt => {
- // Disables dragging the image
- mxEvent.consume(evt);
- });
-
- mxEvent.addListener(img, 'click', evt => {
- graph.removeCells([state.cell]);
- mxEvent.consume(evt);
- this.destroy();
- });
-
- state.view.graph.container.appendChild(img);
- this.images.push(img);
- }
-
- destroy() {
- if (this.images != null) {
- for (const img of this.images) {
- img.parentNode.removeChild(img);
- }
- }
- this.images = null;
- }
- }
-
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
- graph.setConnectable(true);
-
- // Enables rubberband selection
- new mxRubberband(graph);
-
- // Defines the tolerance before removing the icons
- const ICON_TOLERANCE = 20;
-
- // Shows icons if the mouse is over a cell
- graph.addMouseListener({
- currentState: null,
- currentIconSet: null,
-
- mouseDown(sender, me) {
- // Hides icons on mouse down
- if (this.currentState != null) {
- this.dragLeave(me.getEvent(), this.currentState);
- this.currentState = null;
- }
- },
-
- mouseMove(sender, me) {
- if (
- this.currentState != null &&
- (me.getState() === this.currentState || me.getState() == null)
- ) {
- const tol = ICON_TOLERANCE;
- const tmp = new mxRectangle(
- me.getGraphX() - tol,
- me.getGraphY() - tol,
- 2 * tol,
- 2 * tol
- );
- if (mxUtils.intersects(tmp, this.currentState)) {
- return;
- }
- }
-
- let tmp = graph.view.getState(me.getCell());
-
- // Ignore everything but vertices
- if (
- graph.isMouseDown ||
- (tmp != null && !tmp.cell.isVertex())
- ) {
- tmp = null;
- }
-
- if (tmp !== this.currentState) {
- if (this.currentState != null) {
- this.dragLeave(me.getEvent(), this.currentState);
- }
-
- this.currentState = tmp;
- if (this.currentState != null) {
- this.dragEnter(me.getEvent(), this.currentState);
- }
- }
- },
-
- mouseUp(sender, me) {},
-
- dragEnter(evt, state) {
- if (this.currentIconSet == null) {
- this.currentIconSet = new mxIconSet(state);
- }
- },
-
- dragLeave(evt, state) {
- if (this.currentIconSet != null) {
- this.currentIconSet.destroy();
- this.currentIconSet = null;
- }
- },
- });
-
- // 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,
- });
- });
- }
-}
-
-export default HoverIcons;
diff --git a/src/pages/index.js b/src/pages/index.js
deleted file mode 100644
index 144ef21d8..000000000
--- a/src/pages/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import Basic from './basic';
-
-export default function Home() {
- return ;
-}
diff --git a/src/pages/labels/Labels.js b/src/pages/labels/Labels.js
deleted file mode 100644
index 09c538328..000000000
--- a/src/pages/labels/Labels.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxKeyHandler from '../../mxgraph/handler/mxKeyHandler';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxRectangle from '../../mxgraph/util/datatypes/mxRectangle';
-
-class Labels extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Labels
- This example demonstrates the use of wrapping and clipping for HTML
- labels of vertices, truncating labels to fit the size of a vertex, and
- manually placing vertex labels and relative children that act as
- "sublabels".
-
{
- this.el = el;
- }}
- style={{
- position: 'relative',
- overflow: 'hidden',
- height: '300px',
- background: "url('editors/images/grid.gif')",
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
- graph.setTooltips(true);
- graph.htmlLabels = true;
- graph.vertexLabelsMovable = true;
- new mxRubberband(graph);
- new mxKeyHandler(graph);
-
- // Do not allow removing labels from parents
- graph.graphHandler.removeCellsFromParent = false;
-
- // Autosize labels on insert where autosize=1
- graph.autoSizeCellsOnAdd = true;
-
- // Allows moving of relative cells
- graph.isCellLocked = function(cell) {
- return this.isCellsLocked();
- };
-
- graph.isCellResizable = function(cell) {
- const geo = cell.getGeometry();
-
- return geo == null || !geo.relative;
- };
-
- // Truncates the label to the size of the vertex
- graph.getLabel = function(cell) {
- const label = this.labelsVisible ? this.convertValueToString(cell) : '';
- const geometry = cell.getGeometry();
-
- if (
- !cell.isCollapsed() &&
- geometry != null &&
- (geometry.offset == null ||
- (geometry.offset.x == 0 && geometry.offset.y == 0)) &&
- cell.isVertex() &&
- geometry.width >= 2
- ) {
- const style = this.getCellStyle(cell);
- const fontSize =
- style[mxConstants.STYLE_FONTSIZE] || mxConstants.DEFAULT_FONTSIZE;
- const max = geometry.width / (fontSize * 0.625);
-
- if (max < label.length) {
- return `${label.substring(0, max)}...`;
- }
- }
-
- return label;
- };
-
- // Enables wrapping for vertex labels
- graph.isWrapping = function(cell) {
- return cell.isCollapsed();
- };
-
- // Enables clipping of vertex labels if no offset is defined
- graph.isLabelClipped = function(cell) {
- const geometry = cell.getGeometry();
-
- return (
- geometry != null &&
- !geometry.relative &&
- (geometry.offset == null ||
- (geometry.offset.x == 0 && geometry.offset.y == 0))
- );
- };
-
- // 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,
- 'vertexLabelsMovable',
- 20,
- 20,
- 80,
- 30
- );
-
- // Places sublabels inside the vertex
- const label11 = graph.insertVertex(
- v1,
- null,
- 'Label1',
- 0.5,
- 1,
- 0,
- 0,
- null,
- true
- );
- const label12 = graph.insertVertex(
- v1,
- null,
- 'Label2',
- 0.5,
- 0,
- 0,
- 0,
- null,
- true
- );
-
- const v2 = graph.insertVertex(
- parent,
- null,
- 'Wrapping and clipping is enabled only if the cell is collapsed, otherwise the label is truncated if there is no manual offset.',
- 200,
- 150,
- 80,
- 30
- );
- v2.geometry.alternateBounds = new mxRectangle(0, 0, 80, 30);
- const e1 = graph.insertEdge(parent, null, 'edgeLabelsMovable', v1, v2);
-
- // Places sublabels inside the vertex
- const label21 = graph.insertVertex(
- v2,
- null,
- 'Label1',
- 0.5,
- 1,
- 0,
- 0,
- null,
- true
- );
- const label22 = graph.insertVertex(
- v2,
- null,
- 'Label2',
- 0.5,
- 0,
- 0,
- 0,
- null,
- true
- );
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
- }
-}
-
-export default Labels;
diff --git a/src/pages/labels/SecondLabel.js b/src/pages/labels/SecondLabel.js
deleted file mode 100644
index c60096673..000000000
--- a/src/pages/labels/SecondLabel.js
+++ /dev/null
@@ -1,243 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxPoint from '../../mxgraph/util/datatypes/mxPoint';
-import mxRectangle from '../../mxgraph/util/datatypes/mxRectangle';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxRectangleShape from '../../mxgraph/shape/node/mxRectangleShape';
-import mxText from '../../mxgraph/shape/mxText';
-
-class SecondLabel extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Second label
- This example demonstrates how to add another string label to vertices.
-
{
- this.el2 = el;
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Makes the shadow brighter
- mxConstants.SHADOWCOLOR = '#C0C0C0';
-
- // Workaround for Internet Explorer ignoring certain styles
- const container = document.createElement('div');
- container.style.position = 'absolute';
- container.style.overflow = 'hidden';
- container.style.left = '0px';
- container.style.top = '0px';
- container.style.right = '0px';
- container.style.bottom = '0px';
-
- const outline = document.getElementById('outlineContainer');
-
- mxEvent.disableContextMenu(container);
-
- // Sets a gradient background
- if (mxClient.IS_GC || mxClient.IS_SF) {
- container.style.background =
- '-webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFFFFF), to(#E7E7E7))';
- } else if (mxClient.IS_NS) {
- container.style.background =
- '-moz-linear-gradient(top, #FFFFFF, #E7E7E7)';
- }
-
- this.el.appendChild(container);
-
- // Creates the graph inside the given container
- const graph = new mxGraph(container);
-
- // Enables automatic sizing for vertices after editing and
- // panning by using the left mouse button.
- graph.setCellsMovable(false);
- graph.setAutoSizeCells(true);
- graph.setPanning(true);
- graph.centerZoom = false;
- graph.panningHandler.useLeftButtonForPanning = true;
-
- // Displays a popupmenu when the user clicks
- // on a cell (using the left mouse button) but
- // do not select the cell when the popup menu
- // is displayed
- graph.panningHandler.popupMenuHandler = false;
-
- // Creates the outline (navigator, overview) for moving
- // around the graph in the top, right corner of the window.
- const outln = new mxOutline(graph, outline);
-
- // Disables tooltips on touch devices
- graph.setTooltips(!mxClient.IS_TOUCH);
-
- // Set some stylesheet options for the visual appearance of vertices
- let style = graph.getStylesheet().getDefaultVertexStyle();
- style[mxConstants.STYLE_SHAPE] = 'label';
-
- style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
- style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;
- style[mxConstants.STYLE_SPACING_LEFT] = 54;
-
- style[mxConstants.STYLE_GRADIENTCOLOR] = '#7d85df';
- style[mxConstants.STYLE_STROKECOLOR] = '#5d65df';
- style[mxConstants.STYLE_FILLCOLOR] = '#adc5ff';
-
- style[mxConstants.STYLE_FONTCOLOR] = '#1d258f';
- style[mxConstants.STYLE_FONTFAMILY] = 'Verdana';
- style[mxConstants.STYLE_FONTSIZE] = '12';
- style[mxConstants.STYLE_FONTSTYLE] = '1';
-
- style[mxConstants.STYLE_SHADOW] = '1';
- style[mxConstants.STYLE_ROUNDED] = '1';
- style[mxConstants.STYLE_GLASS] = '1';
-
- style[mxConstants.STYLE_IMAGE] = 'editors/images/dude3.png';
- style[mxConstants.STYLE_IMAGE_WIDTH] = '48';
- style[mxConstants.STYLE_IMAGE_HEIGHT] = '48';
- style[mxConstants.STYLE_SPACING] = 8;
-
- // Sets the default style for edges
- style = graph.getStylesheet().getDefaultEdgeStyle();
- style[mxConstants.STYLE_ROUNDED] = true;
- style[mxConstants.STYLE_STROKEWIDTH] = 3;
- style[mxConstants.STYLE_EXIT_X] = 0.5; // center
- style[mxConstants.STYLE_EXIT_Y] = 1.0; // bottom
- style[mxConstants.STYLE_EXIT_PERIMETER] = 0; // disabled
- style[mxConstants.STYLE_ENTRY_X] = 0.5; // center
- style[mxConstants.STYLE_ENTRY_Y] = 0; // top
- style[mxConstants.STYLE_ENTRY_PERIMETER] = 0; // disabled
-
- // Disable the following for straight lines
- style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;
-
- // Stops editing on enter or escape keypress
- const keyHandler = new mxKeyHandler(graph);
-
- // Enables automatic layout on the graph and installs
- // a tree layout for all groups who's children are
- // being changed, added or removed.
- const layout = new mxCompactTreeLayout(graph, false);
- layout.useBoundingBox = false;
- layout.edgeRouting = false;
- layout.levelDistance = 60;
- layout.nodeDistance = 16;
-
- // Allows the layout to move cells even though cells
- // aren't movable in the graph
- layout.isVertexMovable = function(cell) {
- return true;
- };
-
- const layoutMgr = new mxLayoutManager(graph);
-
- layoutMgr.getLayout = function(cell) {
- if (cell.getChildCount() > 0) {
- return layout;
- }
- };
-
- // Installs a popupmenu handler using local function (see below).
- graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {
- return createPopupMenu(graph, menu, cell, evt);
- };
-
- // Fix for wrong preferred size
- const oldGetPreferredSizeForCell = graph.getPreferredSizeForCell;
- graph.getPreferredSizeForCell = function(cell) {
- const result = oldGetPreferredSizeForCell.apply(this, arguments);
-
- if (result != null) {
- result.width = Math.max(120, result.width - 40);
- }
-
- return result;
- };
-
- // Sets the maximum text scale to 1
- graph.cellRenderer.getTextScale = function(state) {
- return Math.min(1, state.view.scale);
- };
-
- // Dynamically adds text to the label as we zoom in
- // (without affecting the preferred size for new cells)
- graph.cellRenderer.getLabelValue = function(state) {
- let result = state.cell.value;
-
- if (state.cell.isVertex()) {
- if (state.view.scale > 1) {
- result += '\nDetails 1';
- }
-
- if (state.view.scale > 1.3) {
- result += '\nDetails 2';
- }
- }
-
- return result;
- };
-
- // 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 the root vertex of the tree
- graph.getModel().beginUpdate();
- try {
- const w = graph.container.offsetWidth;
- const v1 = graph.insertVertex(
- parent,
- 'treeRoot',
- 'Organization',
- w / 2 - 30,
- 20,
- 140,
- 60,
- 'image=editors/images/house.png'
- );
- graph.updateCellSize(v1);
- addOverlays(graph, v1, false);
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- const content = document.createElement('div');
- content.style.padding = '4px';
- this.el2.appendChild(content);
- const tb = new mxToolbar(content);
-
- tb.addItem('Zoom In', 'images/zoom_in32.png', function(evt) {
- graph.zoomIn();
- });
-
- tb.addItem('Zoom Out', 'images/zoom_out32.png', function(evt) {
- graph.zoomOut();
- });
-
- tb.addItem('Actual Size', 'images/view_1_132.png', function(evt) {
- graph.zoomActual();
- });
-
- tb.addItem('Print', 'images/print32.png', function(evt) {
- const preview = new mxPrintPreview(graph, 1);
- preview.open();
- });
-
- tb.addItem('Poster Print', 'images/press32.png', function(evt) {
- const pageCount = mxUtils.prompt('Enter maximum page count', '1');
-
- if (pageCount != null) {
- const scale = mxUtils.getScaleForPageCount(pageCount, graph);
- const preview = new mxPrintPreview(graph, scale);
- preview.open();
- }
- });
-
- // Function to create the entries in the popupmenu
- function createPopupMenu(graph, menu, cell, evt) {
- const model = graph.getModel();
-
- if (cell != null) {
- if (cell.isVertex()) {
- menu.addItem(
- 'Add child',
- 'editors/images/overlays/check.png',
- function() {
- addChild(graph, cell);
- }
- );
- }
-
- menu.addItem('Edit label', 'editors/images/text.gif', function() {
- graph.startEditingAtCell(cell);
- });
-
- if (cell.id != 'treeRoot' && cell.isVertex()) {
- menu.addItem('Delete', 'editors/images/delete.gif', function() {
- deleteSubtree(graph, cell);
- });
- }
-
- menu.addSeparator();
- }
-
- menu.addItem('Fit', 'editors/images/zoom.gif', function() {
- graph.fit();
- });
-
- menu.addItem('Actual', 'editors/images/zoomactual.gif', function() {
- graph.zoomActual();
- });
-
- menu.addSeparator();
-
- menu.addItem('Print', 'editors/images/print.gif', function() {
- const preview = new mxPrintPreview(graph, 1);
- preview.open();
- });
-
- menu.addItem('Poster Print', 'editors/images/print.gif', function() {
- const pageCount = mxUtils.prompt('Enter maximum page count', '1');
-
- if (pageCount != null) {
- const scale = mxUtils.getScaleForPageCount(pageCount, graph);
- const preview = new mxPrintPreview(graph, scale);
- preview.open();
- }
- });
- }
-
- function addOverlays(graph, cell, addDeleteIcon) {
- let overlay = new mxCellOverlay(
- new mxImage('images/add.png', 24, 24),
- 'Add child'
- );
- overlay.cursor = 'hand';
- overlay.align = mxConstants.ALIGN_CENTER;
- overlay.addListener(
- mxEvent.CLICK,
- mxUtils.bind(this, function(sender, evt) {
- addChild(graph, cell);
- })
- );
-
- graph.addCellOverlay(cell, overlay);
-
- if (addDeleteIcon) {
- overlay = new mxCellOverlay(
- new mxImage('images/close.png', 30, 30),
- 'Delete'
- );
- overlay.cursor = 'hand';
- overlay.offset = new mxPoint(-4, 8);
- overlay.align = mxConstants.ALIGN_RIGHT;
- overlay.verticalAlign = mxConstants.ALIGN_TOP;
- overlay.addListener(
- mxEvent.CLICK,
- mxUtils.bind(this, function(sender, evt) {
- deleteSubtree(graph, cell);
- })
- );
-
- graph.addCellOverlay(cell, overlay);
- }
- }
-
- function addChild(graph, cell) {
- const model = graph.getModel();
- const parent = graph.getDefaultParent();
- let vertex;
-
- model.beginUpdate();
- try {
- vertex = graph.insertVertex(parent, null, 'Double click to set name');
- const geometry = vertex.getGeometry();
-
- // Updates the geometry of the vertex with the
- // preferred size computed in the graph
- const size = graph.getPreferredSizeForCell(vertex);
- geometry.width = size.width;
- geometry.height = size.height;
-
- // Adds the edge between the existing cell
- // and the new vertex and executes the
- // automatic layout on the parent
- const edge = graph.insertEdge(parent, null, '', cell, vertex);
-
- // Configures the edge label "in-place" to reside
- // at the end of the edge (x = 1) and with an offset
- // of 20 pixels in negative, vertical direction.
- edge.geometry.x = 1;
- edge.geometry.y = 0;
- edge.geometry.offset = new mxPoint(0, -20);
-
- addOverlays(graph, vertex, true);
- } finally {
- model.endUpdate();
- }
-
- return vertex;
- }
-
- function deleteSubtree(graph, cell) {
- // Gets the subtree from cell downwards
- const cells = [];
- graph.traverse(cell, true, function(vertex) {
- cells.push(vertex);
-
- return true;
- });
-
- graph.removeCells(cells);
- }
- }
-}
-
-export default OrgChart;
diff --git a/src/pages/layout/SwimLanes.js b/src/pages/layout/SwimLanes.js
deleted file mode 100644
index defa281fd..000000000
--- a/src/pages/layout/SwimLanes.js
+++ /dev/null
@@ -1,578 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxPoint from '../../mxgraph/util/datatypes/mxPoint';
-import mxStackLayout from '../../mxgraph/layout/mxStackLayout';
-import mxSwimlaneManager from '../../mxgraph/view/graph/mxSwimlaneManager';
-import mxGraphModel from '../../mxgraph/view/graph/mxGraphModel';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxPerimeter from '../../mxgraph/util/datatypes/style/mxPerimeter';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxEditor from '../../mxgraph/editor/mxEditor';
-import mxConnectionHandler from '../../mxgraph/handler/mxConnectionHandler';
-import mxImage from '../../mxgraph/util/image/mxImage';
-import mxLayoutManager from '../../mxgraph/view/graph/mxLayoutManager';
-import mxEdgeStyle from '../../mxgraph/util/datatypes/style/mxEdgeStyle';
-
-class SwimLanes extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Swimlanes
- This example demonstrates using swimlanes for pools and lanes and adding
- cells and edges between them. This also demonstrates using the stack
- layout as an automatic layout.
-
- This example demonstrates loading graph model data dynamically to limit
- the number of cells in the model.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'visible',
- position: 'absolute',
- height: '100%',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- };
-
- componentDidMount() {
- let requestId = 0;
-
- // Speedup the animation
- mxText.prototype.enableBoundingBox = false;
-
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
-
- // Disables all built-in interactions
- graph.setEnabled(false);
-
- // Handles clicks on cells
- graph.addListener(mxEvent.CLICK, function(sender, evt) {
- const cell = evt.getProperty('cell');
-
- if (cell != null) {
- load(graph, cell);
- }
- });
-
- // Changes the default vertex style in-place
- const style = graph.getStylesheet().getDefaultVertexStyle();
- style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;
- style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;
- style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
-
- // Gets the default parent for inserting new cells. This
- // is normally the first child of the root (ie. layer 0).
- const parent = graph.getDefaultParent();
-
- const cx = graph.container.clientWidth / 2;
- const cy = graph.container.clientHeight / 2;
-
- const cell = graph.insertVertex(
- parent,
- '0-0',
- '0-0',
- cx - 20,
- cy - 15,
- 60,
- 40
- );
-
- // Animates the changes in the graph model
- graph.getModel().addListener(mxEvent.CHANGE, function(sender, evt) {
- const { changes } = evt.getProperty('edit');
- mxEffects.animateChanges(graph, changes);
- });
-
- // Loads the links for the given cell into the given graph
- // by requesting the respective data in the server-side
- // (implemented for this demo using the server-function)
- function load(graph, cell) {
- if (cell.isVertex()) {
- const cx = graph.container.clientWidth / 2;
- const cy = graph.container.clientHeight / 2;
-
- // 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 xml = server(cell.id);
- const doc = mxUtils.parseXml(xml);
- const dec = new mxCodec(doc);
- const model = dec.decode(doc.documentElement);
-
- // Removes all cells which are not in the response
- for (var key in graph.getModel().cells) {
- const tmp = graph.getModel().getCell(key);
-
- if (tmp != cell && tmp.isVertex()) {
- graph.removeCells([tmp]);
- }
- }
-
- // Merges the response model with the client model
- graph.getModel().mergeChildren(model.getRoot().getChildAt(0), parent);
-
- // Moves the given cell to the center
- let geo = cell.getGeometry();
-
- if (geo != null) {
- geo = geo.clone();
- geo.x = cx - geo.width / 2;
- geo.y = cy - geo.height / 2;
-
- graph.getModel().setGeometry(cell, geo);
- }
-
- // Creates a list of the new vertices, if there is more
- // than the center vertex which might have existed
- // previously, then this needs to be changed to analyze
- // the target model before calling mergeChildren above
- const vertices = [];
-
- for (var key in graph.getModel().cells) {
- const tmp = graph.getModel().getCell(key);
-
- if (tmp != cell && tmp.isVertex()) {
- vertices.push(tmp);
-
- // Changes the initial location "in-place"
- // to get a nice animation effect from the
- // center to the radius of the circle
- const geo = tmp.getGeometry();
-
- if (geo != null) {
- geo.x = cx - geo.width / 2;
- geo.y = cy - geo.height / 2;
- }
- }
- }
-
- // Arranges the response in a circle
- const cellCount = vertices.length;
- const phi = (2 * Math.PI) / cellCount;
- const r = Math.min(
- graph.container.clientWidth / 4,
- graph.container.clientHeight / 4
- );
-
- for (let i = 0; i < cellCount; i++) {
- let geo = vertices[i].getGeometry();
-
- if (geo != null) {
- geo = geo.clone();
- geo.x += r * Math.sin(i * phi);
- geo.y += r * Math.cos(i * phi);
-
- graph.getModel().setGeometry(vertices[i], geo);
- }
- }
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
- }
- }
-
- // Simulates the existence of a server that can crawl the
- // big graph with a certain depth and create a graph model
- // for the traversed cells, which is then sent to the client
- function server(cellId) {
- // Increments the request ID as a prefix for the cell IDs
- requestId++;
-
- // Creates a local graph with no display
- const graph = new mxGraph();
-
- // 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 v0 = graph.insertVertex(parent, cellId, 'Dummy', 0, 0, 60, 40);
- const cellCount = parseInt(Math.random() * 16) + 4;
-
- // Creates the random links and cells for the response
- for (let i = 0; i < cellCount; i++) {
- const id = `${requestId}-${i}`;
- const v = graph.insertVertex(parent, id, id, 0, 0, 60, 40);
- const e = graph.insertEdge(parent, null, `Link ${i}`, v0, v);
- }
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- const enc = new mxCodec();
- const node = enc.encode(graph.getModel());
-
- return mxUtils.getXml(node);
- }
-
- load(graph, cell);
- };
-}
-
-export default DynamicLoading;
diff --git a/src/pages/misc/Guides.js b/src/pages/misc/Guides.js
deleted file mode 100644
index 0d7148b56..000000000
--- a/src/pages/misc/Guides.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxGraphHandler from '../../mxgraph/handler/mxGraphHandler';
-import mxEdgeHandler from '../../mxgraph/handler/mxEdgeHandler';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxEdgeStyle from '../../mxgraph/util/datatypes/style/mxEdgeStyle';
-import mxKeyHandler from '../../mxgraph/handler/mxKeyHandler';
-
-class Guides extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Guides
- This example demonstrates the guides feature which aligns the current
- selection to the existing vertices in the graph. This feature is in RFC
- state. Creating a grid using a canvas and installing a key handler for
- cursor keys is also demonstrated here, as well as snapping waypoints to
- terminals.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'hidden',
- height: '601px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Enables guides
- mxGraphHandler.prototype.guidesEnabled = true;
-
- // Alt disables guides
- mxGraphHandler.prototype.useGuidesForEvent = function(me) {
- return !mxEvent.isAltDown(me.getEvent());
- };
-
- // Defines the guides to be red (default)
- mxConstants.GUIDE_COLOR = '#FF0000';
-
- // Defines the guides to be 1 pixel (default)
- mxConstants.GUIDE_STROKEWIDTH = 1;
-
- // Enables snapping waypoints to terminals
- mxEdgeHandler.prototype.snapToTerminals = true;
-
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
- graph.setConnectable(true);
- graph.gridSize = 30;
-
- // Changes the default style for edges "in-place" and assigns
- // an alternate edge style which is applied in mxGraph.flip
- // when the user double clicks on the adjustment control point
- // of the edge. The ElbowConnector edge style switches to TopToBottom
- // if the horizontal style is true.
- const style = graph.getStylesheet().getDefaultEdgeStyle();
- style[mxConstants.STYLE_ROUNDED] = true;
- style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;
- graph.alternateEdgeStyle = 'elbow=vertical';
-
- // 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();
- let v1;
- try {
- v1 = graph.insertVertex(parent, null, 'Hello,', 20, 40, 80, 70);
- const v2 = graph.insertVertex(parent, null, 'World!', 200, 140, 80, 40);
- const e1 = graph.insertEdge(parent, null, '', v1, v2);
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- // Handles cursor keys
- const nudge = function(keyCode) {
- if (!graph.isSelectionEmpty()) {
- let dx = 0;
- let dy = 0;
-
- if (keyCode === 37) {
- dx = -1;
- } else if (keyCode === 38) {
- dy = -1;
- } else if (keyCode === 39) {
- dx = 1;
- } else if (keyCode === 40) {
- dy = 1;
- }
-
- graph.moveCells(graph.getSelectionCells(), dx, dy);
- }
-
- // Transfer initial focus to graph container for keystroke handling
- graph.container.focus();
-
- // Handles keystroke events
- const keyHandler = new mxKeyHandler(graph);
-
- // Ignores enter keystroke. Remove this line if you want the
- // enter keystroke to stop editing
- keyHandler.enter = function() {};
-
- keyHandler.bindKey(37, function() {
- nudge(37);
- });
-
- keyHandler.bindKey(38, function() {
- nudge(38);
- });
-
- keyHandler.bindKey(39, function() {
- nudge(39);
- });
-
- keyHandler.bindKey(40, function() {
- nudge(40);
- });
- };
- }
-}
-
-export default Guides;
diff --git a/src/pages/misc/Merge.js b/src/pages/misc/Merge.js
deleted file mode 100644
index d883e58a4..000000000
--- a/src/pages/misc/Merge.js
+++ /dev/null
@@ -1,237 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxPerimeter from '../../mxgraph/util/datatypes/style/mxPerimeter';
-
-class Merge extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Merge
- This example demonstrates using the mergeChildren function to merge two
- graphs.
-
{
- this.el = el;
- }}
- style={{
- position: 'relative',
- overflow: 'hidden',
- height: '280px',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- mxConstants.SHADOWCOLOR = '#c0c0c0';
-
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
-
- // No size handles, please...
- graph.setCellsResizable(false);
-
- // Makes all cells round with a white, bold label
- let style = graph.stylesheet.getDefaultVertexStyle();
- style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;
- style[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;
- style[mxConstants.STYLE_FONTCOLOR] = 'white';
- style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
- style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;
- style[mxConstants.STYLE_FONTSIZE] = 14;
- style[mxConstants.STYLE_SHADOW] = true;
-
- // Makes all edge labels gray with a white background
- style = graph.stylesheet.getDefaultEdgeStyle();
- style[mxConstants.STYLE_FONTCOLOR] = 'gray';
- style[mxConstants.STYLE_FONTSTYLE] = mxConstants.FONT_BOLD;
- style[mxConstants.STYLE_FONTCOLOR] = 'black';
- style[mxConstants.STYLE_STROKEWIDTH] = 2;
-
- // 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 target model in a single step
- // using custom ids for the vertices and edges
- const w = 40;
- const h = 40;
-
- graph.getModel().beginUpdate();
- try {
- const a = graph.insertVertex(
- parent,
- 'a',
- 'A',
- 20,
- 20,
- w,
- h,
- 'fillColor=blue'
- );
- const b = graph.insertVertex(
- parent,
- 'b',
- 'B',
- 20,
- 200,
- w,
- h,
- 'fillColor=blue'
- );
- const c = graph.insertVertex(
- parent,
- 'c',
- 'C',
- 200,
- 20,
- w,
- h,
- 'fillColor=red'
- );
- const d = graph.insertVertex(
- parent,
- 'd',
- 'D',
- 200,
- 200,
- w,
- h,
- 'fillColor=red'
- );
- const ac = graph.insertEdge(
- parent,
- 'ac',
- 'ac',
- a,
- c,
- 'strokeColor=blue;verticalAlign=bottom'
- );
- const ad = graph.insertEdge(
- parent,
- 'ad',
- 'ad',
- a,
- d,
- 'strokeColor=blue;align=left;verticalAlign=bottom'
- );
- const bd = graph.insertEdge(
- parent,
- 'bd',
- 'bd',
- b,
- d,
- 'strokeColor=blue;verticalAlign=bottom'
- );
- } finally {
- // Updates the display
- graph.getModel().endUpdate();
- }
-
- // Creates the second graph model (without a container)
- const graph2 = new mxGraph();
-
- // Gets the default parent for inserting new cells. This
- // is normally the first child of the root (ie. layer 0).
- const parent2 = graph2.getDefaultParent();
-
- // Adds cells to the target model in a single step
- // using custom ids for the vertices
- graph2.getModel().beginUpdate();
- try {
- const c = graph2.insertVertex(
- parent2,
- 'c',
- 'C',
- 200,
- 20,
- w,
- h,
- 'fillColor=green'
- );
- const d = graph2.insertVertex(
- parent2,
- 'd',
- 'D',
- 200,
- 200,
- w,
- h,
- 'fillColor=green'
- );
- const e = graph2.insertVertex(
- parent2,
- 'e',
- 'E',
- 400,
- 20,
- w,
- h,
- 'fillColor=green'
- );
- const f = graph2.insertVertex(
- parent2,
- 'f',
- 'F',
- 400,
- 200,
- w,
- h,
- 'fillColor=green'
- );
- const ce = graph2.insertEdge(
- parent2,
- 'ce',
- 'ce',
- c,
- e,
- 'strokeColor=green;verticalAlign=bottom'
- );
- const ed = graph2.insertEdge(
- parent2,
- 'ed',
- 'ed',
- e,
- d,
- 'strokeColor=green;align=right;verticalAlign=bottom'
- );
- const fd = graph2.insertEdge(
- parent2,
- 'bd',
- 'fd',
- f,
- d,
- 'strokeColor=green;verticalAlign=bottom'
- );
- } finally {
- // Updates the display
- graph2.getModel().endUpdate();
- }
-
- // Merges the model from the second graph into the model of
- // the first graph. Note: If you add a false to the parameter
- // list then _not_ all edges will be cloned, that is, the
- // edges are assumed to have an identity, and hence the edge
- // "bd" will be changed to point from f to d, as specified in
- // the edge for the same id in the second graph.
- graph.getModel().mergeChildren(parent2, parent /* , false */);
- }
-}
-
-export default Merge;
diff --git a/src/pages/misc/Monitor.js b/src/pages/misc/Monitor.js
deleted file mode 100644
index df3ebadda..000000000
--- a/src/pages/misc/Monitor.js
+++ /dev/null
@@ -1,296 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxEvent from '../../mxgraph/util/event/mxEvent';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxCellOverlay from '../../mxgraph/view/cell/mxCellOverlay';
-import mxUtils from '../../mxgraph/util/mxUtils';
-import mxCodec from '../../mxgraph/serialization/mxCodec';
-import mxPerimeter from '../../mxgraph/util/datatypes/style/mxPerimeter';
-import mxEdgeStyle from '../../mxgraph/util/datatypes/style/mxEdgeStyle';
-
-class Monitor extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Workflow Monitor
- This example demonstrates using a graph to display the current state of
- a workflow.
-
- This example demonstrates changing the style of a cell dynamically by
- overriding mxGraphModel.getStyle.
-
{
- this.el = el;
- }}
- style={{
- overflow: 'hidden',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- }}
- />
- >
- );
- };
-
- componentDidMount() {
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
-
- // Disables moving of edge labels in this examples
- graph.edgeLabelsMovable = false;
-
- // Enables rubberband selection
- new mxRubberband(graph);
-
- // Needs to set a flag to check for dynamic style changes,
- // that is, changes to styles on cells where the style was
- // not explicitely changed using mxStyleChange
- graph.getView().updateStyle = true;
-
- // Overrides mxCell.getStyle to return a specific style
- // for edges that reflects their target terminal (in this case
- // the strokeColor will be equal to the target's fillColor).
-
- const getStyle = function() {
- let style = super.getStyle();
-
- if (this.isEdge()) {
- const target = this.getTerminal(false);
-
- if (target != null) {
- const targetStyle = graph.getCurrentCellStyle(target);
- const fill = mxUtils.getValue(
- targetStyle,
- mxConstants.STYLE_FILLCOLOR
- );
-
- if (fill != null) {
- style += `;strokeColor=${fill}`;
- }
- }
- } else if (this.isVertex()) {
- const geometry = this.getGeometry();
- if (geometry != null && geometry.width > 80) {
- style += ';fillColor=green';
- }
- }
- return style;
- };
-
- // 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],
- style: 'fillColor=green',
- });
- v1.getStyle = getStyle;
-
- const v2 = graph.insertVertex({
- parent,
- value: 'World!',
- position: [200, 150],
- size: [80, 30],
- style: 'fillColor=blue',
- });
- v2.getStyle = getStyle;
-
- const v3 = graph.insertVertex({
- parent,
- value: 'World!',
- position: [20, 150],
- size: [80, 30],
- style: 'fillColor=red',
- });
- v3.getStyle = getStyle;
-
- const e1 = graph.insertEdge({
- parent,
- value: 'Connect',
- source: v1,
- target: v2,
- style: 'perimeterSpacing=4;strokeWidth=4;labelBackgroundColor=white;fontStyle=1',
- });
- e1.getStyle = getStyle;
- });
- };
-}
-
-export default DynamicStyle;
diff --git a/src/pages/styles/HoverStyle.js b/src/pages/styles/HoverStyle.js
deleted file mode 100644
index d0eca3ff1..000000000
--- a/src/pages/styles/HoverStyle.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxRubberband from '../../mxgraph/handler/mxRubberband';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxUtils from '../../mxgraph/util/mxUtils';
-
-class HoverStyle extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Hoverstyle
- This example shows hot to change the style of a vertex on mouseover.
-
{
- this.el = el;
- }}
- style={{
- position: 'relative',
- overflow: 'hidden',
- height: '241px',
- background: "url('editors/images/grid.gif')",
- cursor: 'default',
- }}
- />
- >
- );
- }
-
- componentDidMount() {
- // Creates the graph inside the given container
- const graph = new mxGraph(this.el);
-
- function updateStyle(state, hover) {
- if (hover) {
- state.style[mxConstants.STYLE_FILLCOLOR] = '#ff0000';
- }
-
- // Sets rounded style for both cases since the rounded style
- // is not set in the default style and is therefore inherited
- // once it is set, whereas the above overrides the default value
- state.style[mxConstants.STYLE_ROUNDED] = hover ? '1' : '0';
- state.style[mxConstants.STYLE_STROKEWIDTH] = hover ? '4' : '1';
- state.style[mxConstants.STYLE_FONTSTYLE] = hover
- ? mxConstants.FONT_BOLD
- : '0';
- }
-
- // Changes fill color to red on mouseover
- graph.addMouseListener({
- currentState: null,
- previousStyle: null,
- mouseDown(sender, me) {
- if (this.currentState != null) {
- this.dragLeave(me.getEvent(), this.currentState);
- this.currentState = null;
- }
- },
- mouseMove(sender, me) {
- if (this.currentState != null && me.getState() == this.currentState) {
- return;
- }
-
- let tmp = graph.view.getState(me.getCell());
-
- // Ignores everything but vertices
- if (
- graph.isMouseDown ||
- (tmp != null && !tmp.cell.isVertex())
- ) {
- tmp = null;
- }
-
- if (tmp != this.currentState) {
- if (this.currentState != null) {
- this.dragLeave(me.getEvent(), this.currentState);
- }
-
- this.currentState = tmp;
-
- if (this.currentState != null) {
- this.dragEnter(me.getEvent(), this.currentState);
- }
- }
- },
- mouseUp(sender, me) {},
- dragEnter(evt, state) {
- if (state != null) {
- this.previousStyle = state.style;
- state.style = mxUtils.clone(state.style);
- updateStyle(state, true);
- state.shape.apply(state);
- state.shape.redraw();
-
- if (state.text != null) {
- state.text.apply(state);
- state.text.redraw();
- }
- }
- },
- dragLeave(evt, state) {
- if (state != null) {
- state.style = this.previousStyle;
- updateStyle(state, false);
- state.shape.apply(state);
- state.shape.redraw();
-
- if (state.text != null) {
- state.text.apply(state);
- state.text.redraw();
- }
- }
- },
- });
-
- // 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();
- }
- }
-}
-
-export default HoverStyle;
diff --git a/src/pages/styles/Stylesheet.js b/src/pages/styles/Stylesheet.js
deleted file mode 100644
index 3018c898b..000000000
--- a/src/pages/styles/Stylesheet.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * Copyright (c) 2006-2013, JGraph Ltd
- * Converted to ES9 syntax/React by David Morrissey 2021
- */
-
-import React from 'react';
-import mxGraph from '../../mxgraph/view/graph/mxGraph';
-import mxConstants from '../../mxgraph/util/mxConstants';
-import mxEdgeStyle from '../../mxgraph/util/datatypes/style/mxEdgeStyle';
-import mxPerimeter from '../../mxgraph/util/datatypes/style/mxPerimeter';
-
-class Stylesheet extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- // A container for the graph
- return (
- <>
-
Stylesheet
- This example demonstrates using a custom stylesheet and control points
- in edges, as well as overriding the getLabel and getTooltip function to
- return dynamic information, and making a supercall in JavaScript.
-
-Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
-dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
-ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
-fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
-mollit anim id est laborum.
-
- See Help Index
-
-
diff --git a/src/public/editors/images/connector.gif b/src/public/editors/images/connector.gif
deleted file mode 100644
index 326e061ea..000000000
Binary files a/src/public/editors/images/connector.gif and /dev/null differ
diff --git a/src/public/editors/images/grid.gif b/src/public/editors/images/grid.gif
deleted file mode 100644
index a82a20d00..000000000
Binary files a/src/public/editors/images/grid.gif and /dev/null differ
diff --git a/src/public/editors/images/loading.gif b/src/public/editors/images/loading.gif
deleted file mode 100644
index 7bb834d66..000000000
Binary files a/src/public/editors/images/loading.gif and /dev/null differ
diff --git a/src/public/editors/images/printer.png b/src/public/editors/images/printer.png
deleted file mode 100644
index 7d364686a..000000000
Binary files a/src/public/editors/images/printer.png and /dev/null differ
diff --git a/src/public/editors/js/app.js b/src/public/editors/js/app.js
deleted file mode 100644
index 940162290..000000000
--- a/src/public/editors/js/app.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2006-2013, JGraph Ltd
- *
- * Defines the startup sequence of the application.
- */
-{
- /**
- * Constructs a new application (returns an mxEditor instance)
- */
- function createEditor(config) {
- let editor = null;
-
- const hideSplash = function() {
- // Fades-out the splash screen
- const splash = document.getElementById('splash');
-
- if (splash != null) {
- try {
- mxEvent.release(splash);
- mxEffects.fadeOut(splash, 100, true);
- } catch (e) {
- splash.parentNode.removeChild(splash);
- }
- }
- };
-
- try {
- if (!mxClient.isBrowserSupported()) {
- mxUtils.error('Browser is not supported!', 200, false);
- } else {
- mxObjectCodec.allowEval = true;
- const node = mxUtils.load(config).getDocumentElement();
- editor = new mxEditor(node);
- mxObjectCodec.allowEval = false;
-
- // Adds active border for panning inside the container
- editor.graph.createPanningManager = function() {
- const pm = new mxPanningManager(this);
- pm.border = 30;
-
- return pm;
- };
-
- editor.graph.allowAutoPanning = true;
- editor.graph.timerAutoScroll = true;
-
- // Updates the window title after opening new files
- const { title } = document;
- const funct = function(sender) {
- document.title = `${title} - ${sender.getTitle()}`;
- };
-
- editor.addListener(mxEvent.OPEN, funct);
-
- // Prints the current root in the window title if the
- // current root of the graph changes (drilling).
- editor.addListener(mxEvent.ROOT, funct);
- funct(editor);
-
- // Displays version in statusbar
- editor.setStatus(`mxGraph ${mxClient.VERSION}`);
-
- // Shows the application
- hideSplash();
- }
- } catch (e) {
- hideSplash();
-
- // Shows an error message if the editor cannot start
- mxUtils.alert(`Cannot start application: ${e.message}`);
- throw e; // for debugging
- }
-
- return editor;
- }
-}
diff --git a/src/public/editors/layouteditor.html b/src/public/editors/layouteditor.html
deleted file mode 100644
index 35a1695e6..000000000
--- a/src/public/editors/layouteditor.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- mxGraph Workflow Designer
-
-
-
-
-
-
-
-