bpmn-js/lib/features/modeling/behavior/SubProcessBehavior.js
Philipp Fromme 05fea05834 feat(modeling): prevent expanded subprocess overlap of previous content
This covers two scenarios:

1. When a shape is replaced with an expanded subprocess
2. When a subprocess is toggled from collapsed to expanded

Only when:

1. There are incoming sequence flows (previous content)
2. There are no outgoing sequence flows (following content)
2019-05-15 16:57:32 +02:00

91 lines
2.1 KiB
JavaScript

import inherits from 'inherits';
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
import { is } from '../../../util/ModelUtil';
import { expandedBounds } from './ToggleElementCollapseBehaviour';
export default function SubProcessBehavior(elementFactory, eventBus, modeling) {
CommandInterceptor.call(this, eventBus);
/**
* Adjust position of sub process after it replaces a shape with incoming
* sequence flows and no outgoing sequence flows to prevent overlap.
*/
this.postExecuted('shape.replace', function(event) {
var oldShape = event.context.oldShape,
newShape = event.context.newShape;
if (!is(newShape, 'bpmn:SubProcess') ||
!hasIncomingSequenceFlows(newShape) ||
hasOutgoingSequenceFlows(newShape)) {
return;
}
modeling.moveShape(newShape, {
x: oldShape.x - newShape.x,
y: 0
});
});
/**
* Adjust position of sub process with incoming sequence flows and no outgoing
* sequence flows after toggling to prevent overlap.
*/
this.postExecuted('shape.toggleCollapse', function(event) {
var context = event.context,
shape = context.shape,
defaultSize = elementFactory._getDefaultSize(shape),
newBounds;
if (!is(shape, 'bpmn:SubProcess') ||
shape.collapsed ||
!hasIncomingSequenceFlows(shape) ||
hasOutgoingSequenceFlows(shape)) {
return;
}
newBounds = expandedBounds(shape, defaultSize);
modeling.moveShape(shape, {
x: shape.x - newBounds.x,
y: 0
});
});
}
SubProcessBehavior.$inject = [
'elementFactory',
'eventBus',
'modeling'
];
inherits(SubProcessBehavior, CommandInterceptor);
// helpers //////////
function hasIncomingSequenceFlows(shape) {
shape = shape || {};
if (shape.incoming && shape.incoming.length) {
return shape.incoming.some(isSequenceFlow);
}
return false;
}
function hasOutgoingSequenceFlows(shape) {
shape = shape || {};
if (shape.outgoing && shape.outgoing.length) {
return shape.outgoing.some(isSequenceFlow);
}
return false;
}
function isSequenceFlow(connection) {
return is(connection, 'bpmn:SequenceFlow');
}