Skip to content

Commit

Permalink
feat(modeling): copy and paste boundary events
Browse files Browse the repository at this point in the history
* allow copying boundary events without host
* remove CreateBoundaryEventBehavior in favor of AttachEventBehavior

Closes #1154
Closes #1202
Closes #1204
Closes #1205
  • Loading branch information
philippfromme committed Oct 13, 2019
1 parent 59de759 commit 2e27d74
Show file tree
Hide file tree
Showing 15 changed files with 971 additions and 502 deletions.
95 changes: 62 additions & 33 deletions lib/features/modeling/behavior/AttachEventBehavior.js
Expand Up @@ -2,68 +2,97 @@ import inherits from 'inherits';

import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';

import { isAny } from '../util/ModelingUtil';
import { getBusinessObject } from '../../../util/ModelUtil';

import { isAny } from '../util/ModelingUtil';

import { isLabel } from '../../../util/LabelUtil';

var LOW_PRIORITY = 500;


/**
* BPMN specific attach event behavior
* Replace intermediate event with boundary event when creating or moving results in attached event.
*/
export default function AttachEventBehavior(eventBus, bpmnReplace) {
export default function AttachEventBehavior(bpmnReplace, injector) {
injector.invoke(CommandInterceptor, this);

CommandInterceptor.call(this, eventBus);
this._bpmnReplace = bpmnReplace;

/**
* replace intermediate event with boundary event when
* attaching it to a shape
*/
var self = this;

this.preExecute('elements.move', function(context) {
var shapes = context.shapes,
host = context.newHost,
shape,
eventDefinition,
boundaryEvent,
newShape;
this.postExecuted('elements.create', LOW_PRIORITY, function(context) {
var elements = context.elements;

if (shapes.length !== 1) {
elements = elements.filter(function(shape) {
var host = shape.host;

return shouldReplace(shape, host);
});

if (elements.length !== 1) {
return;
}

shape = shapes[0];
elements.map(function(element) {
return elements.indexOf(element);
}).forEach(function(index) {
var host = elements[ index ];

if (host && isAny(shape, [ 'bpmn:IntermediateThrowEvent', 'bpmn:IntermediateCatchEvent' ])) {
context.elements[ index ] = self.replaceShape(elements[ index ], host);
});
}, true);

eventDefinition = getEventDefinition(shape);

boundaryEvent = {
type: 'bpmn:BoundaryEvent',
host: host
};
this.preExecute('elements.move', LOW_PRIORITY, function(context) {
var shapes = context.shapes,
host = context.newHost;

if (eventDefinition) {
boundaryEvent.eventDefinitionType = eventDefinition.$type;
}
if (shapes.length !== 1) {
return;
}

newShape = bpmnReplace.replaceElement(shape, boundaryEvent, { layoutConnection: false });
var shape = shapes[0];

context.shapes = [ newShape ];
if (shouldReplace(shape, host)) {
context.shapes = [ self.replaceShape(shape, host) ];
}
}, true);
}

AttachEventBehavior.$inject = [
'eventBus',
'bpmnReplace'
'bpmnReplace',
'injector'
];

inherits(AttachEventBehavior, CommandInterceptor);

AttachEventBehavior.prototype.replaceShape = function(shape, host) {
var eventDefinition = getEventDefinition(shape);

var boundaryEvent = {
type: 'bpmn:BoundaryEvent',
host: host
};

if (eventDefinition) {
boundaryEvent.eventDefinitionType = eventDefinition.$type;
}

return this._bpmnReplace.replaceElement(shape, boundaryEvent, { layoutConnection: false });
};


// helpers //////////

// helper /////
function getEventDefinition(element) {
var bo = getBusinessObject(element);
var businessObject = getBusinessObject(element),
eventDefinitions = businessObject.eventDefinitions;

return eventDefinitions && eventDefinitions[0];
}

return bo && bo.eventDefinitions && bo.eventDefinitions[0];
function shouldReplace(shape, host) {
return !isLabel(shape) &&
isAny(shape, [ 'bpmn:IntermediateThrowEvent', 'bpmn:IntermediateCatchEvent' ]) && !!host;
}
54 changes: 0 additions & 54 deletions lib/features/modeling/behavior/CreateBoundaryEventBehavior.js

This file was deleted.

103 changes: 61 additions & 42 deletions lib/features/modeling/behavior/DetachEventBehavior.js
Expand Up @@ -9,67 +9,86 @@ import {

import { isLabel } from '../../../util/LabelUtil';

var LOW_PRIORITY = 500;


/**
* BPMN specific detach event behavior
* Replace boundary event with intermediate event when creating or moving results in detached event.
*/
export default function DetachEventBehavior(eventBus, bpmnReplace) {
export default function DetachEventBehavior(bpmnReplace, injector) {
injector.invoke(CommandInterceptor, this);

this._bpmnReplace = bpmnReplace;

CommandInterceptor.call(this, eventBus);
var self = this;

/**
* replace boundary event with intermediate event when
* detaching from a shape
*/
this.postExecuted('elements.create', LOW_PRIORITY, function(context) {
var elements = context.elements;

this.preExecute('elements.move', function(context) {
elements.filter(function(shape) {
var host = shape.host;

return shouldReplace(shape, host);
}).map(function(shape) {
return elements.indexOf(shape);
}).forEach(function(index) {
context.elements[ index ] = self.replaceShape(elements[ index ]);
});
}, true);

this.preExecute('elements.move', LOW_PRIORITY, function(context) {
var shapes = context.shapes,
host = context.newHost,
shape,
eventDefinition,
intermediateEvent,
newShape;

if (shapes.length !== 1) {
return;
}

shape = shapes[0];

if (!isLabel(shape) && !host && is(shape, 'bpmn:BoundaryEvent')) {

eventDefinition = getEventDefinition(shape);

if (eventDefinition) {
intermediateEvent = {
type: 'bpmn:IntermediateCatchEvent',
eventDefinitionType: eventDefinition.$type
};
} else {
intermediateEvent = {
type: 'bpmn:IntermediateThrowEvent'
};
}
newHost = context.newHost;

newShape = bpmnReplace.replaceElement(shape, intermediateEvent, { layoutConnection: false });
shapes.forEach(function(shape, index) {
var host = shape.host;

context.shapes = [ newShape ];
}
if (shouldReplace(shape, includes(shapes, host) ? host : newHost)) {
shapes[ index ] = self.replaceShape(shape);
}
});
}, true);
}

DetachEventBehavior.$inject = [
'eventBus',
'bpmnReplace'
'bpmnReplace',
'injector'
];

inherits(DetachEventBehavior, CommandInterceptor);

DetachEventBehavior.prototype.replaceShape = function(shape) {
var eventDefinition = getEventDefinition(shape),
intermediateEvent;

if (eventDefinition) {
intermediateEvent = {
type: 'bpmn:IntermediateCatchEvent',
eventDefinitionType: eventDefinition.$type
};
} else {
intermediateEvent = {
type: 'bpmn:IntermediateThrowEvent'
};
}

return this._bpmnReplace.replaceElement(shape, intermediateEvent, { layoutConnection: false });
};


// helpers //////////

// helper /////
function getEventDefinition(element) {
var bo = getBusinessObject(element);
var businessObject = getBusinessObject(element),
eventDefinitions = businessObject.eventDefinitions;

return bo && bo.eventDefinitions && bo.eventDefinitions[0];
return eventDefinitions && eventDefinitions[0];
}

function shouldReplace(shape, host) {
return !isLabel(shape) && is(shape, 'bpmn:BoundaryEvent') && !host;
}

function includes(array, item) {
return array.indexOf(item) !== -1;
}

0 comments on commit 2e27d74

Please sign in to comment.