bugfixes+example cleanups

development
mcyph 2021-03-26 11:56:58 +11:00
parent 8c63f00adb
commit 0319692cca
8 changed files with 266 additions and 244 deletions

View File

@ -1,4 +1,18 @@
class MedianCellSorter { class MedianCellSorter {
/**
* Variable: medianValue
*
* The weighted value of the cell stored.
*/
medianValue = 0;
/**
* Variable: cell
*
* The cell whose median value is being calculated
*/
cell = false;
constructor() { constructor() {
// empty // empty
} }

View File

@ -4533,7 +4533,7 @@ class mxGraph extends mxEventSource {
const params = args[0]; const params = args[0];
parent = params.parent; parent = params.parent;
id = params.id; id = params.id;
value = params.value; value = params.value || '';
source = params.source; source = params.source;
target = params.target; target = params.target;
style = params.style; style = params.style;

View File

@ -83,9 +83,24 @@ class Anchors extends React.Component {
// Adds cells to the model in a single step // Adds cells to the model in a single step
graph.getModel().beginUpdate(); graph.getModel().beginUpdate();
try { try {
const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); const v1 = graph.insertVertex({
const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30); parent,
const e1 = graph.insertEdge(parent, null, '', v1, v2); 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,
value: '',
position: v1,
size: v2,
});
} finally { } finally {
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
@ -97,9 +112,8 @@ class Anchors extends React.Component {
return ( return (
<> <>
<h1>Anchors</h1> <h1>Anchors</h1>
This example demonstrates defining This example demonstrates defining fixed connection points for all
fixed connection points for all shapes. shapes.
<div <div
ref={el => { ref={el => {
this.el = el; this.el = el;

View File

@ -47,34 +47,27 @@ class Animation extends React.Component {
graph.getModel().beginUpdate(); graph.getModel().beginUpdate();
try { try {
const v1 = graph.insertVertex( const v1 = graph.insertVertex({
parent, parent,
null, value: 'Pump',
'Pump', position: [20, 20],
20, size: [60, 60],
20, style: vertexStyle,
60, });
60, const v2 = graph.insertVertex({
vertexStyle
);
const v2 = graph.insertVertex(
parent, parent,
null, value: 'Tank',
'Tank', position: [200, 150],
200, size: [60, 60],
150, style: vertexStyle,
60, });
60, var e1 = graph.insertEdge({
vertexStyle
);
var e1 = graph.insertEdge(
parent, parent,
null, source: v1,
'', target: v2,
v1, style:
v2, 'strokeWidth=3;endArrow=block;endSize=2;endFill=1;strokeColor=black;rounded=1;',
'strokeWidth=3;endArrow=block;endSize=2;endFill=1;strokeColor=black;rounded=1;' });
);
e1.geometry.points = [new mxPoint(230, 50)]; e1.geometry.points = [new mxPoint(230, 50)];
graph.orderCells(true, [e1]); graph.orderCells(true, [e1]);
} finally { } finally {

View File

@ -24,13 +24,12 @@ class AutoLayout extends React.Component {
} }
render = () => { render = () => {
// A this.el for the graph // A container for the graph
return ( return (
<> <>
<h1>Auto layout</h1> <h1>Auto layout</h1>
This example demonstrates running This example demonstrates running and animating a layout algorithm after
and animating a layout algorithm after every change to a graph. every change to a graph.
<div <div
ref={el => { ref={el => {
this.el = el; this.el = el;
@ -50,36 +49,49 @@ class AutoLayout extends React.Component {
componentDidMount = () => { componentDidMount = () => {
mxEvent.disableContextMenu(this.el); mxEvent.disableContextMenu(this.el);
const mxCellRendererInstallCellOverlayListeners = class MyCustomCellRenderer extends mxCellRenderer {
mxCellRenderer.prototype.installCellOverlayListeners; installCellOverlayListeners(state, overlay, shape) {
mxCellRenderer.prototype.installCellOverlayListeners = function( super.installCellOverlayListeners(state, overlay, shape);
state,
overlay,
shape
) {
mxCellRendererInstallCellOverlayListeners.apply(this, arguments);
mxEvent.addListener( mxEvent.addListener(
shape.node, shape.node,
mxClient.IS_POINTER ? 'pointerdown' : 'mousedown', mxClient.IS_POINTER ? 'pointerdown' : 'mousedown',
function(evt) { function(evt) {
overlay.fireEvent( overlay.fireEvent(
new mxEventObject('pointerdown', 'event', evt, 'state', state) new mxEventObject('pointerdown', 'event', evt, 'state', state)
); );
}
);
if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {
mxEvent.addListener(shape.node, 'touchstart', function(evt) {
overlay.fireEvent(
new mxEventObject('pointerdown', 'event', evt, 'state', state)
);
});
} }
); };
}
if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) { class MyCustomEdgeHandler extends mxEdgeHandler {
mxEvent.addListener(shape.node, 'touchstart', function(evt) { connect(edge, terminal, isSource, isClone, me) {
overlay.fireEvent( super.connect(edge, terminal, isSource, isClone, me);
new mxEventObject('pointerdown', 'event', evt, 'state', state) executeLayout();
);
});
} }
}; }
class MyCustomGraph extends mxGraph {
createEdgeHandler(state, edgeStyle) {
return new MyCustomEdgeHandler(state, edgeStyle);
}
createCellRenderer() {
return new MyCustomCellRenderer();
}
}
// Creates the graph inside the given this.el // Creates the graph inside the given this.el
const graph = new mxGraph(this.el); const graph = new MyCustomGraph(this.el);
graph.setPanning(true); graph.setPanning(true);
graph.panningHandler.useLeftButtonForPanning = true; graph.panningHandler.useLeftButtonForPanning = true;
graph.setAllowDanglingEdges(false); graph.setAllowDanglingEdges(false);
@ -94,7 +106,7 @@ class AutoLayout extends React.Component {
const parent = graph.getDefaultParent(); const parent = graph.getDefaultParent();
const layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST); const layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);
const executeLayout = function(change, post) { const executeLayout = (change, post) => {
graph.getModel().beginUpdate(); graph.getModel().beginUpdate();
try { try {
if (change != null) { if (change != null) {
@ -106,15 +118,12 @@ class AutoLayout extends React.Component {
} finally { } finally {
// New API for animating graph layout results asynchronously // New API for animating graph layout results asynchronously
const morph = new mxMorphing(graph); const morph = new mxMorphing(graph);
morph.addListener( morph.addListener(mxEvent.DONE, () => {
mxEvent.DONE, graph.getModel().endUpdate();
mxUtils.bind(this, function() { if (post != null) {
graph.getModel().endUpdate(); post();
if (post != null) { }
post(); });
}
})
);
morph.startAnimation(); morph.startAnimation();
} }
}; };
@ -136,18 +145,19 @@ class AutoLayout extends React.Component {
executeLayout( executeLayout(
function() { function() {
v2 = graph.insertVertex( v2 = graph.insertVertex({
parent, parent,
null, value: 'World!',
'World!', position: [geo.x, geo.y],
geo.x, size: [80, 30],
geo.y, });
80,
30
);
addOverlay(v2); addOverlay(v2);
graph.view.refresh(v2); graph.view.refresh(v2);
const e1 = graph.insertEdge(parent, null, '', cell, v2); const e1 = graph.insertEdge({
parent,
source: cell,
target: v2,
});
}, },
function() { function() {
graph.scrollCellToVisible(v2); graph.scrollCellToVisible(v2);
@ -182,25 +192,18 @@ class AutoLayout extends React.Component {
graph.getModel().beginUpdate(); graph.getModel().beginUpdate();
let v1; let v1;
try { try {
v1 = graph.insertVertex(parent, null, 'Hello,', 0, 0, 80, 30); v1 = graph.insertVertex({
parent,
value: 'Hello,',
position: [0, 0],
size: [80, 30],
});
addOverlay(v1); addOverlay(v1);
} finally { } finally {
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
} }
const edgeHandleConnect = mxEdgeHandler.prototype.connect;
mxEdgeHandler.prototype.connect = function(
edge,
terminal,
isSource,
isClone,
me
) {
edgeHandleConnect.apply(this, arguments);
executeLayout();
};
graph.resizeCell = function() { graph.resizeCell = function() {
mxGraph.prototype.resizeCell.apply(this, arguments); mxGraph.prototype.resizeCell.apply(this, arguments);
executeLayout(); executeLayout();

View File

@ -9,8 +9,8 @@ import mxGraph from '../mxgraph/view/mxGraph';
import mxRubberband from '../mxgraph/handler/mxRubberband'; import mxRubberband from '../mxgraph/handler/mxRubberband';
import mxConstants from '../mxgraph/util/mxConstants'; import mxConstants from '../mxgraph/util/mxConstants';
import mxPoint from '../mxgraph/util/mxPoint'; import mxPoint from '../mxgraph/util/mxPoint';
import mxGraphHandler from "../mxgraph/handler/mxGraphHandler"; import mxGraphHandler from '../mxgraph/handler/mxGraphHandler';
import mxUtils from "../mxgraph/util/mxUtils"; import mxUtils from '../mxgraph/util/mxUtils';
class Boundary extends React.Component { class Boundary extends React.Component {
constructor(props) { constructor(props) {
@ -18,13 +18,11 @@ class Boundary extends React.Component {
} }
render = () => { render = () => {
// A this.el for the graph // A container for the graph
return ( return (
<> <>
<h1>Boundary</h1> <h1>Boundary</h1>
This example demonstrates This example demonstrates implementing boundary events in BPMN diagrams.
implementing boundary events in BPMN diagrams.
<div <div
ref={el => { ref={el => {
this.el = el; this.el = el;
@ -34,7 +32,7 @@ class Boundary extends React.Component {
overflow: 'hidden', overflow: 'hidden',
height: '241px', height: '241px',
background: 'url("editors/images/grid.gif")', background: 'url("editors/images/grid.gif")',
cursor: 'default' cursor: 'default',
}} }}
/> />
</> </>
@ -45,8 +43,96 @@ class Boundary extends React.Component {
// Disables the built-in context menu // Disables the built-in context menu
mxEvent.disableContextMenu(this.el); 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 = this.model.getChildCount(cell);
for (let i = 0; i < childCount; i++) {
const child = this.model.getChildAt(cell, 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 = model.getGeometry(state.cell);
if (geo != null && geo.relative && !model.isEdge(state.cell)) {
const parent = model.getParent(state.cell);
if (model.isVertex(parent)) {
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 = this.model.getGeometry(cell);
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 // Creates the graph inside the given this.el
const graph = new mxGraph(this.el); const graph = new MyCustomGraph(this.el);
// Sets the base style for all vertices // Sets the base style for all vertices
const style = graph.getStylesheet().getDefaultVertexStyle(); const style = graph.getStylesheet().getDefaultVertexStyle();
@ -59,87 +145,6 @@ class Boundary extends React.Component {
style[mxConstants.STYLE_FONTSTYLE] = 1; style[mxConstants.STYLE_FONTSTYLE] = 1;
graph.getStylesheet().putDefaultVertexStyle(style); graph.getStylesheet().putDefaultVertexStyle(style);
// Removes folding icon for relative children
graph.isCellFoldable = function(cell, collapse) {
const childCount = this.model.getChildCount(cell);
for (let i = 0; i < childCount; i++) {
const child = this.model.getChildAt(cell, i);
const geo = this.getCellGeometry(child);
if (geo != null && geo.relative) {
return false;
}
}
return childCount > 0;
};
// Returns the relative position of the given child
function getRelativePosition(state, dx, dy) {
if (state != null) {
const model = graph.getModel();
const geo = model.getGeometry(state.cell);
if (geo != null && geo.relative && !model.isEdge(state.cell)) {
const parent = model.getParent(state.cell);
if (model.isVertex(parent)) {
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
graph.translateCell = function(cell, dx, dy) {
const rel = getRelativePosition(
this.view.getState(cell),
dx * graph.view.scale,
dy * graph.view.scale
);
if (rel != null) {
let geo = this.model.getGeometry(cell);
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);
}
};
// Replaces move preview for relative children // Replaces move preview for relative children
graph.graphHandler.getDelta = function(me) { graph.graphHandler.getDelta = function(me) {
const point = mxUtils.convertPoint( const point = mxUtils.convertPoint(
@ -155,7 +160,7 @@ class Boundary extends React.Component {
this.cells[0] != null this.cells[0] != null
) { ) {
const state = this.graph.view.getState(this.cells[0]); const state = this.graph.view.getState(this.cells[0]);
const rel = getRelativePosition(state, delta.x, delta.y); const rel = graph.getRelativePosition(state, delta.x, delta.y);
if (rel != null) { if (rel != null) {
const pstate = this.graph.view.getState( const pstate = this.graph.view.getState(
@ -190,11 +195,6 @@ class Boundary extends React.Component {
); );
}; };
// Enables moving of relative children
graph.isCellLocked = function(cell) {
return false;
};
// Enables rubberband selection // Enables rubberband selection
new mxRubberband(graph); new mxRubberband(graph);
@ -203,37 +203,34 @@ class Boundary extends React.Component {
const parent = graph.getDefaultParent(); const parent = graph.getDefaultParent();
// Adds cells to the model in a single step // Adds cells to the model in a single step
graph.getModel().beginUpdate(); graph.batchUpdate(() => {
try { const v1 = graph.insertVertex({
const v1 = graph.insertVertex(parent, null, 'Process', 60, 60, 90, 40); parent,
const v2 = graph.insertVertex( value: 'Process',
v1, position: [60, 60],
null, size: [90, 40],
'in', });
0,
0.5, const v2 = graph.insertVertex({
20, parent: v1,
20, value: 'in',
'fontSize=9;shape=ellipse;resizable=0;' position: [0, 0.5],
); size: [20, 20],
style: 'fontSize=9;shape=ellipse;resizable=0;',
});
v2.geometry.offset = new mxPoint(-10, -10); v2.geometry.offset = new mxPoint(-10, -10);
v2.geometry.relative = true; v2.geometry.relative = true;
const v3 = graph.insertVertex(
v1, const v3 = graph.insertVertex({
null, parent: v1,
'out', value: 'out',
1, position: [1, 0.5],
0.5, size: [20, 20],
20, style: 'fontSize=9;shape=ellipse;resizable=0;',
20, });
'fontSize=9;shape=ellipse;resizable=0;'
);
v3.geometry.offset = new mxPoint(-10, -10); v3.geometry.offset = new mxPoint(-10, -10);
v3.geometry.relative = true; v3.geometry.relative = true;
} finally { });
// Updates the display
graph.getModel().endUpdate();
}
}; };
} }

View File

@ -19,13 +19,12 @@ class Clipboard extends React.Component {
} }
render = () => { render = () => {
// A this.el for the graph // A container for the graph
return ( return (
<> <>
<h1>Clipboard</h1> <h1>Clipboard</h1>
This example demonstrates using the clipboard This example demonstrates using the clipboard for providing cross-tab
for providing cross-tab and cross-browser copy and paste. and cross-browser copy and paste.
<div <div
ref={el => { ref={el => {
this.el = el; this.el = el;
@ -277,7 +276,7 @@ class Clipboard extends React.Component {
} }
}; };
// Cross-browser function to fetch text from paste events // Function to fetch text from paste events
const extractGraphModelFromEvent = function(evt) { const extractGraphModelFromEvent = function(evt) {
let data = null; let data = null;
@ -286,22 +285,18 @@ class Clipboard extends React.Component {
evt.dataTransfer != null ? evt.dataTransfer : evt.clipboardData; evt.dataTransfer != null ? evt.dataTransfer : evt.clipboardData;
if (provider != null) { if (provider != null) {
if (document.documentMode === 10 || document.documentMode === 11) { data =
data = provider.getData('Text'); mxUtils.indexOf(provider.types, 'text/html') >= 0
} else { ? provider.getData('text/html')
data = : null;
mxUtils.indexOf(provider.types, 'text/html') >= 0
? provider.getData('text/html')
: null;
if ( if (
mxUtils.indexOf( mxUtils.indexOf(
provider.types, provider.types,
'text/plain' && (data == null || data.length === 0) 'text/plain' && (data == null || data.length === 0)
) )
) { ) {
data = provider.getData('text/plain'); data = provider.getData('text/plain');
}
} }
} }
} }
@ -343,15 +338,21 @@ class Clipboard extends React.Component {
const parent = graph.getDefaultParent(); const parent = graph.getDefaultParent();
// Adds cells to the model in a single step // Adds cells to the model in a single step
graph.getModel().beginUpdate(); graph.batchUpdate(() => {
try { const v1 = graph.insertVertex({
const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30); parent,
const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30); value: 'Hello,',
const e1 = graph.insertEdge(parent, null, '', v1, v2); position: [20, 20],
} finally { size: [80, 30],
// Updates the display });
graph.getModel().endUpdate(); const v2 = graph.insertVertex({
} parent,
value: 'World!',
position: [200, 150],
size: [80, 30],
});
const e1 = graph.insertEdge({ parent, source: v1, target: v2 });
});
}; };
} }

View File

@ -16,7 +16,7 @@ class Drop extends React.Component {
} }
render() { render() {
// A this.el for the graph // A container for the graph
return ( return (
<> <>
<h1>Drop</h1> <h1>Drop</h1>