Files
bpmn-js/lib/features/modeling/behavior/SubProcessPlaneBehavior.js
2022-01-12 09:14:15 +01:00

248 lines
5.9 KiB
JavaScript

import inherits from 'inherits';
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
import { find } from 'min-dash';
import { isExpanded } from '../../../util/DiUtil';
import { getBusinessObject, is } from '../../../util/ModelUtil';
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
import { getBBox } from 'diagram-js/lib/util/Elements';
import { asPlaneId, planeId } from '../../../util/DrilldownUtil';
/**
* Creates diPlanes and canvas planes when collapsed subprocesses are created.
*
*
* @param {Canvas} canvas
* @param {EventBus} eventBus
* @param {Modeling} modeling
* @param {ElementFactory} elementFactory
* @param {BpmnFactory} bpmnFactory
* @param {Bpmnjs} bpmnjs
* @param {ElementRegistry} elementRegistry
*/
export default function SubProcessPlaneBehavior(
canvas, eventBus, modeling,
elementFactory, bpmnFactory, bpmnjs, elementRegistry) {
CommandInterceptor.call(this, eventBus);
this._canvas = canvas;
this._eventBus = eventBus;
this._modeling = modeling;
this._elementFactory = elementFactory;
this._bpmnFactory = bpmnFactory;
this._bpmnjs = bpmnjs;
this._elementRegistry = elementRegistry;
var self = this;
function isCollapsedSubProcess(element) {
return is(element, 'bpmn:SubProcess') && !isExpanded(element);
}
function createRoot(context) {
var shape = context.shape,
rootElement = context.newRootElement;
var businessObject = getBusinessObject(shape);
rootElement = self._addDiagram(rootElement || businessObject);
context.newRootElement = canvas.addRootElement(rootElement);
}
function removeRoot(context) {
var shape = context.shape;
var businessObject = getBusinessObject(shape);
self._removeDiagram(businessObject);
var rootElement = context.newRootElement = elementRegistry.get(planeId(businessObject));
canvas.removeRootElement(rootElement);
}
// add plane elements for newly created sub-processes
// this ensures we can actually drill down into the element
this.executed('shape.create', function(context) {
var shape = context.shape;
if (!isCollapsedSubProcess(shape)) {
return;
}
createRoot(context);
}, true);
this.reverted('shape.create', function(context) {
var shape = context.shape;
if (!isCollapsedSubProcess(shape)) {
return;
}
removeRoot(context);
}, true);
// rename secondary elements (roots) when the primary element changes
// this ensures rootElement.id = element.id + '_plane'
this.executed('element.updateProperties', function(context) {
var shape = context.element;
if (!isCollapsedSubProcess(shape)) {
return;
}
var properties = context.properties;
var oldProperties = context.oldProperties;
var oldId = oldProperties.id,
newId = properties.id;
if (oldId === newId) {
return;
}
var planeElement = elementRegistry.get(asPlaneId(oldId));
if (!planeElement) {
return;
}
elementRegistry.updateId(planeElement, asPlaneId(newId));
}, true);
this.reverted('element.updateProperties', function(context) {
var shape = context.element;
if (!isCollapsedSubProcess(shape)) {
return;
}
var properties = context.properties;
var oldProperties = context.oldProperties;
var oldId = oldProperties.id,
newId = properties.id;
if (oldId === newId) {
return;
}
var planeElement = elementRegistry.get(asPlaneId(newId));
if (!planeElement) {
return;
}
elementRegistry.updateId(planeElement, asPlaneId(oldId));
}, true);
}
inherits(SubProcessPlaneBehavior, CommandInterceptor);
/**
* Adds a given diagram to the definitions and returns a .
*
* @param {Object} planeElement
*/
SubProcessPlaneBehavior.prototype._addDiagram = function(planeElement) {
var bpmnjs = this._bpmnjs;
var diagrams = bpmnjs.getDefinitions().diagrams;
if (!planeElement.businessObject) {
planeElement = this._createNewDiagram(planeElement);
}
diagrams.push(planeElement.di.$parent);
return planeElement;
};
/**
* Adds a given rootElement to the bpmnDi diagrams.
*
* @param {Object} rootElement
* @returns {Object} planeElement
*/
SubProcessPlaneBehavior.prototype._addDiagram = function(planeElement) {
var bpmnjs = this._bpmnjs;
var diagrams = bpmnjs.getDefinitions().diagrams;
if (!planeElement.businessObject) {
planeElement = this._createNewDiagram(planeElement);
}
diagrams.push(planeElement.di.$parent);
return planeElement;
};
/**
* Creates a new plane element for the given sub process.
*
* @param {Object} bpmnElement
*
* @return {Object} new diagram element
*/
SubProcessPlaneBehavior.prototype._createNewDiagram = function(bpmnElement) {
var bpmnFactory = this._bpmnFactory;
var elementFactory = this._elementFactory;
var diPlane = bpmnFactory.create('bpmndi:BPMNPlane', {
bpmnElement: bpmnElement
});
var diDiagram = bpmnFactory.create('bpmndi:BPMNDiagram', {
plane: diPlane
});
diPlane.$parent = diDiagram;
// add a virtual element (not being drawn),
// a copy cat of our BpmnImporter code
var planeElement = elementFactory.createRoot({
id: planeId(bpmnElement),
type: bpmnElement.$type,
di: diPlane,
businessObject: bpmnElement,
collapsed: true
});
return planeElement;
};
/**
* Removes the diagram for a given root element
*
* @param {Object} rootElement
* @returns {Object} removed bpmndi:BPMNDiagram
*/
SubProcessPlaneBehavior.prototype._removeDiagram = function(rootElement) {
var bpmnjs = this._bpmnjs;
var diagrams = bpmnjs.getDefinitions().diagrams;
var removedDiagram = find(diagrams, function(diagram) {
return diagram.plane.bpmnElement.id === rootElement.id;
});
diagrams.splice(diagrams.indexOf(removedDiagram), 1);
return removedDiagram;
};
SubProcessPlaneBehavior.$inject = [
'canvas',
'eventBus',
'modeling',
'elementFactory',
'bpmnFactory',
'bpmnjs',
'elementRegistry'
];