Skip to content

Commit

Permalink
feat(modeling): support toggle collapse with drilldown
Browse files Browse the repository at this point in the history
closes #1539
  • Loading branch information
marstamm committed Dec 15, 2021
1 parent a02f676 commit 408de38
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 167 deletions.
147 changes: 135 additions & 12 deletions lib/features/modeling/behavior/SubProcessPlaneBehavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
import { getBBox } from 'diagram-js/lib/util/Elements';
import { asPlaneId, planeId } from '../../../util/DrilldownUtil';

var DEFAULT_POSITION = {
x: 180,
y: 160
};


/**
* Creates diPlanes and canvas planes when collapsed subprocesses are created.
Expand Down Expand Up @@ -140,27 +145,145 @@ export default function SubProcessPlaneBehavior(

elementRegistry.updateId(planeElement, asPlaneId(oldId));
}, true);


// create/remove plane for the subprocess
this.executed('shape.toggleCollapse', 400, function(context) {
var shape = context.shape;

if (!is(shape, 'bpmn:SubProcess')) {
return;
}

if (!isExpanded(shape)) {
createRoot(context);
self._showRecursively(shape.children);
} else {
removeRoot(context);
}

}, true);


// create/remove plane for the subprocess
this.reverted('shape.toggleCollapse', 400, function(context) {
var shape = context.shape;

if (!is(shape, 'bpmn:SubProcess')) {
return;
}

if (!isExpanded(shape)) {
createRoot(context);
self._showRecursively(shape.children);
} else {
removeRoot(context);
}

}, true);

// move elements between planes
this.postExecuted('shape.toggleCollapse', 600, function(context) {
var shape = context.shape;

if (!is(shape, 'bpmn:SubProcess')) {
return;
}

var rootElement = context.newRootElement;

if (!isExpanded(shape)) {

// collapsed
self._moveChildrenToShape(shape, rootElement);

} else {
self._moveChildrenToShape(rootElement, shape);
}
}, 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;
* Moves the child elements from source to target.
*
* If the target is a plane, the children are moved to the top left corner.
* Otherwise, the center of the target is used.
*
* @param {Object|djs.model.Base} source
* @param {Object|djs.model.Base} target
*/
SubProcessPlaneBehavior.prototype._moveChildrenToShape = function(source, target) {
var modeling = this._modeling;

if (!planeElement.businessObject) {
planeElement = this._createNewDiagram(planeElement);
var children = source.children;
var offset;

if (!children) {
return;
}

diagrams.push(planeElement.di.$parent);
// Only change plane if there are no visible children, but don't move them
var visibleChildren = children.filter(function(child) {
return !child.hidden;
});

return planeElement;
if (!visibleChildren.length) {
modeling.moveElements(children, { x: 0, y: 0 }, target, { autoResize: false });
return;
}

// target is a plane
if (!target.x) {
offset = {
x: DEFAULT_POSITION.x - source.x ,
y: DEFAULT_POSITION.y - source.y
};
}

// source is a plane
else {

// move relative to the center of the shape
var targetMid = getMid(target);
var childrenBounds = getBBox(visibleChildren);
var childrenMid = getMid(childrenBounds);

offset = {
x: targetMid.x - childrenMid.x,
y: targetMid.y - childrenMid.y
};
}

modeling.moveElements(children, offset, target, { autoResize: false });
};

/**
* Sets `hidden` property on all children of the given shape.
*
* @param {Array} elements
* @param {Boolean} [hidden]
* @returns {Array} all child elements
*/
SubProcessPlaneBehavior.prototype._showRecursively = function(elements, hidden) {
var self = this;

var result = [];
elements.forEach(function(element) {
element.hidden = !!hidden;

result = result.concat(element);

if (element.children) {
result = result.concat(
self._showRecursively(element.children, element.collapsed || hidden)
);
}
});

return result;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/features/ordering/BpmnOrderingProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export default function BpmnOrderingProvider(eventBus, canvas, translate) {
// render labels always on top
if (element.labelTarget) {
return {
parent: canvas.getRootElement(),
parent: canvas.findRoot(element.labelTarget) || canvas.getRootElement(),
index: -1
};
}
Expand Down
2 changes: 1 addition & 1 deletion test/spec/features/grid-snapping/BpmnGridSnappingSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ describe('features/grid-snapping', function() {

// then
expect(expandedSubProcess).to.include({
x: 140,
x: 150,
y: 120,
width: 360,
height: 210
Expand Down
Loading

0 comments on commit 408de38

Please sign in to comment.