feat(modeling): add lane modeling operations

This commit adds the functionality to

* add a lane (above/below an existing one)
* split a lane into sub lanes
* remove a lane
* resize a lane

Closes #379
Closes #338
This commit is contained in:
Nico Rehwaldt 2015-10-10 01:40:52 +02:00 committed by pedesen
parent 04d8ef8a18
commit 5e26068f99
25 changed files with 1747 additions and 571 deletions

View File

@ -5,7 +5,10 @@ var inherits = require('inherits');
var BaseModeling = require('diagram-js/lib/features/modeling/Modeling');
var UpdatePropertiesHandler = require('./cmd/UpdatePropertiesHandler'),
UpdateCanvasRootHandler = require('./cmd/UpdateCanvasRootHandler');
UpdateCanvasRootHandler = require('./cmd/UpdateCanvasRootHandler'),
AddLaneHandler = require('./cmd/AddLaneHandler'),
SplitLaneHandler = require('./cmd/SplitLaneHandler'),
ResizeLaneHandler = require('./cmd/ResizeLaneHandler');
/**
@ -34,6 +37,9 @@ Modeling.prototype.getHandlers = function() {
handlers['element.updateProperties'] = UpdatePropertiesHandler;
handlers['canvas.updateRoot'] = UpdateCanvasRootHandler;
handlers['lane.add'] = AddLaneHandler;
handlers['lane.resize'] = ResizeLaneHandler;
handlers['lane.split'] = SplitLaneHandler;
return handlers;
};
@ -66,6 +72,31 @@ Modeling.prototype.updateProperties = function(element, properties) {
});
};
Modeling.prototype.resizeLane = function(laneShape, newBounds, balanced) {
this._commandStack.execute('lane.resize', {
shape: laneShape,
newBounds: newBounds,
balanced: balanced
});
};
Modeling.prototype.addLane = function(targetLaneShape, location) {
var context = {
shape: targetLaneShape,
location: location
};
this._commandStack.execute('lane.add', context);
return context.newLane;
};
Modeling.prototype.splitLane = function(targetLane, count) {
this._commandStack.execute('lane.split', {
shape: targetLane,
count: count
});
};
/**
* Transform the current diagram into a collaboration.

View File

@ -1,19 +0,0 @@
'use strict';
function getParents(element) {
var parents = [];
while (element) {
element = element.parent;
if (element) {
parents.push(element);
}
}
return parents;
}
module.exports.getParents = getParents;

View File

@ -1,80 +0,0 @@
'use strict';
var inherits = require('inherits');
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
var is = require('../../../util/ModelUtil').is;
var every = require('lodash/collection/every');
var round = Math.round;
/**
* BPMN specific create lane behavior
*/
function CreateLaneBehavior(eventBus, modeling) {
CommandInterceptor.call(this, eventBus);
/**
* wrap existing elements with new lane
*/
this.preExecute('shape.create', function(context) {
var parent = context.parent,
shape = context.shape,
children = parent.children;
// check whether we need to wrap
// the existing elements into the new lane
if (is(shape, 'bpmn:Lane')) {
var labelOffset = 0;
if (is(parent, 'bpmn:Participant') || is(parent, 'bpmn:Lane')) {
labelOffset = 30;
}
shape.width = parent.width - labelOffset;
context.position.x = round(parent.x + labelOffset / 2 + parent.width / 2);
// wrap + adjust lane height + y to fit parent
if (every(children, isNonLane)) {
shape.height = parent.height;
context.position.y = round(parent.y + parent.height / 2);
context.wrapInLane = children.slice();
}
}
}, true);
this.postExecute('shape.create', function(context) {
var shape = context.shape,
wrapInLane = context.wrapInLane;
if (wrapInLane) {
// wrap existing elements onto the new lane,
// if this is the first lane in the parent
modeling.moveElements(wrapInLane, { x: 0, y: 0 }, shape);
}
}, true);
}
CreateLaneBehavior.$inject = [ 'eventBus', 'modeling' ];
inherits(CreateLaneBehavior, CommandInterceptor);
module.exports = CreateLaneBehavior;
function isNonLane(element) {
return !is(element, 'bpmn:Lane');
}

View File

@ -0,0 +1,83 @@
'use strict';
var inherits = require('inherits');
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
var is = require('../../../util/ModelUtil').is;
var getChildLanes = require('../util/LaneUtil').getChildLanes;
var eachElement = require('diagram-js/lib/util/Elements').eachElement;
/**
* BPMN specific delete lane behavior
*/
function DeleteLaneBehavior(eventBus, modeling, spaceTool) {
CommandInterceptor.call(this, eventBus);
/**
* adjust sizes of other lanes after lane deletion
*/
this.postExecute('shape.delete', function(context) {
var shape = context.shape;
if (is(shape, 'bpmn:Lane')) {
var siblings = getChildLanes(context.oldParent);
var topAffected = [];
var bottomAffected = [];
eachElement(siblings, function(element) {
if (element.y > shape.y) {
bottomAffected.push(element);
} else {
topAffected.push(element);
}
return element.children;
});
if (!siblings.length) {
return;
}
var offset;
if (bottomAffected.length && topAffected.length) {
offset = shape.height / 2;
} else {
offset = shape.height;
}
var topAdjustments,
bottomAdjustments;
if (topAffected.length) {
topAdjustments = spaceTool.calculateAdjustments(topAffected, 'y', offset, shape.y - 10);
spaceTool.makeSpace(topAdjustments.movingShapes, topAdjustments.resizingShapes, { x: 0, y: offset }, 's');
}
if (bottomAffected.length) {
bottomAdjustments = spaceTool.calculateAdjustments(bottomAffected, 'y', -offset, shape.y + shape.height + 10);
spaceTool.makeSpace(
bottomAdjustments.movingShapes,
bottomAdjustments.resizingShapes,
{ x: 0, y: -offset },
'n');
}
}
}, true);
}
DeleteLaneBehavior.$inject = [ 'eventBus', 'modeling', 'spaceTool' ];
inherits(DeleteLaneBehavior, CommandInterceptor);
module.exports = DeleteLaneBehavior;

View File

@ -0,0 +1,51 @@
'use strict';
var is = require('../../../util/ModelUtil').is;
var roundBounds = require('diagram-js/lib/layout/LayoutUtil').roundBounds;
var SLIGHTLY_HIGHER_PRIORITY = 1001;
/**
* Invoke {@link Modeling#resizeLane} instead of
* {@link Modeling#resizeShape} when resizing a Lane
* or Participant shape.
*/
function ResizeLaneBehavior(eventBus, modeling) {
/**
* Intercept resize end and call resize lane function instead.
*/
eventBus.on('resize.end', SLIGHTLY_HIGHER_PRIORITY, function(event) {
var context = event.context,
shape = context.shape,
canExecute = context.canExecute,
newBounds = context.newBounds,
balanced;
if (is(shape, 'bpmn:Lane') || is(shape, 'bpmn:Participant')) {
if (canExecute) {
// should we resize the opposite lane(s) in
// order to compensate for the resize operation?
balanced = !(event.originalEvent && event.originalEvent.altKey);
// ensure we have actual pixel values for new bounds
// (important when zoom level was > 1 during move)
newBounds = roundBounds(newBounds);
// perform the actual resize
modeling.resizeLane(shape, newBounds, balanced);
}
// stop propagation
return false;
}
});
}
ResizeLaneBehavior.$inject = [ 'eventBus', 'modeling' ];
module.exports = ResizeLaneBehavior;

View File

@ -3,22 +3,24 @@ module.exports = {
'appendBehavior',
'createBoundaryEventBehavior',
'createDataObjectBehavior',
'createLaneBehavior',
'deleteLaneBehavior',
'createOnFlowBehavior',
'createParticipantBehavior',
'modelingFeedback',
'replaceElementBehaviour',
'removeParticipantBehavior',
'replaceConnectionBehavior'
'replaceConnectionBehavior',
'replaceElementBehaviour',
'resizeLaneBehavior'
],
appendBehavior: [ 'type', require('./AppendBehavior') ],
createBoundaryEventBehavior: [ 'type', require('./CreateBoundaryEventBehavior') ],
createDataObjectBehavior: [ 'type', require('./CreateDataObjectBehavior') ],
createLaneBehavior: [ 'type', require('./CreateLaneBehavior') ],
deleteLaneBehavior: [ 'type', require('./DeleteLaneBehavior') ],
createOnFlowBehavior: [ 'type', require('./CreateOnFlowBehavior') ],
createParticipantBehavior: [ 'type', require('./CreateParticipantBehavior') ],
modelingFeedback: [ 'type', require('./ModelingFeedback') ],
replaceElementBehaviour: [ 'type', require('./ReplaceElementBehaviour') ],
removeParticipantBehavior: [ 'type', require('./RemoveParticipantBehavior') ],
replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ]
replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ],
replaceElementBehaviour: [ 'type', require('./ReplaceElementBehaviour') ],
resizeLaneBehavior: [ 'type', require('./ResizeLaneBehavior') ]
};

View File

@ -0,0 +1,83 @@
'use strict';
var filter = require('lodash/collection/filter');
var Elements = require('diagram-js/lib/util/Elements');
var getLanesRoot = require('../util/LaneUtil').getLanesRoot,
getChildLanes = require('../util/LaneUtil').getChildLanes,
LANE_INDENTATION = require('../util/LaneUtil').LANE_INDENTATION;
/**
* A handler that allows us to add a new lane
* above or below an existing one.
*
* @param {Modeling} modeling
*/
function AddLaneHandler(modeling, spaceTool) {
this._modeling = modeling;
this._spaceTool = spaceTool;
}
AddLaneHandler.$inject = [ 'modeling', 'spaceTool' ];
module.exports = AddLaneHandler;
AddLaneHandler.prototype.preExecute = function(context) {
var spaceTool = this._spaceTool,
modeling = this._modeling;
var shape = context.shape,
location = context.location;
var lanesRoot = getLanesRoot(shape);
var isRoot = lanesRoot === shape,
laneParent = isRoot ? shape : shape.parent;
var existingChildLanes = getChildLanes(laneParent);
// (0) add a lane if we currently got none and are adding to root
if (!existingChildLanes.length) {
modeling.createShape({ type: 'bpmn:Lane' }, {
x: shape.x + LANE_INDENTATION,
y: shape.y,
width: shape.width - LANE_INDENTATION,
height: shape.height
}, laneParent);
}
// (1) collect affected elements to create necessary space
var allAffected = [];
Elements.eachElement(lanesRoot, function(element) {
allAffected.push(element);
if (element === shape) {
return [];
}
return filter(element.children, function(c) {
return c !== shape;
});
});
var offset = location === 'top' ? -120 : 120,
lanePosition = location === 'top' ? shape.y : shape.y + shape.height,
spacePos = lanePosition + (location === 'top' ? 10 : -10),
direction = location === 'top' ? 'n' : 's';
var adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos);
spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: 0, y: offset }, direction);
// (2) create new lane at open space
context.newLane = modeling.createShape({ type: 'bpmn:Lane' }, {
x: shape.x + (isRoot ? LANE_INDENTATION : 0),
y: lanePosition - (location === 'top' ? 120 : 0),
width: shape.width - (isRoot ? LANE_INDENTATION : 0),
height: 120
}, laneParent);
};

View File

@ -0,0 +1,126 @@
'use strict';
var is = require('../../../util/ModelUtil').is;
var getLanesRoot = require('../util/LaneUtil').getLanesRoot,
computeLanesResize = require('../util/LaneUtil').computeLanesResize;
var eachElement = require('diagram-js/lib/util/Elements').eachElement;
var asTRBL = require('diagram-js/lib/layout/LayoutUtil').asTRBL,
substractTRBL = require('diagram-js/lib/features/resize/ResizeUtil').substractTRBL;
/**
* A handler that resizes a lane.
*
* @param {Modeling} modeling
*/
function ResizeLaneHandler(modeling, spaceTool) {
this._modeling = modeling;
this._spaceTool = spaceTool;
}
ResizeLaneHandler.$inject = [ 'modeling', 'spaceTool' ];
module.exports = ResizeLaneHandler;
ResizeLaneHandler.prototype.preExecute = function(context) {
var shape = context.shape,
newBounds = context.newBounds,
balanced = context.balanced;
if (balanced !== false) {
this.resizeBalanced(shape, newBounds);
} else {
this.resizeSpace(shape, newBounds);
}
};
/**
* Resize balanced, adjusting next / previous lane sizes.
*
* @param {djs.model.Shape} shape
* @param {Bounds} newBounds
*/
ResizeLaneHandler.prototype.resizeBalanced = function(shape, newBounds) {
var modeling = this._modeling;
var resizeNeeded = computeLanesResize(shape, newBounds);
// resize the lane
modeling.resizeShape(shape, newBounds);
// resize other lanes as needed
resizeNeeded.forEach(function(r) {
modeling.resizeShape(r.shape, r.newBounds);
});
};
/**
* Resize, making actual space and moving below / above elements.
*
* @param {djs.model.Shape} shape
* @param {Bounds} newBounds
*/
ResizeLaneHandler.prototype.resizeSpace = function(shape, newBounds) {
var spaceTool = this._spaceTool;
var shapeTrbl = asTRBL(shape),
newTrbl = asTRBL(newBounds);
var trblDiff = substractTRBL(newTrbl, shapeTrbl);
var lanesRoot = getLanesRoot(shape);
var allAffected = [],
allLanes = [];
eachElement(lanesRoot, function(element) {
allAffected.push(element);
if (is(element, 'bpmn:Lane') || is(element, 'bpmn:Participant')) {
allLanes.push(element);
}
return element.children;
});
var change,
spacePos,
direction,
offset,
adjustments;
if (trblDiff.bottom || trblDiff.top) {
change = trblDiff.bottom || trblDiff.top;
spacePos = shape.y + (trblDiff.bottom ? shape.height : 0) + (trblDiff.bottom ? -10 : 10);
direction = trblDiff.bottom ? 's' : 'n';
offset = trblDiff.top > 0 || trblDiff.bottom < 0 ? -change : change;
adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos);
spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: 0, y: change }, direction);
}
if (trblDiff.left || trblDiff.right) {
change = trblDiff.right || trblDiff.left;
spacePos = shape.x + (trblDiff.right ? shape.width : 0) + (trblDiff.right ? -10 : 100);
direction = trblDiff.right ? 'e' : 'w';
offset = trblDiff.left > 0 || trblDiff.right < 0 ? -change : change;
adjustments = spaceTool.calculateAdjustments(allLanes, 'x', offset, spacePos);
spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: change, y: 0 }, direction);
}
};

View File

@ -0,0 +1,80 @@
'use strict';
var getChildLanes = require('../util/LaneUtil').getChildLanes;
var LANE_INDENTATION = require('../util/LaneUtil').LANE_INDENTATION;
/**
* A handler that splits a lane into a number of sub-lanes,
* creating new sub lanes, if neccessary.
*
* @param {Modeling} modeling
*/
function SplitLaneHandler(modeling) {
this._modeling = modeling;
}
SplitLaneHandler.$inject = [ 'modeling' ];
module.exports = SplitLaneHandler;
SplitLaneHandler.prototype.preExecute = function(context) {
var modeling = this._modeling;
var shape = context.shape,
newLanesCount = context.count;
var childLanes = getChildLanes(shape),
existingLanesCount = childLanes.length;
if (existingLanesCount > newLanesCount) {
throw new Error('more than ' + newLanesCount + ' child lanes');
}
var newLanesHeight = Math.round(shape.height / newLanesCount);
// Iterate from top to bottom in child lane order,
// resizing existing lanes and creating new ones
// so that they split the parent proportionally.
//
// Due to rounding related errors, the bottom lane
// needs to take up all the remaining space.
var laneY,
laneHeight,
laneBounds,
newLaneAttrs,
idx;
for (idx = 0; idx < newLanesCount; idx++) {
laneY = shape.y + idx * newLanesHeight;
// if bottom lane
if (idx === newLanesCount - 1) {
laneHeight = shape.height - (newLanesHeight * idx);
} else {
laneHeight = newLanesHeight;
}
laneBounds = {
x: shape.x + LANE_INDENTATION,
y: laneY,
width: shape.width - LANE_INDENTATION,
height: laneHeight
};
if (idx < existingLanesCount) {
// resize existing lane
modeling.resizeShape(childLanes[idx], laneBounds);
} else {
// create a new lane at position
newLaneAttrs = {
type: 'bpmn:Lane'
};
modeling.createShape(newLaneAttrs, laneBounds, shape);
}
}
};

View File

@ -11,7 +11,8 @@ module.exports = {
require('diagram-js/lib/features/label-support'),
require('diagram-js/lib/features/attach-support'),
require('diagram-js/lib/features/selection'),
require('diagram-js/lib/features/change-support')
require('diagram-js/lib/features/change-support'),
require('diagram-js/lib/features/space-tool')
],
bpmnFactory: [ 'type', require('./BpmnFactory') ],
bpmnUpdater: [ 'type', require('./BpmnUpdater') ],

View File

@ -0,0 +1,157 @@
'use strict';
var is = require('../../../util/ModelUtil').is;
var getParent = require('./ModelingUtil').getParent;
var asTRBL = require('diagram-js/lib/layout/LayoutUtil').asTRBL,
substractTRBL = require('diagram-js/lib/features/resize/ResizeUtil').substractTRBL,
resizeTRBL = require('diagram-js/lib/features/resize/ResizeUtil').resizeTRBL;
var abs = Math.abs;
function getTRBLResize(oldBounds, newBounds) {
return substractTRBL(asTRBL(newBounds), asTRBL(oldBounds));
}
var LANE_PARENTS = [
'bpmn:Participant',
'bpmn:Process',
'bpmn:SubProcess'
];
var LANE_INDENTATION = 30;
module.exports.LANE_INDENTATION = LANE_INDENTATION;
/**
* Collect all lane shapes in the given paren
*
* @param {[type]} shape
* @param {Array<djs.model.Base>} [collectedShapes]
*
* @return {Array<djs.model.Base>}
*/
function collectLanes(shape, collectedShapes) {
collectedShapes = collectedShapes || [];
shape.children.filter(function(s) {
if (is(s, 'bpmn:Lane')) {
collectLanes(s, collectedShapes);
collectedShapes.push(s);
}
});
return collectedShapes;
}
module.exports.collectLanes = collectLanes;
/**
* Return the lane children of the given element.
*
* @param {djs.model.Shape} shape
*
* @return {Array<djs.model.Shape>}
*/
function getChildLanes(shape) {
return shape.children.filter(function(c) {
return is(c, 'bpmn:Lane');
});
}
module.exports.getChildLanes = getChildLanes;
/**
* Return the root element containing the given lane shape
*
* @param {djs.model.Shape} shape
*
* @return {djs.model.Shape}
*/
function getLanesRoot(shape) {
return getParent(shape, LANE_PARENTS) || shape;
}
module.exports.getLanesRoot = getLanesRoot;
/**
* Compute the required resize operations for lanes
* adjacent to the given shape, assuming it will be
* resized to the given new bounds.
*
* @param {djs.model.Shape} shape
* @param {Bounds} newBounds
*
* @return {Array<Object>}
*/
function computeLanesResize(shape, newBounds) {
var rootElement = getLanesRoot(shape);
var initialShapes = is(rootElement, 'bpmn:Process') ? [] : [ rootElement ];
var allLanes = collectLanes(rootElement, initialShapes),
shapeTrbl = asTRBL(shape),
shapeNewTrbl = asTRBL(newBounds),
trblResize = getTRBLResize(shape, newBounds),
resizeNeeded = [];
allLanes.forEach(function(other) {
if (other === shape) {
return;
}
var topResize = 0,
rightResize = trblResize.right,
bottomResize = 0,
leftResize = trblResize.left;
var otherTrbl = asTRBL(other);
if (trblResize.top) {
if (abs(otherTrbl.bottom - shapeTrbl.top) < 10) {
bottomResize = shapeNewTrbl.top - otherTrbl.bottom;
}
if (abs(otherTrbl.top - shapeTrbl.top) < 5) {
topResize = shapeNewTrbl.top - otherTrbl.top;
}
}
if (trblResize.bottom) {
if (abs(otherTrbl.top - shapeTrbl.bottom) < 10) {
topResize = shapeNewTrbl.bottom - otherTrbl.top;
}
if (abs(otherTrbl.bottom - shapeTrbl.bottom) < 5) {
bottomResize = shapeNewTrbl.bottom - otherTrbl.bottom;
}
}
if (topResize || rightResize || bottomResize || leftResize) {
resizeNeeded.push({
shape: other,
newBounds: resizeTRBL(other, {
top: topResize,
right: rightResize,
bottom: bottomResize,
left: leftResize
})
});
}
});
return resizeNeeded;
}
module.exports.computeLanesResize = computeLanesResize;

View File

@ -0,0 +1,66 @@
'use strict';
var any = require('lodash/collection/any');
var is = require('../../../util/ModelUtil').is;
function getParents(element) {
var parents = [];
while (element) {
element = element.parent;
if (element) {
parents.push(element);
}
}
return parents;
}
module.exports.getParents = getParents;
/**
* Return true if element has any of the given types.
*
* @param {djs.model.Base} element
* @param {Array<String>} types
*
* @return {Boolean}
*/
function isAny(element, types) {
return any(types, function(t) {
return is(element, t);
});
}
module.exports.isAny = isAny;
/**
* Return the parent of the element with any of the given types.
*
* @param {djs.model.Base} element
* @param {String|Array<String>} anyType
*
* @return {djs.model.Base}
*/
function getParent(element, anyType) {
if (typeof anyType === 'string') {
anyType = [ anyType ];
}
while ((element = element.parent)) {
if (isAny(element, anyType)) {
return element;
}
}
return null;
}
module.exports.getParent = getParent;

View File

@ -34,6 +34,12 @@ describe('Modeler', function() {
});
it('should import nested lanes', function(done) {
var xml = require('./features/modeling/lanes/lanes.bpmn');
createModeler(xml, done);
});
it('should import empty definitions', function(done) {
var xml = require('../fixtures/bpmn/empty-definitions.bpmn');
createModeler(xml, done);

View File

@ -0,0 +1,263 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var pick = require('lodash/object/pick');
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
var getChildLanes = require('../../../../../lib/features/modeling/util/LaneUtil').getChildLanes;
var DEFAULT_LANE_HEIGHT = 120;
function getBounds(element) {
return pick(element, [ 'x', 'y', 'width', 'height' ]);
}
describe('features/modeling - add Lane', function() {
describe('nested Lanes', function() {
var diagramXML = require('./lanes.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('should add after Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
belowLaneShape = elementRegistry.get('Lane_B');
// when
var newLane = modeling.addLane(laneShape, 'bottom');
// then
expect(newLane).to.have.bounds({
x: laneShape.x,
y: laneShape.y + laneShape.height,
width: laneShape.width,
height: DEFAULT_LANE_HEIGHT
});
// below lanes got moved by { dy: + LANE_HEIGHT }
expect(belowLaneShape).to.have.bounds({
x: laneShape.x,
y: laneShape.y + laneShape.height + DEFAULT_LANE_HEIGHT - 1,
width: laneShape.width,
height: belowLaneShape.height
});
}));
it('should add before Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_B'),
aboveLaneShape = elementRegistry.get('Lane_A');
// when
var newLane = modeling.addLane(laneShape, 'top');
// then
expect(newLane).to.have.bounds({
x: laneShape.x,
y: laneShape.y - DEFAULT_LANE_HEIGHT,
width: laneShape.width,
height: DEFAULT_LANE_HEIGHT
});
// below lanes got moved by { dy: + LANE_HEIGHT }
expect(aboveLaneShape).to.have.bounds({
x: laneShape.x,
y: laneShape.y - aboveLaneShape.height - DEFAULT_LANE_HEIGHT + 1,
width: laneShape.width,
height: aboveLaneShape.height
});
}));
it('should add before nested Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Nested_Lane_A'),
participantShape = elementRegistry.get('Participant_Lane'),
participantBounds = getBounds(participantShape);
// when
var newLane = modeling.addLane(laneShape, 'top');
// then
expect(newLane).to.have.bounds({
x: laneShape.x,
y: laneShape.y - DEFAULT_LANE_HEIGHT,
width: laneShape.width,
height: DEFAULT_LANE_HEIGHT
});
// participant got enlarged { top: + LANE_HEIGHT }
expect(participantShape).to.have.bounds({
x: participantBounds.x,
y: participantBounds.y - newLane.height,
width: participantBounds.width,
height: participantBounds.height + newLane.height
});
}));
it('should add after Participant', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_Lane'),
participantBounds = getBounds(participantShape),
lastLaneShape = elementRegistry.get('Lane_B'),
lastLaneBounds = getBounds(lastLaneShape);
// when
var newLane = modeling.addLane(participantShape, 'bottom');
// then
expect(newLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y + participantBounds.height,
width: participantBounds.width - 30,
height: DEFAULT_LANE_HEIGHT
});
// last lane kept position
expect(lastLaneShape).to.have.bounds(lastLaneBounds);
// participant got enlarged by { dy: + LANE_HEIGHT } at bottom
expect(participantShape).to.have.bounds({
x: participantBounds.x,
y: participantBounds.y,
width: participantBounds.width,
height: participantBounds.height + DEFAULT_LANE_HEIGHT
});
}));
it('should add before Participant', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_Lane'),
participantBounds = getBounds(participantShape),
firstLaneShape = elementRegistry.get('Lane_A'),
firstLaneBounds = getBounds(firstLaneShape);
// when
var newLane = modeling.addLane(participantShape, 'top');
// then
expect(newLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y - DEFAULT_LANE_HEIGHT,
width: participantBounds.width - 30,
height: DEFAULT_LANE_HEIGHT
});
// last lane kept position
expect(firstLaneShape).to.have.bounds(firstLaneBounds);
// participant got enlarged by { dy: + LANE_HEIGHT } at bottom
expect(participantShape).to.have.bounds({
x: participantBounds.x,
y: participantBounds.y - DEFAULT_LANE_HEIGHT,
width: participantBounds.width,
height: participantBounds.height + DEFAULT_LANE_HEIGHT
});
}));
});
describe('Participant without Lane', function() {
var diagramXML = require('./participant-no-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('should add after Participant', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_No_Lane'),
participantBounds = getBounds(participantShape);
// when
modeling.addLane(participantShape, 'bottom');
var childLanes = getChildLanes(participantShape);
// then
expect(childLanes.length).to.eql(2);
var firstLane = childLanes[0],
secondLane = childLanes[1];
// new lane was added at participant location
expect(firstLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y,
width: participantBounds.width - 30,
height: participantBounds.height
});
expect(secondLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y + participantBounds.height,
width: participantBounds.width - 30,
height: DEFAULT_LANE_HEIGHT
});
}));
it('should add before Participant', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_No_Lane'),
participantBounds = getBounds(participantShape);
// when
modeling.addLane(participantShape, 'top');
var childLanes = getChildLanes(participantShape);
// then
expect(childLanes.length).to.eql(2);
var firstLane = childLanes[0],
secondLane = childLanes[1];
// new lane was added at participant location
expect(firstLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y,
width: participantBounds.width - 30,
height: participantBounds.height
});
expect(secondLane).to.have.bounds({
x: participantBounds.x + 30,
y: participantBounds.y - DEFAULT_LANE_HEIGHT,
width: participantBounds.width - 30,
height: DEFAULT_LANE_HEIGHT
});
}));
});
});

View File

@ -1,96 +0,0 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
describe('features/modeling - lanes', function() {
describe('should add Task', function() {
var diagramXML = require('./lane-simple.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('execute', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane'),
// lane = laneShape.businessObject,
participantShape = elementRegistry.get('Participant_Lane'),
bpmnProcess = participantShape.businessObject.processRef;
// when
var newTaskShape = modeling.createShape({ type: 'bpmn:Task' }, { x: 250, y: 150 }, laneShape);
var newTask = newTaskShape.businessObject;
// then
expect(newTask.$parent).to.equal(bpmnProcess);
expect(bpmnProcess.flowElements).to.contain(newTask);
// TODO(nre): correctly wire flowNodeRef(s)
// expect(lane.flowNodeRef).to.contain(newTask);
}));
it('undo', inject(function(elementRegistry, commandStack, modeling) {
// given
var laneShape = elementRegistry.get('Lane'),
// lane = laneShape.businessObject,
participantShape = elementRegistry.get('Participant_Lane'),
bpmnProcess = participantShape.businessObject.processRef;
var newTaskShape = modeling.createShape({ type: 'bpmn:Task' }, { x: 250, y: 150 }, laneShape);
var newTask = newTaskShape.businessObject;
// when
commandStack.undo();
// then
expect(newTask.$parent).not.to.exist;
expect(bpmnProcess.flowElements).not.to.contain(newTask);
// TODO(nre): correctly wire flowNodeRef(s)
// expect(lane.flowNodeRef).not.to.contain(newTask);
}));
it('redo', inject(function(elementRegistry, commandStack, modeling) {
// given
var laneShape = elementRegistry.get('Lane'),
// lane = laneShape.businessObject,
participantShape = elementRegistry.get('Participant_Lane'),
bpmnProcess = participantShape.businessObject.processRef;
var newTaskShape = modeling.createShape({ type: 'bpmn:Task' }, { x: 250, y: 150 }, laneShape);
var newTask = newTaskShape.businessObject;
// when
commandStack.undo();
commandStack.redo();
// then
expect(newTask.$parent).to.equal(bpmnProcess);
expect(bpmnProcess.flowElements).to.contain(newTask);
// TODO(nre): correctly wire flowNodeRef(s)
// expect(lane.flowNodeRef).to.contain(newTask);
}));
});
});

View File

@ -1,249 +0,0 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
describe('features/modeling - lanes', function() {
describe('should add to participant', function() {
var diagramXML = require('./no-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('execute', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant'),
participant = participantShape.businessObject,
bpmnProcess = participant.processRef;
// when
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, participantShape);
var lane = laneShape.businessObject;
// then
// expect it to have an id
expect(lane.id).to.exist;
expect(laneShape).to.exist;
expect(lane).to.exist;
expect(bpmnProcess.laneSets).to.exist;
var laneSet = bpmnProcess.laneSets[0];
// expect correct bpmn containment for new laneSet
expect(laneSet.$parent).to.eql(bpmnProcess);
// expect correct bpmn containment for lane
expect(laneSet.lanes).to.contain(lane);
expect(lane.$parent).to.equal(laneSet);
// expect correct di wiring
expect(lane.di.$parent).to.eql(participant.di.$parent);
expect(lane.di.$parent.planeElement).to.include(lane.di);
}));
it('undo', inject(function(elementRegistry, commandStack, modeling) {
// given
var participantShape = elementRegistry.get('Participant'),
participant = participantShape.businessObject,
bpmnProcess = participant.processRef;
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, participantShape);
var lane = laneShape.businessObject;
var laneSet = lane.$parent;
// when
commandStack.undo();
// then
expect(lane.$parent).to.be.null;
expect(laneSet.lanes).not.to.contain(lane);
// lane sets remain initialized
expect(bpmnProcess.laneSets).to.exist;
expect(bpmnProcess.laneSets.length).to.eql(1);
}));
it('redo', inject(function(elementRegistry, commandStack, modeling) {
// given
var participantShape = elementRegistry.get('Participant'),
participant = participantShape.businessObject,
bpmnProcess = participant.processRef;
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, participantShape);
var lane = laneShape.businessObject;
// when
commandStack.undo();
commandStack.redo();
// then
expect(laneShape).to.exist;
expect(lane).to.exist;
expect(bpmnProcess.laneSets).to.exist;
var laneSet = bpmnProcess.laneSets[0];
// expect correct bpmn containment
expect(laneSet.lanes).to.contain(lane);
expect(lane.$parent).to.equal(laneSet);
// expect correct di wiring
expect(lane.di.$parent).to.eql(participant.di.$parent);
expect(lane.di.$parent.planeElement).to.include(lane.di);
}));
});
describe('should add to lane', function() {
var diagramXML = require('./nested-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('execute', inject(function(elementRegistry, modeling) {
// given
var parentLaneShape = elementRegistry.get('Lane'),
parentLane = parentLaneShape.businessObject;
// when
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, parentLaneShape);
var lane = laneShape.businessObject;
// then
expect(laneShape).to.exist;
expect(lane).to.exist;
var laneSet = parentLane.childLaneSet;
expect(laneSet).to.exist;
// expect correct bpmn containment for new laneSet
expect(laneSet.$parent).to.eql(parentLane);
// expect correct bpmn containment for lane
expect(laneSet.lanes).to.contain(lane);
expect(lane.$parent).to.equal(laneSet);
// expect correct di wiring
expect(lane.di.$parent).to.eql(parentLane.di.$parent);
expect(lane.di.$parent.planeElement).to.include(lane.di);
}));
it('undo', inject(function(elementRegistry, commandStack, modeling) {
// given
var parentLaneShape = elementRegistry.get('Lane'),
parentLane = parentLaneShape.businessObject;
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, parentLaneShape);
var lane = laneShape.businessObject;
var laneSet = lane.$parent;
// when
commandStack.undo();
// then
expect(lane.$parent).to.be.null;
expect(laneSet.lanes).not.to.contain(lane);
// childLaneSet sets remain initialized
expect(parentLane.childLaneSet).to.exist;
}));
it('redo', inject(function(elementRegistry, commandStack, modeling) {
// given
var parentLaneShape = elementRegistry.get('Lane'),
parentLane = parentLaneShape.businessObject;
var laneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, parentLaneShape);
var lane = laneShape.businessObject;
// when
commandStack.undo();
commandStack.redo();
// then
expect(laneShape).to.exist;
expect(lane).to.exist;
var laneSet = parentLane.childLaneSet;
expect(laneSet).to.exist;
// expect correct bpmn containment for new laneSet
expect(laneSet.$parent).to.eql(parentLane);
// expect correct bpmn containment for lane
expect(laneSet.lanes).to.contain(lane);
expect(lane.$parent).to.equal(laneSet);
// expect correct di wiring
expect(lane.di.$parent).to.eql(parentLane.di.$parent);
expect(lane.di.$parent.planeElement).to.include(lane.di);
}));
});
function ids(elements) {
return elements.map(function(e) { return e.id; });
}
describe('should wrap existing children', function() {
var diagramXML = require('./nested-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('execute', inject(function(elementRegistry, modeling) {
// given
var nestedLaneShape = elementRegistry.get('Nested_Lane');
// when
var newLaneShape = modeling.createShape({ type: 'bpmn:Lane' }, { x: 180, y: 100 }, nestedLaneShape);
// then
expect(ids(newLaneShape.children)).to.eql([ 'Task_Boundary', 'Task', 'Boundary', 'Boundary_label' ]);
}));
});
});

View File

@ -0,0 +1,126 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var pick = require('lodash/object/pick');
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
function getBounds(element) {
return pick(element, [ 'x', 'y', 'width', 'height' ]);
}
describe('features/modeling - delete lane', function() {
var diagramXML = require('./lanes.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('should remove first Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
belowLaneShape = elementRegistry.get('Lane_B'),
belowLaneBounds = getBounds(belowLaneShape);
// when
modeling.removeShape(laneShape);
// then
expect(belowLaneShape).to.have.bounds({
x: belowLaneBounds.x,
y: belowLaneBounds.y - laneShape.height,
width: belowLaneBounds.width,
height: belowLaneBounds.height + laneShape.height
});
}));
it('should remove last Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_B'),
aboveLaneShape = elementRegistry.get('Lane_A'),
aboveLaneBounds = getBounds(aboveLaneShape);
// when
modeling.removeShape(laneShape);
// then
expect(aboveLaneShape).to.have.bounds({
x: aboveLaneBounds.x,
y: aboveLaneBounds.y,
width: aboveLaneShape.width,
height: aboveLaneBounds.height + laneShape.height
});
}));
describe('three lanes', function() {
it('should remove middle Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Nested_Lane_B'),
aboveLaneShape = elementRegistry.get('Nested_Lane_A'),
aboveLaneBounds = getBounds(aboveLaneShape),
belowLaneShape = elementRegistry.get('Nested_Lane_C'),
belowLaneBounds = getBounds(belowLaneShape);
// when
modeling.removeShape(laneShape);
// then
expect(aboveLaneShape).to.have.bounds({
x: aboveLaneBounds.x,
y: aboveLaneBounds.y,
width: aboveLaneShape.width,
height: aboveLaneBounds.height + laneShape.height / 2
});
expect(belowLaneShape).to.have.bounds({
x: belowLaneBounds.x,
y: belowLaneBounds.y - laneShape.height / 2,
width: belowLaneBounds.width,
height: belowLaneBounds.height + laneShape.height / 2
});
}));
it('should remove first Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Nested_Lane_A'),
belowLaneShape = elementRegistry.get('Nested_Lane_B'),
belowLaneBounds = getBounds(belowLaneShape),
lastLaneShape = elementRegistry.get('Nested_Lane_C'),
lastLaneBounds = getBounds(lastLaneShape);
// when
modeling.removeShape(laneShape);
// then
expect(belowLaneShape).to.have.bounds({
x: belowLaneBounds.x,
y: belowLaneBounds.y - laneShape.height,
width: belowLaneBounds.width,
height: belowLaneBounds.height + laneShape.height
});
expect(lastLaneShape).to.have.bounds(lastLaneBounds);
}));
});
});

View File

@ -9,7 +9,7 @@ var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
describe('features/modeling - lanes - flowNodeRefs', function() {
describe.skip('features/modeling - lanes - flowNodeRefs', function() {
var diagramXML = require('./flowNodeRefs.bpmn');

View File

@ -0,0 +1,366 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
var resizeTRBL = require('diagram-js/lib/features/resize/ResizeUtil').resizeTRBL;
var pick = require('lodash/object/pick');
function getBounds(element) {
return pick(element, [ 'x', 'y', 'width', 'height']);
}
describe('features/modeling - resize lane', function() {
var diagramXML = require('./lanes.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
describe('vertical', function() {
describe('compensating', function() {
it('should expand Lane top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { top: -50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { top: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds, false);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Lane top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { top: 50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { top: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds, false);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Participant top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newParticipantBounds = resizeTRBL(participantShape, { top: 50 });
var expectedLaneBounds = resizeTRBL(laneShape, { top: 50 });
// when
modeling.resizeLane(participantShape, newParticipantBounds, false);
// then
expect(participantShape).to.have.bounds(newParticipantBounds);
expect(laneShape).to.have.bounds(expectedLaneBounds);
}));
it('should shrink Lane bottom', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { bottom: -50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { bottom: -50 }),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { top: -50, bottom: -50 }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { bottom: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds, false);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
it('should expand Lane bottom', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { bottom: 50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { bottom: 50 }),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { top: 50, bottom: 50 }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { bottom: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds, false);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
});
describe('enlarging / shrinking', function() {
it('should expand Lane top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { top: -50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { top: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Lane top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { top: 50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { top: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Participant top', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newParticipantBounds = resizeTRBL(participantShape, { top: 50 });
var expectedLaneBounds = resizeTRBL(laneShape, { top: 50 });
// when
modeling.resizeLane(participantShape, newParticipantBounds);
// then
expect(participantShape).to.have.bounds(newParticipantBounds);
expect(laneShape).to.have.bounds(expectedLaneBounds);
}));
it('should move up above Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { bottom: -50 });
var expectedParticipantBounds = getBounds(participantShape),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { top: -50 + 1 /* compensation */ }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { bottom: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
it('should move down below Lane', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { bottom: 50 });
var expectedParticipantBounds = getBounds(participantShape),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { top: 50 + 1 /* compensation */ }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { bottom: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
});
});
describe('horizontal', function() {
it('should expand Lane left', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { left: -50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { left: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Lane left', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { left: 50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { left: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
}));
it('should shrink Participant left', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
participantShape = elementRegistry.get('Participant_Lane');
var newParticipantBounds = resizeTRBL(participantShape, { left: 50 });
var expectedLaneBounds = resizeTRBL(laneShape, { left: 50 });
// when
modeling.resizeLane(participantShape, newParticipantBounds);
// then
expect(participantShape).to.have.bounds(newParticipantBounds);
expect(laneShape).to.have.bounds(expectedLaneBounds);
}));
it('should shrink Lane right', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { right: -50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { right: -50 }),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { right: -50 }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { right: -50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
it('should expand Lane right', inject(function(elementRegistry, modeling) {
// given
var laneShape = elementRegistry.get('Lane_A'),
nextLaneShape = elementRegistry.get('Lane_B'),
nestedLaneShape = elementRegistry.get('Nested_Lane_C'),
participantShape = elementRegistry.get('Participant_Lane');
var newLaneBounds = resizeTRBL(laneShape, { right: 50 });
var expectedParticipantBounds = resizeTRBL(participantShape, { right: 50 }),
expectedNextLaneBounds = resizeTRBL(nextLaneShape, { right: 50 }),
expectedNestedLaneBounds = resizeTRBL(nestedLaneShape, { right: 50 });
// when
modeling.resizeLane(laneShape, newLaneBounds);
// then
expect(laneShape).to.have.bounds(newLaneBounds);
expect(participantShape).to.have.bounds(expectedParticipantBounds);
expect(nestedLaneShape).to.have.bounds(expectedNestedLaneBounds);
expect(nextLaneShape).to.have.bounds(expectedNextLaneBounds);
}));
});
});

View File

@ -0,0 +1,217 @@
'use strict';
var TestHelper = require('../../../../TestHelper');
/* global bootstrapModeler, inject */
var pick = require('lodash/object/pick');
var modelingModule = require('../../../../../lib/features/modeling'),
coreModule = require('../../../../../lib/core');
var getChildLanes = require('lib/features/modeling/util/LaneUtil').getChildLanes;
function getBounds(element) {
return pick(element, [ 'x', 'y', 'width', 'height' ]);
}
describe('features/modeling - SplitLane', function() {
describe('should split Participant with Lane', function() {
var diagramXML = require('./participant-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('into two lanes', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_Lane'),
existingLane = elementRegistry.get('Lane'),
oldBounds = getBounds(participantShape);
// when
modeling.splitLane(participantShape, 2);
var childLanes = getChildLanes(participantShape);
var newLaneHeight = Math.round(participantShape.height / 2);
// then
// participant has original size
expect(participantShape).to.have.bounds(oldBounds);
// and two child lanes
expect(childLanes.length).to.eql(2);
// with the first lane being the original one
expect(childLanes[0]).to.equal(existingLane);
// with respective bounds
expect(childLanes[0]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[1]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight,
width: participantShape.width - 30,
height: newLaneHeight - 1 // compensate for rounding issues
});
}));
it('into three lanes', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_Lane'),
existingLane = elementRegistry.get('Lane'),
oldBounds = getBounds(participantShape);
// when
modeling.splitLane(participantShape, 3);
var childLanes = getChildLanes(participantShape);
var newLaneHeight = Math.round(participantShape.height / 3);
// then
// participant has original size
expect(participantShape).to.have.bounds(oldBounds);
// and two child lanes
expect(childLanes.length).to.eql(3);
// with the first lane being the original one
expect(childLanes[0]).to.equal(existingLane);
// with respective bounds
expect(childLanes[0]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[1]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[2]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight * 2,
width: participantShape.width - 30,
height: newLaneHeight - 1 // compensate for rounding issues
});
}));
});
describe('should split Participant without Lane', function() {
var diagramXML = require('./participant-no-lane.bpmn');
var testModules = [ coreModule, modelingModule ];
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('into two lanes', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_No_Lane'),
oldBounds = getBounds(participantShape);
// when
modeling.splitLane(participantShape, 2);
var childLanes = getChildLanes(participantShape);
var newLaneHeight = Math.round(participantShape.height / 2);
// then
// participant has original size
expect(participantShape).to.have.bounds(oldBounds);
// and two child lanes
expect(childLanes.length).to.eql(2);
// with respective bounds
expect(childLanes[0]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[1]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight,
width: participantShape.width - 30,
height: newLaneHeight
});
}));
it('into three lanes', inject(function(elementRegistry, modeling) {
// given
var participantShape = elementRegistry.get('Participant_No_Lane'),
oldBounds = getBounds(participantShape);
// when
modeling.splitLane(participantShape, 3);
var childLanes = getChildLanes(participantShape);
var newLaneHeight = Math.round(participantShape.height / 3);
// then
// participant has original size
expect(participantShape).to.have.bounds(oldBounds);
// and two child lanes
expect(childLanes.length).to.eql(3);
// with respective bounds
expect(childLanes[0]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[1]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight,
width: participantShape.width - 30,
height: newLaneHeight
});
expect(childLanes[2]).to.have.bounds({
x: participantShape.x + 30,
y: participantShape.y + newLaneHeight * 2,
width: participantShape.width - 30,
height: newLaneHeight + 1 // compensate for rounding issues
});
}));
});
});

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="_4bAZoD9WEeWLcNBL4nCk1A" targetNamespace="http://activiti.org/bpmn" exporter="camunda modeler" exporterVersion="2.6.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:collaboration id="_Collaboration_2">
<bpmn2:participant id="Participant_Lane" name="Participant_Lane" processRef="Process_Lane" />
</bpmn2:collaboration>
<bpmn2:process id="Process_Lane" isExecutable="false">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane" name="Lane">
<bpmn2:flowNodeRef>Other_Task</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>Task</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:task id="Other_Task" name="Other_Task">
<bpmn2:outgoing>SequenceFlow</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow" name="" sourceRef="Other_Task" targetRef="Task" />
<bpmn2:task id="Task" name="Task">
<bpmn2:incoming>SequenceFlow</bpmn2:incoming>
</bpmn2:task>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="_Collaboration_2">
<bpmndi:BPMNShape id="_BPMNShape_Participant_2" bpmnElement="Participant_Lane" isHorizontal="true">
<dc:Bounds x="156" y="84" width="540" height="181" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Other_Task">
<dc:Bounds x="348" y="114" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task">
<dc:Bounds x="516" y="114" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="448" y="154" />
<di:waypoint xsi:type="dc:Point" x="516" y="154" />
<bpmndi:BPMNLabel>
<dc:Bounds x="487" y="154" width="6" height="6" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane" isHorizontal="true">
<dc:Bounds x="186" y="84" width="510" height="181" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -5,15 +5,18 @@
</bpmn2:collaboration>
<bpmn2:process id="Process_Lane" isExecutable="false">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane" name="Lane">
<bpmn2:lane id="Lane_A" name="Lane_A">
<bpmn2:childLaneSet xsi:type="bpmn2:tLaneSet" id="LaneSet_2">
<bpmn2:lane id="Nested_Lane" name="Nested_Lane">
<bpmn2:lane id="Nested_Lane_A" name="Nested_Lane_A">
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>Task_Boundary</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>Task</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="Nested_Lane_B" name="Nested_Lane_B"/>
<bpmn2:lane id="Nested_Lane_C" name="Nested_Lane_C"/>
</bpmn2:childLaneSet>
</bpmn2:lane>
<bpmn2:lane id="Lane_B" name="Lane_B"/>
</bpmn2:laneSet>
<bpmn2:boundaryEvent id="Boundary" name="Boundary" attachedToRef="Task_Boundary">
<bpmn2:outgoing>SequenceFlow_From_Boundary</bpmn2:outgoing>
@ -31,41 +34,50 @@
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="_Collaboration_2">
<bpmndi:BPMNShape id="_BPMNShape_Participant_2" bpmnElement="Participant_Lane" isHorizontal="true">
<dc:Bounds height="181.0" width="540.0" x="156.0" y="84.0"/>
<dc:Bounds height="543.0" width="540.0" x="72.0" y="33.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_Boundary">
<dc:Bounds height="80.0" width="100.0" x="348.0" y="114.0"/>
<dc:Bounds height="80.0" width="100.0" x="264.0" y="63.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="Boundary">
<dc:Bounds height="36.0" width="36.0" x="395.0" y="176.0"/>
<dc:Bounds height="36.0" width="36.0" x="311.0" y="125.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="21.0" width="61.0" x="336.0" y="211.0"/>
<dc:Bounds height="21.0" width="61.0" x="252.0" y="160.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task">
<dc:Bounds height="80.0" width="100.0" x="516.0" y="114.0"/>
<dc:Bounds height="80.0" width="100.0" x="432.0" y="63.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_From_Boundary" sourceElement="_BPMNShape_BoundaryEvent_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="413.0" y="212.0"/>
<di:waypoint xsi:type="dc:Point" x="413.0" y="242.0"/>
<di:waypoint xsi:type="dc:Point" x="566.0" y="242.0"/>
<di:waypoint xsi:type="dc:Point" x="566.0" y="194.0"/>
<di:waypoint xsi:type="dc:Point" x="329.0" y="161.0"/>
<di:waypoint xsi:type="dc:Point" x="329.0" y="188.0"/>
<di:waypoint xsi:type="dc:Point" x="482.0" y="188.0"/>
<di:waypoint xsi:type="dc:Point" x="482.0" y="143.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="6.0" width="6.0" x="458.0" y="242.0"/>
<dc:Bounds height="6.0" width="6.0" x="377.0" y="188.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="448.0" y="154.0"/>
<di:waypoint xsi:type="dc:Point" x="516.0" y="154.0"/>
<di:waypoint xsi:type="dc:Point" x="364.0" y="103.0"/>
<di:waypoint xsi:type="dc:Point" x="432.0" y="103.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="6.0" width="6.0" x="487.0" y="154.0"/>
<dc:Bounds height="6.0" width="6.0" x="403.0" y="103.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane" isHorizontal="true">
<dc:Bounds height="181.0" width="510.0" x="186.0" y="84.0"/>
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane_A" isHorizontal="true">
<dc:Bounds height="436.0" width="510.0" x="102.0" y="33.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane" isHorizontal="true">
<dc:Bounds height="181.0" width="480.0" x="216.0" y="84.0"/>
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane_A" isHorizontal="true">
<dc:Bounds height="181.0" width="480.0" x="132.0" y="33.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Lane_5" bpmnElement="Nested_Lane_B" isHorizontal="true">
<dc:Bounds height="133.0" width="480.0" x="132.0" y="213.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Lane_6" bpmnElement="Lane_B" isHorizontal="true">
<dc:Bounds height="108.0" width="510.0" x="102.0" y="468.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Lane_7" bpmnElement="Nested_Lane_C" isHorizontal="true">
<dc:Bounds height="124.0" width="480.0" x="132.0" y="345.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="_4bAZoD9WEeWLcNBL4nCk1A" exporter="camunda modeler" exporterVersion="2.6.0" targetNamespace="http://activiti.org/bpmn">
<bpmn2:collaboration id="Collaboration">
<bpmn2:participant id="Participant" name="Participant" processRef="Process"/>
</bpmn2:collaboration>
<bpmn2:process id="Process" isExecutable="false">
<bpmn2:task id="Task_Boundary" name="Task_Boundary">
<bpmn2:outgoing>SequenceFlow</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:boundaryEvent id="Boundary" name="Boundary" attachedToRef="Task_Boundary">
<bpmn2:outgoing>SequenceFlow_From_Boundary</bpmn2:outgoing>
</bpmn2:boundaryEvent>
<bpmn2:task id="Task" name="Task">
<bpmn2:incoming>SequenceFlow_From_Boundary</bpmn2:incoming>
<bpmn2:incoming>SequenceFlow</bpmn2:incoming>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_From_Boundary" name="" sourceRef="Boundary" targetRef="Task"/>
<bpmn2:sequenceFlow id="SequenceFlow" name="" sourceRef="Task_Boundary" targetRef="Task"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration">
<bpmndi:BPMNShape id="_BPMNShape_Participant_2" bpmnElement="Participant" isHorizontal="true">
<dc:Bounds height="181.0" width="540.0" x="156.0" y="84.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_Boundary">
<dc:Bounds height="80.0" width="100.0" x="348.0" y="114.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="Boundary">
<dc:Bounds height="36.0" width="36.0" x="395.0" y="176.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="21.0" width="61.0" x="336.0" y="211.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task">
<dc:Bounds height="80.0" width="100.0" x="516.0" y="114.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_From_Boundary" sourceElement="_BPMNShape_BoundaryEvent_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="413.0" y="212.0"/>
<di:waypoint xsi:type="dc:Point" x="413.0" y="242.0"/>
<di:waypoint xsi:type="dc:Point" x="566.0" y="242.0"/>
<di:waypoint xsi:type="dc:Point" x="566.0" y="194.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="6.0" width="6.0" x="458.0" y="242.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="448.0" y="154.0"/>
<di:waypoint xsi:type="dc:Point" x="516.0" y="154.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="6.0" width="6.0" x="487.0" y="154.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="_DjEdwG27EeW3UIoxwJSm9g" targetNamespace="http://activiti.org/bpmn" exporter="camunda modeler" exporterVersion="2.6.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:collaboration id="_Collaboration_3">
<bpmn2:participant id="Participant_Lane" name="Participant_Lane" processRef="Process_Lane" />
</bpmn2:collaboration>
<bpmn2:process id="Process_Lane" isExecutable="false">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane" name="Lane">
<bpmn2:flowNodeRef>Task_1</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:task id="Task_1" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPLane" bpmnElement="_Collaboration_3">
<bpmndi:BPMNShape id="_BPMNShape_Participant_3" bpmnElement="Participant_Lane" isHorizontal="true">
<dc:Bounds x="48" y="60" width="540" height="215" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Lane_7" bpmnElement="Lane" isHorizontal="true">
<dc:Bounds x="78" y="60" width="510" height="215" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_4" bpmnElement="Task_1">
<dc:Bounds x="444" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="_DjEdwG27EeW3UIoxwJSm9g" targetNamespace="http://activiti.org/bpmn" exporter="camunda modeler" exporterVersion="2.6.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:collaboration id="_Collaboration_3">
<bpmn2:participant id="Participant_No_Lane" name="Participant_No_Lane" processRef="Process_No_Lane" />
</bpmn2:collaboration>
<bpmn2:process id="Process_No_Lane" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPLane" bpmnElement="_Collaboration_3">
<bpmndi:BPMNShape id="_BPMNShape_Participant_4" bpmnElement="Participant_No_Lane" isHorizontal="true">
<dc:Bounds x="48" y="60" width="567" height="190" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="397" y="89" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="370" y="130" width="90" height="0" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>