@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.
1,021 lines (1,020 loc) • 173 kB
JavaScript
/* eslint-disable jsdoc/require-returns-check */
import { Point } from './../primitives/point';
import { Rect } from './../primitives/rect';
import { getPoints, intersect3 } from './diagram-util';
import { NoOfSegments } from '../enum/enum';
import { StraightSegment, BezierSegment, OrthogonalSegment } from './../objects/connector';
import { PathElement } from './../core/elements/path-element';
import { cornersPointsBeforeRotation, rotatePoint } from './base-util';
/**
* Connector modules are used to dock and update the connectors
*/
/**
* intermeditatePoints method\
*
* @returns { Function } getFunction method .\
* @param {PointModel} element - provide the angle value.
* @param {PointModel} layoutOrientation - provide the angle value.
* @param {PointModel} lineDistribution - provide the angle value.
* @private
*/
export function findConnectorPoints(element, layoutOrientation, lineDistribution) {
//const intermeditatePoints: PointModel[];
var sourcePoint;
if (element.type === 'Straight' || !element.sourceWrapper) {
sourcePoint = getSourcePoint(element);
}
else {
sourcePoint = element.sourceWrapper.corners.center;
}
// eslint-disable-next-line
var intermeditatePoints = terminateConnection(element, sourcePoint, element.targetPoint, layoutOrientation, lineDistribution);
setLineEndPoint(element, intermeditatePoints[0], false);
setLineEndPoint(element, intermeditatePoints[intermeditatePoints.length - 1], true);
return intermeditatePoints;
}
/**
* getSourcePoint method\
*
* @returns { PointModel } getFunction method .\
* @param {PointModel} element - provide the angle value.
* @private
*/
function getSourcePoint(element) {
var srcPoint;
if (element.sourcePortWrapper) {
var srcPort = element.sourcePortWrapper;
//const srcNode: DiagramElement = element.sourceWrapper;
var pt = { x: srcPort.offsetX, y: srcPort.offsetY };
//const direction: string = getPortDirection(pt, cornersPointsBeforeRotation(srcNode), srcNode.bounds, false);
srcPoint = pt;
}
else if (element.sourceID && element.sourceWrapper) {
if (element.targetWrapper) {
var sPoint = element.sourceWrapper.corners.center;
var tPoint = element.targetWrapper.corners.center;
srcPoint = getIntersection(element, element.sourceWrapper, sPoint, tPoint, false);
}
else {
srcPoint = element.sourcePoint;
}
}
else {
srcPoint = element.sourcePoint;
}
return srcPoint;
}
/**
* getDirection method \
*
* @returns { void } getDirection method .\
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
* @param {LayoutOrientation} layoutOrientation - provide the layoutOrientation value.
*
* @private
*/
function getDirection(source, target, layoutOrientation) {
if (layoutOrientation === 'LeftToRight') {
source.direction = source.direction ? source.direction : 'Right';
target.direction = target.direction ? target.direction : 'Left';
}
else if (layoutOrientation === 'RightToLeft') {
source.direction = source.direction ? source.direction : 'Left';
target.direction = target.direction ? target.direction : 'Right';
}
else if (layoutOrientation === 'TopToBottom') {
source.direction = source.direction ? source.direction : 'Bottom';
target.direction = target.direction ? target.direction : 'Top';
}
else if (layoutOrientation === 'BottomToTop') {
source.direction = source.direction ? source.direction : 'Top';
target.direction = target.direction ? target.direction : 'Bottom';
}
}
/**
* terminateConnection method \
*
* @returns { PointModel[] } terminateConnection method .\
* @param {Connector} element - provide the element value.
* @param {PointModel} srcPoint - provide the srcPoint value.
* @param {PointModel} tarPoint - provide the tarPoint value.
* @param {LayoutOrientation} layoutOrientation - provide the layoutOrientation value.
* @param {boolean} lineDistribution - provide the lineDistribution value.
*
* @private
*/
function terminateConnection(element, srcPoint, tarPoint, layoutOrientation, lineDistribution) {
var sourceNode = element.sourceWrapper;
var targetNode = element.targetWrapper;
var sourcePort = element.sourcePortWrapper;
var targetPort = element.targetPortWrapper;
var srcCorner;
var tarCorner;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
var intermeditatePoints = [];
var segPoint;
var srcDir;
var tarDir;
var minSpace = findMargin(element);
var sourceMargin = { left: 5, right: 5, bottom: 5, top: 5 };
var targetMargin = { left: 5, right: 5, bottom: 5, top: 5 };
var source = { corners: srcCorner, point: srcPoint, direction: srcDir, margin: sourceMargin };
var target = { corners: tarCorner, point: tarPoint, direction: tarDir, margin: targetMargin };
var sourceCorners;
var targetCorners;
if (sourceNode !== undefined && targetNode !== undefined) {
sourceCorners = cornersPointsBeforeRotation(sourceNode);
targetCorners = cornersPointsBeforeRotation(targetNode);
source.corners = sourceNode.corners;
target.corners = targetNode.corners;
}
//946138: Connector Does Not Follow Shortest Path When Drawn from a Port.
if (sourcePort && sourcePort.isPathPort && targetPort) {
tarPoint = { x: targetPort.offsetX, y: targetPort.offsetY };
}
if (sourcePort !== undefined) {
var port = { x: sourcePort.offsetX, y: sourcePort.offsetY };
if (sourcePort.connectionDirection === 'Left' || sourcePort.connectionDirection === 'Top' || sourcePort.connectionDirection === 'Bottom' || sourcePort.connectionDirection === 'Right') {
source.direction = sourcePort.connectionDirection;
}
else {
//946138: Connector Does Not Follow Shortest Path When Drawn from a Port
if (sourcePort.isPathPort) {
source.direction = determineConnectorDirection(element.parentObj, element.sourceID, sourcePort, tarPoint);
}
else {
source.direction = getPortDirection(port, sourceCorners, sourceNode.bounds, false);
}
}
}
if (targetPort !== undefined) {
var tarPortPt = { x: targetPort.offsetX, y: targetPort.offsetY };
if (targetPort.connectionDirection === 'Left' || targetPort.connectionDirection === 'Right' || targetPort.connectionDirection === 'Bottom' || targetPort.connectionDirection === 'Top') {
target.direction = targetPort.connectionDirection;
}
else {
//946138: Connector Does Not Follow Shortest Path When Drawn from a Port
if (targetPort.isPathPort) {
target.direction = determineConnectorDirection(element.parentObj, element.targetID, targetPort, srcPoint);
}
else {
target.direction = getPortDirection(tarPortPt, targetCorners, targetNode.bounds, false);
}
}
}
if (element.type === 'Bezier') {
if (!element.isBezierEditing) {
if (element.segments.length > 0) {
var i = element.segments.length - 1;
while (i >= 0) {
var seg = element.segments[parseInt(i.toString(), 10)];
if (seg.isInternalSegment) {
element.segments.pop();
}
i--;
}
}
}
}
if (sourceNode !== undefined && targetNode !== undefined) {
if (source.direction === undefined || target.direction === undefined) {
if (layoutOrientation) {
getDirection(source, target, layoutOrientation);
}
else {
if (source.corners.top > target.corners.bottom &&
Math.abs(source.corners.top - target.corners.bottom) > minSpace) {
source.direction = source.direction ? source.direction : 'Top';
target.direction = target.direction ? target.direction : 'Bottom';
}
else if (source.corners.bottom < target.corners.top &&
Math.abs(source.corners.bottom - target.corners.top) > minSpace) {
source.direction = source.direction ? source.direction : 'Bottom';
target.direction = target.direction ? target.direction : 'Top';
}
else if ((source.corners.right < target.corners.left &&
Math.abs(source.corners.right - target.corners.left) > minSpace) ||
((source.corners.right + minSpace < target.corners.left) ||
(target.corners.right >= source.corners.left - minSpace && source.corners.left > target.corners.left))) {
source.direction = source.direction ? source.direction : 'Right';
target.direction = target.direction ? target.direction : 'Left';
}
else if ((source.corners.left > target.corners.right &&
Math.abs(source.corners.left - target.corners.right) > (source.margin.left + source.margin.right)) ||
((target.corners.right + minSpace < source.corners.left ||
(source.corners.right >= target.corners.left - minSpace
&& source.corners.left < target.corners.left)))) {
source.direction = source.direction ? source.direction : 'Left';
target.direction = target.direction ? target.direction : 'Right';
}
else {
if (sourceNode.id !== targetNode.id && (!sourceCorners.equals(sourceCorners, targetCorners)) &&
targetCorners.containsPoint(sourceCorners.topCenter, source.margin.top)) {
source.direction = source.direction ? source.direction : 'Bottom';
target.direction = target.direction ? target.direction : 'Top';
}
else {
source.direction = source.direction ? source.direction : 'Top';
target.direction = target.direction ? target.direction : 'Bottom';
}
}
}
}
return defaultOrthoConnection(element, source.direction, target.direction, source.point, target.point, lineDistribution, tarPoint);
}
//It will be called only when there is only one end node
checkLastSegmentasTerminal(element);
if (element.sourceWrapper || element.targetWrapper) {
connectToOneEnd(element, source, target);
}
if (element.type === 'Straight' || element.type === 'Bezier') {
intermeditatePoints = intermeditatePointsForStraight(element, source, target);
}
else {
if (element.type === 'Orthogonal' && element.segments && element.segments.length > 0 &&
element.segments[0].length !== null &&
element.segments[0].direction !== null) {
intermeditatePoints = findPointToPointOrtho(element, source, target, sourceNode, targetNode, sourcePort, targetPort, tarPoint);
}
else {
var extra = void 0;
if (!source.direction) {
source.direction = (target.direction) ? ((element.targetPortWrapper !== undefined) ? target.direction : getOppositeDirection(target.direction)) :
Point.direction(source.point, target.point);
}
else {
extra = adjustSegmentLength(sourceNode.bounds, source, 20);
}
element.segments[0].points = intermeditatePoints = orthoConnection3Segment(element, source, target, extra);
}
}
return intermeditatePoints;
}
/**
* determineConnectorDirection method \
*
* @returns {Direction | null} Determines the direction of a connector relative to a port and target point.\
* @param {Diagram} diagram - The diagram object containing connectors and elements.
* @param {string} connectorId - The Id of the connector in which the port is located.
* @param {DiagramElement} port - The port attached to the connector.
* @param {PointModel} tarPoint - The target point used to determine direction.
*
* @private
*/
function determineConnectorDirection(diagram, connectorId, port, tarPoint) {
var direction = null;
var parentConnector = diagram.nameTable["" + connectorId];
if (port && parentConnector) {
var portPosition = { x: port.offsetX, y: port.offsetY };
var segment = getSegmentOrientation(portPosition, parentConnector);
if (segment) {
direction = (segment === 'Horizontal') ? ((tarPoint.y > portPosition.y) ? 'Bottom' : 'Top') : ((tarPoint.x > portPosition.x) ? 'Right' : 'Left');
}
}
return direction;
}
/**
* getSegmentOrientation method \
*
* @returns {'Horizontal' | 'Vertical' | null} Identifies if the port position is on a horizontal or vertical segment of the connector.\
* @param {PointModel} portPosition - The position of the port on the connector.
* @param {Connector} parentConnector - The connector being analyzed for segments.
*
* @private
*/
function getSegmentOrientation(portPosition, parentConnector) {
var points = parentConnector.intermediatePoints;
for (var i = 0; i < points.length - 1; i++) {
var point1 = points[parseInt(i.toString(), 10)];
var point2 = points[i + 1];
if (isPortOnConnectorSegment(portPosition, point1, point2)) {
return point1.x === point2.x ? 'Vertical' : 'Horizontal';
}
}
if (points.length >= 2) {
var lastPoint1 = points[points.length - 2];
var lastPoint2 = points[points.length - 1];
return lastPoint1.x === lastPoint2.x ? 'Vertical' : 'Horizontal';
}
return null;
}
/**
* isPortOnConnectorSegment method \
*
* @returns {boolean} Checks if a port position lies between two given points on the same line.\
* @param {PointModel} portPosition - The position of the port.
* @param {PointModel} point1 - The first point of the line segment.
* @param {PointModel} point2 - The second point of the line segment.
*
* @private
*/
function isPortOnConnectorSegment(portPosition, point1, point2) {
if (point1.x === point2.x && portPosition.x === point1.x) {
return portPosition.y >= Math.min(point1.y, point2.y) && portPosition.y <= Math.max(point1.y, point2.y);
}
if (point1.y === point2.y && portPosition.y === point1.y) {
return portPosition.x >= Math.min(point1.x, point2.x) && portPosition.x <= Math.max(point1.x, point2.x);
}
return false;
}
/**
* updateSegmentPoints method \
*
* @returns { PointModel[] } updateSegmentPoints method .\
* @param {End} source - provide the source value.
* @param {OrthogonalSegment} segment - provide the segment value.
*
* @private
*/
function updateSegmentPoints(source, segment) {
//let segPoint: PointModel; //let angle: number; //let extra: number;
source.direction = segment.direction;
segment.points = [];
segment.points.push(source.point);
var extra = (segment.direction === 'Left' || segment.direction === 'Top') ? -(segment.length) : segment.length;
var angle = (segment.direction === 'Left' || segment.direction === 'Right') ? 0 : 90;
var segPoint = addLineSegment(source.point, extra, angle);
segment.points.push(segPoint);
return segPoint;
}
/**
* pointToPoint method \
*
* @returns { void } pointToPoint method .\
* @param {Connector} element - provide the element value.
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
*
* @private
*/
function pointToPoint(element, source, target) {
var point;
var direction;
var portdirection;
source.corners = (element.sourceWrapper) ? element.sourceWrapper.corners : undefined;
if (element.sourcePortWrapper) {
var port = { x: element.sourcePortWrapper.offsetX, y: element.sourcePortWrapper.offsetY };
portdirection = getPortDirection(port, cornersPointsBeforeRotation(element.sourceWrapper), element.sourceWrapper.bounds, false);
if (source.corners && (source.direction === 'Bottom' || source.direction === 'Top')) {
if (target.point.x > source.corners.left && target.point.x < source.corners.right) {
direction = (source.point.y > target.point.y) ? 'Top' : 'Bottom';
}
}
else if (source.corners && (source.direction === 'Left' || source.direction === 'Right')) {
if (target.point.y > source.corners.top && target.point.y < source.corners.bottom) {
direction = (source.point.x > target.point.x) ? 'Left' : 'Right';
}
}
}
if (element.sourcePortWrapper && portdirection === getOppositeDirection(direction)) {
var length_1;
if ((portdirection === 'Left' || portdirection === 'Right') && (source.point.y >= source.corners.top
&& source.point.y <= source.corners.center.y) &&
(target.point.y >= source.corners.top && target.point.y <= source.corners.center.y)) {
source.direction = 'Top';
length_1 = source.point.y - source.corners.top + 20;
}
else if ((portdirection === 'Left' || portdirection === 'Right') && (source.point.y > source.corners.center.y
&& source.point.y <= source.corners.bottom) &&
(target.point.y > source.corners.center.y && target.point.y <= source.corners.bottom)) {
source.direction = 'Bottom';
length_1 = source.corners.bottom - source.point.y + 20;
}
else if ((portdirection === 'Top' || portdirection === 'Bottom') && (source.point.x >= source.corners.left
&& source.point.x <= source.corners.center.x) &&
(target.point.x >= source.corners.left && target.point.x <= source.corners.center.x)) {
source.direction = 'Left';
length_1 = source.point.x - source.corners.left + 20;
}
else if ((portdirection === 'Top' || portdirection === 'Bottom') && (source.point.x <= source.corners.right
&& source.point.x > source.corners.center.x) &&
(target.point.x <= source.corners.right && target.point.x < source.corners.center.x)) {
source.direction = 'Right';
length_1 = source.corners.right - source.point.x + 20;
}
if (source.direction && length_1) {
point = orthoConnection3Segment(element, source, target, length_1, true);
}
}
else {
source.direction = (direction) ? direction : findSourceDirection(source.direction, source.point, target.point);
point = orthoConnection2Segment(source, target);
}
return point;
}
/**
* pointToNode method \
*
* @returns { void } pointToNode method .\
* @param {Connector} element - provide the element value.
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
*
* @private
*/
function pointToNode(element, source, target) {
var point;
target.corners = element.targetWrapper.corners;
findDirection(element.targetWrapper, source, target, element);
var direction = findSourceDirection(target.direction, source.point, target.point);
if (source.direction === target.direction && (source.direction === 'Left' || source.direction === 'Right')) {
source.direction = direction;
point = orthoConnection3Segment(element, source, target, element.targetWrapper.width / 2 + 20);
var source1 = source;
source1.point = point[1];
findDirection(element.targetWrapper, source, target, element);
point = orthoConnection3Segment(element, source, target);
}
else {
source.direction = direction;
point = orthoConnection2Segment(source, target);
}
return point;
}
/**
* addPoints method \
*
* @returns { void } addPoints method .\
* @param {Connector} element - provide the element value.
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
*
* @private
*/
function addPoints(element, source, target) {
target.corners = element.targetWrapper.corners;
var direction;
var length;
if (source.direction !== 'Left' && source.direction !== 'Right') {
if (target.corners.center.y === source.point.y &&
(!(target.corners.left <= source.point.x && source.point.x <= target.corners.right))) {
direction = 'Top';
length = target.corners.height / 2 + 20;
}
else if ((target.corners.center.y === source.point.y &&
element.segments[element.segments.length - 2].direction === 'Bottom') ||
(target.corners.center.y > source.point.y && source.point.y >= target.corners.top)) {
direction = 'Top';
length = (source.point.y - target.corners.top) + 20;
}
else if ((target.corners.center.y === source.point.y &&
element.segments[element.segments.length - 2].direction === 'Top') ||
(target.corners.center.y < source.point.y && source.point.y <= target.corners.bottom)) {
direction = 'Bottom';
length = (target.corners.bottom - source.point.y) + 20;
}
else if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
source.corners.top <= source.point.y && source.point.y <= source.corners.bottom) {
direction = source.direction;
length = (source.point.y > target.point.y) ? (source.point.y - source.corners.top + 20) :
(source.corners.bottom - source.point.y + 20);
}
}
else {
if (target.corners.center.x === source.point.x &&
(!(target.corners.top < source.point.y && source.point.y <= target.corners.bottom))) {
direction = 'Left';
length = target.corners.width / 2 + 20;
}
else if ((target.corners.center.x === source.point.x &&
element.segments[element.segments.length - 2].direction === 'Right')
|| (target.corners.center.x > source.point.x && source.point.x >= target.corners.left)) {
direction = 'Left';
length = (source.point.x - target.corners.left) + 20;
}
else if ((target.corners.center.x === source.point.x &&
element.segments[element.segments.length - 2].direction === 'Left') ||
(target.corners.center.x <= source.point.x && source.point.x <= target.corners.right)) {
direction = 'Right';
length = (target.corners.right - source.point.x) + 20;
}
else if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
source.corners.left <= source.point.x && source.point.x <= source.corners.right) {
direction = source.direction;
length = (source.point.x > target.point.x) ? (source.point.x - source.corners.left + 20) :
(source.corners.right - source.point.x + 20);
}
}
var extra = (direction === 'Left' || direction === 'Top') ? -(length) : length;
var angle = (direction === 'Left' || direction === 'Right') ? 0 : 90;
var refPoint = source.point;
source.point = addLineSegment(source.point, extra, angle);
source.direction = Point.direction(source.point, target.point);
if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
(source.corners.center.x === target.corners.center.x || source.corners.center.y === target.corners.center.y)) {
source.direction = target.direction;
}
var point = orthoConnection3Segment(element, source, target);
point.splice(0, 0, refPoint);
return point;
}
/**
* findSegmentDirection method \
*
* @returns { void } findSegmentDirection method .\
* @param {Connector} element - provide the element value.
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
* @param {Direction} portDir - provide the target value.
*
* @private
*/
function findSegmentDirection(element, source, target, portDir) {
var update = false;
switch (target.direction) {
case 'Left':
if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined && (portDir === 'Right' &&
source.point.x > target.point.x && source.point.y >= source.corners.top &&
source.point.y <= source.corners.bottom)
|| (((portDir === 'Bottom' && source.point.y > target.point.y) ||
(portDir === 'Top' && source.point.y < target.point.y)) &&
source.point.x >= source.corners.left && source.point.x <= source.corners.right)) {
source.direction = (portDir === 'Right') ? ((source.point.y > target.point.y) ? 'Top' : 'Bottom') :
(source.point.x < target.point.x ? 'Right' : 'Left');
update = true;
}
else if (source.point.x > target.point.x && (source.point.y > target.point.y || source.point.y < target.point.y)
&& (!(target.corners.top > source.point.y && target.corners.bottom < source.point.y))) {
source.direction = 'Left';
}
else if ((source.point.x < target.point.x && source.point.y > target.point.y) ||
(source.point.x > target.point.x && (source.point.y <= target.point.y)
&& ((target.corners.top < source.point.y && target.corners.center.y >= source.point.y)))) {
source.direction = 'Top';
}
else if ((source.point.x < target.point.x && source.point.y < target.point.y) ||
(source.point.x > target.point.x && (source.point.y > target.point.y)
&& ((target.corners.bottom < source.point.y && target.corners.center.y > source.point.y)))) {
source.direction = 'Bottom';
}
else if (source.point.y === target.point.y && source.point.x < target.point.x) {
source.direction = 'Right';
}
break;
case 'Right':
if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
((portDir === 'Bottom' && source.point.y > target.point.y) ||
(portDir === 'Top' && source.point.y < target.point.y)) && source.point.x > target.point.x &&
(source.point.x >= source.corners.left && source.point.x <= source.corners.right)) {
source.direction = (source.point.x > target.point.x) ? 'Left' : 'Right';
update = true;
}
else if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
portDir === 'Left' && source.point.x < target.point.x && (source.point.y >= source.corners.top &&
source.point.y <= source.corners.bottom)) {
source.direction = (source.point.y > target.point.y) ? 'Top' : 'Bottom';
update = true;
}
else if (source.point.x < target.point.x && target.corners.top <= source.point.y
&& target.corners.bottom >= source.point.y && source.point.y === target.point.y) {
source.direction = 'Top';
}
else if (source.point.y > target.point.y && source.point.x > target.point.x) {
source.direction = 'Top';
}
else if (source.point.y < target.point.y && source.point.x > target.point.x) {
source.direction = 'Bottom';
}
else if (source.point.x < target.point.x && (source.point.y > target.point.y ||
source.point.y < target.point.y)) {
source.direction = 'Right';
}
else if (source.point.y === target.point.y && source.point.x > target.point.x) {
source.direction = 'Left';
}
break;
case 'Top':
if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined && (portDir === 'Bottom' &&
source.point.y > target.point.y && source.point.x >= source.corners.left &&
source.point.x <= source.corners.right) || (((portDir === 'Right' && source.point.x > target.point.x) ||
(portDir === 'Left' && target.point.y > source.point.y && target.point.x > source.point.x)) &&
(source.point.y >= source.corners.top && source.point.y <= source.corners.bottom))) {
source.direction = (portDir === 'Bottom') ? ((source.point.x > target.point.x) ? 'Left' : 'Right') :
(source.point.y < target.point.y) ? 'Bottom' : 'Top';
update = true;
}
else if (source.point.x === target.point.x && source.point.y < target.point.y) {
source.direction = 'Bottom';
}
else if (source.point.y > target.point.y && source.point.x > target.corners.left &&
source.point.x < target.corners.right) {
source.direction = 'Left';
}
else if (source.point.y >= target.point.y) {
source.direction = 'Top';
}
else if (source.point.y < target.point.y && source.point.x > target.point.x) {
source.direction = 'Left';
}
else if (source.point.y < target.point.y && source.point.x < target.point.x) {
source.direction = 'Right';
}
break;
case 'Bottom':
if (element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined && ((((portDir === 'Right') ||
(portDir === 'Left' && target.point.x > source.point.x)) && (source.point.y > target.point.y) &&
source.point.y >= source.corners.top && source.point.y <= source.corners.bottom) ||
(((portDir === 'Top' && source.point.y < target.point.y)) &&
(source.point.x >= source.corners.left && source.point.x <= source.corners.right)))) {
if (portDir === 'Right' || portDir === 'Left') {
source.direction = (source.point.y > target.point.y) ? 'Top' : 'Bottom';
}
else {
source.direction = (source.point.x > target.point.x) ? 'Left' : 'Right';
}
update = true;
}
else if (source.point.y < target.point.y && source.point.x > target.corners.left &&
target.corners.right > source.point.x) {
if (source.point.y < target.point.y && source.point.x > target.corners.left &&
target.corners.center.x >= source.point.x) {
source.direction = 'Left';
}
else if (source.point.y < target.point.y && source.point.x < target.corners.right &&
target.corners.center.x < source.point.x) {
source.direction = 'Right';
}
}
else if (source.point.y > target.point.y && source.point.x > target.point.x) {
source.direction = 'Left';
}
else if (source.point.y > target.point.y && source.point.x < target.point.x) {
source.direction = 'Right';
}
else if (source.point.y <= target.point.y && (source.point.x > target.point.x || target.point.x > source.point.x)) {
source.direction = 'Bottom';
}
break;
}
return update;
}
/**
* pointToPort method \
*
* @returns { void } pointToPort method .\
* @param {Connector} element - provide the element value.
* @param {End} source - provide the source value.
* @param {End} target - provide the target value.
*
* @private
*/
function pointToPort(element, source, target) {
var point;
target.corners = element.targetWrapper.corners;
var portdirection;
var length;
if (element.sourcePortWrapper !== undefined) {
var port = { x: element.sourcePortWrapper.offsetX, y: element.sourcePortWrapper.offsetY };
portdirection = getPortDirection(port, cornersPointsBeforeRotation(element.sourceWrapper), element.sourceWrapper.bounds, false);
}
var update = findSegmentDirection(element, source, target, portdirection);
// EJ2-65063 - Added below condition !selectedSegmentIndex to prevent the connector segment to split from two points into four points
if ((!element.selectedSegmentIndex) && element.sourcePortWrapper !== undefined && element.targetPortWrapper !== undefined &&
target.direction === getOppositeDirection(portdirection) &&
((((target.direction === 'Left' && source.point.x > target.point.x) || (target.direction === 'Right' &&
source.point.x < target.point.x)) && source.point.y >= source.corners.top &&
source.point.y <= source.corners.bottom) || (target.direction === 'Bottom' && source.point.y < target.point.y &&
(source.point.x >= source.corners.left && source.point.x <= source.corners.right)))) {
point = addPoints(element, source, target);
}
else if ((!element.selectedSegmentIndex) && source.direction === target.direction) {
point = orthoConnection3Segment(element, source, target);
}
else if ((!element.selectedSegmentIndex) && (((target.direction === 'Left' && source.point.x > target.point.x) ||
(target.direction === 'Right' && source.point.x < target.point.x)) && (source.direction === 'Top' || source.direction === 'Bottom')
&& ((source.point.y <= target.point.y) &&
((target.corners.top <= source.point.y && target.corners.bottom >= source.point.y)))) ||
((target.direction === 'Top' && source.point.y > target.point.y) ||
(target.direction === 'Bottom' && source.point.y < target.point.y) &&
((target.corners.left <= source.point.x && target.corners.right >= source.point.x)))) {
// EJ2-69304 - Return the 2 segment points if allowNodeOverlap is set as true.
if (!element.selectedSegmentIndex) {
point = addPoints(element, source, target);
}
else {
point = orthoConnection2Segment(source, target);
}
}
else {
if ((!element.selectedSegmentIndex) && element.sourceWrapper !== undefined && element.targetWrapper !== undefined
&& element.targetPortWrapper !== undefined && ((source.direction === 'Left' || source.direction === 'Right')
&& (source.point.y >= source.corners.top && source.point.y <= source.corners.bottom)
&& (target.direction === 'Top' || target.direction === 'Bottom') &&
(target.corners.center.x === source.corners.center.x))) {
source.direction = (target.direction === 'Top') ? 'Bottom' : 'Top';
length = (target.direction === 'Top') ? (source.corners.bottom - source.point.y + 20) :
(source.point.y - source.corners.top + 20);
point = orthoConnection3Segment(element, source, target, length);
}
else if ((!element.selectedSegmentIndex) && element.sourceWrapper !== undefined && element.targetWrapper !== undefined
&& element.targetPortWrapper !== undefined && ((source.direction === 'Top' || source.direction === 'Bottom') &&
(source.point.x >= source.corners.left && source.point.x <= source.corners.right) &&
(target.direction === 'Left' || target.direction === 'Right') && (target.corners.center.y === source.corners.center.y))) {
source.direction = (target.direction === 'Left') ? 'Right' : 'Left';
length = (target.direction === 'Left') ? (source.corners.right - source.point.x + 20) :
(source.point.x - source.corners.left + 20);
point = orthoConnection3Segment(element, source, target, length);
}
else if (update) {
if (source.direction === 'Left' || source.direction === 'Right') {
length = (source.direction === 'Left') ? (source.point.x - source.corners.left + 20) :
(source.corners.right - source.point.x + 20);
}
else {
length = (source.direction === 'Top') ? (source.point.y - source.corners.top + 20) :
(source.corners.bottom - source.point.y + 20);
}
point = orthoConnection3Segment(element, source, target, length);
}
else {
point = orthoConnection2Segment(source, target);
}
}
return point;
}
/**
* findPointToPointOrtho method \
*
* @returns { void } findPointToPointOrtho method .\
* @param {Connector} element - provide the element value.
* @param {DiagramElement} source - provide the source value.
* @param {DiagramElement} target - provide the target value.
* @param {DiagramElement} sourceNode - provide the target value.
* @param {DiagramElement} targetNode - provide the target value.
* @param {DiagramElement} sourcePort - provide the sourcePort value.
* @param {DiagramElement} targetPort - provide the targetPort value.
* @param {PointModel} tarPoint - provide the target point of the connector.
*
* @private
*/
function findPointToPointOrtho(element, source, target, sourceNode, targetNode, sourcePort, targetPort, tarPoint) {
var j;
var point;
var intermeditatePoints = [];
var direction;
var port; //let seg: OrthogonalSegment;
checkLastSegmentasTerminal(element);
var removeSegment;
if (element.segments.length > 0) {
for (var i = 0; i < element.segments.length; i++) {
var seg = element.segments[parseInt(i.toString(), 10)];
if (i === 0 && element.sourcePortWrapper !== undefined) {
port = { x: sourcePort.offsetX, y: sourcePort.offsetY };
direction = getPortDirection(port, cornersPointsBeforeRotation(sourceNode), sourceNode.bounds, false);
if (seg.direction === getOppositeDirection(direction)) {
seg.direction = direction;
}
}
if (i > 0 && element.segments[i - 1].direction === seg.direction) {
i = checkConsectiveSegmentAsSame(element, i, source);
}
else {
var lastSegment = element.segments[i - 1];
source.point = (seg.direction) ? updateSegmentPoints(source, seg) :
lastSegment.points[lastSegment.points.length - 1];
}
if (i === element.segments.length - 1) {
if (!targetPort && !targetNode) {
point = pointToPoint(element, source, target);
}
else if (element.targetWrapper && element.targetPortWrapper === undefined) {
checkSourcePointInTarget(element, source);
point = pointToNode(element, source, target);
}
else {
point = pointToPort(element, source, target);
}
if (point) {
checkPreviousSegment(point, element, source);
seg.points = [];
if (point.length >= 2) {
for (j = 0; j < point.length; j++) {
seg.points.push(point[parseInt(j.toString(), 10)]);
}
}
else {
removeSegment = i;
}
}
}
if (sourcePort && i === 0) {
var sourcePoint = checkPortdirection(element, sourcePort, sourceNode, tarPoint);
if (sourcePoint) {
source.point = sourcePoint;
}
}
}
if (removeSegment !== undefined) {
if (removeSegment === element.segments.length - 1) {
element.segments[removeSegment - 1].direction = null;
element.segments[removeSegment - 1].length = null;
}
element.segments.splice(removeSegment, 1);
}
intermeditatePoints = returnIntermeditatePoints(element, intermeditatePoints);
}
return intermeditatePoints;
}
/**
* checkPortdirection method \
*
* @returns { PointModel } checkPortdirection method .\
* @param {Connector} element - provide the element value.
* @param {DiagramElement} sourcePort - provide the target value.
* @param {DiagramElement} sourceNode - provide the target value.
* @param {PointModel} targetPoint - provide the target point of the connector.
*
* @private
*/
function checkPortdirection(element, sourcePort, sourceNode, targetPoint) {
var port = { x: sourcePort.offsetX, y: sourcePort.offsetY };
var point;
var bounds = cornersPointsBeforeRotation(sourceNode);
var direction;
//946138: Connector Does Not Follow Shortest Path When Drawn from a Port
if (sourcePort.isPathPort && targetPoint) {
direction = determineConnectorDirection(element.parentObj, element.sourceID, sourcePort, targetPoint);
}
else {
direction = getPortDirection(port, bounds, sourceNode.bounds, false);
}
var seg = element.segments[0];
if (seg.direction !== direction) {
pointsFromNodeToPoint(seg, direction, bounds, seg.points[0], seg.points[seg.points.length - 1], false);
point = seg.points[seg.points.length - 1];
seg.direction = Point.direction(seg.points[seg.points.length - 2], seg.points[seg.points.length - 1]);
}
return point;
}
/**
* checkPreviousSegment method \
*
* @returns { PointModel } checkPreviousSegment method .\
* @param {Connector} tPoints - provide the element value.
* @param {DiagramElement} connector - provide the target value.
* @param {DiagramElement} source - provide the target value.
*
* @private
*/
function checkPreviousSegment(tPoints, connector, source) {
var actualSegment = connector.segments[connector.segments.length - 2];
var actualLastPoint = actualSegment.points[actualSegment.points.length - 1];
var direction;
if (((actualSegment.direction === 'Top' || actualSegment.direction === 'Bottom') && (actualLastPoint.x === tPoints[1].x)) ||
((actualSegment.direction === 'Left' || actualSegment.direction === 'Right') && (actualLastPoint.y === tPoints[1].y))) {
actualSegment.points[actualSegment.points.length - 1] = tPoints[1];
direction = Point.direction(actualSegment.points[0], actualSegment.points[actualSegment.points.length - 1]);
if (connector.sourceWrapper !== undefined && connector.sourcePortWrapper === undefined &&
direction === getOppositeDirection(actualSegment.direction)) {
if (actualSegment.direction === 'Left' || actualSegment.direction === 'Right') {
actualSegment.points[0].x = (actualSegment.direction === 'Right') ?
actualSegment.points[0].x - connector.sourceWrapper.corners.width :
actualSegment.points[0].x + connector.sourceWrapper.corners.width;
}
else {
actualSegment.points[0].y = (actualSegment.direction === 'Bottom') ?
actualSegment.points[0].y - connector.sourceWrapper.corners.height :
actualSegment.points[0].y + connector.sourceWrapper.corners.height;
}
}
actualSegment.direction = direction;
actualSegment.length = Point.distancePoints(actualSegment.points[0], actualSegment.points[actualSegment.points.length - 1]);
tPoints.splice(0, 1);
}
}
/**
* connectToOneEnd method \
*
* @returns { void } connectToOneEnd method .\
* @param {Connector} element - provide the element value.
* @param {DiagramElement} source - provide the target value.
* @param {DiagramElement} target - provide the target value.
*
* @private
*/
function connectToOneEnd(element, source, target) {
var sourcePort = element.sourcePortWrapper;
var targetPort = element.targetPortWrapper;
var node = element.sourceWrapper;
var fixedPoint = source.point;
var nodeMargin = { left: 0, right: 0, top: 0, bottom: 0 };
var nodeConnectingPoint = { x: 0, y: 0 };
var refPoint;
var nodeDirection = 'Top';
if (!node) {
node = element.targetWrapper;
nodeMargin = target.margin;
}
else {
fixedPoint = target.point;
nodeMargin = source.margin;
}
if (element.type === 'Orthogonal') {
if ((element.segments && element.segments.length > 0) && element.sourceWrapper &&
element.segments[0].direction) {
source.direction = element.segments[0].direction;
nodeConnectingPoint = findPoint(node.corners, source.direction);
refPoint = findPoint(node.corners, getOppositeDirection(source.direction));
nodeConnectingPoint = getIntersection(element, node, nodeConnectingPoint, refPoint, false);
}
else {
var source_1 = { corners: null, direction: null, point: fixedPoint, margin: nodeMargin };
var target_1 = { corners: null, direction: null, point: null, margin: null };
findDirection(node, source_1, target_1, element);
nodeConnectingPoint = target_1.point;
nodeDirection = target_1.direction;
}
}
else {
var segmentPoint = void 0;
if (element.segments && element.segments.length > 1) {
if (node === element.sourceWrapper) {
segmentPoint = element.segments[0].point;
}
else {
segmentPoint = element.segments[element.segments.length - 2].point;
}
}
nodeConnectingPoint = getIntersection(element, node, node.bounds.center, (element.segments && element.segments.length > 1) ? segmentPoint : fixedPoint, node === element.targetWrapper);
}
if (node === element.sourceWrapper) {
source.direction = source.direction || nodeDirection;
source.point = nodeConnectingPoint;
if (element.sourcePortWrapper) {
source.point = { x: sourcePort.offsetX, y: sourcePort.offsetY };
if (element.sourcePadding) {
source.point = addPaddingToConnector(element, source, target, false);
}
}
}
else {
target.direction = target.direction || nodeDirection;
target.point = nodeConnectingPoint;
if (element.targetPortWrapper) {
target.point = { x: targetPort.offsetX, y: targetPort.offsetY };
if (element.targetPadding) {
target.point = addPaddingToConnector(element, source, target, true);
}
}
}
}
/**
* addPaddingToConnector method \
*
* @returns { void } addPaddingToConnector method .\
* @param {Connector} element - provide the element value.
* @param {DiagramElement} source - provide the target value.
* @param {DiagramElement} target - provide the target value.
* @param {DiagramElement} isTarget - provide the target value.
*
* @private
*/
function addPaddingToConnector(element, source, target, isTarget) {
var sourcePort = element.sourcePortWrapper;
var targetPort = element.targetPortWrapper;
var padding = (isTarget) ? element.targetPadding : element.sourcePadding;
var paddingPort = (isTarget) ? targetPort : sourcePort;
var rect = new Rect(paddingPort.bounds.x - padding, paddingPort.bounds.y - padding, paddingPort.actualSize.width + 2 * padding, paddingPort.actualSize.height + 2 * padding);
var segmentPoints = [rect.topLeft, rect.topRight, rect.bottomRight, rect.bottomLeft];
segmentPoints[segmentPoints.length] = segmentPoints[0];
//const length: number = segmentPoints.length;
var thisSegment = { x1: source.point.x, y1: source.point.y, x2: target.point.x, y2: target.point.y };
var point = (isTarget) ? target.point : source.point;
return getIntersectionPoints(thisSegment, segmentPoints, true, point) || point;
}
/**
* checkSourceAndTargetIntersect method \
*
* @returns { void } checkSourceAndTargetIntersect method .\
* @param {DiagramElement} sourceWrapper - provide the sourceWrapper value.
* @param {DiagramElement} targetWrapper - provide the targetWrapper value.
* @param {Connector} connector - provide the Connector value.
*
* @private
*/
function checkSourceAndTargetIntersect(sourceWrapper, targetWrapper, connector) {
var sourceSegment = createSegmentsCollection(sourceWrapper, connector.sourcePadding);
var targetSegment = createSegmentsCollection(targetWrapper, connector.targetPadding);
for (var i = 0; i < sourceSegment.length - 1; i++) {
var srcSegment = sourceSegment[parseInt(i.toString(), 10)];
for (var j = 0; j < targetSegment.length - 1; j++) {
var tarSegmet = targetSegment[parseInt(j.toString(), 10)];
if (intersect3(srcSegment, tarSegmet).enabled) {
return true;
}
}
}
return false;
}
/**
* createSegmentsCollection method \
*
* @returns { Segment[] } createSegmentsCollection method .\
* @param {DiagramElement} sourceWrapper - provide the sourceWrapper value.
* @param {number} padding - provide the padding value.
*
* @private
*/
function createSegmentsCollection(sourceWrapper, padding) {
var segments = [];