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,054 lines (1,053 loc) 143 kB
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable jsdoc/require-returns */ /* eslint-disable jsdoc/require-param */ /* eslint-disable valid-jsdoc */ /* eslint-disable @typescript-eslint/ban-types */ import { Lane } from './../objects/node'; import { DiagramElement } from './../core/elements/diagram-element'; import { Canvas } from './../core/containers/canvas'; import { GroupableView } from './../core/containers/container'; import { PathElement } from './../core/elements/path-element'; import { TextElement } from './../core/elements/text-element'; import { updateStyle } from './../../diagram/utility/diagram-util'; import { randomId, cloneObject } from './../utility/base-util'; import { Diagram } from './../../diagram/diagram'; import { Transform, DiagramAction } from '../enum/enum'; import { findAngle, getPortDirection } from '../utility/connector'; import { Point } from '../primitives/point'; import { NodeConstraints } from '../enum/enum'; import { PointPort } from './../objects/port'; import { Rect } from '../primitives/rect'; import { Size } from '../primitives/size'; import { getDiagramElement } from '../utility/dom-util'; import { isBlazor } from '@syncfusion/ej2-base'; import { removeElement } from '../utility/dom-util'; /** * BPMN Diagrams contains the BPMN functionalities */ var BpmnDiagrams = /** @class */ (function () { //End size region /** * Constructor for the BpmnDiagrams module * * @private */ function BpmnDiagrams() { //Code conversion for Bpmn Shapes //Start Region /** @private */ this.bpmnTextAnnotationConnector = []; //constructs the BpmnDiagrams module } /** @private */ BpmnDiagrams.prototype.getSize = function (node, content) { var size = new Size(node.width, node.height); if (!(content instanceof PathElement)) { size.width = size.width || 50; size.height = size.height || 50; } if (content.actualSize.width && content.actualSize.height) { return content.actualSize; } else { content.measure(new Size()); size.width = size.width || content.desiredSize.width; size.height = size.height || content.desiredSize.height; } if (node.maxWidth !== undefined) { size.width = Math.min(size.width, node.maxWidth); } if (node.maxHeight !== undefined) { size.height = Math.min(size.height, node.maxHeight); } if (node.minWidth !== undefined) { size.width = Math.max(size.width, node.minWidth); } if (node.minHeight !== undefined) { size.height = Math.max(size.height, node.minHeight); } return size; }; /** @private */ BpmnDiagrams.prototype.initBPMNContent = function (content, node, diagram) { var shape = node.shape; var bpmnShape = node.shape.shape; if (bpmnShape === 'Event') { content = this.getBPMNEventShape(node, shape.event); } if (bpmnShape === 'Gateway') { content = this.getBPMNGatewayShape(node); } if (bpmnShape === 'DataObject') { content = this.getBPMNDataObjectShape(node); } if (bpmnShape === 'Message' || bpmnShape === 'DataSource') { content = this.getBPMNShapes(node); } //848061-BPMN Group shape to be function Like Subprocess Node if (bpmnShape === 'Group') { //854195 - bpmn group serialization issue content = this.getBPMNGroup(node, diagram); content.style.strokeDashArray = node.style.strokeDashArray !== '' ? node.style.strokeDashArray : '2 2 6 2'; content.cornerRadius = 10; } if (bpmnShape === 'Activity') { content = this.getBPMNActivityShape(node); } //Task 866412: Should revamp BPMN text annotation node. if (bpmnShape === 'TextAnnotation') { if (node.parentObj instanceof Diagram || node.parentObj instanceof Lane) { content = this.getBpmnTextAnnotationShape(node, node.shape, diagram); } else { content = this.getBpmnTextAnnotationSymbol(node, node.shape, diagram); } } return content; }; BpmnDiagrams.prototype.getBpmnTextAnnotationShape = function (textAnnotation, bpmnTextAnnotation, diagram) { var annotationsContainer = new Canvas(); annotationsContainer.measureChildren = false; annotationsContainer.offsetX = textAnnotation.offsetX; annotationsContainer.offsetY = textAnnotation.offsetY; annotationsContainer.float = true; annotationsContainer.id = textAnnotation.id + "_textannotation"; annotationsContainer.style.strokeColor = 'transparent'; annotationsContainer.style.fill = 'transparent'; annotationsContainer.relativeMode = 'Object'; annotationsContainer.rotateAngle = 0; var width = textAnnotation.width; var height = textAnnotation.height; var bounds = new Rect(0, 0, 0, 0); if (width !== 0 && height !== 0) { bounds = new Rect(textAnnotation.offsetX - width / 2, textAnnotation.offsetY - height / 2, width, height); } var oldIsProtectedOnChange = diagram.isProtectedOnChange; diagram.isProtectedOnChange = false; this.setAnnotationPath(bounds, annotationsContainer, textAnnotation, bpmnTextAnnotation, bpmnTextAnnotation.textAnnotation.textAnnotationDirection, diagram); diagram.isProtectedOnChange = oldIsProtectedOnChange; return annotationsContainer; }; //Task 866412: Should revamp BPMN text annotation node. To render text annotation in symbol palette. BpmnDiagrams.prototype.getBpmnTextAnnotationSymbol = function (annotation, bpmnTextAnnotation, diagram) { var data = 'M33.33,15 L0,43 M39.33,0 L33.33,0 L33.33,30 L39.33,30 M60,0'; if (bpmnTextAnnotation.textAnnotation.textAnnotationDirection === 'Top') { data = 'M15,33.33 L43,0 M0,39.33 L0,33.33 L30,33.33 L30,39.33 M0,60'; } else if (bpmnTextAnnotation.textAnnotation.textAnnotationDirection === 'Right') { data = 'M6,15 L39.33,43 M0,0 L6,0 L6,30 L0,30 M-20,0'; } else if (bpmnTextAnnotation.textAnnotation.textAnnotationDirection === 'Bottom') { data = 'M15,6 L43,39.33 M0,0 L0,6 L30,6 L30,0 M0,-20'; } var path = new PathElement(); path.data = data; path.style.fill = ((annotation.style.fill === 'white') ? 'transparent' : annotation.style.fill); path.style.strokeDashArray = (annotation.style.strokeDashArray ? annotation.style.strokeDashArray : ''); path.style.strokeWidth = annotation.style.strokeWidth; path.style.strokeColor = ((annotation.style.strokeColor === 'transparent') ? 'black' : annotation.style.strokeColor); path.style.opacity = annotation.style.opacity; return path; }; /** @private */ BpmnDiagrams.prototype.getBPMNShapes = function (node) { var bpmnShape = new PathElement(); //set style this.setStyle(bpmnShape, node); //941052: Issue with visible property doesn't hide shadows if ((node.constraints & NodeConstraints.Shadow) !== 0 && node.visible) { bpmnShape.shadow = node.shadow; } var bpmnShapeData = getBpmnShapePathData(node.shape.shape); bpmnShape.data = bpmnShapeData; bpmnShape.id = node.id + '_' + node.shape.shape; if (node.width !== undefined && node.height !== undefined) { bpmnShape.width = node.width; bpmnShape.height = node.height; } return bpmnShape; }; //854195 - Method to add the children as canvas in the Bpmn group node container /** @private */ BpmnDiagrams.prototype.getBPMNGroup = function (node, diagram) { var group = new Canvas(); //set style this.setStyle(group, node); group.id = node.id + '_group'; if (!group.children) { group.children = []; } var groupShapeObj = (node.shape.group); if (node.shape.group) { for (var i = 0; i < groupShapeObj.children.length; i++) { var child = diagram.nameTable[groupShapeObj.children[parseInt(i.toString(), 10)]]; group.children.push(child.wrapper); } } group.width = node.width; group.height = node.height; return group; }; /** @private */ BpmnDiagrams.prototype.getBPMNGatewayShape = function (node) { var gatewayshape = new Canvas(); //childNode0 var gatewayNode = new PathElement(); gatewayNode.id = node.id + '_0_gateway'; gatewayNode.offsetX = node.offsetX; gatewayNode.offsetY = node.offsetY; gatewayNode.data = 'M 40 20 L 20 40 L 0 20 L 20 0 L 40 20 Z'; this.setStyle(gatewayNode, node); //childNode1 var gatewayTypeNode = new PathElement(); gatewayTypeNode.id = node.id + '_1_gatewayType'; //set style - opacity gatewayTypeNode.style.opacity = node.style.opacity; gatewayTypeNode.style.strokeColor = node.style.strokeColor; gatewayTypeNode.horizontalAlignment = 'Center'; gatewayTypeNode.verticalAlignment = 'Center'; gatewayTypeNode.relativeMode = 'Object'; var shapeType = node.shape.gateway; //let gatewayTypeNodeShapeData: string; var gatewayTypeNodeShapeData = getBpmnGatewayShapePathData(shapeType.type); if (shapeType.type === 'EventBased' || shapeType.type === 'ExclusiveEventBased' || shapeType.type === 'ParallelEventBased') { gatewayTypeNode.style.fill = 'white'; } else { gatewayTypeNode.style.fill = 'black'; } gatewayTypeNode.data = gatewayTypeNodeShapeData; // append child and set style gatewayshape.style.fill = 'transparent'; gatewayshape.style.strokeColor = 'transparent'; gatewayshape.style.strokeWidth = 0; gatewayshape.children = [gatewayNode, gatewayTypeNode]; var size = this.getSize(node, gatewayNode); this.setSizeForBPMNGateway(node.shape.gateway, gatewayshape, size.width, size.height); return gatewayshape; }; /** @private */ BpmnDiagrams.prototype.getBPMNDataObjectShape = function (node) { var dataObjectshape = new Canvas(); var shape = node.shape.dataObject; //childNode0 var dataobjNode = new PathElement(); dataobjNode.id = node.id + '_0_dataobj'; dataobjNode.data = 'M29.904,5 L7.853,5 L7.853,45 L42.147,45 L42.147,17.242,L29.932,5,L29.932,17.242,L42.147,17.242'; var size = this.getSize(node, dataobjNode); dataobjNode.width = size.width; dataobjNode.height = size.height; this.setStyle(dataobjNode, node); //childNode1 var dataobjTypeNode = new PathElement(); dataobjTypeNode.id = node.id + '_1_type'; dataobjTypeNode.width = 25; dataobjTypeNode.height = 20; dataobjTypeNode.margin.left = 5; dataobjTypeNode.margin.top = 5; dataobjTypeNode.data = 'M 3 9.4 l 6 0 v 2.4 l 3.6 -4 L 9 4 v 2.5 H 3 V 9.4 Z'; //set style - opacity dataobjTypeNode.style.opacity = node.style.opacity; //childNode2 var dataobjCollectionNode = new PathElement(); dataobjCollectionNode.id = node.id + '_2_collection'; dataobjCollectionNode.width = 7.5; dataobjCollectionNode.height = 15; dataobjCollectionNode.style.fill = 'black'; dataobjCollectionNode.visible = true; dataobjCollectionNode.horizontalAlignment = 'Center'; dataobjCollectionNode.verticalAlignment = 'Bottom'; dataobjCollectionNode.relativeMode = 'Object'; //set style - opacity dataobjCollectionNode.style.opacity = node.style.opacity; dataobjCollectionNode.data = 'M 0 0 L 0.1 0 L 0.1 2 L 0 2 Z M 0.4 0 L 0.6 0 L 0.6 2 L0.4 2 Z M 0.9 0 L 1 0 L 1 2 L 0.9 2 Z'; switch (shape.type) { case 'None': dataobjTypeNode.visible = false; break; case 'Input': dataobjTypeNode.style.fill = 'white'; break; case 'Output': dataobjTypeNode.style.fill = 'black'; break; } if (shape.collection === false) { dataobjCollectionNode.visible = false; } //append child and set style dataObjectshape.style.fill = 'transparent'; dataObjectshape.style.strokeColor = 'transparent'; dataObjectshape.style.strokeWidth = 0; dataObjectshape.children = [dataobjNode, dataobjTypeNode, dataobjCollectionNode]; return dataObjectshape; }; /** @private */ BpmnDiagrams.prototype.getBPMNTaskShape = function (node) { var shape = node.shape.activity; var task = shape.task; var taskShapes = new Canvas(); //childNode0 var taskNode = new DiagramElement(); taskNode.cornerRadius = 10; var size = this.getSize(node, taskNode); taskNode.id = node.id + '_0_task'; taskNode.width = size.width; taskNode.height = size.height; this.setStyle(taskNode, node); // if task as call if ((task.call !== undefined) && task.call === true) { taskNode.style.strokeWidth = 4; } taskShapes.width = size.width; taskShapes.height = size.height; var childCount = this.getTaskChildCount(node); var x; var childSpace = childCount * 12; var area = size.width / 2 - childSpace; if (childCount === 1) { x = area + 8; } else { x = area + (childCount - 1) * 8; } //childNode1 var taskTypeNode = new PathElement(); if (task.type === 'Receive' || task.type === 'Send') { taskTypeNode.width = 18; taskTypeNode.height = 16; } else if (task.type === 'Manual') { taskTypeNode.width = 16; taskTypeNode.height = 11; } else { taskTypeNode.width = 20; taskTypeNode.height = 20; } taskTypeNode.id = node.id + '_1_tasktType'; taskTypeNode.margin.left = 5; taskTypeNode.margin.top = 5; task.type = task.type || 'None'; var taskTypeNodeData = getBpmnTaskShapePathData(task.type); taskTypeNode.data = taskTypeNodeData; taskTypeNode.style.fill = 'transparent'; taskTypeNode.style.opacity = node.style.opacity; if (task.type === 'Send') { taskTypeNode.style.fill = 'black'; } // append child and set style taskShapes.style.fill = 'transparent'; taskShapes.style.strokeColor = 'transparent'; taskShapes.style.strokeWidth = 0; taskShapes.children = [taskNode, taskTypeNode]; //childnode for service if (task.type === 'Service') { var taskTypeNodeService = new PathElement(); taskTypeNodeService.id = node.id + '_1_taskTypeService'; taskTypeNodeService.data = taskTypeNodeData; taskTypeNodeService.margin.left = taskTypeNode.margin.left + 9; taskTypeNodeService.margin.top = taskTypeNode.margin.top + 9; taskTypeNodeService.style.fill = 'white'; taskTypeNodeService.style.opacity = node.style.opacity; taskShapes.children.push(taskTypeNodeService); } // if task as loop var loopType = task.loop; var taskLoopNode = new PathElement(); //let childNode2data: string; var childNode2data = getBpmnLoopShapePathData(loopType); taskLoopNode.data = childNode2data; taskLoopNode.style.fill = 'black'; if (loopType !== 'None') { taskLoopNode.visible = true; } else { taskLoopNode.visible = false; } if (childCount === 1) { x = area + 9; } //891296: Position of BPMN activity loop node is not proper while save and load taskLoopNode.margin.left = x - 3; if (taskLoopNode.visible === true) { x += 12 + 8; } taskLoopNode.width = 12; taskLoopNode.height = 12; taskLoopNode.margin.bottom = 5; taskLoopNode.id = node.id + '_2_loop'; taskLoopNode.horizontalAlignment = 'Left'; taskLoopNode.verticalAlignment = 'Bottom'; taskLoopNode.setOffsetWithRespectToBounds(0, 1, 'Fraction'); taskLoopNode.relativeMode = 'Point'; taskLoopNode.style.fill = 'transparent'; taskTypeNode.style.opacity = node.style.opacity; taskShapes.children.push(taskLoopNode); //if task as compensation var taskCompNode = new PathElement(); taskCompNode = this.getBPMNCompensationShape(node, taskCompNode); if (task.compensation === true) { taskCompNode.visible = true; } else { taskCompNode.visible = false; } if (childCount === 1) { x = area + 9; } taskCompNode.margin.left = x - 3; x += 12 + 6; taskShapes.children.push(taskCompNode); return taskShapes; }; /** @private */ BpmnDiagrams.prototype.getBPMNEventShape = function (node, subEvent, sub, id) { var eventshape = new Canvas(); var event; var trigger; var width; var height; id = id || node.id; var pathdata = 'M164.1884,84.6909000000001C156.2414,84.6909000000001,149.7764,78.2259000000001,149.7764,70.2769000000001' + 'C149.7764,62.3279000000001,156.2414,55.8629000000001,164.1884,55.8629000000001C172.1354,55.8629000000001,178.6024,' + '62.3279000000001,178.6024,70.2769000000001C178.6024,78.2259000000001,172.1354,84.6909000000001,164.1884,84.6909000000001'; var shapeEvent = node.shape.event; if ((!isBlazor() && node.shape.shape === 'Event')) { event = shapeEvent.event; trigger = shapeEvent.trigger; } width = subEvent.width; height = subEvent.height; if (sub) { width = width || 20; height = height || 20; } else if (subEvent.width === undefined || subEvent.height === undefined) { var pathElement = new PathElement(); pathElement.data = pathdata; var size = this.getSize(node, pathElement); width = size.width; height = size.height; } var shapeActivity = node.shape.activity; if ((!isBlazor() && node.shape.shape === 'Activity')) { var subProcess = shapeActivity.subProcess; event = subEvent.event; trigger = subEvent.trigger; } //childNode0 var innerEvtNode = new PathElement(); innerEvtNode.data = pathdata; innerEvtNode.id = id + '_0_event'; innerEvtNode.width = width; innerEvtNode.height = height; innerEvtNode.horizontalAlignment = 'Center'; innerEvtNode.verticalAlignment = 'Center'; innerEvtNode.relativeMode = 'Object'; this.setStyle(innerEvtNode, node); //childNode1 var outerEvtNode = new PathElement(); outerEvtNode.data = pathdata; outerEvtNode.id = id + '_1_event'; outerEvtNode.style.gradient = node.style.gradient; outerEvtNode.horizontalAlignment = 'Center'; outerEvtNode.verticalAlignment = 'Center'; outerEvtNode.relativeMode = 'Object'; // set style opacity & strokeColor outerEvtNode.style.strokeColor = node.style.strokeColor; outerEvtNode.style.opacity = node.style.opacity; //childNode2 var triggerNode = new PathElement(); var triggerNodeData = getBpmnTriggerShapePathData(trigger); triggerNode.data = triggerNodeData; triggerNode.id = id + '_2_trigger'; triggerNode.horizontalAlignment = 'Center'; triggerNode.verticalAlignment = 'Center'; triggerNode.relativeMode = 'Object'; // set style opacity & strokeColor triggerNode.style.strokeColor = node.style.strokeColor; triggerNode.style.opacity = node.style.opacity; switch (event) { case 'Start': outerEvtNode.visible = false; break; case 'NonInterruptingStart': innerEvtNode.style.strokeDashArray = '2 3'; outerEvtNode.visible = false; break; case 'Intermediate': innerEvtNode.style.fill = node.style.fill; innerEvtNode.style.gradient = null; break; case 'NonInterruptingIntermediate': innerEvtNode.style.fill = node.style.fill; innerEvtNode.style.gradient = null; innerEvtNode.style.strokeDashArray = '2 3'; outerEvtNode.style.strokeDashArray = '2 3'; break; case 'ThrowingIntermediate': case 'End': innerEvtNode.style.fill = event !== 'End' ? node.style.fill : node.style.fill !== 'white' ? node.style.fill : 'black'; innerEvtNode.style.gradient = null; triggerNode.style.fill = 'black'; triggerNode.style.strokeColor = 'white'; break; } //append child and set style eventshape.style.fill = 'transparent'; eventshape.style.strokeColor = 'transparent'; eventshape.style.strokeWidth = 0; eventshape.children = [innerEvtNode, outerEvtNode, triggerNode]; this.setSizeForBPMNEvents(shapeEvent, eventshape, width, height); return eventshape; }; BpmnDiagrams.prototype.setEventVisibility = function (node, canvas) { var event = node.shape.event.event; var innerEvtNode = canvas[0]; var outerEvtNode = canvas[1]; var triggerNode = canvas[2]; switch (event) { case 'Start': outerEvtNode.visible = false; break; case 'NonInterruptingStart': innerEvtNode.style.strokeDashArray = '2 3'; outerEvtNode.visible = false; break; } }; BpmnDiagrams.prototype.setSubProcessVisibility = function (node) { var subProcess = node.shape.activity.subProcess; var eventLength = subProcess.events.length; var index = (node.shape.activity.subProcess.type === 'Transaction') ? 2 : 0; var elementWrapper = node.wrapper.children[0].children[0]; if (subProcess.adhoc === false) { elementWrapper.children[3 + index + eventLength].visible = false; } if (subProcess.compensation === false) { elementWrapper.children[4 + index + eventLength].visible = false; } if (eventLength > 0) { for (var i = 0; i < eventLength; i++) { this.setEventVisibility(node, elementWrapper.children[2 + i].children); } } }; /** @private */ BpmnDiagrams.prototype.getBPMNSubProcessShape = function (node) { var subProcessShapes = new Canvas(); var loopType; var events; var event; var subprocessAdhoc = new PathElement(); var subProcessEventsShapes = new Canvas(); var subProcessLoopShapes = new PathElement(); var shape = node.shape.activity; var subProcess = shape.subProcess; var subChildCount = this.getSubprocessChildCount(node); var x; var subprocessNode = new DiagramElement(); subprocessNode.id = node.id + '_0_Subprocess'; subprocessNode.style.fill = 'transparent'; subprocessNode.cornerRadius = 10; var size = this.getSize(node, subprocessNode); subprocessNode.width = size.width; subprocessNode.height = size.height; subProcessShapes.children = [subprocessNode]; if (shape.subProcess.type === 'Transaction') { this.getBPMNSubProcessTransaction(node, node.shape, subProcessShapes); } var iconSpace = 4; var subChildSpace = 12; var childSpace = subChildCount * subChildSpace; var area = size.width / 2; if (subChildCount === 1) { x = area - (subChildSpace * 0.5); } else { x = area - (childSpace / 2) - ((subChildCount - 1) * iconSpace) / 2; } //set style this.setStyle(subprocessNode, node); //941052: Issue with visible property doesn't hide shadows if ((node.constraints & NodeConstraints.Shadow) !== 0 && node.visible) { subProcessShapes.shadow = node.shadow; } var collapsedShape = new PathElement(); collapsedShape.id = node.id + '_0_collapsed'; collapsedShape.width = 12; collapsedShape.height = 12; collapsedShape.style.fill = 'black'; collapsedShape.style.strokeColor = node.style.strokeColor; collapsedShape.margin.bottom = 5; collapsedShape.style.opacity = node.style.opacity; collapsedShape.horizontalAlignment = 'Left'; collapsedShape.verticalAlignment = 'Bottom'; collapsedShape.setOffsetWithRespectToBounds(0, 1, 'Fraction'); collapsedShape.relativeMode = 'Point'; collapsedShape.data = getBpmnShapePathData('collapsedShape'); collapsedShape.margin.left = x; if (subProcess.collapsed === true && !subProcess.processes) { collapsedShape.visible = true; } else { collapsedShape.visible = false; } if (collapsedShape.visible === true) { x += subChildSpace + iconSpace; } subProcessShapes.children.push(collapsedShape); if (subProcess.type === 'Event') { subprocessNode.style.strokeWidth = 1; subprocessNode.style.strokeDashArray = '2 2'; events = subProcess.events; for (var i = 0; i < events.length; i++) { event = events[parseInt(i.toString(), 10)]; this.getBPMNSubEvent(event, node, subProcessShapes); } } // set loop for subprocess subProcessLoopShapes = this.getBPMNSubProcessLoopShape(node); if (subChildCount === 1) { x = area - 6; } subProcessLoopShapes.margin.left = x; if (subProcessLoopShapes.visible === true) { x += subChildSpace + iconSpace; } subProcessLoopShapes.style.opacity = node.style.opacity; subProcessShapes.children.push(subProcessLoopShapes); // set boundary for subprocess subprocessNode.id = node.id + '_boundary'; if (subProcess.boundary === 'Default') { //937170: Stroke width not applied after save and load subprocessNode.style.strokeWidth = node.style.strokeWidth ? node.style.strokeWidth : 1; subprocessNode.style.strokeDashArray = '1 0'; } if (subProcess.boundary === 'Call') { subprocessNode.style.strokeWidth = 4; subprocessNode.style.strokeDashArray = '1 0'; } if (subProcess.boundary === 'Event') { subprocessNode.style.strokeWidth = node.style.strokeWidth ? node.style.strokeWidth : 1; subprocessNode.style.strokeDashArray = '2 2'; } //set adhoc for subprocess subprocessAdhoc = this.getBPMNAdhocShape(node, subprocessAdhoc, subProcess); if (subChildCount === 1) { x = area - 6; } subprocessAdhoc.margin.left = x; if (subprocessAdhoc.visible === true) { x += subChildSpace + iconSpace; } subprocessAdhoc.style.opacity = node.style.opacity; subProcessShapes.children.push(subprocessAdhoc); //set compensation for subprocess var subprocessComp = new PathElement(); if (subProcess.compensation === true) { subprocessComp.visible = true; } else { subprocessComp.visible = false; } subprocessComp = this.getBPMNCompensationShape(node, subprocessComp); if (subChildCount === 1) { x = area - 6; } subprocessComp.margin.left = x; if (subprocessComp.visible === true) { x += subChildSpace + iconSpace; } subprocessComp.style.opacity = node.style.opacity; subProcessShapes.children.push(subprocessComp); //set style for subprocess subProcessShapes.style.strokeColor = 'transparent'; subProcessShapes.style.strokeWidth = 0; subProcessShapes.style.fill = 'transparent'; return subProcessShapes; }; BpmnDiagrams.prototype.getBPMNSubEvent = function (event, node, container, id) { container.children = container.children || []; //let eventContainer: Canvas; var eventContainer = this.getBPMNEventShape(node, event, true, id); this.getBPMNSubprocessEvent(node, eventContainer, event); eventContainer.id = id || (node.id + '_subprocessEvents'); eventContainer.width = event.width || 20; eventContainer.height = event.height || 20; // set offset for subevents eventContainer.setOffsetWithRespectToBounds(event.offset.x, event.offset.y, 'Fraction'); eventContainer.relativeMode = 'Point'; //set margin for subevents eventContainer.margin = event.margin; //set alignment for subevents eventContainer.horizontalAlignment = event.horizontalAlignment; eventContainer.verticalAlignment = event.verticalAlignment; // set style for subevent eventContainer.style.fill = 'transparent'; eventContainer.style.strokeColor = 'transparent'; eventContainer.style.strokeWidth = 0; container.children.push(eventContainer); }; BpmnDiagrams.prototype.getBPMNSubProcessTransaction = function (node, shape, container) { var shapeWidth = container.children[0].width; var shapeHeight = container.children[0].height; var innerRect = new DiagramElement(); innerRect.margin = { left: 3, right: 0, top: 3, bottom: 0 }; innerRect.id = node.id + '_0_Subprocess_innnerRect'; innerRect.cornerRadius = 10; innerRect.width = shapeWidth - 6; //EJ2-824711 - Fill color is not applied properly for BPMN transaction subProcess. innerRect.style.fill = 'transparent'; innerRect.height = shapeHeight - 6; container.children.push(innerRect); var transactionEvents = new Canvas(); transactionEvents.id = node.id + '_transaction_events'; transactionEvents.style.gradient = node.style.gradient; var transaction = shape.activity.subProcess.transaction; this.getBPMNSubEvent(transaction.success, node, transactionEvents, node.id + '_success'); this.getBPMNSubEvent(transaction.cancel, node, transactionEvents, node.id + '_cancel'); this.getBPMNSubEvent(transaction.failure, node, transactionEvents, node.id + '_failure'); this.updateDiagramContainerVisibility(transactionEvents.children[0], transaction.success.visible); this.updateDiagramContainerVisibility(transactionEvents.children[1], transaction.cancel.visible); this.updateDiagramContainerVisibility(transactionEvents.children[2], transaction.failure.visible); transactionEvents.float = true; transactionEvents.width = shapeWidth; transactionEvents.height = shapeHeight; transactionEvents.style.fill = transactionEvents.style.strokeColor = 'transparent'; container.children.push(transactionEvents); }; /** @private */ BpmnDiagrams.prototype.getBPMNSubProcessLoopShape = function (node) { var shape = node.shape.activity; var loopType; var subprocessLoop = new PathElement(); var subprocessLoopData; var subProcess = shape.subProcess; // eslint-disable-next-line prefer-const loopType = subProcess.loop; // eslint-disable-next-line prefer-const subprocessLoopData = getBpmnLoopShapePathData(loopType); if (loopType !== 'None') { subprocessLoop.visible = true; } else { subprocessLoop.visible = false; } subprocessLoop.id = node.id + '_loop'; subprocessLoop.data = subprocessLoopData; subprocessLoop.style.fill = 'black'; subprocessLoop.width = 12; subprocessLoop.height = 12; subprocessLoop.horizontalAlignment = 'Left'; subprocessLoop.verticalAlignment = 'Bottom'; subprocessLoop.setOffsetWithRespectToBounds(0, 1, 'Fraction'); subprocessLoop.relativeMode = 'Point'; subprocessLoop.margin.bottom = 5; subprocessLoop.style.fill = 'transparent'; subprocessLoop.style.strokeColor = node.style.strokeColor; return subprocessLoop; }; /** @private */ BpmnDiagrams.prototype.drag = function (obj, tx, ty, diagram) { var node = diagram.nameTable[(obj).processId]; var oldLeft = obj.margin.left; var oldTop = obj.margin.top; //905286: Dragging bpmn node in subprocess using public method is not proper var newMargin = { top: obj.margin.top + ty >= 0 ? obj.margin.top + ty : obj.margin.top, left: obj.margin.left + tx >= 0 ? obj.margin.left + tx : obj.margin.left }; if (newMargin.top !== obj.margin.top || newMargin.left !== obj.margin.left) { diagram.nodePropertyChange(obj, {}, { margin: newMargin }); } if (diagram.eventHandler.currentAction !== 'Drag' && !diagram.eventHandler.isNudgeKey && !obj.hasTextAnnotation && (oldTop !== obj.margin.top || oldLeft !== obj.margin.left)) { var newOffset = { offsetX: obj.offsetX + tx >= 0 ? obj.offsetX + tx : obj.offsetX, offsetY: obj.offsetY + ty >= 0 ? obj.offsetY + ty : obj.offsetY }; diagram.nodePropertyChange(obj, {}, { offsetX: newOffset.offsetX, offsetY: newOffset.offsetY }); } var bound = this.getChildrenBound(node, obj.id, diagram); this.updateSubProcessess(bound, obj, diagram); //For Subproceess connected with Text Annotation Drag and drop issue var diffX = obj.margin.left - oldLeft; var diffY = obj.margin.top - oldTop; if (obj.outEdges.length !== 0) { for (var i = 0; i < obj.outEdges.length; i++) { var connector = diagram.nameTable[obj.outEdges[parseInt(i.toString(), 10)]]; if (connector && connector.shape.type === 'Bpmn' && connector.isBpmnAnnotationConnector) { var targetNode = diagram.nameTable[connector.targetID]; var oldValue = { offsetX: targetNode.offsetX, offsetY: targetNode.offsetY }; targetNode.offsetX += diffX; targetNode.offsetY += diffY; var newValue = { offsetX: targetNode.offsetX, offsetY: targetNode.offsetY }; diagram.nodePropertyChange(targetNode, oldValue, newValue); } } } node.wrapper.measure(new Size(undefined, undefined)); node.wrapper.arrange(node.wrapper.desiredSize); diagram.refreshCanvasLayers(); diagram.updateSelector(); //909205: The selector updates properly, but the node does not update correctly, so call the updateDiagramObject method. diagram.updateDiagramObject(node); //941048: The connectors not updates properly on redo, so call the updateConnectorEdges method. diagram.updateConnectorEdges(obj); this.updateDocks(obj, diagram); }; /** @private */ BpmnDiagrams.prototype.dropBPMNchild = function (target, source, diagram) { if (source && source.shape.type === 'Bpmn' && target.shape.type === 'Bpmn' && !isBlazor()) { var subProcess = diagram.nameTable[target.id].shape.activity.subProcess; if (diagram.currentSymbol && target.shape.type === 'Bpmn' && !subProcess.collapsed) { source.processId = target.id; return; } subProcess.processes = subProcess.processes || []; if (subProcess.processes && subProcess.processes.indexOf(source.id) === -1 && !subProcess.collapsed) { subProcess.processes.push(source.id); // To arrange the process based on zIndex, which cause issue in save and load. if (subProcess.processes.length > 1) { this.sortProcessOrder(subProcess.processes, diagram); } var redoElement = cloneObject(source); var sources = diagram.nameTable[source.id].wrapper; var targetWrapper = diagram.nameTable[target.id].wrapper; sources.margin.top = (sources.offsetY - (sources.actualSize.height / 2)) - (target.offsetY - (target.actualSize.height / 2)); sources.margin.left = (sources.offsetX - (sources.actualSize.width / 2)) - (target.offsetX - (target.actualSize.width / 2)); sources.margin.top = (sources.margin.top < 0) ? 0 : sources.margin.top; sources.margin.left = (sources.margin.left < 0) ? 0 : sources.margin.left; diagram.nameTable[source.id].processId = target.id; targetWrapper.children.push(diagram.nameTable[source.id].wrapper); //To identify the processess added at runtime. //diagram.nameTable[source.id].wrapper.isDroppedProcess = true; var bound = this.getChildrenBound(target, source.id, diagram); this.updateSubProcessess(bound, source, diagram); targetWrapper.measure(new Size(undefined, undefined)); targetWrapper.arrange(targetWrapper.desiredSize); diagram.refreshCanvasLayers(); diagram.updateSelector(); // 908136: Node goes behind the subprocess and the connector connected to it is destroyed Issue Fix by commenting these lines // let edges: string[] = []; // edges = edges.concat((source as Node).outEdges, (source as Node).inEdges); // for (let i: number = edges.length - 1; i >= 0; i--) { // if (diagram.bpmnModule.bpmnTextAnnotationConnector.indexOf(diagram.nameTable[edges[parseInt(i.toString(), 10)]]) // === -1) { // diagram.remove(diagram.nameTable[edges[parseInt(i.toString(), 10)]]); // } // } var obj = cloneObject(source); var entry = { type: 'PositionChanged', undoObject: { nodes: [redoElement] }, redoObject: { nodes: [obj] }, category: 'Internal' }; diagram.addHistoryEntry(entry); if (diagram.mode === 'SVG') { if (source.zIndex < target.zIndex) { diagram.updateProcesses(source); this.updateSubprocessNodeIndex(source, diagram, target); } //909204-The node inside the subprocess disappears while grouping var parent_1 = getDiagramElement(target.id + '_groupElement'); parent_1.appendChild(getDiagramElement(source.id + '_groupElement')); } this.updateDocks(source, diagram); } } }; BpmnDiagrams.prototype.sortProcessOrder = function (processes, diagram) { // Sort the process array based on node zIndex processes.sort(function (a, b) { return diagram.nameTable["" + a].zIndex - diagram.nameTable["" + b].zIndex; }); }; BpmnDiagrams.prototype.updateIndex = function (diagram, source) { //let processNode: Node; var processNode = source; var nodeindex = diagram.getIndex(processNode, processNode.id); diagram.nodes.splice(Number(nodeindex), 1); processNode.zIndex = ++diagram.activeLayer.objectZIndex; diagram.nodes.push(processNode); }; BpmnDiagrams.prototype.updateSubprocessNodeIndex = function (source, diagram, target) { if (source.shape.activity.subProcess.processes && source.shape.activity.subProcess.processes.length > 0) { for (var i = 0; i < source.shape.activity.subProcess.processes.length; i++) { this.updateIndex(diagram, source); var processes = source.shape.activity.subProcess.processes[parseInt(i.toString(), 10)]; if (diagram.nameTable["" + processes].shape.activity.subProcess.processes.length > 0) { this.updateSubprocessNodeIndex(diagram.nameTable["" + processes], diagram, target); } else { var node = diagram.nameTable[source.shape.activity.subProcess.processes[parseInt(i.toString(), 10)]]; this.updateIndex(diagram, node); } } } else { this.updateIndex(diagram, source); } }; /** @private */ BpmnDiagrams.prototype.updateDocks = function (obj, diagram) { if (obj.shape.type === 'Bpmn' && obj.shape.activity.subProcess.processes && !obj.shape.activity.subProcess.collapsed) { var processTable = obj.shape.activity.subProcess.processes; for (var _i = 0, processTable_1 = processTable; _i < processTable_1.length; _i++) { var i = processTable_1[_i]; var actualObject = diagram.nameTable["" + i]; if (actualObject) { diagram.updateConnectorEdges(actualObject); actualObject.wrapper.measure(new Size(actualObject.wrapper.width, actualObject.wrapper.height)); actualObject.wrapper.arrange(actualObject.wrapper.desiredSize); if (actualObject.shape.activity.subProcess.processes && actualObject.shape.activity.subProcess.processes.length) { this.updateDocks(actualObject, diagram); } } } } }; /** @private */ BpmnDiagrams.prototype.removeBpmnProcesses = function (currentObj, diagram) { var element = diagram.nameTable[currentObj.processId]; if (currentObj.shape.type === 'Bpmn' && currentObj.shape.activity.subProcess.processes && currentObj.shape.activity.subProcess.processes.length > 0) { var processes = currentObj.shape.activity.subProcess.processes; for (var j = processes.length - 1; j >= 0; j--) { diagram.remove(diagram.nameTable[processes[parseInt(j.toString(), 10)]]); } } if (element) { diagram.removeDependentConnector(currentObj); var processes = element.shape.activity.subProcess.processes; this.removeChildFromBPMN(element.wrapper, currentObj.id, diagram, true); var processIndex = processes.indexOf(currentObj.id); processes.splice(processIndex, 1); } }; /** @private */ BpmnDiagrams.prototype.removeChildFromBPMN = function (wrapper, name, diagram, isDelete) { for (var _i = 0, _a = wrapper.children; _i < _a.length; _i++) { var i = _a[_i]; if (i.id === name) { wrapper.children.splice(wrapper.children.indexOf(i), 1); if (!isDelete) { // To remove the child node from subprocess to diagram in DOM. this.removeGElement(i.id, diagram); } } else if (i.children) { this.removeChildFromBPMN(i, name, diagram, isDelete); } } }; //Bug 858761: Default Tooltip of sub-process node is not positioned properly after drag and drop the child of subprocess in diagram. // To remove the child node from subprocess to diagram in DOM. BpmnDiagrams.prototype.removeGElement = function (id, diagram) { var element = document.getElementById(id + '_groupElement'); var diagramLayer = document.getElementById(diagram.element.id + '_diagramLayer'); var parent = element.parentElement; parent.removeChild(element); diagramLayer.appendChild(element); var node = diagram.nameTable["" + id]; var subProcess = diagram.nameTable["" + node.processId]; var beforeIndex = node.zIndex + 1; var getNode = this.getNode(beforeIndex, diagram); if (getNode.length > 0) { var neighborElement_1 = document.getElementById(getNode[0].id + '_groupElement'); var index = Array.from(diagramLayer.children).findIndex(function (child) { return child === neighborElement_1; }); var domIndex = index !== -1 ? index : 1; // 889550: issue with dragging process nodes of the sub process // Remove the adjacent element of the node which z index is lessthan subprocess z index if (node.zIndex < subProcess.zIndex) { diagramLayer.children[parseInt(domIndex.toString(), 10)].insertAdjacentElement('beforebegin', element); } } }; BpmnDiagrams.prototype.getNode = function (index, diagram) { var getNode = diagram.nodes.filter(function (x) { return x.zIndex === index; }); if (getNode.length === 0 && index > 0) { return this.getNode(index - 1, diagram); } return getNode; }; /** @private */ BpmnDiagrams.prototype.removeProcess = function (id, diagram) { var node = diagram.nameTable["" + id]; if (node) { var parent_2 = diagram.nameTable[node.processId]; var undoElement = cloneObject(node); if (parent_2 && parent_2.shape.type === 'Bpmn') { var processes = parent_2.shape.activity.subProcess.processes; this.removeChildFromBPMN(parent_2.wrapper, id, diagram, true); var processIndex = processes.indexOf(id); processes.splice(processIndex, 1); node.processId = ''; //934140-Removing of process node to expanded subprocess at runtime won't be undoed if (!(diagram.diagramActions & DiagramAction.UndoRedo)) { var obj = cloneObject(node); var entry = { type: 'PositionChanged', undoObject: { nodes: [undoElement] }, redoObject: { nodes: [obj] }, category: 'Internal' }; diagram.addHistoryEntry(entry); } diagram.refreshDiagramLayer(); diagram.updateSelector(); } } }; /** @private */ BpmnDiagrams.prototype.addProcess = function (process, parentId, diagram) { //let id: string; process.id = process.id || randomId(); var id = process.id; var node = diagram.nameTable["" + id]; //913821-Adding of process node to expanded subprocess at runtime won't be undoed. var undoElement = cloneObject(node); if (!node) { diagram.add(process); } process.processId = parentId; var parentNode = diagram.nameTable["" + parentId]; var subProcess = parentNode.shape.activity.subProcess; var isUndoRedo = diagram.diagramActions & DiagramAction.UndoRedo; if (!isUndoRedo) { diagram.protectPropertyChange(true); } //EJ2-942115-The function addProcess is not working when empty processes are not defined in the subprocess object. if (!subProcess.processes) { subProcess.processes = []; } if (!isUndoRedo) { diagram.protectPropertyChange(false); } if (node && parentNode && parentNode.shape.type === 'Bpmn' && node.shape.type === 'Bpmn') { node.processId = parentId; //934140: Save and Load Functionality Not Working Properly in Subprocess if (!isUndoRedo) { diagram.protectPropertyChange(true); if (node.zIndex < parentNode.zIndex) { this.updateIndex(diagram, node); } //937210: Add processes to subprocess at runtime and remove by button click, save and load not working var nodeOffsetX = (parentNode.offsetX - parentNode.width * parentNode.pivot.x) + (node.margin.left + node.width * node.pivot.x); var nodeOffsetY = (parentNode.offsetY - parentNode.height * parentNode.pivot.y) + (node.margin.top + node.height * node.pivot.y); if (node.offsetX !== nodeOffsetX || node.offsetY !== nodeOffsetY) { node.offsetX = nodeOffsetX; node.offsetY = nodeOffsetY; } diagram.protectPropertyChange(false); } var processes = parentNode.shape.activity.subProcess.processes; if (processes.indexOf(id) < 0) { processes.push(id); } parentNode.wrapper.children.push(node.wrapper);