@syncfusion/ej2-diagrams
Version:
Feature-rich diagram control to create diagrams like flow charts, organizational charts, mind maps, and BPMN diagrams. Its rich feature set includes built-in shapes, editing, serializing, exporting, printing, overview, data binding, and automatic layouts.
974 lines • 62.4 kB
JavaScript
import { OrthogonalSegment } from '../objects/connector';
import { Rect } from '../primitives/rect';
import { findDistance, findPort, getConnectorDirection } from '../utility/diagram-util';
import { randomId } from '../utility/base-util';
import { Point } from '../primitives/point';
import { PointPort } from '../objects/port';
import { Size } from '../primitives/size';
/**
* Line Distribution
* @private
*/
var LineDistribution = /** @class */ (function () {
///** @private */
//public edgeMapper: EdgeMapperObject[];
/**
* Constructor for the line distribution module
* @private
*/
function LineDistribution() {
//constructs the line distribution module
}
/**
* To destroy the line distribution module
* @returns {void}
* @private
*/
LineDistribution.prototype.destroy = function () {
/**
* Destroys the line distribution module
*/
};
///**
// * Get the diagram instance.
// */
//private diagram: Diagram;
/**
* Core method to return the component name.
*
* @returns {string} Core method to return the component name.
* @private
*/
LineDistribution.prototype.getModuleName = function () {
/**
* Returns the module name
*/
return 'LineDistribution';
};
/** @private */
LineDistribution.prototype.initLineDistribution = function (graph, diagram) {
var srcDirection = 'Bottom';
//this.diagram = diagram;
if (diagram.layout.connectionPointOrigin === 'DifferentPoint' || diagram.layout.enableRouting) {
var tarDirection = 'Top';
if (graph.orientation === 'BottomToTop') {
srcDirection = 'Top';
tarDirection = 'Bottom';
}
else if (graph.orientation === 'RightToLeft') {
srcDirection = 'Left';
tarDirection = 'Right';
}
else if (graph.orientation === 'LeftToRight') {
srcDirection = 'Right';
tarDirection = 'Left';
}
var graphnodes = diagram.nodes;
if (graphnodes.length > 0) {
for (var i = 0; i < graphnodes.length; i++) {
var node = diagram.nameTable[graphnodes[parseInt(i.toString(), 10)].id];
this.addDynamicPortandDistrrbuteLine(graph, node, srcDirection, tarDirection, diagram);
}
}
}
};
LineDistribution.prototype.ObstacleSegment = function (options) {
options.direction = getConnectorDirection(options.startpt, options.endpt);
options.distance = Point.findLength(options.startpt, options.endpt);
options.orientation = options.direction === 'Left' || options.direction === 'Right' ? 'horizontal' : 'vertical';
// eslint-disable-next-line no-self-assign
options.id = options.id;
if (options.orientation === 'horizontal') {
options.coord = options.startpt.y;
if (options.direction === 'Left') {
options.start = options.endpt.x;
options.end = options.startpt.x;
}
else {
options.start = options.startpt.x;
options.end = options.endpt.x;
}
}
else {
options.coord = options.startpt.x;
if (options.direction === 'Top') {
options.start = options.endpt.y;
options.end = options.startpt.y;
}
else {
options.start = options.startpt.y;
options.end = options.endpt.y;
}
}
return options;
};
/** @private */
LineDistribution.prototype.distributeLines = function (layout, diagram) {
var isHorizontal = layout.orientation === 'LeftToRight'
|| layout.orientation === 'RightToLeft';
var inversespacing = !isHorizontal ? layout.verticalSpacing : layout.horizontalSpacing;
var srcdecoratorSize = 8.0;
var obstacleCollection = 'obstaclePointCollection';
var tardecoratorSize = 10.0;
var avaibaleSpace = inversespacing - srcdecoratorSize - tardecoratorSize;
var graph = [];
var connectorObstacles = [];
var globalConnectors = diagram.connectors;
for (var i = 0; i < globalConnectors.length; i++) {
var connector = globalConnectors[parseInt(i.toString(), 10)];
var pts = [];
for (var key = 0; key < connector.segments.length; key++) {
var seg = connector.segments[parseInt(key.toString(), 10)];
for (var k = 0; k < seg.points.length; k++) {
var pt = seg.points[parseInt(k.toString(), 10)];
if (pts.length === 0 || !(Point.equals(pt, pts[pts.length - 1]))) {
pts.push(pt);
}
}
}
var obssegments = [];
for (var j = 1; j < pts.length; j++) {
var obstacle = this.ObstacleSegment({
startpt: pts[j - 1], endpt: pts[parseInt(j.toString(), 10)], id: connector.id
});
obssegments.push(obstacle);
}
var connectorObstacle = { wrapper: connector, segments: obssegments };
var segments = [];
if (!isHorizontal) {
for (var key = 0; key < connectorObstacle.segments.length; key++) {
var obstacle = connectorObstacle.segments[parseInt(key.toString(), 10)];
if (obstacle.orientation === 'horizontal' && obstacle.distance > 1) {
segments.push(obstacle);
}
}
}
else {
for (var key = 0; key < connectorObstacle.segments.length; key++) {
var obstacle = connectorObstacle.segments[parseInt(key.toString(), 10)];
if (obstacle.orientation === 'vertical' && obstacle.distance > 1) {
segments.push(obstacle);
}
}
}
for (var j = 0; j < segments.length; j++) {
var obstacleSegment = segments[parseInt(j.toString(), 10)];
if (!this.containsValue(graph, obstacleSegment.coord)) {
graph.push({ key: obstacleSegment.coord, value: [] });
}
var index = void 0;
for (var k = 0; k < graph.length; k++) {
var key = graph[parseInt(k.toString(), 10)].key;
if (Number(key) === obstacleSegment.coord) {
index = k;
break;
}
}
graph[parseInt(index.toString(), 10)].value.push(obstacleSegment);
}
connectorObstacles.push(connectorObstacle);
}
if (graph.length > 0) {
var keys = graph.map(function (e) { return e.key; }).sort(function (a, b) { return a - b; });
var i = 0;
var _loop_1 = function () {
var key1 = keys[parseInt(i.toString(), 10)];
var key2 = keys[i + 1];
if (Math.abs(key2 - key1) < inversespacing * 0.5) {
var idx1 = graph.findIndex(function (e) { return e.key === key1; });
var idx2 = graph.findIndex(function (e) { return e.key === key2; });
if (idx1 === -1 || idx2 === -1) {
i++;
return "continue";
}
var obj1 = graph[parseInt(idx1.toString(), 10)];
var obj2 = graph[parseInt(idx2.toString(), 10)];
var midKey = (key1 + key2) / 2;
var combinedValues = obj1.value.concat(obj2.value);
// Remove both entries (larger index first), then push the merged one
var maxIdx = Math.max(idx1, idx2);
var minIdx = Math.min(idx1, idx2);
graph.splice(maxIdx, 1);
graph.splice(minIdx, 1);
graph.push({ key: midKey, value: combinedValues });
// Recompute sorted keys after modification
keys = graph.map(function (e) { return e.key; }).sort(function (a, b) { return a - b; });
// Keep i at the same position to re-check with the new neighbor
}
else {
i++;
}
};
while (i < keys.length - 1) {
_loop_1();
}
}
this.sortConnectors(graph, diagram);
var modifiedgrap = [];
for (var m = 0; m < graph.length; m++) {
var row = graph[parseInt(m.toString(), 10)];
var sortedrow = row.value;
//Bug 969032: Connectors Overlapping Issue in Complex Hierarchical Tree
//Sort the connectors by start point from lowest to highest
sortedrow.sort(function (a, b) { return a.start - b.start; });
var groupby = void 0;
groupby = [];
var index = 0;
var maxEnd = Number.MIN_VALUE;
groupby.push([]);
for (var n = 0; n < sortedrow.length; n++) {
var obstacleSegment = sortedrow[parseInt(n.toString(), 10)];
if (!(groupby[parseInt(index.toString(), 10)].length > 0) || maxEnd >= obstacleSegment.start) {
groupby[parseInt(index.toString(), 10)].push(obstacleSegment);
maxEnd = Math.max(maxEnd, groupby[parseInt(index.toString(), 10)][groupby[parseInt(index.toString(), 10)].length - 1].end);
}
else {
index++;
groupby.push([]);
groupby[parseInt(index.toString(), 10)].push(obstacleSegment);
maxEnd = groupby[parseInt(index.toString(), 10)][groupby[parseInt(index.toString(), 10)].length - 1].end;
}
}
for (var n = 0; n < groupby.length; n++) {
var group = groupby[parseInt(n.toString(), 10)];
var sortedGroup = [];
for (var j = 0; j < group.length; j++) {
var e = group[parseInt(j.toString(), 10)];
if (e.start) {
sortedGroup.push(e);
}
}
var comparingDir = isHorizontal ? 'Bottom' : 'Right';
var directed = [];
for (var j = 0; j < sortedGroup.length; j++) {
var e = sortedGroup[parseInt(j.toString(), 10)];
if (e.direction === comparingDir) {
directed.push(e);
}
}
var reversedirected = [];
for (var j = 0; j < sortedGroup.length; j++) {
var e = sortedGroup[parseInt(j.toString(), 10)];
if (e.direction !== comparingDir) {
reversedirected.push(e);
}
}
var mutual = [];
if (directed.length > 0) {
var temp = directed[0].start;
var j = 0;
while (j < reversedirected.length) {
if (reversedirected[parseInt(j.toString(), 10)].end > temp) {
mutual.push(reversedirected[parseInt(j.toString(), 10)]);
reversedirected.splice(j, 1);
}
else {
j++;
}
}
}
var mutualRow = [];
mutualRow = this.updateSegmentRow(mutual, mutualRow);
var directedRow = [];
directedRow = [];
directedRow = this.updateSegmentRow(reversedirected, directedRow);
directed.reverse();
directedRow = this.updateSegmentRow(directed, directedRow);
if (!(mutualRow[mutualRow.length - 1].length > 0)) {
mutualRow.splice(mutualRow.length - 1, 1);
}
if (!(directedRow[directedRow.length - 1].length > 0)) {
directedRow.splice(directedRow.length - 1, 1);
}
var subrow = [];
var descAdding = mutual.length > 0 && (sortedGroup[sortedGroup.length - 1].direction
=== mutual[mutual.length - 1].direction
|| sortedGroup[0].direction === mutual[0].direction);
if (descAdding) {
subrow = directedRow;
for (var p = 0; p < mutualRow.length; p++) {
var obj = mutualRow[parseInt(p.toString(), 10)];
subrow[subrow.length] = obj;
}
}
else {
subrow = mutualRow;
for (var p = 0; p < directedRow.length; p++) {
var obj = directedRow[parseInt(p.toString(), 10)];
subrow[subrow.length] = obj;
}
}
if (subrow.length > 1) {
var directionModifier = 1;
if (layout.orientation === 'BottomToTop'
|| layout.orientation === 'RightToLeft') {
directionModifier = -1;
}
var startCoord = row.key - (directionModifier * avaibaleSpace / 2.0);
var diff = avaibaleSpace / subrow.length;
for (var i = 0; i < subrow.length; i++) {
var newcoord = startCoord + (i * diff * directionModifier);
for (var p = 0; p < subrow[parseInt(i.toString(), 10)].length; p++) {
var obstacleSegment = subrow[parseInt(i.toString(), 10)][parseInt(p.toString(), 10)];
obstacleSegment.coord = newcoord;
if (!this.containsValue(modifiedgrap, obstacleSegment.coord)) {
modifiedgrap.push({ key: obstacleSegment.coord, value: [] });
}
var index_1 = void 0;
for (var k = 0; k < modifiedgrap.length; k++) {
var keyCheck = modifiedgrap[parseInt(k.toString(), 10)].key;
if (keyCheck === obstacleSegment.coord) {
index_1 = k;
break;
}
}
modifiedgrap[parseInt(index_1.toString(), 10)].value.push(obstacleSegment);
}
}
}
}
}
for (var m = 0; m < connectorObstacles.length; m++) {
var connectorObstacle = connectorObstacles[parseInt(m.toString(), 10)];
var pts = [];
for (var i = 0; i < connectorObstacle.segments.length; i++) {
if (i === 0) {
pts.push(this.getObstacleStartPoint(connectorObstacle.segments[parseInt(i.toString(), 10)]));
}
else if (isHorizontal) {
if (connectorObstacle.segments[parseInt(i.toString(), 10)].orientation === 'vertical') {
pts[pts.length - 1] = this.getObstacleStartPoint(connectorObstacle.segments[parseInt(i.toString(), 10)]);
}
}
else if (!isHorizontal) {
if (connectorObstacle.segments[parseInt(i.toString(), 10)].orientation === 'horizontal') {
pts[pts.length - 1] = this.getObstacleStartPoint(connectorObstacle.segments[parseInt(i.toString(), 10)]);
}
}
pts.push(this.getObstacleEndPoint(connectorObstacle.segments[parseInt(i.toString(), 10)]));
}
/* tslint:disable */
connectorObstacle.wrapper["" + obstacleCollection] = [];
for (var j = 0; j < pts.length; j++) {
var point = pts[parseInt(j.toString(), 10)];
if (j === 0 || (j > 0 && !(Point.equals(point, pts[j - 1])))) {
connectorObstacle.wrapper["" + obstacleCollection].push(this.getPointvalue(point.x, point.y));
}
}
/* tslint:enable */
//EJ2-70198 - The layout ConnectionPointOrigin DifferentPoint property is not working for bezier connector
//Bug 851920: Connector overlaps the node in complex hierarchical tree layout. Here the below condition is modified to check connector type.
if (connectorObstacle.wrapper.type === 'Orthogonal') {
this.resetConnectorPoints(connectorObstacle.wrapper, diagram);
}
}
};
//Bug 862601: Connectors are not rendered properly with lineRouting and lineDistribution enables during doLayout process.
//To sort the connectors order in graph based on its target point and orientation to avoid connector segments path in same line.
LineDistribution.prototype.sortConnectors = function (graph, diagram) {
for (var i = 0; i < graph.length; i++) {
for (var j = 0; j < graph[parseInt(i.toString(), 10)].value.length; j++) {
if (graph[parseInt(i.toString(), 10)].value.length > 1) {
if (diagram.layout.orientation === 'LeftToRight' || diagram.layout.orientation === 'RightToLeft') {
graph[parseInt(i.toString(), 10)].value.sort(function (a, b) {
var connectorA = diagram.nameTable["" + a.id];
var connectorB = diagram.nameTable["" + b.id];
return connectorA.targetPoint.y - connectorB.targetPoint.y;
});
}
else if (diagram.layout.orientation === 'TopToBottom' || diagram.layout.orientation === 'BottomToTop') {
graph[parseInt(i.toString(), 10)].value.sort(function (a, b) {
var connectorA = diagram.nameTable["" + a.id];
var connectorB = diagram.nameTable["" + b.id];
return connectorA.targetPoint.x - connectorB.targetPoint.x;
});
}
}
}
}
};
//private inflate(rect: Rect, x: number, y: number): Rect {
// rect.x -= x;
// rect.y -= y;
// rect.width += 2 * x;
// rect.height += 2 * y;
// return rect;
//}
//private updateConnectorPoints(
// connectorPoints: Point[], startSegmentSize: number, intermediatePoint: Point, bounds: object, orientation: string):
// Point[] {
// const layoutBounds: Rect = bounds as Rect;
// const isHorizontal: boolean = orientation === 'LeftToRight' || orientation === 'RightToLeft';
// const pts: Point[] = connectorPoints;
// if (pts.length > 2) {
// const newPt: Point = Point.transform(pts[0], Point.findAngle(pts[0], pts[1]), startSegmentSize) as Point;
// const nextPt: Point = Point.transform(newPt, Point.findAngle(pts[1], pts[2]), Point.findLength(pts[1], pts[2])) as Point;
// pts.splice(1, 2, newPt, nextPt);
// if (intermediatePoint != null) {
// const index: number = 2;
// const ptsCount: number = pts.length;
// const newPt1: Point = Point.transform(
// pts[ptsCount - 1],
// Point.findAngle(pts[ptsCount - 1], pts[ptsCount - 2]),
// startSegmentSize) as Point;
// pts.splice(ptsCount - 1, 0, newPt1);
// while (index < (pts.length - 2)) {
// pts.splice(index, 1);
// }
// const edgePt: Point = intermediatePoint;
// this.inflate((layoutBounds as Rect), (layoutBounds as Rect).width, layoutBounds.height);
// const line1: Point[] = [];
// line1[0] = this.getPointvalue(edgePt.x, layoutBounds.y) as Point;
// line1[1] = this.getPointvalue(edgePt.x, layoutBounds.y + layoutBounds.height) as Point;
// const line2: Point[] = [];
// line2[0] = this.getPointvalue(layoutBounds.x, pts[1].y) as Point;
// line2[1] = this.getPointvalue(layoutBounds.x + layoutBounds.width, pts[1].y) as Point;
// const line3: Point[] = [];
// line3[0] = this.getPointvalue(layoutBounds.x, newPt1.y) as Point;
// line3[1] = this.getPointvalue(layoutBounds.x + layoutBounds.width, newPt1.y) as Point;
// if (isHorizontal) {
// line1[0] = this.getPointvalue(layoutBounds.x, edgePt.y) as Point;
// line1[1] = this.getPointvalue(layoutBounds.x + layoutBounds.width, edgePt.y) as Point;
// line2[0] = this.getPointvalue(pts[1].x, layoutBounds.y) as Point;
// line2[1] = this.getPointvalue(pts[1].x, layoutBounds.y + layoutBounds.height) as Point;
// line3[0] = this.getPointvalue(newPt1.x, layoutBounds.y) as Point;
// line2[1] = this.getPointvalue(newPt1.x, layoutBounds.y + layoutBounds.height) as Point;
// }
// const intercepts1: Point[] = [intersect2(
// line1[0] as Point,
// line1[1] as Point, line2[0] as Point, line2[1] as Point)] as Point[];
// const intercepts2: Point[] = [intersect2(
// line1[0] as Point, line1[1] as Point,
// line3[0] as Point, line3[1] as Point)] as Point[];
// if (intercepts2.length > 0) {
// pts.splice(2, 0, intercepts2[0]);
// }
// if (intercepts1.length > 0) {
// pts.splice(2, 0, intercepts1[0]);
// }
// }
// }
// let i: number = 1;
// while (i < pts.length - 1) {
// if (Point.equals(pts[i - 1], pts[parseInt(i.toString(), 10)])) {
// pts.splice(i, 1);
// } else if (Point.findAngle(pts[i - 1], pts[parseInt(i.toString(), 10)])
// === Point.findAngle(pts[parseInt(i.toString(), 10)], pts[i + 1])) {
// pts.splice(i, 1);
// } else {
// i++;
// }
// }
// return pts;
//}
/* tslint:disable */
LineDistribution.prototype.resetConnectorPoints = function (edge, diagram) {
var obstacleCollection = 'obstaclePointCollection';
if (edge.segments[0].points
&& edge.segments[0].points.length > 0 && edge["" + obstacleCollection]) {
var connector = edge;
connector.sourcePoint = edge["" + obstacleCollection][0];
connector.targetPoint = edge["" + obstacleCollection][edge["" + obstacleCollection].length - 1];
var segments = void 0;
segments = [];
for (var i = 0; i < edge["" + obstacleCollection].length - 1; i++) {
var point1 = edge["" + obstacleCollection][parseInt(i.toString(), 10)];
var point2 = edge["" + obstacleCollection][i + 1];
var length_1 = findDistance(point1, point2);
var direction = getConnectorDirection(point1, point2);
if (i === edge["" + obstacleCollection].length - 2) {
if ((diagram.layout.orientation === 'RightToLeft' && direction === 'Left')
|| (diagram.layout.orientation === 'LeftToRight' && direction === 'Right')
|| (diagram.layout.orientation === 'TopToBottom' && direction === 'Bottom')
|| (diagram.layout.orientation === 'BottomToTop' && direction === 'Top')) {
length_1 = length_1 / 2;
}
}
/* tslint:enable */
var tempSegment = new OrthogonalSegment(edge, 'segments', { type: 'Orthogonal' }, true);
tempSegment.length = length_1;
tempSegment.direction = direction;
segments.push(tempSegment);
}
connector.segments = segments;
connector.type = 'Orthogonal';
diagram.connectorPropertyChange(connector, {}, {
type: 'Orthogonal',
segments: connector.segments
});
}
};
LineDistribution.prototype.getObstacleEndPoint = function (segment) {
if (segment.orientation === 'horizontal') {
if (segment.direction === 'Left') {
return this.getPointvalue(segment.start, segment.coord);
}
return this.getPointvalue(segment.end, segment.coord);
}
if (segment.direction === 'Top') {
return this.getPointvalue(segment.coord, segment.start);
}
return this.getPointvalue(segment.coord, segment.end);
};
LineDistribution.prototype.getObstacleStartPoint = function (segment) {
if (segment.orientation === 'horizontal') {
if (segment.direction === 'Left') {
return this.getPointvalue(segment.end, segment.coord);
}
return this.getPointvalue(segment.start, segment.coord);
}
if (segment.direction === 'Top') {
return this.getPointvalue(segment.coord, segment.end);
}
return this.getPointvalue(segment.coord, segment.start);
};
LineDistribution.prototype.updateSegmentRow = function (obstacleSegments, segmentRow) {
var k = 0;
if (!(segmentRow.length > 0)) {
segmentRow[0] = [];
}
for (var i = 0; i < obstacleSegments.length; i++) {
var obstacleSegment = obstacleSegments[parseInt(i.toString(), 10)];
while (k < segmentRow.length) {
if (k === segmentRow.length - 1) {
segmentRow[k + 1] = [];
}
if (!(segmentRow[parseInt(k.toString(), 10)].length > 0)
|| segmentRow[parseInt(k.toString(), 10)][segmentRow[parseInt(k.toString(), 10)].length - 1].end
< obstacleSegment.start) {
segmentRow[parseInt(k.toString(), 10)].push(obstacleSegment);
break;
}
k++;
}
}
return segmentRow;
};
LineDistribution.prototype.portOffsetCalculation = function (port, length, direction, i) {
if (direction === 'Top') {
port.offset = { x: (i + 1) * (1.0 / (length + 1)), y: 0 };
}
if (direction === 'Bottom') {
port.offset = { x: (i + 1) * (1.0 / (length + 1)), y: 1 };
}
if (direction === 'Left') {
port.offset = { x: 0, y: (i + 1) * (1.0 / (length + 1)) };
}
if (direction === 'Right') {
port.offset = { x: 1, y: (i + 1) * (1.0 / (length + 1)) };
}
};
LineDistribution.prototype.addDynamicPortandDistrrbuteLine = function (layout, node, sourceDirection, targetDirection, diagram) {
if ((node.ports && node.ports.length > 0)) {
var port = node.ports;
diagram.removePorts(node, port);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
var existingPorts = node.ports;
var outConnectors = node.outEdges;
var inConnectors = node.inEdges;
this.initPort(outConnectors, diagram, node, sourceDirection, false);
this.initPort(inConnectors, diagram, node, targetDirection, true);
};
/* tslint:disable */
LineDistribution.prototype.initPort = function (connectors, diagram, node, targetDirection, inConnectors) {
var obstacleCollection = 'obstaclePointCollection';
var objects = connectors;
// EJ2-61463 - Added below code to sort the objects based on the source node offset position
if (connectors.length > 1 && inConnectors) {
connectors = this.sortObjects(objects, inConnectors, diagram);
}
for (var i = 0; i <= connectors.length - 1; i++) {
var internalConnector = diagram.nameTable[connectors[parseInt(i.toString(), 10)]];
internalConnector["" + obstacleCollection] = [];
var newPort = findPort(node, inConnectors ? internalConnector.targetPortID : internalConnector.sourcePortID);
var direction = targetDirection;
if (newPort === undefined) {
newPort = new PointPort(node, 'ports', '', true);
newPort.id = randomId() + '_LineDistribution';
if (inConnectors) {
internalConnector.targetPortID = newPort.id;
}
else {
internalConnector.sourcePortID = newPort.id;
}
}
this.portOffsetCalculation(newPort, connectors.length, direction, i);
node.ports.push(newPort);
var portWrapper = node.initPortWrapper(node.ports[node.ports.length - 1]);
node.wrapper.children.push(portWrapper);
// EJ2-66867 - Exception occurs on calling doLayout while injecting Linerouting module
// nodes portWrapper bouds is updated below
node.wrapper.measure(new Size(node.width, node.height), node.id);
node.wrapper.arrange(node.wrapper.desiredSize);
diagram.connectorPropertyChange(internalConnector, inConnectors ? { targetPortID: '' } : { sourcePortID: '' },
// eslint-disable-next-line
inConnectors ? { targetPortID: newPort.id } : { sourcePortID: newPort.id });
}
};
/* tslint:enable */
//EJ2-61463 - Method used to sort the connectors based on the source node offset position
LineDistribution.prototype.sortObjects = function (objects, inConnectors, diagram) {
var temp;
for (var i = 0; i < objects.length; i++) {
for (var j = i + 1; j < objects.length; j++) {
var internalConnector = diagram.nameTable[objects[parseInt(i.toString(), 10)]];
var internalConnector2 = diagram.nameTable[objects[parseInt(j.toString(), 10)]];
if (inConnectors) {
var childNode = diagram.nameTable[internalConnector.sourceID];
var childNode2 = diagram.nameTable[internalConnector2.sourceID];
// For LeftToRight and RightToLeft we want to consider source node offsetY position
if (diagram.layout.orientation === 'LeftToRight' || diagram.layout.orientation === 'RightToLeft') {
if (childNode.offsetY > childNode2.offsetY) {
temp = objects[parseInt(i.toString(), 10)];
objects[parseInt(i.toString(), 10)] = objects[parseInt(j.toString(), 10)];
objects[parseInt(j.toString(), 10)] = temp;
}
}
else {
// For TopToBottom or BottomToTop means we want to consider source node offsetX position
if (childNode.offsetX > childNode2.offsetX) {
temp = objects[parseInt(i.toString(), 10)];
objects[parseInt(i.toString(), 10)] = objects[parseInt(j.toString(), 10)];
objects[parseInt(j.toString(), 10)] = temp;
}
}
}
}
}
return objects;
};
//private shiftMatrixCells(
// value: number, startingCell: MatrixCellGroupObject, shiftChildren: boolean,
// parentCell: MatrixCellGroupObject, matrixModel: MatrixModelObject):
// void {
// if (!(value === 0)) {
// const matrix: MatrixObject[] = matrixModel.matrix;
// const matrixRow: MatrixCellGroupObject[] = matrix[startingCell.level].value;
// const index: number = matrixRow.indexOf(startingCell);
// for (let i: number = index; i < matrixRow.length; i++) {
// matrixRow[parseInt(i.toString(), 10)].offset += value;
// }
// if (shiftChildren) {
// if (startingCell.visitedChildren.length > 0) {
// this.shiftMatrixCells(
// value,
// startingCell.visitedChildren[0],
// true,
// startingCell,
// matrixModel);
// } else {
// let i: number = 1;
// let nextSibilingwithChild: MatrixCellGroupObject = null;
// while (index + i < matrixRow.length) {
// const nextCell: MatrixCellGroupObject = matrixRow[index + i];
// if (parentCell != null && this.containsValue(nextCell.visitedParents, parentCell)) {
// if (nextCell.visitedChildren.length > 0) {
// nextSibilingwithChild = nextCell;
// } else {
// i++;
// continue;
// }
// }
// break;
// }
// if (nextSibilingwithChild != null) {
// this.shiftMatrixCells(
// value,
// nextSibilingwithChild.visitedChildren[0],
// true,
// nextSibilingwithChild,
// matrixModel);
// }
// }
// }
// }
//}
//private arrangeMatrix(cell: MatrixCellGroupObject, parent: MatrixCellGroupObject, matrixModel: MatrixModelObject): void {
// const layoutSettings: LayoutProp = matrixModel.model.layout;
// const isHorizontal: boolean = layoutSettings.orientation === 'LeftToRight'
// || layoutSettings.orientation === 'RightToLeft';
// const spacing: number = isHorizontal ? layoutSettings.verticalSpacing : layoutSettings.horizontalSpacing;
// const matrix: MatrixObject[] = matrixModel.matrix;
// const matrixRow: MatrixCellGroupObject[] = matrix[cell.level].value;
// const matrixIndex: number = matrixRow.indexOf(cell);
// if (cell.visitedParents.length > 0) {
// if (cell.visitedParents.length === 1) {
// cell.initialOffset = cell.offset;
// }
// if (matrixIndex + 1 < matrixRow.length) {
// const nextCell: MatrixCellGroupObject = matrixRow[matrixIndex + 1];
// if (nextCell.visitedParents.length > 0) {
// if (!this.containsValue(cell.visitedParents, parent)) {
// cell.visitedParents.push(parent);
// parent.ignoredChildren.push(cell);
// return;
// }
// }
// }
// }
// if (!(cell.children.length > 0)) {
// let validOffset: number = cell.offset;
// if (matrixIndex > 0) {
// const prevCell: MatrixCellGroupObject = matrixRow[matrixIndex - 1];
// validOffset = prevCell.offset + (prevCell.size / 2) + spacing + (cell.size / 2);
// }
// this.shiftMatrixCells(validOffset - cell.offset, cell, false, null, matrixModel);
// } else {
// for (let i: number = 0; i < cell.children.length; i++) {
// const matrixCellChild: MatrixCellGroupObject = cell.children[parseInt(i.toString(), 10)];
// if (!this.containsValue(cell.visitedChildren, matrixCellChild)) {
// this.arrangeMatrix(matrixCellChild, cell, matrixModel);
// cell.visitedChildren.push(matrixCellChild);
// }
// }
// if (cell.visitedChildren.length > 0) {
// const children: MatrixCellGroupObject[] = cell.visitedChildren.slice();
// for (let i: number = 0; i < cell.ignoredChildren.length; i++) {
// //let cellIgnoredChild: MatrixCellGroupObject = cell.ignoredChildren[i];
// children.splice(0, 1);
// cell.visitedChildren.splice(0, 1);
// }
// if (children.length > 0) {
// const firstChild: MatrixCellGroupObject = cell.visitedChildren[0];
// const lastChild: MatrixCellGroupObject = cell.visitedChildren[cell.visitedChildren.length - 1];
// const x1: number = firstChild.offset - (firstChild.size / 2);
// const x2: number = lastChild.offset + (lastChild.size / 2);
// const newoffset: number = (x1 + x2) / 2;
// if (newoffset < cell.offset) {
// this.shiftMatrixCells(cell.offset - newoffset, firstChild, true, cell, matrixModel);
// } else if (newoffset > cell.offset) {
// this.shiftMatrixCells(newoffset - cell.offset, cell, false, null, matrixModel);
// }
// }
// }
// }
// if (!this.containsValue(cell.visitedParents, parent)) {
// cell.visitedParents.push(parent);
// }
//}
/** @private */
LineDistribution.prototype.resetConnectorSegments = function (connector) {
var segements = connector.segments;
for (var i = segements.length; i > 0; i--) {
segements.splice(i - 1, 1);
}
};
/* tslint:disable */
/** @private */
LineDistribution.prototype.resetRoutingSegments = function (connector, diagram, points) {
if (connector['levelSkip']) {
//Bug 877799: Optimize the routing segment distance while using enableRouting in layout.
var sourceLevel = void 0;
var targetLevel = void 0;
var collection = diagram.layout.ranks.reverse();
//To find the source level and target level of the level skip connector
for (var i = 0; i < collection.length; i++) {
for (var j = 0; j < collection[parseInt(i.toString(), 10)].length; j++) {
if (connector.sourceID === collection[parseInt(i.toString(), 10)][parseInt(j.toString(), 10)].id) {
sourceLevel = i;
}
if (connector.targetID === collection[parseInt(i.toString(), 10)][parseInt(j.toString(), 10)].id) {
targetLevel = i;
}
}
}
// To find the overlapping collection between the source and target level
var overlappCollection = [];
if (sourceLevel < targetLevel) {
for (var i = 0; i < collection.length; i++) {
//EJ2-949872 - Connector Lines Overlapping Nodes in Child-to-Parent Flow
if (i >= sourceLevel && i <= targetLevel) {
overlappCollection.push(collection[parseInt(i.toString(), 10)]);
}
}
}
else {
for (var i = 0; i < collection.length; i++) {
//EJ2-949872 - Connector Lines Overlapping Nodes in Child-to-Parent Flow
if (i <= sourceLevel && i >= targetLevel) {
overlappCollection.push(collection[parseInt(i.toString(), 10)]);
}
}
}
// To find the overlapping nodes between the source and target level
var overLapNodesCollection = [];
for (var i = 0; i < overlappCollection.length; i++) {
for (var j = 0; j < overlappCollection[parseInt(i.toString(), 10)].length; j++) {
if (overlappCollection[parseInt(i.toString(), 10)][parseInt(j.toString(), 10)].edges === undefined) {
var node = diagram.nameTable[overlappCollection[parseInt(i.toString(), 10)][parseInt(j.toString(), 10)].id];
overLapNodesCollection.push(node);
}
}
}
var isInsideBounds = false;
if (!diagram.routingConnectors) {
diagram.routingConnectors = [];
}
//To find whether the connector is overlapping with the nodes in the overlapping collection.
var connectorBounds = this.getConnectorBounds(connector);
// eslint-disable-next-line no-labels
overlapping: for (var count = 0; count < overLapNodesCollection.length; count++) {
var bounds = overLapNodesCollection[parseInt(count.toString(), 10)].wrapper.bounds;
//EJ2-949872 - Connector Lines Overlapping Nodes in Child-to-Parent Flow
if (connectorBounds.intersects(bounds)) {
for (var i = 0; i < connector.segments.length; i++) {
var points_1 = connector.segments[parseInt(i.toString(), 10)].points;
for (var j = 0; j < points_1.length; j++) {
var lineStart = points_1[parseInt(j.toString(), 10)];
var lineEnd = points_1[j + 1];
if (lineEnd) {
var connectorPoints = this.pointsAlongLine(lineStart, lineEnd);
isInsideBounds = this.pointInsideBounds(connectorPoints, bounds);
if (isInsideBounds) {
diagram.routingConnectors.push(connector);
// eslint-disable-next-line no-labels
break overlapping;
}
}
}
}
}
}
}
};
/**
* Calculates the bounds of a connector by iterating through its segments and points.
* @param connector Provide the connector value.
* @returns An object representing the bounds of the connector.
*/
LineDistribution.prototype.getConnectorBounds = function (connector) {
var minX = Number.MAX_VALUE;
var minY = Number.MAX_VALUE;
var maxX = Number.MIN_VALUE;
var maxY = Number.MIN_VALUE;
// Iterate through all segments of the connector
/* eslint-disable */
for (var i = 0; i < connector.segments.length; i++) {
var segment = connector.segments[i];
var points = segment.points;
// Iterate through all points in the segment
for (var j = 0; j < points.length; j++) {
var point = points[j];
minX = Math.min(minX, point.x);
minY = Math.min(minY, point.y);
maxX = Math.max(maxX, point.x);
maxY = Math.max(maxY, point.y);
}
}
//Return the bounds as an object
return new Rect(minX, minY, maxX - minX, maxY - minY);
};
/**
* Calculates points along a line between two given points.
* @param start The starting point of the line.
* @param end The ending point of the line.
* @return An array of points along the line.
*/
LineDistribution.prototype.pointsAlongLine = function (start, end) {
// The distance between each generated point along the line. Must be > 0. Default is 2.
var granularity = 2;
var dx = end.x - start.x;
var dy = end.y - start.y;
var length = Math.sqrt(dx * dx + dy * dy);
var stepX = (dx / length);
var stepY = (dy / length);
var points = [];
for (var i = 0; i <= length; i += granularity) {
points.push({ x: start.x + stepX * i, y: start.y + stepY * i });
}
return points;
};
/**
*
* Checks if any of the given points fall inside the specified bounding rectangle.
* @param points An array of points to be checked.
* @param bounds The bounding rectangle to check against.
* @return True if any point is inside the bounds, false otherwise.
*/
LineDistribution.prototype.pointInsideBounds = function (points, bounds) {
var padding = 10;
for (var _i = 0, points_2 = points; _i < points_2.length; _i++) {
var point = points_2[_i];
if (bounds.right > point.x &&
bounds.left < point.x &&
bounds.top < point.y &&
bounds.bottom > point.y) {
return true;
}
}
return false;
};
/* tslint:enable */
/** @private */
//public arrangeElements(matrixModel: MatrixModelObject, layout: Layout): void {
// const layoutSettings: LayoutProp = matrixModel.model.layout;
// let isHorizontal: boolean;
// if (layout.orientation === 'LeftToRight' || layout.orientation === 'RightToLeft') {
// isHorizontal = true;
// } else {
// isHorizontal = false;
// }
// const spacing: number = isHorizontal ? layoutSettings.verticalSpacing : layoutSettings.horizontalSpacing;
// //let spacingInverse: number = !isHorizontal ? layoutSettings.verticalSpacing : layoutSettings.horizontalSpacing;
// // Need to group element before
// this.groupLayoutCells(matrixModel);
// this.createMatrixCells(matrixModel);
// for (let j: number = 0; j < matrixModel.matrix.length; j++) {
// const matrixKey: number = matrixModel.matrix[parseInt(j.toString(), 10)].key;
// const matrixrow: MatrixCellGroupObject[] = matrixModel.matrix[parseInt(matrixKey.toString(), 10)].value;
// for (let i: number = 1; i < matrixrow.length; i++) {
// const cell: MatrixCellGroupObject = matrixrow[parseInt(i.toString(), 10)];
// const prevCell: MatrixCellGroupObject = matrixrow[i - 1];
// cell.offset += prevCell.offset + (prevCell.size / 2) + spacing + (cell.size / 2);
// }
// }
// for (let j: number = 0; j < matrixModel.matrix[0].value.length; j++) {
// const root: MatrixCellGroupObject = matrixModel.matrix[0].value[parseInt(j.toString(), 10)];
// this.arrangeMatrix(root, null, matrixModel);
// }
// for (let k: number = 0; k < matrixModel.matrix.length; k++) {
// const row: MatrixCellGroupObject[] = matrixModel.matrix[parseInt(k.toString(), 10)].value;
// for (let i: number = 0; i < row.length; i++) {
// const cell: MatrixCellGroupObject = row[parseInt(i.toString(), 10)];
// if (cell.visitedParents.length > 1) {
// let firstParent: MatrixCellGroupObject = cell.visitedParents[0];
// let lastParent: MatrixCellGroupObject = cell.visitedParents[cell.visitedParents.length - 1];
// const firstVertexParent: MatrixCellGroupObject = this.findParentVertexCellGroup(firstParent);
// const lastVertexParent: MatrixCellGroupObject = this.findParentVertexCellGroup(lastParent);
// if (firstParent !== firstVertexParent && firstVertexParent.offset < firstParent.offset) {
// firstParent = firstVertexParent;
// }
// if (lastParent !== lastVertexParent && lastVertexParent.offset > lastParent.offset) {
// lastParent = firstVertexParent;
// }
// const newoffset: number = (firstParent.offset + lastParent.offset) / 2;
// const availOffsetMin: number = cell.initialOffset;
// const availOffsetMax: number = cell.offset;
// if (!(availOffsetMax === availOffsetMin)) {
// if (newoffset >= availOffsetMin && newoffset <= availOffsetMax) {
// this.translateMatrixCells(newoffset - cell.offset, cell);
// } else if (newoffset < availOffsetMin) {
// this.translateMatrixCells(availOffsetMin - cell.offset, cell);
// }
// }
// }
// }
// }
// this.setXYforMatrixCell(matrixModel);
//}
//private findParentVertexCellGroup(cell: MatrixCellGroupObject): MatrixCellGroupObject {
// if (cell.cells[0]) {
// return cell;
// }
// if (cell.parents.length > 0) {
// return this.findParentVertexCellGroup(cell.parents[0]);
// }
// return cell;
//}
//private setXYforMatrixCell(matrixModel: MatrixModelObject): void {
// const layoutSettings: LayoutProp = matrixModel.model.layout;
// const isHorizontal: boolean = layoutSettings.orientation === 'LeftToRight'
// || layoutSettings.orientation === 'RightToLeft';
// const spacing: number = isHorizontal ? layoutSettings.verticalSpacing : layoutSettings.horizontalSpacing;
// for (let i: number = 0; i < matrixModel.matrix.length; i++)