98 lines
3.6 KiB
TypeScript
98 lines
3.6 KiB
TypeScript
|
import go from "gojs";
|
||
|
|
||
|
export function parallelRoutedLink() {
|
||
|
// This custom-routing Link class tries to separate parallel links from each other.
|
||
|
// This assumes that ports are lined up in a row/column on a side of the node.
|
||
|
function CustomLink() {
|
||
|
go.Link.call(this);
|
||
|
};
|
||
|
go.Diagram.inherit(CustomLink, go.Link);
|
||
|
|
||
|
CustomLink.prototype.findSidePortIndexAndCount = function (node, port) {
|
||
|
const nodedata = node.data;
|
||
|
let len = null;
|
||
|
if (nodedata !== null) {
|
||
|
const portdata = port.data;
|
||
|
const side = port._side;
|
||
|
const arr = nodedata[side + "Array"];
|
||
|
len = arr.length;
|
||
|
for (let i = 0; i < len; i++) {
|
||
|
if (arr[i] === portdata) return [i, len];
|
||
|
}
|
||
|
}
|
||
|
return [-1, len];
|
||
|
};
|
||
|
|
||
|
CustomLink.prototype.computeEndSegmentLength = function (node, port, spot, from) {
|
||
|
const esl = go.Link.prototype.computeEndSegmentLength.call(this, node, port, spot, from);
|
||
|
const other = this.getOtherPort(port);
|
||
|
if (port !== null && other !== null) {
|
||
|
const thispt = port.getDocumentPoint(this.computeSpot(from));
|
||
|
const otherpt = other.getDocumentPoint(this.computeSpot(!from));
|
||
|
if (Math.abs(thispt.x - otherpt.x) > 20 || Math.abs(thispt.y - otherpt.y) > 20) {
|
||
|
const info = this.findSidePortIndexAndCount(node, port);
|
||
|
const idx = info[0];
|
||
|
const count = info[1];
|
||
|
if (port._side == "top" || port._side == "bottom") {
|
||
|
if (otherpt.x < thispt.x) {
|
||
|
return esl + 4 + idx * 8;
|
||
|
} else {
|
||
|
return esl + (count - idx - 1) * 8;
|
||
|
}
|
||
|
} else { // left or right
|
||
|
if (otherpt.y < thispt.y) {
|
||
|
return esl + 4 + idx * 8;
|
||
|
} else {
|
||
|
return esl + (count - idx - 1) * 8;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return esl;
|
||
|
};
|
||
|
|
||
|
CustomLink.prototype.hasCurviness = function () {
|
||
|
if (isNaN(this.curviness)) return true;
|
||
|
return go.Link.prototype.hasCurviness.call(this);
|
||
|
};
|
||
|
|
||
|
CustomLink.prototype.computeCurviness = function () {
|
||
|
if (isNaN(this.curviness)) {
|
||
|
const fromnode = this.fromNode;
|
||
|
const fromport = this.fromPort;
|
||
|
const fromspot = this.computeSpot(true);
|
||
|
const frompt = fromport.getDocumentPoint(fromspot);
|
||
|
const tonode = this.toNode;
|
||
|
const toport = this.toPort;
|
||
|
const tospot = this.computeSpot(false);
|
||
|
const topt = toport.getDocumentPoint(tospot);
|
||
|
if (Math.abs(frompt.x - topt.x) > 20 || Math.abs(frompt.y - topt.y) > 20) {
|
||
|
if ((fromspot.equals(go.Spot.Left) || fromspot.equals(go.Spot.Right)) &&
|
||
|
(tospot.equals(go.Spot.Left) || tospot.equals(go.Spot.Right))) {
|
||
|
var fromseglen = this.computeEndSegmentLength(fromnode, fromport, fromspot, true);
|
||
|
var toseglen = this.computeEndSegmentLength(tonode, toport, tospot, false);
|
||
|
var c = (fromseglen - toseglen) / 2;
|
||
|
if (frompt.x + fromseglen >= topt.x - toseglen) {
|
||
|
if (frompt.y < topt.y) return c;
|
||
|
if (frompt.y > topt.y) return -c;
|
||
|
}
|
||
|
} else if ((fromspot.equals(go.Spot.Top) || fromspot.equals(go.Spot.Bottom)) &&
|
||
|
(tospot.equals(go.Spot.Top) || tospot.equals(go.Spot.Bottom))) {
|
||
|
var fromseglen = this.computeEndSegmentLength(fromnode, fromport, fromspot, true);
|
||
|
var toseglen = this.computeEndSegmentLength(tonode, toport, tospot, false);
|
||
|
var c = (fromseglen - toseglen) / 2;
|
||
|
if (frompt.x + fromseglen >= topt.x - toseglen) {
|
||
|
if (frompt.y < topt.y) return c;
|
||
|
if (frompt.y > topt.y) return -c;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return go.Link.prototype.computeCurviness.call(this);
|
||
|
};
|
||
|
// end CustomLink class
|
||
|
|
||
|
return CustomLink;
|
||
|
}
|
||
|
|