UNPKG

@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
/* 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 = [];