@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,218 lines • 151 kB
JavaScript
import { Size } from './../primitives/size';
import { Rect } from './../primitives/rect';
import { identityMatrix, rotateMatrix, transformPointByMatrix, scaleMatrix } from './../primitives/matrix';
import { DiagramElement } from './../core/elements/diagram-element';
import { GroupableView } from './../core/containers/container';
import { StrokeStyle, Stop } from './../core/appearance';
import { Point } from './../primitives/point';
import { ConnectorConstraints, NodeConstraints, PortConstraints, DiagramConstraints, DiagramTools, Transform, BlazorAction, ControlPointsVisibility, DiagramEvent, ElementAction } from './../enum/enum';
import { SelectorConstraints, ThumbsConstraints, FlipDirection } from './../enum/enum';
import { PathElement } from './../core/elements/path-element';
import { DiagramNativeElement } from './../core/elements/native-element';
import { TextElement } from '../core/elements/text-element';
import { ImageElement } from '../core/elements/image-element';
import { PathAnnotation, ShapeAnnotation } from './../objects/annotation';
import { Node, FlowShape, BasicShape, Native, Html, UmlActivityShape, BpmnGateway, BpmnDataObject, BpmnEvent, BpmnSubEvent, BpmnActivity, BpmnAnnotation, MethodArguments, UmlClassAttribute, UmlClassMethod, UmlClass, UmlInterface, UmlEnumerationMember, UmlEnumeration, Lane, Phase, ChildContainer, SwimLane, Path, Image, Text, BpmnShape, UmlClassifierShape, Header } from './../objects/node';
import { Connector, bezierPoints, BezierSegment, StraightSegment, OrthogonalSegment } from './../objects/connector';
import { getBasicShape } from './../objects/dictionary/basic-shapes';
import { getFlowShape } from './../objects/dictionary/flow-shapes';
import { Diagram } from './../diagram';
import { findAngle } from './connector';
import { getContent, removeElement, hasClass, getDiagramElement } from './dom-util';
import { getBounds, cloneObject, rotatePoint, getFunction, cornersPointsBeforeRotation, getOffset } from './base-util';
import { getPolygonPath } from './../utility/path-util';
import { DiagramHtmlElement } from '../core/elements/html-element';
import { getRulerSize } from '../ruler/ruler';
import { canResize } from './constraints-util';
import { UserHandle } from '../interaction/selector';
import { getUMLActivityShape } from '../objects/dictionary/umlactivity-shapes';
import { Canvas } from '../core/containers/canvas';
import { PointPort } from '../objects/port';
import { Command } from '../diagram/keyboard-commands';
import { pasteSwimLane } from './swim-lane-util';
import { isBlazor, Browser, isNullOrUndefined } from '@syncfusion/ej2-base';
import { ConnectorFixedUserHandle } from '../objects/fixed-user-handle';
import { Overview } from '../../overview/overview';
/**
* completeRegion method\
*
* @returns { void } completeRegion method .\
* @param {Rect} region - provide the region value.
* @param {(NodeModel | ConnectorModel)[]} selectedObjects - provide the selectedObjects value.
* @private
*/
export function completeRegion(region, selectedObjects) {
var collection = [];
for (var i = 0; i < selectedObjects.length; i++) {
var obj = selectedObjects[parseInt(i.toString(), 10)];
if (region.containsRect(obj.wrapper.bounds)) {
collection.push(obj);
}
}
return collection;
}
/**
* findNodeByName method \
*
* @returns { boolean } findNodeByName method .\
* @param {(NodeModel | ConnectorModel)[]} nodes - provide the nodes value.
* @param {string} name - provide the orientation value.
* @private
*/
export function findNodeByName(nodes, name) {
for (var i = 0; i < nodes.length; i++) {
if (nodes[parseInt(i.toString(), 10)].id === name) {
return true;
}
}
return false;
}
/**
* findNodeByName method \
*
* @returns { string } findNodeByName method .\
* @param {(NodeModel | ConnectorModel)[]} drawingObject - provide the drawingObject value.
* @private
*/
export function findObjectType(drawingObject) {
var type;
if (drawingObject) {
if (drawingObject.type) {
type = 'Connector';
}
else if (drawingObject.shape && !drawingObject.type) {
type = 'Node';
}
}
return type;
}
/**
* setSwimLaneDefaults method \
*
* @returns { void } setSwimLaneDefaults method .\
* @param {NodeModel | ConnectorModel} child - provide the child value.
* @param {NodeModel | ConnectorModel} node - provide the node value.
* @private
*/
export function setSwimLaneDefaults(child, node) {
if (node instanceof Node) {
if (!child.shape.header) {
node.shape.hasHeader = false;
}
}
}
/**
* getSpaceValue method \
*
* @returns { number } getSpaceValue method .\
* @param {number[]} intervals - provide the intervals value.
* @param {boolean} isLine - provide the isLine value.
* @param {number} i - provide the i value.
* @param {number} space - provide the space value.
* @private
*/
export function getSpaceValue(intervals, isLine, i, space) {
space = !isLine ? ((intervals[i - 1] !== undefined) ? intervals[i - 1] + space : 0) : space;
return space;
}
/**
* getInterval method \
*
* @returns { number[] } getInterval method .\
* @param {number[]} intervals - provide the intervals value.
* @param {boolean} isLine - provide the isLine value.
* @private
*/
export function getInterval(intervals, isLine) {
var newInterval = [];
if (!isLine) {
for (var k = 0; k < intervals.length; k++) {
newInterval.push(intervals[parseInt(k.toString(), 10)]);
}
newInterval.push(intervals[newInterval.length - 2]);
newInterval.push(intervals[newInterval.length - 2]);
}
else {
newInterval = intervals;
}
return newInterval;
}
/**
* setPortsEdges method \
*
* @returns { Node } setPortsEdges method .\
* @param {Node} node - provide the node value.
* @private
*/
export function setPortsEdges(node) {
for (var k = 0; k < node.ports.length; k++) {
node.ports[parseInt(k.toString(), 10)].inEdges = [];
node.ports[parseInt(k.toString(), 10)].outEdges = [];
}
return node;
}
/**
* setUMLActivityDefaults method \
*
* @returns { void } setUMLActivityDefaults method .\
* @param {NodeModel | ConnectorModel} child - provide the child value.
* @param {NodeModel | ConnectorModel} node - provide the node value.
* @private
*/
export function setUMLActivityDefaults(child, node) {
if (node instanceof Node) {
var shape = child.shape.shape;
switch (shape) {
case 'JoinNode':
if (!child.width) {
node.width = 20;
}
if (!child.height) {
node.height = 90;
}
if (!child.style || !child.style.fill) {
node.style.fill = 'black';
}
break;
case 'ForkNode':
if (!child.width) {
node.width = 90;
}
if (!child.height) {
node.height = 20;
}
if (!child.style || !child.style.fill) {
node.style.fill = 'black';
}
break;
case 'InitialNode':
if (!child.style || !child.style.fill) {
node.style.fill = 'black';
}
break;
case 'FinalNode':
if (!child.style || !child.style.fill) {
node.style.fill = 'black';
}
break;
}
}
else {
var flow = child.shape.flow;
switch (flow) {
case 'Object':
if (!child.style || !child.style.strokeDashArray) {
node.style.strokeDashArray = '8 4';
}
if (!child.style || !child.style.strokeWidth) {
node.style.strokeWidth = 2;
}
if (!child.targetDecorator || !child.targetDecorator.shape) {
node.targetDecorator.shape = 'OpenArrow';
}
break;
case 'Control':
if (!child.style || !child.style.strokeWidth) {
node.style.strokeWidth = 2;
}
if (!child.targetDecorator || !child.targetDecorator.shape) {
node.targetDecorator.shape = 'OpenArrow';
}
if (!child.sourceDecorator || !child.sourceDecorator.shape) {
node.sourceDecorator.shape = 'None';
}
break;
}
}
}
/* eslint-disable */
/**
* setConnectorDefaults method \
*
* @returns { void } setConnectorDefaults method .\
* @param {ConnectorModel} child - provide the child value.
* @param {ConnectorModel} node - provide the node value.
* @private
*/
export function setConnectorDefaults(child, node) {
switch ((child.shape).type) {
case 'Bpmn':
var bpmnFlow = child.shape.flow;
switch (bpmnFlow) {
case 'Sequence':
if ((((child.shape.sequence) === 'Normal' && child.type !== 'Bezier')) ||
((child.shape.sequence) === 'Default') || ((child.shape.sequence) === 'Conditional')) {
if (node.targetDecorator && node.targetDecorator.style) {
node.targetDecorator.style.fill = (child.targetDecorator && child.targetDecorator.style
&& child.targetDecorator.style.fill) || 'black';
}
if ((child.shape.sequence) === 'Conditional' && node.sourceDecorator) {
if (node.sourceDecorator.style) {
node.sourceDecorator.style.fill = (child.sourceDecorator && child.sourceDecorator.style &&
child.sourceDecorator.style.fill) || 'white';
}
node.sourceDecorator.width = (child.sourceDecorator && child.sourceDecorator.width) || 20;
node.sourceDecorator.height = (child.sourceDecorator && child.sourceDecorator.width) || 10;
}
}
break;
case 'Association':
if (((child.shape.association) === 'Default') ||
((child.shape.association) === 'Directional') ||
((child.shape.association) === 'BiDirectional')) {
if (node.targetDecorator && node.targetDecorator.style) {
node.targetDecorator.style.fill = (child.targetDecorator && child.targetDecorator.style &&
child.targetDecorator.style.fill) || 'black';
}
if ((child.shape.association) === 'BiDirectional') {
if (node.sourceDecorator && node.sourceDecorator.style) {
node.sourceDecorator.style.fill = (child.sourceDecorator && child.sourceDecorator.style &&
child.sourceDecorator.style.fill) || 'white';
node.sourceDecorator.width = (child.sourceDecorator && child.sourceDecorator.width) || 5;
node.sourceDecorator.height = (child.sourceDecorator && child.sourceDecorator.height) || 10;
}
}
}
break;
case 'Message':
if (node.style && !node.style.strokeDashArray) {
node.style.strokeDashArray = (child.style && child.style.strokeDashArray) || '4 4';
}
break;
}
break;
case 'UmlActivity':
var flow = child.shape.flow;
switch (flow) {
case 'Exception':
if (((child.shape.association) === 'Directional') ||
((child.shape.association) === 'BiDirectional')) {
node.style.strokeDashArray = (child.style && child.style.strokeDashArray) || '2 2';
}
break;
}
break;
case 'UmlClassifier':
var hasRelation = false;
if (child.shape.relationship === 'Association') {
hasRelation = true;
}
else if (child.shape.relationship === 'Inheritance') {
if (node.targetDecorator && node.targetDecorator.style) {
node.targetDecorator.style.fill = (child.targetDecorator && child.targetDecorator.style &&
child.targetDecorator.style.fill) || 'white';
}
if (node.style) {
hasRelation = true;
}
}
else if (child.shape.relationship === 'Composition') {
if (node.sourceDecorator && node.sourceDecorator.style) {
node.sourceDecorator.style.fill = (child.sourceDecorator && child.sourceDecorator.style &&
child.sourceDecorator.style.fill) || 'black';
}
hasRelation = true;
}
else if (child.shape.relationship === 'Aggregation' ||
child.shape.relationship === undefined) {
if (node.sourceDecorator && node.sourceDecorator.style) {
node.sourceDecorator.style.fill = (child.sourceDecorator && child.sourceDecorator.style &&
child.sourceDecorator.style.fill) || 'white';
}
hasRelation = true;
}
else if (child.shape.relationship === 'Dependency') {
if (node.sourceDecorator && node.sourceDecorator.style) {
node.sourceDecorator.style.fill = (child.sourceDecorator && child.sourceDecorator.style &&
child.sourceDecorator.style.fill) || 'white';
}
hasRelation = true;
node.style.strokeDashArray = '4 4';
}
else if (child.shape.relationship === 'Realization') {
if (node.targetDecorator && node.targetDecorator.style) {
node.targetDecorator.style.fill = (child.targetDecorator && child.targetDecorator.style &&
child.targetDecorator.style.fill) || 'white';
}
hasRelation = true;
node.style.strokeDashArray = '4 4';
}
if (hasRelation) {
node.style.strokeWidth = (child.style && child.style.strokeWidth) || 2;
}
break;
}
}
/* eslint-enable */
/**
* findNearestPoint method \
*
* @returns { PointModel } findNearestPoint method .\
* @param {PointModel} reference - provide the reference value.
* @param {PointModel} start - provide the start value.
* @param {PointModel} end - provide the end value.
* @private
*/
export function findNearestPoint(reference, start, end) {
var shortestPoint;
var shortest = Point.findLength(start, reference);
var shortest1 = Point.findLength(end, reference);
if (shortest > shortest1) {
shortestPoint = end;
}
else {
shortestPoint = start;
}
var angleBWStAndEnd = Point.findAngle(start, end);
var angleBWStAndRef = Point.findAngle(shortestPoint, reference);
var r = Point.findLength(shortestPoint, reference);
var vaAngle = angleBWStAndRef + ((angleBWStAndEnd - angleBWStAndRef) * 2);
return {
x: (shortestPoint.x + r * Math.cos(vaAngle * Math.PI / 180)),
y: (shortestPoint.y + r * Math.sin(vaAngle * Math.PI / 180))
};
}
/**
* pointsForBezier method \
*
* @returns { PointModel[] } pointsForBezier method .\
* @param {ConnectorModel} connector - provide the connector value.
* @private
*/
function pointsForBezier(connector) {
var points = [];
if (connector.type === 'Bezier') {
var k = 0;
for (var i = 0; i < connector.segments.length; i++) {
var tolerance = 1.5;
var segment = connector.segments[parseInt(i.toString(), 10)];
//const pt: PointModel = { x: 0, y: 0 };
var point1 = !Point.isEmptyPoint(segment.point1) ? segment.point1 : segment.bezierPoint1;
var point2 = !Point.isEmptyPoint(segment.point2) ? segment.point2 : segment.bezierPoint2;
var max = Number((connector.distance(point1, segment.points[0]) +
connector.distance(point2, point1) +
connector.distance(segment.points[1], point2)) / tolerance);
for (var j = 0; j < max - 1; j = j + 10) {
points[parseInt(k.toString(), 10)] =
bezierPoints(connector, segment.points[0], !Point.isEmptyPoint(segment.point1) ? segment.point1 : segment.bezierPoint1, !Point.isEmptyPoint(segment.point2) ? segment.point2 : segment.bezierPoint2, segment.points[1], j, max);
k++;
}
}
}
return points;
}
/**
* isDiagramChild method \
*
* @returns { boolean } isDiagramChild method .\
* @param {HTMLElement} htmlLayer - provide the htmlLayer value.
* @private
*/
export function isDiagramChild(htmlLayer) {
var element = htmlLayer.parentElement;
do {
if (hasClass(element, 'e-diagram')) {
return true;
}
element = element.parentElement;
} while (element);
return false;
}
/**
* groupHasType method \
*
* @returns { boolean } groupHasType method .\
* @param {NodeModel} node - provide the node value.
* @param {Shapes} type - provide the type value.
* @param {{}} nameTable - provide the nameTable value.
* @private
*/
// eslint-disable-next-line @typescript-eslint/ban-types
export function groupHasType(node, type, nameTable) {
var contains = false;
if (node && node.children && node.children.length > 0) {
var child = void 0;
var i = 0;
for (; i < node.children.length; i++) {
child = nameTable[node.children[parseInt(i.toString(), 10)]];
if (child.shape.type === type) {
return true;
}
return groupHasType(child, type, nameTable);
}
}
return contains;
}
/**
* groupHasType method \
*
* @returns { void } groupHasType method .\
* @param {NodeModel | ConnectorModel} actualNode - provide the actualNode value.
* @param { NodeModel | ConnectorModel} plainValue - provide the plainValue value.
* @param {object} defaultValue - provide the defaultValue value.
* @param {NodeModel | ConnectorModel} property - provide the property value.
* @param {string} oldKey - provide the oldKey value.
* @private
*/
export function updateDefaultValues(actualNode, plainValue,
// eslint-disable-next-line @typescript-eslint/ban-types
defaultValue, property, oldKey) {
if (defaultValue && ((actualNode instanceof Connector) || actualNode
&& ((actualNode.shape && actualNode.shape.type !== 'SwimLane') || actualNode.shape === undefined))) {
// eslint-disable-next-line @typescript-eslint/ban-types
var keyObj = void 0;
for (var _i = 0, _a = Object.keys(defaultValue); _i < _a.length; _i++) {
var key = _a[_i];
keyObj = defaultValue["" + key];
if (key === 'shape' && keyObj.type) {
actualNode.shape = { type: keyObj.type };
}
if (keyObj) {
if (Array.isArray(keyObj) && keyObj.length && keyObj.length > 0 && (oldKey !== 'annotations' && oldKey !== 'ports')) {
if (actualNode["" + key].length > 0) {
for (var i = 0; i <= actualNode["" + key].length; i++) {
updateDefaultValues(actualNode["" + key], plainValue ? plainValue["" + key] : undefined, defaultValue["" + key], (key === 'annotations' || key === 'ports') ? actualNode : undefined, key);
}
}
else {
updateDefaultValues(actualNode["" + key], plainValue ? plainValue["" + key] : undefined, defaultValue["" + key], (key === 'annotations' || key === 'ports') ? actualNode : undefined, key);
}
}
else if (keyObj instanceof Object && plainValue && (oldKey !== 'annotations' && oldKey !== 'ports')) {
updateDefaultValues(actualNode["" + key], plainValue["" + key], defaultValue["" + key]);
}
else if ((oldKey !== 'annotations' && oldKey !== 'ports')
&& (plainValue && !plainValue["" + key]) || (!plainValue && actualNode
&& (actualNode["" + key] || actualNode["" + key] !== undefined))) {
actualNode["" + key] = defaultValue["" + key];
}
else {
var createObject = void 0;
if (oldKey === 'annotations' || oldKey === 'ports') {
if (oldKey === 'annotations') {
if (actualNode["" + key]) {
updateDefaultValues(actualNode["" + key], plainValue["" + key], defaultValue["" + key]);
}
if (!actualNode["" + key]) {
if (getObjectType(property) === Connector) {
createObject = new PathAnnotation(property, 'annotations', defaultValue["" + key]);
property.annotations.push(createObject);
}
else {
createObject = new ShapeAnnotation(property, 'annotations', defaultValue["" + key]);
property.annotations.push(createObject);
}
}
}
else {
if (actualNode["" + key]) {
updateDefaultValues(actualNode["" + key], plainValue["" + key], defaultValue["" + key]);
}
else {
createObject = new PointPort(property, 'ports', defaultValue["" + key]);
property.ports.push(createObject);
}
}
}
}
}
}
}
}
/* tslint:disable:no-string-literal */
/**
* updateLayoutValue method \
*
* @returns { void } updateLayoutValue method .\
* @param {TreeInfo} actualNode - provide the actualNode value.
* @param { object} defaultValue - provide the defaultValue value.
* @param {INode[]} nodes - provide the nodes value.
* @param {INode} node - provide the node value.
* @private
*/
// eslint-disable-next-line @typescript-eslint/ban-types
export function updateLayoutValue(actualNode, defaultValue, nodes, node) {
// eslint-disable-next-line @typescript-eslint/ban-types
var keyObj;
var assistantKey = 'Role';
if (defaultValue) {
for (var _i = 0, _a = Object.keys(defaultValue); _i < _a.length; _i++) {
var key = _a[_i];
keyObj = defaultValue["" + key];
if (key === 'getAssistantDetails') {
//Removed isBlazor code
if (node.data["" + assistantKey] === defaultValue["" + key]['root']) {
var assitants = defaultValue["" + key]['assistants'];
for (var i = 0; i < assitants.length; i++) {
for (var j = 0; j < nodes.length; j++) {
if (nodes[parseInt(j.toString(), 10)].data["" + assistantKey] === assitants[parseInt(i.toString(), 10)]) {
actualNode.assistants.push(nodes[parseInt(j.toString(), 10)].id);
actualNode.children.splice(0, 1);
}
}
}
}
}
else if (keyObj) {
actualNode["" + key] = defaultValue["" + key];
}
}
}
if (!actualNode.hasSubTree && defaultValue.canEnableSubTree) {
actualNode.orientation = node.layoutInfo.orientation;
actualNode.type = node.layoutInfo.type;
if (node.layoutInfo.offset !== actualNode.offset && (node.layoutInfo.offset) !== undefined) {
actualNode.offset = node.layoutInfo.offset;
}
}
node.layoutInfo.hasSubTree = actualNode.hasSubTree;
}
/* tslint:enable:no-string-literal */
/**
* isPointOverConnector method \
*
* @returns { boolean } isPointOverConnector method .\
* @param {ConnectorModel} connector - provide the connector value.
* @param { PointModel} reference - provide the reference value.
* @private
*/
export function isPointOverConnector(connector, reference) {
//let intermediatePoints: PointModel[];
var intermediatePoints = connector.type === 'Bezier' ? pointsForBezier(connector) :
connector.intermediatePoints;
for (var i = 0; i < intermediatePoints.length - 1; i++) {
var start = intermediatePoints[parseInt(i.toString(), 10)];
var end = intermediatePoints[i + 1];
var rect = Rect.toBounds([start, end]);
rect.Inflate(connector.hitPadding);
if (rect.containsPoint(reference)) {
var intersectinPt = findNearestPoint(reference, start, end);
var segment1 = { x1: start.x, x2: end.x, y1: start.y, y2: end.y };
var segment2 = { x1: reference.x, x2: intersectinPt.x, y1: reference.y, y2: intersectinPt.y };
var intersectDetails = intersect3(segment1, segment2);
if (intersectDetails.enabled) {
var distance = Point.findLength(reference, intersectDetails.intersectPt);
if (Math.abs(distance) < connector.hitPadding) {
return true;
}
}
else {
var rect_1 = Rect.toBounds([reference, reference]);
rect_1.Inflate(3);
if (rect_1.containsPoint(start) || rect_1.containsPoint(end)) {
return true;
}
}
if (Point.equals(reference, intersectinPt)) {
return true;
}
}
}
if (connector.annotations.length > 0 || connector.ports.length > 0) {
var container = connector.wrapper.children;
for (var i = 3; i < container.length; i++) {
var textElement = container[parseInt(i.toString(), 10)];
if (textElement.bounds.containsPoint(reference)) {
return true;
}
}
}
return false;
}
/**
* intersect3 method \
*
* @returns { Intersection } intersect3 method .\
* @param {ConnectorModel} lineUtil1 - provide the lineUtil1 value.
* @param { PointModel} lineUtil2 - provide the lineUtil2 value.
* @private
*/
export function intersect3(lineUtil1, lineUtil2) {
var point = { x: 0, y: 0 };
var l1 = lineUtil1;
var l2 = lineUtil2;
var d = (l2.y2 - l2.y1) * (l1.x2 - l1.x1) - (l2.x2 - l2.x1) * (l1.y2 - l1.y1);
var na = (l2.x2 - l2.x1) * (l1.y1 - l2.y1) - (l2.y2 - l2.y1) * (l1.x1 - l2.x1);
var nb = (l1.x2 - l1.x1) * (l1.y1 - l2.y1) - (l1.y2 - l1.y1) * (l1.x1 - l2.x1);
/*( EJ2-42102 - Connector segments not update properly ) by sivakumar sekar - condition added to avoid bridging for
overlapping segments in the connectors and to validate whether the connector is intersecting over the other */
if (d === 0 || ((lineUtil1.x1 === lineUtil2.x1 || lineUtil1.y1 === lineUtil2.y1) &&
(lineUtil1.x2 === lineUtil2.x2 || lineUtil1.y2 === lineUtil2.y2) && ((na === 0 || nb === 0) && d > 0))) {
return { enabled: false, intersectPt: point };
}
var ua = na / d;
var ub = nb / d;
if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
point.x = l1.x1 + (ua * (l1.x2 - l1.x1));
point.y = l1.y1 + (ua * (l1.y2 - l1.y1));
return { enabled: true, intersectPt: point };
}
return { enabled: false, intersectPt: point };
}
/**
* intersect2 method \
*
* @returns { PointModel } intersect2 method .\
* @param {PointModel} start1 - provide the start1 value.
* @param { PointModel} end1 - provide the end1 value.
* @param { PointModel} start2 - provide the start2 value.
* @param { PointModel} end2 - provide the end2 value.
* @private
*/
export function intersect2(start1, end1, start2, end2) {
var point = { x: 0, y: 0 };
var lineUtil1 = getLineSegment(start1.x, start1.y, end1.x, end1.y);
var lineUtil2 = getLineSegment(start2.x, start2.y, end2.x, end2.y);
var line3 = intersect3(lineUtil1, lineUtil2);
if (line3.enabled) {
return line3.intersectPt;
}
else {
return point;
}
}
/**
* getLineSegment method \
*
* @returns { Segment } getLineSegment method .\
* @param {number} x1 - provide the x1 value.
* @param { number} y1 - provide the y1 value.
* @param { number} x2 - provide the x2 value.
* @param { number} y2 - provide the y2 value.
* @private
*/
export function getLineSegment(x1, y1, x2, y2) {
return { 'x1': Number(x1) || 0, 'y1': Number(y1) || 0, 'x2': Number(x2) || 0, 'y2': Number(y2) || 0 };
}
/**
* getPoints method \
*
* @returns { PointModel[] } getPoints method .\
* @param {number} element - provide the element value.
* @param { number} corners - provide the corners value.
* @param { number} padding - provide the padding value.
* @private
*/
export function getPoints(element, corners, padding) {
var line = [];
padding = padding || 0;
var left = { x: corners.topLeft.x - padding, y: corners.topLeft.y };
var right = { x: corners.topRight.x + padding, y: corners.topRight.y };
var top = { x: corners.bottomRight.x, y: corners.bottomRight.y - padding };
var bottom = { x: corners.bottomLeft.x, y: corners.bottomLeft.y + padding };
line.push(left);
line.push(right);
line.push(top);
line.push(bottom);
return line;
}
/**
* getTooltipOffset method \
*
* @returns { PointModel[] } getTooltipOffset method .\
* @param {number} diagram - provide the diagram value.
* @param { number} mousePosition - provide the mousePosition value.
* @param { NodeModel | ConnectorModel | PointPortModel} node - provide the node value.
* @param { string} type - provide the type value.
* @private
*/
export function getTooltipOffset(diagram, mousePosition, node, type) {
//let offset: PointModel;
var inheritTooltip = (node instanceof Node) ? (node.constraints & NodeConstraints.InheritTooltip)
: (node instanceof Connector) ? (node.constraints & ConnectorConstraints.InheritTooltip)
: (node.constraints & PortConstraints.InheritTooltip);
var objectTooltip = (node instanceof Node) ? (node.constraints & NodeConstraints.Tooltip)
: (node instanceof Connector) ? (node.constraints & ConnectorConstraints.Tooltip)
: (node.constraints & PortConstraints.ToolTip);
var isMouseBased = ((!inheritTooltip && objectTooltip ? node.tooltip.relativeMode
: diagram.tooltip.relativeMode) === 'Mouse') ? true : false;
if (type === 'Mouse') {
isMouseBased = true;
}
else if (type === 'Object') {
isMouseBased = false;
}
var offset = tooltipOffset(node, mousePosition, diagram, isMouseBased);
var rulerSize = getRulerSize(diagram);
return { x: offset.x + rulerSize.width, y: offset.y + rulerSize.height };
}
/**
* tooltipOffset method \
*
* @returns { PointModel } tooltipOffset method .\
* @param {NodeModel | ConnectorModel | PointPortModel} node - provide the node value.
* @param { PointModel} mousePosition - provide the mousePosition value.
* @param { Diagram } diagram - provide the diagram value.
* @param { boolean} isMouseBased - provide the isMouseBased value.
* @private
*/
function tooltipOffset(node, mousePosition, diagram, isMouseBased) {
var point = {};
//let scale: number = diagram.scroller.transform.scale;
var element = document.getElementById(diagram.element.id);
var bounds;
//EJ2-62120-Tooltip support for ports
if (node instanceof Node || node instanceof Connector) {
bounds = node.wrapper.bounds;
}
else {
var objects = diagram.findObjectsUnderMouse(mousePosition);
var obj = diagram.findObjectUnderMouse(objects, 'Select', false);
var portElement = diagram.findElementUnderMouse(obj, mousePosition, diagram);
bounds = portElement.bounds;
}
var rect = element.getBoundingClientRect();
/* eslint-enable */
//let horizontalOffset: number = diagram.scroller.horizontalOffset;
//let verticalOffset: number = diagram.scroller.verticalOffset;
switch (diagram.tooltipObject.position) {
case 'BottomCenter':
point = offsetPoint(mousePosition, bounds.bottomCenter, diagram, isMouseBased, (rect.width / 2), rect.height);
break;
case 'BottomLeft':
case 'LeftBottom':
point = offsetPoint(mousePosition, bounds.bottomLeft, diagram, isMouseBased, 0, rect.height);
break;
case 'BottomRight':
case 'RightBottom':
point = offsetPoint(mousePosition, bounds.bottomRight, diagram, isMouseBased, rect.width, rect.height);
break;
case 'LeftCenter':
point = offsetPoint(mousePosition, bounds.middleLeft, diagram, isMouseBased, 0, (rect.height / 2));
break;
case 'LeftTop':
case 'TopLeft':
point = offsetPoint(mousePosition, bounds.topLeft, diagram, isMouseBased, 0, 0);
break;
case 'RightCenter':
point = offsetPoint(mousePosition, bounds.middleRight, diagram, isMouseBased, rect.width, (rect.height / 2));
break;
case 'RightTop':
case 'TopRight':
point = offsetPoint(mousePosition, bounds.topRight, diagram, isMouseBased, rect.width, 0);
break;
case 'TopCenter':
point = offsetPoint(mousePosition, bounds.topCenter, diagram, isMouseBased, (rect.width / 2), 0);
break;
}
return point;
}
/**
* offsetPoint method \
*
* @returns { PointModel } offsetPoint method .\
* @param { PointModel} mousePosition - provide the mousePosition value.
* @param { PointModel } bound - provide the diagram value.
* @param { Diagram} diagram - provide the isMouseBased value.
* @param { boolean} isMouseBased - provide the isMouseBased value.
* @param { number} x - provide the isMouseBased value.
* @param { number} y - provide the isMouseBased value.
* @private
*/
function offsetPoint(mousePosition, bound, diagram, isMouseBased, x, y) {
var point = {};
var scale = diagram.scroller.transform.scale;
var horizontalOffset = diagram.scroller.horizontalOffset;
var verticalOffset = diagram.scroller.verticalOffset;
horizontalOffset = diagram.modifyClientOffset(horizontalOffset, true);
verticalOffset = diagram.modifyClientOffset(verticalOffset, true);
point.x = (isMouseBased ? mousePosition.x : bound.x) * scale + horizontalOffset - x;
point.y = (isMouseBased ? mousePosition.y : bound.y) * scale + verticalOffset - y;
return point;
}
/**
* Gets the fixed user handles symbol \
*
* @returns { DiagramElement } Gets the fixed user handles symbol .\
* @param {ConnectorFixedUserHandleModel | NodeFixedUserHandleModel} options - provide the options value.
* @param { Canvas} fixedUserHandleContainer - provide the fixedUserHandleContainer value.
* @private
*/
export function initFixedUserHandlesSymbol(options, fixedUserHandleContainer) {
//let fixedUserHandleContent: PathElement | DiagramNativeElement;
var fixedUserHandleContent = new PathElement();
fixedUserHandleContent.data = options.pathData;
fixedUserHandleContent.height =
options.height > 10 ? options.height - (options.padding.bottom + options.padding.top) : options.height;
fixedUserHandleContent.width =
options.width > 10 ? options.width - (options.padding.left + options.padding.right) : options.width;
//Bug 912616: Not able to hide the fixedUserHandle in diagram
fixedUserHandleContent.visible = options.visibility;
fixedUserHandleContent.id = fixedUserHandleContainer.id + '_shape';
fixedUserHandleContent.inversedAlignment = false;
fixedUserHandleContent.horizontalAlignment = 'Center';
fixedUserHandleContent.verticalAlignment = 'Center';
fixedUserHandleContent.style = {
fill: options.iconStrokeColor, strokeColor: options.iconStrokeColor,
strokeWidth: options.iconStrokeWidth
};
fixedUserHandleContent.setOffsetWithRespectToBounds(0.5, 0.5, 'Fraction');
fixedUserHandleContent.relativeMode = 'Object';
fixedUserHandleContent.description = fixedUserHandleContainer.description || '';
return fixedUserHandleContent;
}
/**
* sort method \
*
* @returns { (NodeModel | ConnectorModel)[] } sort method .\
* @param {(NodeModel | ConnectorModel)[]} objects - provide the options value.
* @param { DistributeOptions} option - provide the fixedUserHandleContainer value.
* @private
*/
export function sort(objects, option) {
var i = 0;
var j = 0;
var temp;
for (i = 0; i < objects.length; i++) {
for (j = i + 1; j < objects.length; j++) {
// 986178 - Distribution of Objects Updates Incorrectly
var b = getBounds(objects[parseInt(i.toString(), 10)].wrapper);
var bounds = getBounds(objects[parseInt(j.toString(), 10)].wrapper);
if (option === 'Top' || option === 'Bottom' || option === 'BottomToTop' || option === 'Middle') {
if (b.center.y > bounds.center.y) {
temp = objects[parseInt(i.toString(), 10)];
objects[parseInt(i.toString(), 10)] = objects[parseInt(j.toString(), 10)];
objects[parseInt(j.toString(), 10)] = temp;
}
}
else {
if (b.center.x > bounds.center.x) {
temp = objects[parseInt(i.toString(), 10)];
objects[parseInt(i.toString(), 10)] = objects[parseInt(j.toString(), 10)];
objects[parseInt(j.toString(), 10)] = temp;
}
}
}
}
return objects;
}
/**
* getAnnotationPosition method \
*
* @returns {SegmentInfo } getAnnotationPosition method .\
* @param {PointModel[]} pts - provide the pts value.
* @param { PathAnnotation | ConnectorFixedUserHandle} annotation - provide the annotation value.
* @param { Rect } bound - provide the bound value.
* @private
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function getAnnotationPosition(pts, annotation, bound) {
//let angle: number;
//let getloop: SegmentInfo;
//let point: PointModel;
var getloop = getOffsetOfConnector(pts, annotation);
var angle = Point.findAngle(pts[getloop.index], pts[getloop.index + 1]);
var alignednumber = getAlignedPosition(annotation);
var point = Point.transform(getloop.point, angle + 45, alignednumber);
getloop.point = point;
getloop.angle = angle;
return getloop;
}
/**
* getPortsPosition method \
*
* @returns {SegmentInfo } getPortsPosition method .\
* @param {PointModel[]} pts - provide the pts value.
* @param { Port} ports - provide the ports value.
* @param { Rect } bound - provide the bound value.
* @private
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function getPortsPosition(pts, ports, bound) {
var getloop = getOffsetOfPorts(pts, ports);
var angle = Point.findAngle(pts[getloop.index], pts[getloop.index + 1]);
var alignednumber = getAlignedPositionForPorts(ports);
var point = Point.transform(getloop.point, angle + 45, alignednumber);
getloop.point = point;
getloop.angle = angle;
return getloop;
}
/**
* getOffsetOfPorts method \
*
* @returns {SegmentInfo } getOffsetOfPorts method .\
* @param {PointModel[]} points - provide the pts value.
* @param { PathAnnotation | ConnectorFixedUserHandle} ports - provide the ports value.
* @private
*/
export function getOffsetOfPorts(points, ports) {
// eslint-disable-next-line
var distance = 0;
var offset = ports.offset;
var point;
var angle;
var pointDistance = [];
var prevLength;
var kCount;
for (var j = 0; j < points.length - 1; j++) {
distance += Point.distancePoints(points[parseInt(j.toString(), 10)], points[j + 1]);
pointDistance.push(distance);
}
var offsetLength = offset * distance;
for (var k = 0; k < pointDistance.length; k++) {
if (pointDistance[parseInt(k.toString(), 10)] >= offsetLength) {
angle = Point.findAngle(points[parseInt(k.toString(), 10)], points[k + 1]);
point = Point.transform(points[parseInt(k.toString(), 10)], angle, offsetLength - (prevLength || 0));
kCount = k;
return { point: point, index: kCount };
}
prevLength = pointDistance[parseInt(k.toString(), 10)];
}
return { point: point, index: kCount };
}
/**
* getAlignedPosition method . To get the port alignment position \
*
* @returns {number } getAlignedPosition method .\
* @param {PointModel[]} ports - provide the annotation value.
* @private
*/
export function getAlignedPositionForPorts(ports) {
var constant = 0;
var state = 0;
switch (ports.alignment) {
case 'Center':
state = 0;
break;
case 'Before':
state = -((0) / 2 + constant);
break;
case 'After':
state = ((0) / 2 + constant);
break;
}
return state;
}
/**
* getOffsetOfConnector method \
*
* @returns {SegmentInfo } getOffsetOfConnector method .\
* @param {PointModel[]} points - provide the pts value.
* @param { PathAnnotation | ConnectorFixedUserHandle} annotation - provide the annotation value.
* @private
*/
export function getOffsetOfConnector(points, annotation) {
// eslint-disable-next-line
var length = 0;
var offset = annotation.offset;
var point;
var angle;
var lengths = [];
var prevLength;
var kCount;
for (var j = 0; j < points.length - 1; j++) {
length += Point.distancePoints(points[parseInt(j.toString(), 10)], points[j + 1]);
lengths.push(length);
}
var offsetLength = offset * length;
for (var k = 0; k < lengths.length; k++) {
if (lengths[parseInt(k.toString(), 10)] >= offsetLength) {
angle = Point.findAngle(points[parseInt(k.toString(), 10)], points[k + 1]);
point = Point.transform(points[parseInt(k.toString(), 10)], angle, offsetLength - (prevLength || 0));
kCount = k;
return { point: point, index: kCount };
}
prevLength = lengths[parseInt(k.toString(), 10)];
}
return { point: point, index: kCount };
}
/**
* getAlignedPosition method \
*
* @returns {number } getAlignedPosition method .\
* @param {PointModel[]} annotation - provide the annotation value.
* @private
*/
export function getAlignedPosition(annotation) {
var cnst;
if ((annotation instanceof ConnectorFixedUserHandle)) {
cnst = 0;
}
else {
cnst = annotation.content === undefined ? 10 : 0;
}
var state = 0;
switch (annotation.alignment) {
case 'Center':
state = 0;
break;
case 'Before':
state = -((0) / 2 + cnst);
break;
case 'After':
state = ((0) / 2 + cnst);
break;
}
return state;
}
/**
* alignLabelOnSegments method \
*
* @returns {Alignment } alignLabelOnSegments method .\
* @param {PathAnnotation | ConnectorFixedUserHandle} obj - provide the obj value.
* @param { number } ang - provide the ang value.
* @param { PointModel[] } pts - provide the pts value.
* @private
*/
export function alignLabelOnSegments(obj, ang, pts) {
//let angle: number = ang % 360;
ang %= 360;
var fourty5 = 45;
var one35 = 135;
var two25 = 225;
var three15 = 315;
var vAlign;
var hAlign;
switch (obj.alignment) {
case 'Before':
if (ang >= fourty5 && ang <= one35) {
hAlign = 'right';
vAlign = obj.offset === 0.5 ? 'center' : 'top';
}
else if (ang >= two25 && ang <= three15) {
hAlign = 'left';
vAlign = obj.offset === 0.5 ? 'center' : 'bottom';
}
else if (ang > fourty5 && ang < two25) {
vAlign = 'top';
hAlign = obj.offset === 0.5 ? 'center' : 'right';
}
else {
vAlign = 'bottom';
hAlign = (obj.offset === 0.5) ? 'center' : 'left';
}
break;
case 'After':
if (ang >= fourty5 && ang <= one35) {
hAlign = 'left';
vAlign = obj.offset === 0.5 ? 'center' : 'top';
}
else if (ang >= two25 && ang <= three15) {
hAlign = 'right';
vAlign = obj.offset === 0.5 ? 'center' : 'bottom';
}
else if (ang > fourty5 && ang < two25) {
vAlign = 'bottom';
hAlign = obj.offset === 0.5 ? 'center' : 'right';
}
else {
vAlign = 'top';
hAlign = obj.offset === 0.5 ? 'center' : 'left';
}
break;
case 'Center':
hAlign = !isNullOrUndefined(obj.horizontalAlignment) ? obj.horizontalAlignment.toLowerCase() : 'center';
vAlign = !isNullOrUndefined(obj.verticalAlignment) ? obj.verticalAlignment.toLowerCase() : 'center';
break;
}
if (obj.offset === 0 || obj.offset === 1) {
//let direction: string;
var direction = getBezierDirection(pts[0], pts[1]);
switch (direction) {
case 'left':
hAlign = obj.offset === 0 ? 'right' : 'left';
break;
case 'right':
hAlign = obj.offset === 0 ? 'left' : 'right';
break;
case 'bottom':
vAlign = obj.offset === 0 ? 'top' : 'bottom';
break;
case 'top':
vAlign = obj.offset === 0 ? 'bottom' : 'top';
break;
}
}
return { hAlign: hAlign, vAlign: vAlign };
}
/**
* getBezierDirection method \
*
* @returns {string } getBezierDirection method .\
* @param {PointModel} src - provide the src value.
* @param { PointModel } tar - provide the tar value.
* @private
*/
export function getBezierDirection(src, tar) {
if (Math.abs(tar.x - src.x) > Math.abs(tar.y - src.y)) {
return src.x < tar.x ? 'right' : 'left';
}
else {
return src.y < tar.y ? 'bottom' : 'top';
}
}
/**
* removeChildNodes method \
*
* @returns {void } removeChildNodes method .\
* @param {NodeModel} node - provide the node value.
* @param { Diagram } diagram - provide the diagram value.
* @private
*/
export function removeChildNodes(node, diagram) {
if (node instanceof Node && node.children) {
for (var i = 0; i < node.children.length; i++) {
if (diagram.nameTable[node.children[parseInt(i.toString(), 10)]].children) {
removeChildNodes(node, diagram);
}
diagram.removeFromAQuad(diagram.nameTable[node.children[parseInt(i.toString(), 10)]]);
diagram.removeObjectsFromLayer(diagram.nameTable[node.children[parseInt(i.toString(), 10)]]);
delete diagram.nameTable[node.children[parseInt(i.toString(), 10)]];
}
}
}
/**
* getChild method \
*
* @returns {string[] } getChild method .\
* @param {Canvas} child - provide the child value.
* @param { string[] } children - provide the children value.
* @private
*/
export function getChild(child, children) {
if (child && child.children && child.children.length > 0) {
for (var j = 0; j < child.children.length; j++) {
var subChild = child.children[parseInt(j.toString(), 10)];
if (subChild instanceof Canvas) {
getChild(subChild, children);
}
}
}
if (children.indexOf(child.id) === -1) {
children.push(child.id);
}
return children;
}
/**
* getSwimLaneChildren method \
*
* @returns {string[] } getSwimLaneChildren method .\
* @param {NodeModel[]} nodes - provide the nodes value.
* @private
*/
export function getSwimLaneChildren(nodes) {
var children = [];
var node;
var grid;
var childTable;
var child;
var gridChild = 'childTable';
for (var i = 0; i < nodes.length; i++) {
node = nodes[parseInt(i.toString(), 10)];
if (node.shape.type === 'SwimLane') {
grid = node.wrapper.children[0];
childTable = grid["" + gridChild];
for (var _i = 0, _a = Object.keys(childTable); _i < _a.length; _i++) {
var key = _a[_i];
child = childTable["" + key];
children = getChild(child, children);
}
}
}
return children;
}
/**
* removeUnnecessaryNodes method \
*
* @returns {void } removeUnnecessaryNodes method .\
* @p