mirror of
https://github.com/sartography/bpmn-js.git
synced 2025-02-17 03:16:32 +00:00
chore(bpmn-snapping): move participant fitting to participant behavior
Related to #1290
This commit is contained in:
parent
8862865e2a
commit
ca12ac91a4
@ -4,23 +4,81 @@ import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
||||
|
||||
import { is } from '../../../util/ModelUtil';
|
||||
|
||||
import { isLabel } from '../../../util/LabelUtil';
|
||||
|
||||
import { getBBox } from 'diagram-js/lib/util/Elements';
|
||||
|
||||
import { assign } from 'min-dash';
|
||||
|
||||
var HORIZONTAL_PARTICIPANT_PADDING = 20,
|
||||
VERTICAL_PARTICIPANT_PADDING = 20,
|
||||
PARTICIPANT_BORDER_WIDTH = 30;
|
||||
|
||||
var HIGH_PRIORITY = 2000;
|
||||
|
||||
|
||||
/**
|
||||
* BPMN specific create participant behavior
|
||||
* BPMN-specific behavior for creating participants.
|
||||
*/
|
||||
export default function CreateParticipantBehavior(
|
||||
eventBus, modeling, elementFactory,
|
||||
bpmnFactory, canvas) {
|
||||
|
||||
export default function CreateParticipantBehavior(canvas, eventBus, modeling) {
|
||||
CommandInterceptor.call(this, eventBus);
|
||||
|
||||
/**
|
||||
* morph process into collaboration before adding
|
||||
* participant onto collaboration
|
||||
*/
|
||||
// fit participant
|
||||
eventBus.on([
|
||||
'create.start',
|
||||
'shape.move.start'
|
||||
], HIGH_PRIORITY, function(event) {
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
rootElement = canvas.getRootElement();
|
||||
|
||||
if (!is(shape, 'bpmn:Participant') ||
|
||||
!is(rootElement, 'bpmn:Process') ||
|
||||
!rootElement.children.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore connections, groups and labels
|
||||
var children = rootElement.children.filter(function(element) {
|
||||
return !is(element, 'bpmn:Group') &&
|
||||
!isLabel(element) &&
|
||||
!isConnection(element);
|
||||
});
|
||||
|
||||
var childrenBBox = getBBox(children);
|
||||
|
||||
var participantBounds = getParticipantBounds(shape, childrenBBox);
|
||||
|
||||
// assign width and height
|
||||
assign(shape, participantBounds);
|
||||
|
||||
// assign create constraints
|
||||
context.createConstraints = getParticipantCreateConstraints(shape, childrenBBox);
|
||||
});
|
||||
|
||||
// force hovering process when creating first participant
|
||||
eventBus.on('create.start', HIGH_PRIORITY, function(event) {
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootElementGfx = canvas.getGraphics(rootElement);
|
||||
|
||||
function ensureHoveringProcess(event) {
|
||||
event.element = rootElement;
|
||||
event.gfx = rootElementGfx;
|
||||
}
|
||||
|
||||
if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
|
||||
eventBus.on('element.hover', HIGH_PRIORITY, ensureHoveringProcess);
|
||||
|
||||
eventBus.once('create.cleanup', function() {
|
||||
eventBus.off('element.hover', ensureHoveringProcess);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// turn process into collaboration before adding participant
|
||||
this.preExecute('shape.create', function(context) {
|
||||
|
||||
var parent = context.parent,
|
||||
shape = context.shape,
|
||||
position = context.position;
|
||||
@ -48,9 +106,7 @@ export default function CreateParticipantBehavior(
|
||||
}
|
||||
}, true);
|
||||
|
||||
|
||||
this.execute('shape.create', function(context) {
|
||||
|
||||
var processRoot = context.processRoot,
|
||||
shape = context.shape;
|
||||
|
||||
@ -62,39 +118,63 @@ export default function CreateParticipantBehavior(
|
||||
}
|
||||
}, true);
|
||||
|
||||
|
||||
this.revert('shape.create', function(context) {
|
||||
var processRoot = context.processRoot,
|
||||
shape = context.shape;
|
||||
|
||||
if (processRoot) {
|
||||
|
||||
// assign the participant processRef
|
||||
shape.businessObject.processRef = context.oldProcessRef;
|
||||
}
|
||||
}, true);
|
||||
|
||||
|
||||
this.postExecute('shape.create', function(context) {
|
||||
|
||||
var processRoot = context.processRoot,
|
||||
shape = context.shape;
|
||||
|
||||
if (processRoot) {
|
||||
|
||||
// process root is already detached at this point
|
||||
var processChildren = processRoot.children.slice();
|
||||
|
||||
modeling.moveElements(processChildren, { x: 0, y: 0 }, shape);
|
||||
}
|
||||
|
||||
}, true);
|
||||
|
||||
}
|
||||
|
||||
CreateParticipantBehavior.$inject = [
|
||||
'canvas',
|
||||
'eventBus',
|
||||
'modeling',
|
||||
'elementFactory',
|
||||
'bpmnFactory',
|
||||
'canvas'
|
||||
'modeling'
|
||||
];
|
||||
|
||||
inherits(CreateParticipantBehavior, CommandInterceptor);
|
||||
inherits(CreateParticipantBehavior, CommandInterceptor);
|
||||
|
||||
// helpers //////////
|
||||
|
||||
function getParticipantBounds(shape, childrenBBox) {
|
||||
childrenBBox = {
|
||||
width: childrenBBox.width + HORIZONTAL_PARTICIPANT_PADDING * 2 + PARTICIPANT_BORDER_WIDTH,
|
||||
height: childrenBBox.height + VERTICAL_PARTICIPANT_PADDING * 2
|
||||
};
|
||||
|
||||
return {
|
||||
width: Math.max(shape.width, childrenBBox.width),
|
||||
height: Math.max(shape.height, childrenBBox.height)
|
||||
};
|
||||
}
|
||||
|
||||
function getParticipantCreateConstraints(shape, childrenBBox) {
|
||||
return {
|
||||
bottom: childrenBBox.y + shape.height / 2 - VERTICAL_PARTICIPANT_PADDING,
|
||||
left: childrenBBox.x + childrenBBox.width - shape.width / 2 + HORIZONTAL_PARTICIPANT_PADDING,
|
||||
top: childrenBBox.y + childrenBBox.height - shape.height / 2 + VERTICAL_PARTICIPANT_PADDING,
|
||||
right: childrenBBox.x + shape.width / 2 - HORIZONTAL_PARTICIPANT_PADDING - PARTICIPANT_BORDER_WIDTH
|
||||
};
|
||||
}
|
||||
|
||||
function isConnection(element) {
|
||||
return !!element.waypoints;
|
||||
}
|
@ -5,41 +5,30 @@ import {
|
||||
isNumber
|
||||
} from 'min-dash';
|
||||
|
||||
import {
|
||||
getBBox as getBoundingBox
|
||||
} from 'diagram-js/lib/util/Elements';
|
||||
import Snapping from 'diagram-js/lib/features/snapping/Snapping';
|
||||
|
||||
import { is } from '../../util/ModelUtil';
|
||||
|
||||
import { isAny } from '../modeling/util/ModelingUtil';
|
||||
|
||||
import {
|
||||
isExpanded
|
||||
} from '../../util/DiUtil';
|
||||
|
||||
import Snapping from 'diagram-js/lib/features/snapping/Snapping';
|
||||
import { isExpanded } from '../../util/DiUtil';
|
||||
|
||||
import {
|
||||
mid,
|
||||
topLeft,
|
||||
bottomRight,
|
||||
isSnapped,
|
||||
setSnapped
|
||||
mid,
|
||||
setSnapped,
|
||||
topLeft
|
||||
} from 'diagram-js/lib/features/snapping/SnapUtil';
|
||||
|
||||
import {
|
||||
asTRBL
|
||||
} from 'diagram-js/lib/layout/LayoutUtil';
|
||||
|
||||
import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil';
|
||||
|
||||
import {
|
||||
getBoundaryAttachment,
|
||||
getParticipantSizeConstraints
|
||||
} from './BpmnSnappingUtil';
|
||||
|
||||
import {
|
||||
getLanesRoot
|
||||
} from '../modeling/util/LaneUtil';
|
||||
import { getLanesRoot } from '../modeling/util/LaneUtil';
|
||||
|
||||
var round = Math.round;
|
||||
|
||||
@ -47,59 +36,14 @@ var HIGH_PRIORITY = 1500;
|
||||
|
||||
|
||||
/**
|
||||
* BPMN specific snapping functionality
|
||||
*
|
||||
* * snap on process elements if a pool is created inside a
|
||||
* process diagram
|
||||
* BPMN-specific snapping.
|
||||
*
|
||||
* @param {EventBus} eventBus
|
||||
* @param {Canvas} canvas
|
||||
*/
|
||||
export default function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistry) {
|
||||
|
||||
// instantiate super
|
||||
export default function BpmnSnapping(bpmnRules, canvas, elementRegistry, eventBus) {
|
||||
Snapping.call(this, eventBus, canvas);
|
||||
|
||||
|
||||
/**
|
||||
* Drop participant on process <> process elements snapping
|
||||
*/
|
||||
eventBus.on('create.start', function(event) {
|
||||
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
rootElement = canvas.getRootElement();
|
||||
|
||||
// snap participant around existing elements (if any)
|
||||
if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
|
||||
initParticipantSnapping(context, shape, rootElement.children);
|
||||
}
|
||||
});
|
||||
|
||||
eventBus.on([ 'create.move', 'create.end' ], HIGH_PRIORITY, function(event) {
|
||||
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
participantSnapBox = context.participantSnapBox;
|
||||
|
||||
if (!isSnapped(event) && participantSnapBox) {
|
||||
snapParticipant(participantSnapBox, shape, event);
|
||||
}
|
||||
});
|
||||
|
||||
eventBus.on('shape.move.start', function(event) {
|
||||
|
||||
var context = event.context,
|
||||
shape = context.shape,
|
||||
rootElement = canvas.getRootElement();
|
||||
|
||||
// snap participant around existing elements (if any)
|
||||
if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) {
|
||||
initParticipantSnapping(context, shape, rootElement.children);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function canAttach(shape, target, position) {
|
||||
return bpmnRules.canAttach([ shape ], target, null, position) === 'attach';
|
||||
}
|
||||
@ -108,6 +52,9 @@ export default function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistr
|
||||
return bpmnRules.canConnect(source, target);
|
||||
}
|
||||
|
||||
// creating first participant
|
||||
eventBus.on([ 'create.move', 'create.end' ], HIGH_PRIORITY, setSnappedIfConstrained);
|
||||
|
||||
/**
|
||||
* Snap boundary events to elements border
|
||||
*/
|
||||
@ -233,15 +180,13 @@ export default function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistr
|
||||
inherits(BpmnSnapping, Snapping);
|
||||
|
||||
BpmnSnapping.$inject = [
|
||||
'eventBus',
|
||||
'canvas',
|
||||
'bpmnRules',
|
||||
'elementRegistry'
|
||||
'canvas',
|
||||
'elementRegistry',
|
||||
'eventBus'
|
||||
];
|
||||
|
||||
|
||||
BpmnSnapping.prototype.initSnap = function(event) {
|
||||
|
||||
var context = event.context,
|
||||
shape = event.shape,
|
||||
shapeMid,
|
||||
@ -250,11 +195,11 @@ BpmnSnapping.prototype.initSnap = function(event) {
|
||||
shapeBottomRight,
|
||||
snapContext;
|
||||
|
||||
|
||||
snapContext = Snapping.prototype.initSnap.call(this, event);
|
||||
|
||||
if (is(shape, 'bpmn:Participant')) {
|
||||
// assign higher priority for outer snaps on participants
|
||||
|
||||
// snap to borders with higher priority
|
||||
snapContext.setSnapLocations([ 'top-left', 'bottom-right', 'mid' ]);
|
||||
}
|
||||
|
||||
@ -393,67 +338,7 @@ BpmnSnapping.prototype.addTargetSnaps = function(snapPoints, shape, target) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// participant snapping //////////////////////
|
||||
|
||||
function initParticipantSnapping(context, shape, elements) {
|
||||
|
||||
if (!elements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var snapBox = getBoundingBox(elements.filter(function(e) {
|
||||
return !e.labelTarget && !e.waypoints && !is(e, 'bpmn:Group');
|
||||
}));
|
||||
|
||||
snapBox.x -= 50;
|
||||
snapBox.y -= 20;
|
||||
snapBox.width += 70;
|
||||
snapBox.height += 40;
|
||||
|
||||
// adjust shape height to include bounding box
|
||||
shape.width = Math.max(shape.width, snapBox.width);
|
||||
shape.height = Math.max(shape.height, snapBox.height);
|
||||
|
||||
context.participantSnapBox = snapBox;
|
||||
}
|
||||
|
||||
function snapParticipant(snapBox, shape, event, offset) {
|
||||
offset = offset || 0;
|
||||
|
||||
var shapeHalfWidth = shape.width / 2 - offset,
|
||||
shapeHalfHeight = shape.height / 2;
|
||||
|
||||
var currentTopLeft = {
|
||||
x: event.x - shapeHalfWidth - offset,
|
||||
y: event.y - shapeHalfHeight
|
||||
};
|
||||
|
||||
var currentBottomRight = {
|
||||
x: event.x + shapeHalfWidth + offset,
|
||||
y: event.y + shapeHalfHeight
|
||||
};
|
||||
|
||||
var snapTopLeft = snapBox,
|
||||
snapBottomRight = bottomRight(snapBox);
|
||||
|
||||
if (currentTopLeft.x >= snapTopLeft.x) {
|
||||
setSnapped(event, 'x', snapTopLeft.x + offset + shapeHalfWidth);
|
||||
} else
|
||||
if (currentBottomRight.x <= snapBottomRight.x) {
|
||||
setSnapped(event, 'x', snapBottomRight.x - offset - shapeHalfWidth);
|
||||
}
|
||||
|
||||
if (currentTopLeft.y >= snapTopLeft.y) {
|
||||
setSnapped(event, 'y', snapTopLeft.y + shapeHalfHeight);
|
||||
} else
|
||||
if (currentBottomRight.y <= snapBottomRight.y) {
|
||||
setSnapped(event, 'y', snapBottomRight.y - shapeHalfHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// boundary event snapping //////////////////////
|
||||
// helpers //////////
|
||||
|
||||
function snapBoundaryEvent(event, shape, target) {
|
||||
var targetTRBL = asTRBL(target);
|
||||
@ -479,4 +364,26 @@ function snapBoundaryEvent(event, shape, target) {
|
||||
function snapToPosition(event, position) {
|
||||
setSnapped(event, 'x', position.x);
|
||||
setSnapped(event, 'y', position.y);
|
||||
}
|
||||
|
||||
function setSnappedIfConstrained(event) {
|
||||
var context = event.context,
|
||||
createConstraints = context.createConstraints;
|
||||
|
||||
if (!createConstraints) {
|
||||
return;
|
||||
}
|
||||
|
||||
var top = createConstraints.top,
|
||||
right = createConstraints.right,
|
||||
bottom = createConstraints.bottom,
|
||||
left = createConstraints.left;
|
||||
|
||||
if ((left && left >= event.x) || (right && right <= event.x)) {
|
||||
setSnapped(event, 'x', event.x);
|
||||
}
|
||||
|
||||
if ((top && top >= event.y) || (bottom && bottom <= event.y)) {
|
||||
setSnapped(event, 'y', event.y);
|
||||
}
|
||||
}
|
@ -153,5 +153,5 @@ export function getExternalLabelBounds(semantic, element) {
|
||||
}
|
||||
|
||||
export function isLabel(element) {
|
||||
return element && element.labelTarget;
|
||||
return element && !!element.labelTarget;
|
||||
}
|
||||
|
@ -3,220 +3,394 @@ import {
|
||||
inject
|
||||
} from 'test/TestHelper';
|
||||
|
||||
import modelingModule from 'lib/features/modeling';
|
||||
import coreModule from 'lib/core';
|
||||
import createModule from 'diagram-js/lib/features/create';
|
||||
import modelingModule from 'lib/features/modeling';
|
||||
|
||||
import {
|
||||
getBBox
|
||||
} from 'diagram-js/lib/util/Elements';
|
||||
|
||||
import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil';
|
||||
|
||||
import {
|
||||
createCanvasEvent as canvasEvent
|
||||
} from '../../../../util/MockEvents';
|
||||
|
||||
|
||||
describe('features/modeling - create participant', function() {
|
||||
|
||||
var testModules = [ coreModule, modelingModule ];
|
||||
var testModules = [
|
||||
coreModule,
|
||||
createModule,
|
||||
modelingModule
|
||||
];
|
||||
|
||||
describe('process', function() {
|
||||
|
||||
describe('on process diagram', function() {
|
||||
|
||||
describe('should transform diagram into collaboration', function() {
|
||||
describe('should turn diagram into collaboration', function() {
|
||||
|
||||
var processDiagramXML = require('../../../../fixtures/bpmn/collaboration/process-empty.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
|
||||
|
||||
var collaboration,
|
||||
collaborationBo,
|
||||
collaborationDi,
|
||||
diRoot,
|
||||
participant,
|
||||
participantBo,
|
||||
participantDi,
|
||||
process,
|
||||
processBo,
|
||||
processDi;
|
||||
|
||||
it('execute', inject(function(modeling, elementFactory, canvas) {
|
||||
beforeEach(inject(function(canvas, elementFactory, modeling) {
|
||||
|
||||
// given
|
||||
var processShape = canvas.getRootElement(),
|
||||
process = processShape.businessObject,
|
||||
participantShape = elementFactory.createParticipantShape(true),
|
||||
participant = participantShape.businessObject,
|
||||
diRoot = process.di.$parent;
|
||||
process = canvas.getRootElement();
|
||||
processBo = process.businessObject;
|
||||
processDi = processBo.di;
|
||||
|
||||
diRoot = processBo.di.$parent;
|
||||
|
||||
participant = elementFactory.createParticipantShape();
|
||||
participantBo = participant.businessObject;
|
||||
participantDi = participantBo.di;
|
||||
|
||||
// when
|
||||
modeling.createShape(participantShape, { x: 350, y: 200 }, processShape);
|
||||
modeling.createShape(participant, { x: 350, y: 200 }, process);
|
||||
|
||||
// then
|
||||
expect(participant.processRef).to.eql(process);
|
||||
|
||||
var collaborationRoot = canvas.getRootElement(),
|
||||
collaboration = collaborationRoot.businessObject,
|
||||
collaborationDi = collaboration.di;
|
||||
|
||||
expect(collaboration.$instanceOf('bpmn:Collaboration')).to.be.true;
|
||||
|
||||
// participant / collaboration are wired
|
||||
expect(participant.$parent).to.eql(collaboration);
|
||||
expect(collaboration.participants).to.include(participant);
|
||||
|
||||
|
||||
// collaboration is added to root elements
|
||||
expect(collaboration.$parent).to.eql(process.$parent);
|
||||
|
||||
// di is wired
|
||||
var participantDi = participant.di;
|
||||
|
||||
expect(participantDi.$parent).to.eql(collaborationDi);
|
||||
expect(collaborationDi.$parent).to.eql(diRoot);
|
||||
collaboration = canvas.getRootElement();
|
||||
collaborationBo = collaboration.businessObject;
|
||||
collaborationDi = collaborationBo.di;
|
||||
}));
|
||||
|
||||
|
||||
it('undo', inject(function(modeling, elementFactory, canvas, commandStack) {
|
||||
it('execute', function() {
|
||||
|
||||
// given
|
||||
var processShape = canvas.getRootElement(),
|
||||
process = processShape.businessObject,
|
||||
processDi = process.di,
|
||||
participantShape = elementFactory.createParticipantShape(true),
|
||||
participant = participantShape.businessObject,
|
||||
oldParticipantProcessRef = participant.processRef,
|
||||
diRoot = process.di.$parent;
|
||||
// then
|
||||
expect(participantBo.$parent).to.equal(collaborationBo);
|
||||
expect(participantBo.processRef).to.equal(processBo);
|
||||
|
||||
modeling.createShape(participantShape, { x: 350, y: 200 }, processShape);
|
||||
expect(collaborationBo.$instanceOf('bpmn:Collaboration')).to.be.true;
|
||||
expect(collaborationBo.$parent).to.equal(processBo.$parent);
|
||||
expect(collaborationBo.participants).to.include(participantBo);
|
||||
|
||||
var collaborationRoot = canvas.getRootElement(),
|
||||
collaboration = collaborationRoot.businessObject;
|
||||
expect(participantDi.$parent).to.equal(collaborationDi);
|
||||
expect(collaborationDi.$parent).to.equal(diRoot);
|
||||
});
|
||||
|
||||
|
||||
it('undo', inject(function(commandStack) {
|
||||
|
||||
// when
|
||||
commandStack.undo();
|
||||
|
||||
|
||||
// then
|
||||
expect(participant.processRef).to.eql(oldParticipantProcessRef);
|
||||
expect(participantBo.$parent).not.to.exist;
|
||||
expect(participantBo.processRef).not.to.equal(processBo);
|
||||
|
||||
expect(participant.$parent).to.be.null;
|
||||
expect(collaboration.participants).not.to.include(participant);
|
||||
expect(collaborationBo.$parent).not.to.exist;
|
||||
expect(collaborationBo.participants).not.to.include(participantBo);
|
||||
|
||||
// collaboration is detached
|
||||
expect(collaboration.$parent).to.be.null;
|
||||
|
||||
// di is wired
|
||||
expect(processDi.$parent).to.eql(diRoot);
|
||||
expect(processDi.$parent).to.equal(diRoot);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('should wrap existing elements', function() {
|
||||
describe('should move existing elements', function() {
|
||||
|
||||
var processDiagramXML = require('../../../../fixtures/bpmn/collaboration/process.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
|
||||
|
||||
var collaboration,
|
||||
collaborationBo,
|
||||
collaborationDi,
|
||||
participant,
|
||||
process,
|
||||
processBo,
|
||||
processDi;
|
||||
|
||||
it('execute', inject(function(modeling, elementFactory, canvas) {
|
||||
beforeEach(inject(function(canvas, elementFactory, modeling) {
|
||||
|
||||
// given
|
||||
var processShape = canvas.getRootElement(),
|
||||
process = processShape.businessObject,
|
||||
participantShape = elementFactory.createParticipantShape(true),
|
||||
participant = participantShape.businessObject;
|
||||
process = canvas.getRootElement();
|
||||
processBo = process.businessObject;
|
||||
processDi = processBo.di;
|
||||
|
||||
participant = elementFactory.createParticipantShape();
|
||||
|
||||
// when
|
||||
modeling.createShape(participantShape, { x: 350, y: 200 }, processShape);
|
||||
modeling.createShape(participant, { x: 350, y: 200 }, process);
|
||||
|
||||
// then
|
||||
expect(participant.processRef).to.eql(process);
|
||||
|
||||
var newRootShape = canvas.getRootElement(),
|
||||
collaboration = newRootShape.businessObject;
|
||||
|
||||
expect(collaboration.$instanceOf('bpmn:Collaboration')).to.be.true;
|
||||
|
||||
expect(participant.$parent).to.eql(collaboration);
|
||||
expect(collaboration.participants).to.include(participant);
|
||||
collaboration = canvas.getRootElement();
|
||||
collaborationBo = collaboration.businessObject;
|
||||
collaborationDi = collaborationBo.di;
|
||||
}));
|
||||
|
||||
|
||||
it('undo', inject(function(modeling, elementFactory, elementRegistry, canvas, commandStack) {
|
||||
it('execute', function() {
|
||||
|
||||
// given
|
||||
var processShape = canvas.getRootElement(),
|
||||
participantShape = elementFactory.createParticipantShape(true);
|
||||
// then
|
||||
expect(collaboration.children).to.have.length(4);
|
||||
|
||||
modeling.createShape(participantShape, { x: 350, y: 200 }, processShape);
|
||||
collaboration.children.forEach(function(child) {
|
||||
var childBo = child.businessObject,
|
||||
childDi = childBo.di;
|
||||
|
||||
expect(childDi.$parent).to.eql(collaborationDi);
|
||||
expect(collaborationDi.planeElement).to.include(childDi);
|
||||
});
|
||||
|
||||
expect(participant.children).to.have.length(5);
|
||||
|
||||
participant.children.forEach(function(child) {
|
||||
var childBo = child.businessObject,
|
||||
childDi = childBo.di;
|
||||
|
||||
expect(childDi.$parent).to.eql(collaborationDi);
|
||||
expect(collaborationDi.planeElement).to.include(childDi);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('undo', inject(function(commandStack) {
|
||||
|
||||
// when
|
||||
commandStack.undo();
|
||||
|
||||
var startEventElement = elementRegistry.get('StartEvent_1'),
|
||||
startEventDi = startEventElement.businessObject.di,
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootShapeDi = rootElement.businessObject.di;
|
||||
expect(process.children).to.have.length(8);
|
||||
|
||||
// then
|
||||
expect(participantShape.children.length).to.equal(0);
|
||||
expect(processShape.children.length).to.equal(8);
|
||||
process.children.forEach(function(child) {
|
||||
var childBo = child.businessObject,
|
||||
childDi = childBo.di;
|
||||
|
||||
// children di is wired
|
||||
expect(startEventDi.$parent).to.eql(rootShapeDi);
|
||||
expect(rootShapeDi.planeElement).to.include(startEventDi);
|
||||
expect(childDi.$parent).to.eql(processDi);
|
||||
expect(processDi.planeElement).to.include(childDi);
|
||||
});
|
||||
|
||||
expect(participant.children.length).to.equal(0);
|
||||
}));
|
||||
|
||||
|
||||
it('should detach DI on update canvas root', inject(
|
||||
function(canvas, elementFactory, commandStack, modeling, elementRegistry) {
|
||||
it('should detach DI when turning process into collaboration', inject(function(modeling) {
|
||||
|
||||
// when
|
||||
modeling.makeCollaboration();
|
||||
// when
|
||||
modeling.makeCollaboration();
|
||||
|
||||
var startEventElement = elementRegistry.get('StartEvent_1'),
|
||||
startEventDi = startEventElement.businessObject.di,
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootShapeDi = rootElement.businessObject.di;
|
||||
// then
|
||||
process.children.forEach(function(child) {
|
||||
var childBo = child.businessObject,
|
||||
childDi = childBo.di;
|
||||
|
||||
// then
|
||||
expect(startEventDi.$parent).not.to.be.ok;
|
||||
expect(rootShapeDi.planeElement).not.to.include(startEventDi);
|
||||
expect(childDi.$parent).not.to.exist;
|
||||
expect(processDi.planeElement).not.to.include(childDi);
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('hovering process when creating first participant', function() {
|
||||
|
||||
var processDiagramXML = require('../../../../fixtures/bpmn/collaboration/process.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
|
||||
|
||||
var participant,
|
||||
process,
|
||||
processGfx,
|
||||
subProcess,
|
||||
subProcessGfx;
|
||||
|
||||
beforeEach(inject(function(canvas, elementFactory, elementRegistry) {
|
||||
|
||||
// given
|
||||
process = canvas.getRootElement();
|
||||
processGfx = canvas.getGraphics(process);
|
||||
|
||||
participant = elementFactory.createParticipantShape();
|
||||
|
||||
subProcess = elementRegistry.get('SubProcess_1');
|
||||
subProcessGfx = canvas.getGraphics(subProcess);
|
||||
}));
|
||||
|
||||
|
||||
it('should ensure hovering process', inject(function(create, dragging, eventBus) {
|
||||
|
||||
// given
|
||||
create.start(canvasEvent({ x: 100, y: 100 }), participant);
|
||||
|
||||
var event = eventBus.createEvent({
|
||||
element: subProcess,
|
||||
gfx: subProcessGfx
|
||||
});
|
||||
|
||||
// when
|
||||
eventBus.fire('element.hover', event);
|
||||
|
||||
// then
|
||||
expect(event.element).to.equal(process);
|
||||
expect(event.gfx).to.equal(processGfx);
|
||||
}));
|
||||
|
||||
|
||||
it('should clean up', inject(function(create, dragging, eventBus) {
|
||||
|
||||
// given
|
||||
create.start(canvasEvent({ x: 100, y: 100 }), participant);
|
||||
|
||||
// when
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
var event = eventBus.createEvent({
|
||||
element: subProcess,
|
||||
gfx: subProcessGfx
|
||||
});
|
||||
|
||||
eventBus.fire('element.hover', event);
|
||||
|
||||
expect(event.element).to.equal(subProcess);
|
||||
expect(event.gfx).to.equal(subProcessGfx);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('fitting participant (default size)', function() {
|
||||
|
||||
var processDiagramXML = require('../../../../fixtures/bpmn/collaboration/process.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
|
||||
|
||||
var participant,
|
||||
participantBo,
|
||||
process,
|
||||
processGfx;
|
||||
|
||||
beforeEach(inject(function(canvas, create, dragging, elementFactory) {
|
||||
|
||||
// given
|
||||
process = canvas.getRootElement();
|
||||
processGfx = canvas.getGraphics(process);
|
||||
|
||||
participant = elementFactory.createParticipantShape();
|
||||
participantBo = participant.businessObject;
|
||||
|
||||
create.start(canvasEvent({ x: 100, y: 100 }), participant);
|
||||
|
||||
dragging.hover({ element: process, gfx: processGfx });
|
||||
}));
|
||||
|
||||
|
||||
it('should fit participant', inject(function(elementFactory) {
|
||||
|
||||
// then
|
||||
var defaultSize = elementFactory._getDefaultSize(participantBo);
|
||||
|
||||
expect(participant.width).to.equal(defaultSize.width);
|
||||
expect(participant.height).to.equal(defaultSize.height);
|
||||
}));
|
||||
|
||||
|
||||
describe('create constraints', function() {
|
||||
|
||||
function expectBoundsWithin(inner, outer, padding) {
|
||||
expect(inner.top >= outer.top + padding.top).to.be.true;
|
||||
expect(inner.right <= outer.right - padding.right).to.be.true;
|
||||
expect(inner.bottom <= outer.bottom - padding.bottom).to.be.true;
|
||||
expect(inner.left >= outer.left + padding.left).to.be.true;
|
||||
}
|
||||
));
|
||||
|
||||
var padding = {
|
||||
top: 20,
|
||||
right: 20,
|
||||
bottom: 20,
|
||||
left: 50
|
||||
};
|
||||
|
||||
|
||||
[
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1000, y: 0 },
|
||||
{ x: 0, y: 1000 },
|
||||
{ x: 1000, y: 1000 }
|
||||
].forEach(function(position) {
|
||||
|
||||
it('should constrain ' + JSON.stringify(position), inject(function(dragging) {
|
||||
|
||||
// when
|
||||
dragging.move(canvasEvent(position));
|
||||
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
expectBoundsWithin(
|
||||
asTRBL(getBBox(participant.children)),
|
||||
asTRBL(getBBox(participant)),
|
||||
padding
|
||||
);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('should add to collaboration', function() {
|
||||
describe('collaboration', function() {
|
||||
|
||||
var collaborationDiagramXML = require('../../../../fixtures/bpmn/collaboration/collaboration-participant.bpmn');
|
||||
var collaborationDiagramXML =
|
||||
require('../../../../fixtures/bpmn/collaboration/collaboration-participant.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(collaborationDiagramXML, { modules: testModules }));
|
||||
|
||||
var collaborationBo,
|
||||
participant,
|
||||
participantBo,
|
||||
rootElement;
|
||||
|
||||
it('execute', inject(function(modeling, elementFactory, canvas) {
|
||||
beforeEach(inject(function(canvas, elementFactory, modeling) {
|
||||
|
||||
// given
|
||||
var collaborationRoot = canvas.getRootElement(),
|
||||
collaboration = collaborationRoot.businessObject,
|
||||
participantShape = elementFactory.createParticipantShape(true),
|
||||
participant = participantShape.businessObject;
|
||||
rootElement = canvas.getRootElement();
|
||||
collaborationBo = rootElement.businessObject;
|
||||
|
||||
participant = elementFactory.createParticipantShape();
|
||||
participantBo = participant.businessObject;
|
||||
|
||||
// when
|
||||
modeling.createShape(participantShape, { x: 350, y: 500 }, collaborationRoot);
|
||||
|
||||
// then
|
||||
expect(collaborationRoot.children).to.include(participantShape);
|
||||
|
||||
expect(participant.$parent).to.eql(collaboration);
|
||||
expect(collaboration.participants).to.include(participant);
|
||||
modeling.createShape(participant, { x: 350, y: 500 }, rootElement);
|
||||
}));
|
||||
|
||||
|
||||
it('undo', inject(function(modeling, elementFactory, canvas, commandStack) {
|
||||
it('execute', function() {
|
||||
|
||||
// given
|
||||
var collaborationRoot = canvas.getRootElement(),
|
||||
collaboration = collaborationRoot.businessObject,
|
||||
participantShape = elementFactory.createParticipantShape(true),
|
||||
participant = participantShape.businessObject;
|
||||
// then
|
||||
expect(rootElement.children).to.include(participant);
|
||||
|
||||
modeling.createShape(participantShape, { x: 350, y: 500 }, collaborationRoot);
|
||||
expect(participantBo.$parent).to.equal(collaborationBo);
|
||||
expect(collaborationBo.participants).to.include(participantBo);
|
||||
});
|
||||
|
||||
|
||||
it('undo', inject(function(commandStack) {
|
||||
|
||||
// when
|
||||
commandStack.undo();
|
||||
|
||||
// then
|
||||
expect(collaborationRoot.children).not.to.include(participantShape);
|
||||
expect(rootElement.children).not.to.include(participant);
|
||||
|
||||
expect(participant.$parent).not.to.be.ok;
|
||||
expect(collaboration.participants).not.to.include(participant);
|
||||
expect(participantBo.$parent).not.to.exist;
|
||||
expect(collaborationBo.participants).not.to.include(participantBo);
|
||||
}));
|
||||
|
||||
});
|
||||
|
@ -3,6 +3,8 @@ import {
|
||||
inject
|
||||
} from 'test/TestHelper';
|
||||
|
||||
import TestContainer from 'mocha-test-container-support';
|
||||
|
||||
import {
|
||||
createCanvasEvent as canvasEvent
|
||||
} from '../../../util/MockEvents';
|
||||
@ -16,6 +18,8 @@ import moveModule from 'diagram-js/lib/features/move';
|
||||
import rulesModule from 'lib/features/rules';
|
||||
import connectModule from 'diagram-js/lib/features/connect';
|
||||
|
||||
import { isSnapped } from 'diagram-js/lib/features/snapping/SnapUtil';
|
||||
|
||||
|
||||
describe('features/snapping - BpmnSnapping', function() {
|
||||
|
||||
@ -29,7 +33,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
||||
connectModule
|
||||
];
|
||||
|
||||
describe('general', function() {
|
||||
describe('on itself', function() {
|
||||
|
||||
var diagramXML = require('./BpmnSnapping.general.bpmn');
|
||||
|
||||
@ -75,6 +79,7 @@ describe('features/snapping - BpmnSnapping', function() {
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('on Boundary Events', function() {
|
||||
|
||||
var diagramXML = require('../../../fixtures/bpmn/collaboration/process.bpmn');
|
||||
@ -304,89 +309,43 @@ describe('features/snapping - BpmnSnapping', function() {
|
||||
|
||||
var diagramXML = require('../../../fixtures/bpmn/collaboration/process.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, {
|
||||
modules: testModules
|
||||
}));
|
||||
it('should set snapped if outside of constraints', function(done) {
|
||||
|
||||
beforeEach(inject(function(dragging) {
|
||||
dragging.setOptions({ manual: true });
|
||||
}));
|
||||
|
||||
|
||||
it('should snap to process children bounds / top left',
|
||||
inject(function(canvas, create, dragging, elementFactory) {
|
||||
|
||||
// given
|
||||
var participantShape = elementFactory.createParticipantShape(false),
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootGfx = canvas.getGraphics(rootElement);
|
||||
bootstrapModeler(diagramXML, {
|
||||
container: TestContainer.get(this),
|
||||
modules: testModules
|
||||
})(function() {
|
||||
|
||||
// when
|
||||
create.start(canvasEvent({ x: 50, y: 50 }), participantShape);
|
||||
inject(function(canvas, create, dragging, elementFactory, eventBus) {
|
||||
|
||||
dragging.hover({ element: rootElement, gfx: rootGfx });
|
||||
// given
|
||||
dragging.setOptions({ manual: true });
|
||||
|
||||
dragging.move(canvasEvent({ x: 65, y: 65 }));
|
||||
dragging.end(canvasEvent({ x: 65, y: 65 }));
|
||||
var participantShape = elementFactory.createParticipantShape(false),
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootGfx = canvas.getGraphics(rootElement);
|
||||
|
||||
// then
|
||||
expect(participantShape).to.have.bounds({
|
||||
width: 600, height: 250, x: 18, y: -8
|
||||
});
|
||||
})
|
||||
);
|
||||
create.start(canvasEvent({ x: 50, y: 50 }), participantShape);
|
||||
|
||||
dragging.hover({ element: rootElement, gfx: rootGfx });
|
||||
|
||||
it('should not snap to group bounds',
|
||||
inject(function(canvas, create, dragging, elementFactory, elementRegistry) {
|
||||
eventBus.once('create.move', function(event) {
|
||||
|
||||
// given
|
||||
var participantShape = elementFactory.createParticipantShape(false),
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootGfx = canvas.getGraphics(rootElement),
|
||||
groupElement = elementRegistry.get('Group_1');
|
||||
// then
|
||||
// expect snapped to avoid snapping outside of constraints
|
||||
expect(isSnapped(event)).to.be.true;
|
||||
|
||||
// when
|
||||
create.start(canvasEvent({ x: 50, y: 50 }), participantShape);
|
||||
done();
|
||||
});
|
||||
|
||||
dragging.hover({ element: rootElement, gfx: rootGfx });
|
||||
// when
|
||||
dragging.move(canvasEvent({ x: 0, y: 0 }));
|
||||
})();
|
||||
|
||||
dragging.move(canvasEvent({ x: 400, y: 400 }));
|
||||
dragging.end(canvasEvent({ x: 400, y: 400 }));
|
||||
});
|
||||
|
||||
// then
|
||||
var totalWidth = groupElement.x + groupElement.width + 70,
|
||||
totalHeight = groupElement.y + groupElement.height + 40;
|
||||
|
||||
expect(participantShape).not.to.have.bounds({
|
||||
width: totalWidth, height: totalHeight, x: 100, y: 52
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should snap to process children bounds / bottom right',
|
||||
inject(function(canvas, create, dragging, elementFactory) {
|
||||
|
||||
// given
|
||||
var participantShape = elementFactory.createParticipantShape(false),
|
||||
rootElement = canvas.getRootElement(),
|
||||
rootGfx = canvas.getGraphics(rootElement);
|
||||
|
||||
// when
|
||||
create.start(canvasEvent({ x: 50, y: 50 }), participantShape);
|
||||
|
||||
dragging.hover({ element: rootElement, gfx: rootGfx });
|
||||
|
||||
dragging.move(canvasEvent({ x: 400, y: 400 }));
|
||||
dragging.end(canvasEvent({ x: 400, y: 400 }));
|
||||
|
||||
// then
|
||||
expect(participantShape).to.have.bounds({
|
||||
width: 600, height: 250, x: 100, y: 52
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -1188,4 +1147,4 @@ describe('features/snapping - BpmnSnapping', function() {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user