2021-09-07 09:07:27 +00:00
|
|
|
import {
|
|
|
|
Graph,
|
|
|
|
Rubberband,
|
|
|
|
Point,
|
|
|
|
EdgeHandler,
|
|
|
|
ConstraintHandler,
|
|
|
|
ImageBox,
|
|
|
|
Shape,
|
|
|
|
TriangleShape,
|
|
|
|
Constants,
|
|
|
|
ConnectionConstraint,
|
|
|
|
mxClient,
|
|
|
|
} from '@maxgraph/core';
|
2021-04-20 12:22:55 +00:00
|
|
|
|
2021-04-21 04:54:09 +00:00
|
|
|
import { globalTypes } from '../.storybook/preview';
|
2021-04-20 12:22:55 +00:00
|
|
|
|
|
|
|
export default {
|
|
|
|
title: 'Connections/PortRefs',
|
|
|
|
argTypes: {
|
2021-08-30 14:20:26 +00:00
|
|
|
...globalTypes,
|
|
|
|
},
|
2021-04-20 12:22:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const Template = ({ label, ...args }) => {
|
2021-04-25 03:39:40 +00:00
|
|
|
mxClient.setImageBasePath('/images');
|
|
|
|
|
2021-04-20 12:22:55 +00:00
|
|
|
const container = document.createElement('div');
|
|
|
|
container.style.position = 'relative';
|
|
|
|
container.style.overflow = 'hidden';
|
|
|
|
container.style.width = `${args.width}px`;
|
|
|
|
container.style.height = `${args.height}px`;
|
|
|
|
container.style.background = 'url(/images/grid.gif)';
|
|
|
|
container.style.cursor = 'default';
|
|
|
|
|
|
|
|
// Replaces the port image
|
2021-08-30 14:20:26 +00:00
|
|
|
ConstraintHandler.prototype.pointImage = new ImageBox('/images/dot.gif', 10, 10);
|
2021-04-20 12:22:55 +00:00
|
|
|
|
2021-08-30 14:20:26 +00:00
|
|
|
const graph = new Graph(container);
|
2021-04-20 12:22:55 +00:00
|
|
|
graph.setConnectable(true);
|
|
|
|
|
|
|
|
// Disables automatic handling of ports. This disables the reset of the
|
2021-08-30 14:20:26 +00:00
|
|
|
// respective style in Graph.cellConnected. Note that this feature may
|
2021-04-20 12:22:55 +00:00
|
|
|
// be useful if floating and fixed connections are combined.
|
|
|
|
graph.setPortsEnabled(false);
|
|
|
|
|
|
|
|
// Enables rubberband selection
|
2021-08-30 14:20:26 +00:00
|
|
|
new Rubberband(graph);
|
2021-04-20 12:22:55 +00:00
|
|
|
|
|
|
|
// 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
|
2021-08-30 14:20:26 +00:00
|
|
|
Shape.prototype.getPorts = function () {
|
2021-04-20 12:22:55 +00:00
|
|
|
return ports;
|
|
|
|
};
|
|
|
|
|
2021-08-30 14:20:26 +00:00
|
|
|
TriangleShape.prototype.getPorts = function () {
|
2021-04-20 12:22:55 +00:00
|
|
|
return ports2;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Disables floating connections (only connections via ports allowed)
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.connectionHandler.isConnectableCell = function (cell) {
|
2021-04-20 12:22:55 +00:00
|
|
|
return false;
|
|
|
|
};
|
2021-08-30 14:20:26 +00:00
|
|
|
EdgeHandler.prototype.isConnectableCell = function (cell) {
|
2021-04-20 12:22:55 +00:00
|
|
|
return graph.connectionHandler.isConnectableCell(cell);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Disables existing port functionality
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.view.getTerminalPort = function (state, terminal, source) {
|
2021-04-20 12:22:55 +00:00
|
|
|
return terminal;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Returns all possible ports for a given terminal
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.getAllConnectionConstraints = function (terminal, source) {
|
|
|
|
if (terminal != null && terminal.shape != null && terminal.shape.stencil != null) {
|
2021-04-20 12:22:55 +00:00
|
|
|
// for stencils with existing constraints...
|
|
|
|
if (terminal.shape.stencil != null) {
|
|
|
|
return terminal.shape.stencil.constraints;
|
|
|
|
}
|
2021-04-25 03:39:40 +00:00
|
|
|
} else if (terminal != null && terminal.cell.isVertex()) {
|
2021-04-20 12:22:55 +00:00
|
|
|
if (terminal.shape != null) {
|
|
|
|
const ports = terminal.shape.getPorts();
|
|
|
|
const cstrs = new Array();
|
|
|
|
|
|
|
|
for (const id in ports) {
|
|
|
|
const port = ports[id];
|
|
|
|
|
2021-08-30 14:20:26 +00:00
|
|
|
const cstr = new ConnectionConstraint(
|
|
|
|
new Point(port.x, port.y),
|
2021-04-20 12:22:55 +00:00
|
|
|
port.perimeter
|
|
|
|
);
|
|
|
|
cstr.id = id;
|
|
|
|
cstrs.push(cstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cstrs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Sets the port for the given connection
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.setConnectionConstraint = function (edge, terminal, source, constraint) {
|
2021-04-20 12:22:55 +00:00
|
|
|
if (constraint != null) {
|
2021-08-30 14:20:26 +00:00
|
|
|
const key = source ? 'sourcePort' : 'targetPort';
|
2021-04-20 12:22:55 +00:00
|
|
|
|
|
|
|
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
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.getConnectionConstraint = function (edge, terminal, source) {
|
|
|
|
const key = source ? 'sourcePort' : 'targetPort';
|
2021-04-20 12:22:55 +00:00
|
|
|
const id = edge.style[key];
|
|
|
|
|
|
|
|
if (id != null) {
|
2021-08-30 14:20:26 +00:00
|
|
|
const c = new ConnectionConstraint(null, null);
|
2021-04-20 12:22:55 +00:00
|
|
|
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;
|
2021-08-30 14:20:26 +00:00
|
|
|
graph.getConnectionPoint = function (vertex, constraint) {
|
2021-04-20 12:22:55 +00:00
|
|
|
if (constraint.id != null && vertex != null && vertex.shape != null) {
|
|
|
|
const port = vertex.shape.getPorts()[constraint.id];
|
|
|
|
|
|
|
|
if (port != null) {
|
2021-08-30 14:20:26 +00:00
|
|
|
constraint = new ConnectionConstraint(new Point(port.x, port.y), port.perimeter);
|
2021-04-20 12:22:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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'
|
|
|
|
);
|
2021-08-30 14:20:26 +00:00
|
|
|
const e1 = graph.insertEdge(parent, null, '', v1, v2, 'sourcePort=s;targetPort=nw');
|
|
|
|
const e2 = graph.insertEdge(parent, null, '', v1, v3, 'sourcePort=e;targetPort=out3');
|
2021-04-20 12:22:55 +00:00
|
|
|
} 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';
|
2021-08-30 14:20:26 +00:00
|
|
|
/* let mxUtilsGetPortConstraints = utils.getPortConstraints;
|
|
|
|
utils.getPortConstraints = function(terminal, edge, source, defaultValue)
|
2021-04-20 12:22:55 +00:00
|
|
|
{
|
2021-08-30 14:20:26 +00:00
|
|
|
let key = (source) ? Constants.STYLE_SOURCE_PORT : Constants.STYLE_TARGET_PORT;
|
2021-04-20 12:22:55 +00:00
|
|
|
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);
|
|
|
|
|
2021-08-30 14:20:26 +00:00
|
|
|
return new CellState(this.graph.view, edge, this.graph.getCellStyle(edge));
|
2021-04-20 12:22:55 +00:00
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
return container;
|
2021-08-30 14:20:26 +00:00
|
|
|
};
|
2021-04-20 12:22:55 +00:00
|
|
|
|
2021-08-30 14:20:26 +00:00
|
|
|
export const Default = Template.bind({});
|