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 {
/**
* Variable: medianValue
*
* The weighted value of the cell stored.
*/
medianValue = 0;
/**
* Variable: cell
*
* The cell whose median value is being calculated
*/
cell = false;
constructor() {
// empty
}

View File

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

View File

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

View File

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

View File

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

View File

@ -9,8 +9,8 @@ import mxGraph from '../mxgraph/view/mxGraph';
import mxRubberband from '../mxgraph/handler/mxRubberband';
import mxConstants from '../mxgraph/util/mxConstants';
import mxPoint from '../mxgraph/util/mxPoint';
import mxGraphHandler from "../mxgraph/handler/mxGraphHandler";
import mxUtils from "../mxgraph/util/mxUtils";
import mxGraphHandler from '../mxgraph/handler/mxGraphHandler';
import mxUtils from '../mxgraph/util/mxUtils';
class Boundary extends React.Component {
constructor(props) {
@ -18,13 +18,11 @@ class Boundary extends React.Component {
}
render = () => {
// A this.el for the graph
// A container for the graph
return (
<>
<h1>Boundary</h1>
This example demonstrates
implementing boundary events in BPMN diagrams.
This example demonstrates implementing boundary events in BPMN diagrams.
<div
ref={el => {
this.el = el;
@ -34,7 +32,7 @@ class Boundary extends React.Component {
overflow: 'hidden',
height: '241px',
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
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
const graph = new mxGraph(this.el);
const graph = new MyCustomGraph(this.el);
// Sets the base style for all vertices
const style = graph.getStylesheet().getDefaultVertexStyle();
@ -59,87 +145,6 @@ class Boundary extends React.Component {
style[mxConstants.STYLE_FONTSTYLE] = 1;
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
graph.graphHandler.getDelta = function(me) {
const point = mxUtils.convertPoint(
@ -155,7 +160,7 @@ class Boundary extends React.Component {
this.cells[0] != null
) {
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) {
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
new mxRubberband(graph);
@ -203,37 +203,34 @@ class Boundary extends React.Component {
const parent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try {
const v1 = graph.insertVertex(parent, null, 'Process', 60, 60, 90, 40);
const v2 = graph.insertVertex(
v1,
null,
'in',
0,
0.5,
20,
20,
'fontSize=9;shape=ellipse;resizable=0;'
);
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(
v1,
null,
'out',
1,
0.5,
20,
20,
'fontSize=9;shape=ellipse;resizable=0;'
);
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;
} finally {
// Updates the display
graph.getModel().endUpdate();
}
});
};
}

View File

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

View File

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