reduced various prototype sharing issues

development
mcyph 2021-04-10 14:04:32 +10:00
parent 685fe13682
commit 6205852cac
4 changed files with 160 additions and 145 deletions

View File

@ -71,7 +71,7 @@ const toBool = (i: any): boolean => {
*/ */
class mxShape { class mxShape {
constructor(stencil: mxStencil | null=null) { constructor(stencil: mxStencil | null=null) {
if (stencil !== mxConstants.DO_NOTHING) { if (stencil) {
this.stencil = stencil; this.stencil = stencil;
} }
} }

View File

@ -3660,6 +3660,8 @@ class mxGraph extends mxEventSource {
* style - Optional string that defines the cell style. * style - Optional string that defines the cell style.
* relative - Optional boolean that specifies if the geometry is relative. * relative - Optional boolean that specifies if the geometry is relative.
* Default is false. * Default is false.
* geometryClass - Optional class reference to a class derived from mxGeometry.
* This can be useful for defining custom constraints.
*/ */
insertVertex = (...args: any[]): mxCell => { insertVertex = (...args: any[]): mxCell => {
let parent; let parent;
@ -3671,6 +3673,7 @@ class mxGraph extends mxEventSource {
let height; let height;
let style; let style;
let relative; let relative;
let geometryClass;
if (args.length === 1) { if (args.length === 1) {
// If only a single parameter, treat as an object // If only a single parameter, treat as an object
@ -3687,10 +3690,11 @@ class mxGraph extends mxEventSource {
style = params.style; style = params.style;
relative = params.relative; relative = params.relative;
geometryClass = params.geometryClass;
} else { } else {
// Otherwise treat as arguments // Otherwise treat as arguments
[parent, id, value, x, y, width, height, style, relative] = args; [parent, id, value, x, y, width, height, style, relative, geometryClass] = args;
} }
const vertex = this.createVertex( const vertex = this.createVertex(
@ -3702,7 +3706,8 @@ class mxGraph extends mxEventSource {
width, width,
height, height,
style, style,
relative relative,
geometryClass
); );
return this.addCell(vertex, parent); return this.addCell(vertex, parent);
}; };
@ -3720,10 +3725,11 @@ class mxGraph extends mxEventSource {
width: number, width: number,
height: number, height: number,
style: any, style: any,
relative: boolean=false) { relative: boolean=false,
geometryClass: typeof mxGeometry=mxGeometry) {
// Creates the geometry for the vertex // Creates the geometry for the vertex
const geometry = new mxGeometry(x, y, width, height); const geometry = new geometryClass(x, y, width, height);
geometry.relative = relative != null ? relative : false; geometry.relative = relative != null ? relative : false;
// Creates the vertex // Creates the vertex

View File

@ -100,7 +100,7 @@ class Anchors extends React.Component {
// Edges have no connection points // Edges have no connection points
mxPolyline.prototype.constraints = null; mxPolyline.prototype.constraints = null;
// Creates the graph inside the given this.el // Creates the graph inside the given container
const graph = new MyCustomGraph(this.el); const graph = new MyCustomGraph(this.el);
graph.setConnectable(true); graph.setConnectable(true);

View File

@ -43,112 +43,126 @@ class FixedPoints extends React.Component {
} }
componentDidMount() { componentDidMount() {
// Snaps to fixed points class MyCustomConstraintHandler extends mxConstraintHandler {
mxConstraintHandler.prototype.intersects = function( // Snaps to fixed points
icon, intersects(icon, point, source, existingEdge) {
point, return (
source, !source || existingEdge || mxUtils.intersects(icon.bounds, point)
existingEdge
) {
return !source || existingEdge || mxUtils.intersects(icon.bounds, point);
};
// Special case: Snaps source of new connections to fixed points
// Without a connect preview in connectionHandler.createEdgeState mouseMove
// and getSourcePerimeterPoint should be overriden by setting sourceConstraint
// sourceConstraint to null in mouseMove and updating it and returning the
// nearest point (cp) in getSourcePerimeterPoint (see below)
const mxConnectionHandlerUpdateEdgeState =
mxConnectionHandler.prototype.updateEdgeState;
mxConnectionHandler.prototype.updateEdgeState = function(pt, constraint) {
if (pt != null && this.previous != null) {
const constraints = this.graph.getAllConnectionConstraints(
this.previous
); );
let nearestConstraint = null;
let dist = null;
for (let i = 0; i < constraints.length; i++) {
const cp = this.graph.getConnectionPoint(
this.previous,
constraints[i]
);
if (cp != null) {
const tmp =
(cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
if (dist == null || tmp < dist) {
nearestConstraint = constraints[i];
dist = tmp;
}
}
}
if (nearestConstraint != null) {
this.sourceConstraint = nearestConstraint;
}
// In case the edge style must be changed during the preview:
// this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';
// And to use the new edge style in the new edge inserted into the graph,
// update the cell style as follows:
// this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);
} }
mxConnectionHandlerUpdateEdgeState.apply(this, arguments);
};
// Creates the graph inside the given container
const graph = new mxGraph(this.el);
graph.setConnectable(true);
// graph.connectionHandler.connectImage = new mxImage('images/connector.gif', 16, 16);
// Disables floating connections (only use with no connect image)
if (graph.connectionHandler.connectImage == null) {
graph.connectionHandler.isConnectableCell = function(cell) {
return false;
};
mxEdgeHandler.prototype.isConnectableCell = function(cell) {
return graph.connectionHandler.isConnectableCell(cell);
};
} }
graph.getAllConnectionConstraints = function(terminal) { class MyCustomConnectionHandler extends mxConnectionHandler {
if (terminal != null && this.model.isVertex(terminal.cell)) { // connectImage = new mxImage('images/connector.gif', 16, 16);
return [
new mxConnectionConstraint(new mxPoint(0, 0), true), isConnectableCell(cell) {
new mxConnectionConstraint(new mxPoint(0.5, 0), true), return false;
new mxConnectionConstraint(new mxPoint(1, 0), true),
new mxConnectionConstraint(new mxPoint(0, 0.5), true),
new mxConnectionConstraint(new mxPoint(1, 0.5), true),
new mxConnectionConstraint(new mxPoint(0, 1), true),
new mxConnectionConstraint(new mxPoint(0.5, 1), true),
new mxConnectionConstraint(new mxPoint(1, 1), true),
];
} }
return null; /*
}; * Special case: Snaps source of new connections to fixed points
* Without a connect preview in connectionHandler.createEdgeState mouseMove
* and getSourcePerimeterPoint should be overriden by setting sourceConstraint
* sourceConstraint to null in mouseMove and updating it and returning the
* nearest point (cp) in getSourcePerimeterPoint (see below)
*/
updateEdgeState(pt, constraint) {
if (pt != null && this.previous != null) {
const constraints = this.graph.getAllConnectionConstraints(
this.previous
);
let nearestConstraint = null;
let dist = null;
// Connect preview for (let i = 0; i < constraints.length; i++) {
graph.connectionHandler.createEdgeState = function(me) { const cp = this.graph.getConnectionPoint(
const edge = graph.createEdge( this.previous,
null, constraints[i]
null, );
null,
null,
null,
'edgeStyle=orthogonalEdgeStyle'
);
return new mxCellState( if (cp != null) {
this.graph.view, const tmp =
edge, (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
this.graph.getCellStyle(edge)
); if (dist == null || tmp < dist) {
}; nearestConstraint = constraints[i];
dist = tmp;
}
}
}
if (nearestConstraint != null) {
this.sourceConstraint = nearestConstraint;
}
// In case the edge style must be changed during the preview:
// this.edgeState.style['edgeStyle'] = 'orthogonalEdgeStyle';
// And to use the new edge style in the new edge inserted into the graph,
// update the cell style as follows:
// this.edgeState.cell.style = mxUtils.setStyle(this.edgeState.cell.style, 'edgeStyle', this.edgeState.style['edgeStyle']);
}
return super.updateEdgeState(pt, constraint);
}
createEdgeState(me) {
// Connect preview
const edge = this.graph.createEdge(
null,
null,
null,
null,
null,
'edgeStyle=orthogonalEdgeStyle'
);
return new mxCellState(
this.graph.view,
edge,
this.graph.getCellStyle(edge)
);
}
}
class MyCustomEdgeHandler extends mxEdgeHandler {
// Disables floating connections (only use with no connect image)
isConnectableCell(cell) {
return graph.connectionHandler.isConnectableCell(cell);
}
}
class MyCustomGraph extends mxGraph {
createConnectionHandler() {
const r = new MyCustomConnectionHandler();
r.constraintHandler = new MyCustomConstraintHandler(this);
return r;
}
createEdgeHandler(state, edgeStyle) {
const r = new MyCustomEdgeHandler(state, edgeStyle);
r.constraintHandler = new MyCustomConstraintHandler(this);
return r;
}
getAllConnectionConstraints(terminal) {
if (terminal != null && this.model.isVertex(terminal.cell)) {
return [
new mxConnectionConstraint(new mxPoint(0, 0), true),
new mxConnectionConstraint(new mxPoint(0.5, 0), true),
new mxConnectionConstraint(new mxPoint(1, 0), true),
new mxConnectionConstraint(new mxPoint(0, 0.5), true),
new mxConnectionConstraint(new mxPoint(1, 0.5), true),
new mxConnectionConstraint(new mxPoint(0, 1), true),
new mxConnectionConstraint(new mxPoint(0.5, 1), true),
new mxConnectionConstraint(new mxPoint(1, 1), true),
];
}
return null;
}
}
// Creates the graph inside the given container
const graph = new MyCustomGraph(this.el);
graph.setConnectable(true);
// Enables rubberband selection // Enables rubberband selection
new mxRubberband(graph); new mxRubberband(graph);
@ -158,51 +172,46 @@ class FixedPoints 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, parent,
null, value: 'Hello,',
'Hello,', position: [20, 20],
20, size: [80, 60],
20, style: 'shape=triangle;perimeter=trianglePerimeter',
80, });
60, const v2 = graph.insertVertex({
'shape=triangle;perimeter=trianglePerimeter'
);
const v2 = graph.insertVertex(
parent, parent,
null, value: 'World!',
'World!', position: [200, 150],
200, size: [80, 60],
150, style: 'shape=ellipse;perimeter=ellipsePerimeter',
80, });
60, const v3 = graph.insertVertex({
'shape=ellipse;perimeter=ellipsePerimeter'
);
const v3 = graph.insertVertex(parent, null, 'Hello,', 200, 20, 80, 30);
const e1 = graph.insertEdge(
parent, parent,
null, value: 'Hello,',
'', position: [200, 20],
v1, size: [80, 30],
v2, });
'edgeStyle=elbowEdgeStyle;elbow=horizontal;' + const e1 = graph.insertEdge({
'exitX=0.5;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;'
);
const e2 = graph.insertEdge(
parent, parent,
null, value: '',
'', source: v1,
v3, target: v2,
v2, style:
'edgeStyle=elbowEdgeStyle;elbow=horizontal;orthogonal=0;' + 'edgeStyle=elbowEdgeStyle;elbow=horizontal;' +
'entryX=0;entryY=0;entryPerimeter=1;' 'exitX=0.5;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;',
); });
} finally { const e2 = graph.insertEdge({
// Updates the display parent,
graph.getModel().endUpdate(); value: '',
} source: v3,
target: v2,
style:
'edgeStyle=elbowEdgeStyle;elbow=horizontal;orthogonal=0;' +
'entryX=0;entryY=0;entryPerimeter=1;',
});
});
// Use this code to snap the source point for new connections without a connect preview, // Use this code to snap the source point for new connections without a connect preview,
// ie. without an overridden graph.connectionHandler.createEdgeState // ie. without an overridden graph.connectionHandler.createEdgeState