255 lines
6.7 KiB
JavaScript
255 lines
6.7 KiB
JavaScript
import inherits from 'inherits';
|
|
|
|
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
|
|
|
import { is } from '../../../util/ModelUtil';
|
|
|
|
import { isLabel } from '../../../util/LabelUtil';
|
|
|
|
import { getBBox } from 'diagram-js/lib/util/Elements';
|
|
|
|
import {
|
|
assign,
|
|
find
|
|
} from 'min-dash';
|
|
|
|
import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil';
|
|
|
|
var HORIZONTAL_PARTICIPANT_PADDING = 20,
|
|
VERTICAL_PARTICIPANT_PADDING = 20;
|
|
|
|
export var PARTICIPANT_BORDER_WIDTH = 30;
|
|
|
|
var HIGH_PRIORITY = 2000;
|
|
|
|
|
|
/**
|
|
* BPMN-specific behavior for creating participants.
|
|
*/
|
|
export default function CreateParticipantBehavior(canvas, eventBus, modeling) {
|
|
CommandInterceptor.call(this, eventBus);
|
|
|
|
// fit participant
|
|
eventBus.on([
|
|
'create.start',
|
|
'shape.move.start'
|
|
], HIGH_PRIORITY, function(event) {
|
|
var context = event.context,
|
|
shape = context.shape,
|
|
rootElement = canvas.getRootElement();
|
|
|
|
if (!is(shape, 'bpmn:Participant') ||
|
|
!is(rootElement, 'bpmn:Process') ||
|
|
!rootElement.children.length) {
|
|
return;
|
|
}
|
|
|
|
// ignore connections, groups and labels
|
|
var children = rootElement.children.filter(function(element) {
|
|
return !is(element, 'bpmn:Group') &&
|
|
!isLabel(element) &&
|
|
!isConnection(element);
|
|
});
|
|
|
|
// ensure for available children to calculate bounds
|
|
if (!children.length) {
|
|
return;
|
|
}
|
|
|
|
var childrenBBox = getBBox(children);
|
|
|
|
var participantBounds = getParticipantBounds(shape, childrenBBox);
|
|
|
|
// assign width and height
|
|
assign(shape, participantBounds);
|
|
|
|
// assign create constraints
|
|
context.createConstraints = getParticipantCreateConstraints(shape, childrenBBox);
|
|
});
|
|
|
|
// force hovering process when creating first participant
|
|
eventBus.on('create.start', HIGH_PRIORITY, function(event) {
|
|
var context = event.context,
|
|
shape = context.shape,
|
|
rootElement = canvas.getRootElement(),
|
|
rootElementGfx = canvas.getGraphics(rootElement);
|
|
|
|
function ensureHoveringProcess(event) {
|
|
event.element = rootElement;
|
|
event.gfx = rootElementGfx;
|
|
}
|
|
|
|
if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
|
|
eventBus.on('element.hover', HIGH_PRIORITY, ensureHoveringProcess);
|
|
|
|
eventBus.once('create.cleanup', function() {
|
|
eventBus.off('element.hover', ensureHoveringProcess);
|
|
});
|
|
}
|
|
});
|
|
|
|
function ensureCollaboration(context) {
|
|
var parent = context.parent,
|
|
collaboration;
|
|
|
|
var rootElement = canvas.getRootElement();
|
|
|
|
if (is(rootElement, 'bpmn:Collaboration')) {
|
|
collaboration = rootElement;
|
|
} else {
|
|
|
|
// update root element by making collaboration
|
|
collaboration = modeling.makeCollaboration();
|
|
|
|
// re-use process when creating first participant
|
|
context.process = parent;
|
|
}
|
|
|
|
context.parent = collaboration;
|
|
}
|
|
|
|
// turn process into collaboration before adding participant
|
|
this.preExecute('shape.create', function(context) {
|
|
var parent = context.parent,
|
|
shape = context.shape;
|
|
|
|
if (is(shape, 'bpmn:Participant') && is(parent, 'bpmn:Process')) {
|
|
ensureCollaboration(context);
|
|
}
|
|
}, true);
|
|
|
|
this.execute('shape.create', function(context) {
|
|
var process = context.process,
|
|
shape = context.shape;
|
|
|
|
if (process) {
|
|
context.oldProcessRef = shape.businessObject.processRef;
|
|
|
|
// re-use process when creating first participant
|
|
shape.businessObject.processRef = process.businessObject;
|
|
}
|
|
}, true);
|
|
|
|
this.revert('shape.create', function(context) {
|
|
var process = context.process,
|
|
shape = context.shape;
|
|
|
|
if (process) {
|
|
|
|
// re-use process when creating first participant
|
|
shape.businessObject.processRef = context.oldProcessRef;
|
|
}
|
|
}, true);
|
|
|
|
this.postExecute('shape.create', function(context) {
|
|
var process = context.process,
|
|
shape = context.shape;
|
|
|
|
if (process) {
|
|
|
|
// move children from process to participant
|
|
var processChildren = process.children.slice();
|
|
|
|
modeling.moveElements(processChildren, { x: 0, y: 0 }, shape);
|
|
}
|
|
|
|
}, true);
|
|
|
|
// turn process into collaboration when creating participants
|
|
this.preExecute('elements.create', HIGH_PRIORITY, function(context) {
|
|
var elements = context.elements,
|
|
parent = context.parent,
|
|
participant;
|
|
|
|
var hasParticipants = findParticipant(elements);
|
|
|
|
if (hasParticipants && is(parent, 'bpmn:Process')) {
|
|
ensureCollaboration(context);
|
|
|
|
participant = findParticipant(elements);
|
|
|
|
context.oldProcessRef = participant.businessObject.processRef;
|
|
|
|
// re-use process when creating first participant
|
|
participant.businessObject.processRef = parent.businessObject;
|
|
}
|
|
}, true);
|
|
|
|
this.revert('elements.create', function(context) {
|
|
var elements = context.elements,
|
|
process = context.process,
|
|
participant;
|
|
|
|
if (process) {
|
|
participant = findParticipant(elements);
|
|
|
|
// re-use process when creating first participant
|
|
participant.businessObject.processRef = context.oldProcessRef;
|
|
}
|
|
}, true);
|
|
|
|
this.postExecute('elements.create', function(context) {
|
|
var elements = context.elements,
|
|
process = context.process,
|
|
participant;
|
|
|
|
if (process) {
|
|
participant = findParticipant(elements);
|
|
|
|
// move children from process to first participant
|
|
var processChildren = process.children.slice();
|
|
|
|
modeling.moveElements(processChildren, { x: 0, y: 0 }, participant);
|
|
}
|
|
|
|
}, true);
|
|
|
|
}
|
|
|
|
CreateParticipantBehavior.$inject = [
|
|
'canvas',
|
|
'eventBus',
|
|
'modeling'
|
|
];
|
|
|
|
inherits(CreateParticipantBehavior, CommandInterceptor);
|
|
|
|
// helpers //////////
|
|
|
|
function getParticipantBounds(shape, childrenBBox) {
|
|
childrenBBox = {
|
|
width: childrenBBox.width + HORIZONTAL_PARTICIPANT_PADDING * 2 + PARTICIPANT_BORDER_WIDTH,
|
|
height: childrenBBox.height + VERTICAL_PARTICIPANT_PADDING * 2
|
|
};
|
|
|
|
var width = Math.max(shape.width, childrenBBox.width),
|
|
height = Math.max(shape.height, childrenBBox.height);
|
|
|
|
return {
|
|
x: -width / 2,
|
|
y: -height / 2,
|
|
width: width,
|
|
height: height
|
|
};
|
|
}
|
|
|
|
function getParticipantCreateConstraints(shape, childrenBBox) {
|
|
childrenBBox = asTRBL(childrenBBox);
|
|
|
|
return {
|
|
bottom: childrenBBox.top + shape.height / 2 - VERTICAL_PARTICIPANT_PADDING,
|
|
left: childrenBBox.right - shape.width / 2 + HORIZONTAL_PARTICIPANT_PADDING,
|
|
top: childrenBBox.bottom - shape.height / 2 + VERTICAL_PARTICIPANT_PADDING,
|
|
right: childrenBBox.left + shape.width / 2 - HORIZONTAL_PARTICIPANT_PADDING - PARTICIPANT_BORDER_WIDTH
|
|
};
|
|
}
|
|
|
|
function isConnection(element) {
|
|
return !!element.waypoints;
|
|
}
|
|
|
|
function findParticipant(elements) {
|
|
return find(elements, function(element) {
|
|
return is(element, 'bpmn:Participant');
|
|
});
|
|
} |