feat(snapping): add lane snapping
This commit is contained in:
parent
5e26068f99
commit
fefc748a9a
|
@ -5,14 +5,15 @@ var inherits = require('inherits');
|
|||
var forEach = require('lodash/collection/forEach');
|
||||
|
||||
var getBoundingBox = require('diagram-js/lib/util/Elements').getBBox;
|
||||
var is = require('../modeling/ModelingUtil').is,
|
||||
|
||||
var is = require('../../util/ModelUtil').is,
|
||||
isAny = require('../modeling/util/ModelingUtil').isAny,
|
||||
isExpanded = require('../../util/DiUtil').isExpanded;
|
||||
|
||||
var Snapping = require('diagram-js/lib/features/snapping/Snapping'),
|
||||
SnapUtil = require('diagram-js/lib/features/snapping/SnapUtil');
|
||||
|
||||
var is = require('../../util/ModelUtil').is;
|
||||
|
||||
var asTRBL = require('diagram-js/lib/layout/LayoutUtil').asTRBL;
|
||||
|
||||
var round = Math.round;
|
||||
|
||||
|
@ -20,8 +21,12 @@ var mid = SnapUtil.mid,
|
|||
topLeft = SnapUtil.topLeft,
|
||||
bottomRight = SnapUtil.bottomRight,
|
||||
isSnapped = SnapUtil.isSnapped,
|
||||
setSnapped = SnapUtil.setSnapped,
|
||||
getBoundaryAttachment = require('./BpmnSnappingUtil').getBoundaryAttachment;
|
||||
setSnapped = SnapUtil.setSnapped;
|
||||
|
||||
var getBoundaryAttachment = require('./BpmnSnappingUtil').getBoundaryAttachment,
|
||||
getParticipantSizeConstraints = require('./BpmnSnappingUtil').getParticipantSizeConstraints,
|
||||
getLanesRoot = require('../modeling/util/LaneUtil').getLanesRoot;
|
||||
|
||||
|
||||
/**
|
||||
* BPMN specific snapping functionality
|
||||
|
@ -32,7 +37,7 @@ var mid = SnapUtil.mid,
|
|||
* @param {EventBus} eventBus
|
||||
* @param {Canvas} canvas
|
||||
*/
|
||||
function BpmnSnapping(eventBus, canvas, bpmnRules) {
|
||||
function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistry) {
|
||||
|
||||
// instantiate super
|
||||
Snapping.call(this, eventBus, canvas);
|
||||
|
@ -84,7 +89,12 @@ function BpmnSnapping(eventBus, canvas, bpmnRules) {
|
|||
/**
|
||||
* Snap boundary events to elements border
|
||||
*/
|
||||
eventBus.on([ 'create.move', 'create.end' ], 1500, function(event) {
|
||||
eventBus.on([
|
||||
'create.move',
|
||||
'create.end',
|
||||
'shape.move.move',
|
||||
'shape.move.end'
|
||||
], 1500, function(event) {
|
||||
|
||||
var context = event.context,
|
||||
target = context.target,
|
||||
|
@ -95,18 +105,118 @@ function BpmnSnapping(eventBus, canvas, bpmnRules) {
|
|||
}
|
||||
});
|
||||
|
||||
eventBus.on([ 'shape.move.move', 'shape.move.end' ], 1500, function(event) {
|
||||
|
||||
/**
|
||||
* Adjust parent for flowElements to the target participant
|
||||
* when droping onto lanes.
|
||||
*/
|
||||
eventBus.on([
|
||||
'shape.move.hover',
|
||||
'shape.move.move',
|
||||
'shape.move.end',
|
||||
'create.hover',
|
||||
'create.move',
|
||||
'create.end'
|
||||
], 1500, function(event) {
|
||||
var context = event.context,
|
||||
target = context.target,
|
||||
shape = context.shape;
|
||||
shape = context.shape,
|
||||
hover = event.hover;
|
||||
|
||||
if (target && !isSnapped(event) && canAttach(shape, target, event)) {
|
||||
snapBoundaryEvent(event, shape, target);
|
||||
if (is(hover, 'bpmn:Lane') && !isAny(shape, [ 'bpmn:Lane', 'bpmn:Participant' ])) {
|
||||
event.hover = getLanesRoot(hover);
|
||||
event.hoverGfx = elementRegistry.getGraphics(event.hover);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var abs = Math.abs;
|
||||
|
||||
var filter = require('lodash/collection/filter'),
|
||||
assign = require('lodash/object/assign');
|
||||
|
||||
|
||||
eventBus.on([
|
||||
'create.move',
|
||||
'shape.move.move'
|
||||
], function(event) {
|
||||
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
target = context.target;
|
||||
|
||||
var threshold = 30;
|
||||
|
||||
if (is(shape, 'bpmn:Lane')) {
|
||||
if (isAny(target, [ 'bpmn:Lane', 'bpmn:Participant' ])) {
|
||||
|
||||
var childLanes = filter(target.children, function(c) {
|
||||
return is(c, 'bpmn:Lane');
|
||||
});
|
||||
|
||||
var y = event.y,
|
||||
targetTrbl;
|
||||
|
||||
var insert = childLanes.reduce(function(insert, l) {
|
||||
|
||||
var laneTrbl = asTRBL(l);
|
||||
|
||||
if (abs(laneTrbl.top - y) < threshold) {
|
||||
insert = assign(insert || {}, { before: { element: l, y: laneTrbl.top } });
|
||||
} else
|
||||
if (abs(laneTrbl.bottom - y) < threshold) {
|
||||
insert = assign(insert || {}, { after: { element: l, y: laneTrbl.bottom } });
|
||||
} else
|
||||
if (laneTrbl.top < y && laneTrbl.bottom > y) {
|
||||
if (abs(laneTrbl.top - y) > abs(laneTrbl.bottom - y)) {
|
||||
insert = assign(insert || {}, { after: { element: l, y: laneTrbl.bottom } });
|
||||
} else {
|
||||
insert = assign(insert || {}, { before: { element: l, y: laneTrbl.top } });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return insert;
|
||||
}, false);
|
||||
|
||||
|
||||
if (!insert) {
|
||||
targetTrbl = asTRBL(target);
|
||||
|
||||
if (abs(targetTrbl.top - y) < threshold) {
|
||||
insert = { before: { element: target, y: targetTrbl.top } };
|
||||
} else
|
||||
if (abs(targetTrbl.bottom - y) < threshold) {
|
||||
insert = { after: { element: target, y: targetTrbl.bottom } };
|
||||
} else {
|
||||
insert = { into: { element: target, y: (targetTrbl.top + targetTrbl.bottom) / 2 } };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (insert.before && insert.after) {
|
||||
console.log('insert between', insert.before.element.id, 'and', insert.after.element.id);
|
||||
setSnapped(event, 'x', insert.before.element.x + insert.before.element.width / 2);
|
||||
setSnapped(event, 'y', insert.before.y);
|
||||
} else
|
||||
if (insert.after) {
|
||||
console.log('insert after', insert.after.element.id);
|
||||
setSnapped(event, 'x', insert.after.element.x + insert.after.element.width / 2);
|
||||
setSnapped(event, 'y', insert.after.y);
|
||||
} else
|
||||
if (insert.before) {
|
||||
console.log('insert before', insert.before.element.id);
|
||||
setSnapped(event, 'x', insert.before.element.x + insert.before.element.width / 2);
|
||||
setSnapped(event, 'y', insert.before.y);
|
||||
} else
|
||||
if (insert.into) {
|
||||
console.log('insert into', insert.into.element.id);
|
||||
setSnapped(event, 'x', insert.into.element.x + insert.into.element.width / 2);
|
||||
setSnapped(event, 'y', insert.into.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
eventBus.on('resize.start', 1500, function(event) {
|
||||
var context = event.context,
|
||||
shape = context.shape;
|
||||
|
@ -119,8 +229,8 @@ function BpmnSnapping(eventBus, canvas, bpmnRules) {
|
|||
context.minDimensions = { width: 300, height: 150 };
|
||||
}
|
||||
|
||||
if (is(shape, 'bpmn:Participant') || is(shape, 'bpmn:Lane')) {
|
||||
context.minBounds = computeParticipantMinBounds(shape);
|
||||
if (is(shape, 'bpmn:Lane') || is(shape, 'bpmn:Participant')) {
|
||||
context.resizeConstraints = getParticipantSizeConstraints(shape, context.direction);
|
||||
}
|
||||
|
||||
if (is(shape, 'bpmn:TextAnnotation')) {
|
||||
|
@ -132,7 +242,7 @@ function BpmnSnapping(eventBus, canvas, bpmnRules) {
|
|||
|
||||
inherits(BpmnSnapping, Snapping);
|
||||
|
||||
BpmnSnapping.$inject = [ 'eventBus', 'canvas', 'bpmnRules' ];
|
||||
BpmnSnapping.$inject = [ 'eventBus', 'canvas', 'bpmnRules', 'elementRegistry' ];
|
||||
|
||||
module.exports = BpmnSnapping;
|
||||
|
||||
|
@ -227,6 +337,12 @@ BpmnSnapping.prototype.addTargetSnaps = function(snapPoints, shape, target) {
|
|||
var siblings = this.getSiblings(shape, target) || [];
|
||||
|
||||
forEach(siblings, function(s) {
|
||||
|
||||
// do not snap to lanes
|
||||
if (is(s, 'bpmn:Lane')) {
|
||||
return;
|
||||
}
|
||||
|
||||
snapPoints.add('mid', mid(s));
|
||||
|
||||
if (is(s, 'bpmn:Participant')) {
|
||||
|
@ -321,11 +437,8 @@ function snapParticipant(snapBox, shape, event, offset) {
|
|||
/////// boundary event snapping /////////////////////////
|
||||
|
||||
|
||||
var LayoutUtil = require('diagram-js/lib/layout/LayoutUtil');
|
||||
|
||||
|
||||
function snapBoundaryEvent(event, shape, target) {
|
||||
var targetTRBL = LayoutUtil.asTRBL(target);
|
||||
var targetTRBL = asTRBL(target);
|
||||
|
||||
var direction = getBoundaryAttachment(event, target);
|
||||
|
||||
|
@ -343,46 +456,3 @@ function snapBoundaryEvent(event, shape, target) {
|
|||
setSnapped(event, 'x', targetTRBL.right);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////// participant / lane min bounds
|
||||
|
||||
var getBBox = require('diagram-js/lib/util/Elements').getBBox,
|
||||
addPadding = require('diagram-js/lib/features/resize/ResizeUtil').addPadding;
|
||||
|
||||
function computeParticipantMinBounds(element) {
|
||||
|
||||
var lanePadding = {
|
||||
left: 30,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
};
|
||||
|
||||
var flowElementPadding = {
|
||||
left: 50,
|
||||
right: 35
|
||||
};
|
||||
|
||||
function getChildBox(child) {
|
||||
if (is(child, 'bpmn:Lane')) {
|
||||
return addPadding(child, lanePadding);
|
||||
}
|
||||
|
||||
if (child.labelTarget || child.waypoints) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return addPadding(child, flowElementPadding);
|
||||
}
|
||||
|
||||
function nonNull(e) {
|
||||
return !!e;
|
||||
}
|
||||
|
||||
var childrenBoxes = element.children.map(getChildBox).filter(nonNull);
|
||||
|
||||
if (childrenBoxes.length) {
|
||||
return getBBox(childrenBoxes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
var getOrientation = require('diagram-js/lib/layout/LayoutUtil').getOrientation;
|
||||
|
||||
|
||||
module.exports.getBoundaryAttachment = function(position, targetBounds) {
|
||||
function getBoundaryAttachment(position, targetBounds) {
|
||||
|
||||
var orientation = getOrientation(position, targetBounds, -15);
|
||||
|
||||
|
@ -12,4 +12,149 @@ module.exports.getBoundaryAttachment = function(position, targetBounds) {
|
|||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.getBoundaryAttachment = getBoundaryAttachment;
|
||||
|
||||
|
||||
|
||||
// participant snapping box implementation /////////////////
|
||||
|
||||
var is = require('../../util/ModelUtil').is;
|
||||
|
||||
var asTRBL = require('diagram-js/lib/layout/LayoutUtil').asTRBL;
|
||||
|
||||
var collectLanes = require('../modeling/util/LaneUtil').collectLanes,
|
||||
getLanesRoot = require('../modeling/util/LaneUtil').getLanesRoot;
|
||||
|
||||
var abs = Math.abs,
|
||||
min = Math.min,
|
||||
max = Math.max;
|
||||
|
||||
|
||||
function addToTrbl(trbl, attr, value, choice) {
|
||||
|
||||
var current = trbl[attr];
|
||||
|
||||
// make sure to set the value if it does not exist
|
||||
// or apply the correct value by comparing against
|
||||
// choice(value, currentValue)
|
||||
trbl[attr] = current === undefined ? value : choice(value, current);
|
||||
}
|
||||
|
||||
function addMin(trbl, attr, value) {
|
||||
return addToTrbl(trbl, attr, value, min);
|
||||
}
|
||||
|
||||
function addMax(trbl, attr, value) {
|
||||
return addToTrbl(trbl, attr, value, max);
|
||||
}
|
||||
|
||||
|
||||
var LANE_MIN_HEIGHT = 60,
|
||||
LANE_MIN_WIDTH = 300,
|
||||
LANE_RIGHT_PADDING = 20,
|
||||
LANE_LEFT_PADDING = 50,
|
||||
LANE_TOP_PADDING = 20,
|
||||
LANE_BOTTOM_PADDING = 20;
|
||||
|
||||
|
||||
function getParticipantSizeConstraints(laneShape, resizeDirection) {
|
||||
|
||||
var lanesRoot = getLanesRoot(laneShape);
|
||||
|
||||
var isFirst = true,
|
||||
isLast = true;
|
||||
|
||||
///// max top/bottom size for lanes
|
||||
|
||||
var allLanes = collectLanes(lanesRoot, [ lanesRoot ]);
|
||||
|
||||
var laneTrbl = asTRBL(laneShape);
|
||||
|
||||
var maxTrbl = {},
|
||||
minTrbl = {};
|
||||
|
||||
if (/e/.test(resizeDirection)) {
|
||||
minTrbl.right = laneTrbl.left + LANE_MIN_WIDTH;
|
||||
} else
|
||||
if (/w/.test(resizeDirection)) {
|
||||
minTrbl.left = laneTrbl.right - LANE_MIN_WIDTH;
|
||||
}
|
||||
|
||||
allLanes.forEach(function(other) {
|
||||
|
||||
var otherTrbl = asTRBL(other);
|
||||
|
||||
if (/n/.test(resizeDirection)) {
|
||||
|
||||
if (otherTrbl.top < (laneTrbl.top - 10)) {
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
// max top size (based on next element)
|
||||
if (abs(laneTrbl.top - otherTrbl.bottom) < 10) {
|
||||
addMax(maxTrbl, 'top', otherTrbl.top + LANE_MIN_HEIGHT);
|
||||
}
|
||||
|
||||
// min top size (based on self or nested element)
|
||||
if (abs(laneTrbl.top - otherTrbl.top) < 5) {
|
||||
addMin(minTrbl, 'top', otherTrbl.bottom - LANE_MIN_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
if (/s/.test(resizeDirection)) {
|
||||
|
||||
if (otherTrbl.bottom > (laneTrbl.bottom + 10)) {
|
||||
isLast = false;
|
||||
}
|
||||
|
||||
// max bottom size (based on previous element)
|
||||
if (abs(laneTrbl.bottom - otherTrbl.top) < 10) {
|
||||
addMin(maxTrbl, 'bottom', otherTrbl.bottom - LANE_MIN_HEIGHT);
|
||||
}
|
||||
|
||||
// min bottom size (based on self or nested element)
|
||||
if (abs(laneTrbl.bottom - otherTrbl.bottom) < 5) {
|
||||
addMax(minTrbl, 'bottom', otherTrbl.top + LANE_MIN_HEIGHT);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
///// max top/bottom/left/right size based on flow nodes
|
||||
|
||||
var flowElements = lanesRoot.children.filter(function(s) {
|
||||
return !s.hidden && !s.waypoints && (is(s, 'bpmn:FlowElement') || is(s, 'bpmn:Artifact'));
|
||||
});
|
||||
|
||||
flowElements.forEach(function(flowElement) {
|
||||
|
||||
var flowElementTrbl = asTRBL(flowElement);
|
||||
|
||||
if (isFirst && /n/.test(resizeDirection)) {
|
||||
addMin(minTrbl, 'top', flowElementTrbl.top - LANE_TOP_PADDING);
|
||||
}
|
||||
|
||||
if (/e/.test(resizeDirection)) {
|
||||
addMax(minTrbl, 'right', flowElementTrbl.right + LANE_RIGHT_PADDING);
|
||||
}
|
||||
|
||||
if (isLast && /s/.test(resizeDirection)) {
|
||||
addMax(minTrbl, 'bottom', flowElementTrbl.bottom + LANE_BOTTOM_PADDING);
|
||||
}
|
||||
|
||||
if (/w/.test(resizeDirection)) {
|
||||
addMin(minTrbl, 'left', flowElementTrbl.left - LANE_LEFT_PADDING);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
min: minTrbl,
|
||||
max: maxTrbl
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports.getParticipantSizeConstraints = getParticipantSizeConstraints;
|
|
@ -14,9 +14,18 @@ var coreModule = require('../../../../lib/core'),
|
|||
moveModule = require('diagram-js/lib/features/move'),
|
||||
rulesModule = require('../../../../lib/features/rules');
|
||||
|
||||
|
||||
describe('features/snapping - BpmnSnapping', function() {
|
||||
|
||||
var testModules = [ coreModule, snappingModule, modelingModule, createModule, rulesModule, moveModule ];
|
||||
var testModules = [
|
||||
coreModule,
|
||||
snappingModule,
|
||||
modelingModule,
|
||||
createModule,
|
||||
rulesModule,
|
||||
moveModule
|
||||
];
|
||||
|
||||
|
||||
describe('on Boundary Events', function() {
|
||||
|
||||
|
@ -225,7 +234,13 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
|
||||
var diagramXML = require('./BpmnSnapping.participant-resize.bpmn');
|
||||
|
||||
var testResizeModules = [ coreModule, resizeModule, rulesModule, snappingModule ];
|
||||
var testResizeModules = [
|
||||
coreModule,
|
||||
resizeModule,
|
||||
modelingModule,
|
||||
rulesModule,
|
||||
snappingModule
|
||||
];
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: testResizeModules }));
|
||||
|
||||
|
@ -238,7 +253,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.move(canvasEvent({ x: 0, y: 0 }));
|
||||
dragging.end();
|
||||
|
||||
expect(participant.width).to.equal(497);
|
||||
expect(participant.width).to.equal(482);
|
||||
expect(participant.height).to.equal(252);
|
||||
}));
|
||||
|
||||
|
@ -265,7 +280,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.end();
|
||||
|
||||
expect(participant.width).to.equal(300);
|
||||
expect(participant.height).to.equal(150);
|
||||
expect(participant.height).to.equal(60);
|
||||
}));
|
||||
|
||||
|
||||
|
@ -278,7 +293,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.end();
|
||||
|
||||
expect(participant.width).to.equal(300);
|
||||
expect(participant.height).to.equal(150);
|
||||
expect(participant.height).to.equal(60);
|
||||
}));
|
||||
|
||||
|
||||
|
@ -290,7 +305,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.move(canvasEvent({ x: 0, y: 0 }));
|
||||
dragging.end();
|
||||
|
||||
expect(participant.width).to.equal(320);
|
||||
expect(participant.width).to.equal(305);
|
||||
|
||||
// snap to children rather than min dimensions
|
||||
expect(participant.height).to.equal(143);
|
||||
|
@ -316,7 +331,13 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
|
||||
var diagramXML = require('./BpmnSnapping.lanes-resize.bpmn');
|
||||
|
||||
var testResizeModules = [ coreModule, resizeModule, rulesModule, snappingModule ];
|
||||
var testResizeModules = [
|
||||
coreModule,
|
||||
resizeModule,
|
||||
modelingModule,
|
||||
rulesModule,
|
||||
snappingModule
|
||||
];
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: testResizeModules }));
|
||||
|
||||
|
@ -329,8 +350,8 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.move(canvasEvent({ x: 500, y: 500 }));
|
||||
dragging.end();
|
||||
|
||||
expect(participant.width).to.equal(600);
|
||||
expect(participant.height).to.equal(254);
|
||||
expect(participant.width).to.equal(563);
|
||||
expect(participant.height).to.equal(223);
|
||||
}));
|
||||
|
||||
|
||||
|
@ -342,8 +363,8 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
dragging.move(canvasEvent({ x: -500, y: -500 }));
|
||||
dragging.end();
|
||||
|
||||
expect(lane.width).to.equal(570);
|
||||
expect(lane.height).to.equal(118);
|
||||
expect(lane.width).to.equal(313);
|
||||
expect(lane.height).to.equal(122);
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?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_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_A" name="Lane_A">
|
||||
<bpmn2:childLaneSet xsi:type="bpmn2:tLaneSet" id="LaneSet_2">
|
||||
<bpmn2:lane id="Nested_Lane_A" name="Nested_Lane_A">
|
||||
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>Task_Boundary</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="Nested_Lane_B" name="Nested_Lane_B"/>
|
||||
</bpmn2:childLaneSet>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="Lane_B" name="Lane_B">
|
||||
<bpmn2:flowNodeRef>Task</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
</bpmn2:laneSet>
|
||||
<bpmn2:boundaryEvent id="Boundary" name="Boundary" attachedToRef="Task_Boundary">
|
||||
<bpmn2:outgoing>SequenceFlow_From_Boundary</bpmn2:outgoing>
|
||||
</bpmn2:boundaryEvent>
|
||||
<bpmn2:sequenceFlow id="SequenceFlow_From_Boundary" name="" sourceRef="Boundary" targetRef="Task"/>
|
||||
<bpmn2:task id="Task_Boundary" name="Task_Boundary">
|
||||
<bpmn2:outgoing>SequenceFlow</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:sequenceFlow id="SequenceFlow" name="" sourceRef="Task_Boundary" targetRef="Task"/>
|
||||
<bpmn2:task id="Task" name="Task">
|
||||
<bpmn2:incoming>SequenceFlow_From_Boundary</bpmn2:incoming>
|
||||
<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 height="532.0" width="540.0" x="156.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_Boundary">
|
||||
<dc:Bounds height="80.0" width="100.0" x="348.0" y="30.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="Boundary">
|
||||
<dc:Bounds height="36.0" width="36.0" x="395.0" y="92.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="21.0" width="61.0" x="336.0" y="127.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="384.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="128.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="413.0" y="156.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="413.0" y="423.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="516.0" y="424.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="6.0" width="6.0" x="410.0" y="206.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="70.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="482.0" y="70.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="566.0" y="70.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="566.0" y="384.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="6.0" width="6.0" x="487.0" y="70.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane_A" isHorizontal="true">
|
||||
<dc:Bounds height="361.0" width="510.0" x="186.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane_A" isHorizontal="true">
|
||||
<dc:Bounds height="181.0" width="480.0" x="216.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_5" bpmnElement="Nested_Lane_B" isHorizontal="true">
|
||||
<dc:Bounds height="181.0" width="480.0" x="216.0" y="180.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_6" bpmnElement="Lane_B" isHorizontal="true">
|
||||
<dc:Bounds height="172.0" width="510.0" x="186.0" y="360.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
|
@ -0,0 +1,36 @@
|
|||
<?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_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_A" name="Lane_A">
|
||||
<bpmn2:childLaneSet xsi:type="bpmn2:tLaneSet" id="LaneSet_2">
|
||||
<bpmn2:lane id="Nested_Lane_A" name="Nested_Lane_A"/>
|
||||
<bpmn2:lane id="Nested_Lane_B" name="Nested_Lane_B"/>
|
||||
</bpmn2:childLaneSet>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="Lane_B" name="Lane_B"/>
|
||||
</bpmn2:laneSet>
|
||||
</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 height="532.0" width="540.0" x="156.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane_A" isHorizontal="true">
|
||||
<dc:Bounds height="361.0" width="510.0" x="186.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane_A" isHorizontal="true">
|
||||
<dc:Bounds height="181.0" width="480.0" x="216.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_5" bpmnElement="Nested_Lane_B" isHorizontal="true">
|
||||
<dc:Bounds height="181.0" width="480.0" x="216.0" y="180.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_6" bpmnElement="Lane_B" isHorizontal="true">
|
||||
<dc:Bounds height="172.0" width="510.0" x="186.0" y="360.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
|
@ -0,0 +1,286 @@
|
|||
'use strict';
|
||||
|
||||
var TestHelper = require('test/TestHelper');
|
||||
|
||||
/* global bootstrapModeler, inject */
|
||||
|
||||
|
||||
var getParticipantSizeConstraints = require('lib/features/snapping/BpmnSnappingUtil').getParticipantSizeConstraints;
|
||||
|
||||
var coreModule = require('lib/core');
|
||||
|
||||
var LANE_MIN_HEIGHT = 60,
|
||||
LANE_RIGHT_PADDING = 20,
|
||||
LANE_LEFT_PADDING = 50,
|
||||
LANE_TOP_PADDING = 20,
|
||||
LANE_BOTTOM_PADDING = 20;
|
||||
|
||||
|
||||
describe('features/snapping - BpmnSnappingUtil', function() {
|
||||
|
||||
describe('#getParticipantSizeConstraints', function() {
|
||||
|
||||
describe('lanes', function() {
|
||||
|
||||
var diagramXML = require('./BpmnSnappingUtil.lanes.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: [ coreModule ] }));
|
||||
|
||||
|
||||
it('resize participant (S)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Participant_Lane'),
|
||||
otherLaneShape = elementRegistry.get('Lane_B');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 's');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
bottom: otherLaneShape.y + LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('bottom lane (S)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Lane_B'),
|
||||
otherLaneShape = elementRegistry.get('Lane_B');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 's');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
bottom: otherLaneShape.y + LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize participant (N)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Participant_Lane'),
|
||||
otherLaneShape = elementRegistry.get('Nested_Lane_A');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'n');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
top: otherLaneShape.y + otherLaneShape.height - LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize top lane (N)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Lane_A'),
|
||||
otherLaneShape = elementRegistry.get('Nested_Lane_A');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'n');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
top: otherLaneShape.y + otherLaneShape.height - LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize middle lane (N)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Nested_Lane_B'),
|
||||
aboveLaneShape = elementRegistry.get('Nested_Lane_A');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'n');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
top: resizeShape.y + resizeShape.height - LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {
|
||||
top: aboveLaneShape.y + LANE_MIN_HEIGHT
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize middle lane (S)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Nested_Lane_B'),
|
||||
otherLaneShape = elementRegistry.get('Lane_B');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 's');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
bottom: resizeShape.y + LANE_MIN_HEIGHT
|
||||
},
|
||||
max: {
|
||||
bottom: otherLaneShape.y + otherLaneShape.height - LANE_MIN_HEIGHT
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('flowNodes', function() {
|
||||
|
||||
var diagramXML = require('./BpmnSnappingUtil.lanes-flowNodes.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: [ coreModule ] }));
|
||||
|
||||
|
||||
it('resize participant (S)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Participant_Lane'),
|
||||
taskShape = elementRegistry.get('Task');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 's');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
bottom: taskShape.y + taskShape.height + LANE_BOTTOM_PADDING
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('bottom lane (S)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Lane_B'),
|
||||
taskShape = elementRegistry.get('Task');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 's');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
bottom: taskShape.y + taskShape.height + LANE_BOTTOM_PADDING
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize participant (N)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Participant_Lane'),
|
||||
taskShape = elementRegistry.get('Task_Boundary');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'n');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
top: taskShape.y - LANE_TOP_PADDING
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize top lane (N)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Lane_A'),
|
||||
taskShape = elementRegistry.get('Task_Boundary');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'n');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
top: taskShape.y - LANE_TOP_PADDING
|
||||
},
|
||||
max: {}
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize lane (W)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Nested_Lane_B'),
|
||||
otherShape = elementRegistry.get('Boundary_label');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'w');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
left: otherShape.x - LANE_LEFT_PADDING
|
||||
},
|
||||
max: { }
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('resize lane (E)', inject(function(elementRegistry) {
|
||||
|
||||
// given
|
||||
var resizeShape = elementRegistry.get('Lane_B'),
|
||||
otherShape = elementRegistry.get('Task');
|
||||
|
||||
// when
|
||||
var sizeConstraints = getParticipantSizeConstraints(resizeShape, 'e');
|
||||
|
||||
// then
|
||||
expect(sizeConstraints).to.eql({
|
||||
min: {
|
||||
right: otherShape.x + otherShape.width + LANE_RIGHT_PADDING
|
||||
},
|
||||
max: { }
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue