Skip to content

Commit

Permalink
feat(snapping): add TRBL snapping against containers
Browse files Browse the repository at this point in the history
Adds TRBL snapping with containers only.

Closes #1104
  • Loading branch information
nikku authored and merge-me[bot] committed Jun 27, 2019
1 parent 92bdcb8 commit 3b42519
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 11 deletions.
33 changes: 33 additions & 0 deletions lib/features/snapping/BpmnCreateMoveSnapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import CreateMoveSnapping from 'diagram-js/lib/features/snapping/CreateMoveSnapp
import {
isSnapped,
setSnapped,
topLeft,
bottomRight
} from 'diagram-js/lib/features/snapping/SnapUtil';

import {
isExpanded
} from '../../util/DiUtil';

import { is } from '../../util/ModelUtil';

import {
Expand Down Expand Up @@ -105,6 +111,18 @@ BpmnCreateMoveSnapping.prototype.addSnapTargetPoints = function(snapPoints, shap

var snapTargets = this.getSnapTargets(shape, target);

forEach(snapTargets, function(snapTarget) {

// handle TRBL alignment
//
// * with container elements
// * with text annotations
if (isContainer(snapTarget) || areAll([ shape, snapTarget ], 'bpmn:TextAnnotation')) {
snapPoints.add('top-left', topLeft(snapTarget));
snapPoints.add('bottom-right', bottomRight(snapTarget));
}
});

// snap to docking points
forEach(shape.incoming, function(connection) {

Expand Down Expand Up @@ -168,6 +186,21 @@ function snapBoundaryEvent(event, target) {
}
}

function areAll(elements, type) {
return elements.every(function(el) {
return is(el, type);
});
}

function isContainer(element) {
if (is(element, 'bpmn:SubProcess') && isExpanded(element)) {
return true;
}

return is(element, 'bpmn:Participant');
}


function setSnappedIfConstrained(event) {
var context = event.context,
createConstraints = context.createConstraints;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="sid-38422fae-e03e-43a3-bef4-bd33b32041b2" targetNamespace="http://bpmn.io/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="4.0.0-beta.6">
<collaboration id="Collaboration_0802rol">
<participant id="PARTICIPANT_1" name="PARTICIPANT_1" processRef="Process_1" />
<participant id="PARTICIPANT_2" name="PARTICIPANT_2" processRef="Process_2" />
<textAnnotation id="TEXT_1">
<text>TEXT_1</text>
</textAnnotation>
<textAnnotation id="TEXT_2">
<text>TEXT_2</text>
</textAnnotation>
</collaboration>
<process id="Process_1" isExecutable="false">
<subProcess id="SUB_PROCESS_1" name="SUB_PROCESS_1">
<startEvent id="START_EVENT" />
</subProcess>
<task id="TASK" name="TASK" />
</process>
<process id="Process_2" />
<bpmndi:BPMNDiagram id="BpmnDiagram_1">
<bpmndi:BPMNPlane id="BpmnPlane_1" bpmnElement="Collaboration_0802rol">
<bpmndi:BPMNShape id="PARTICIPANT_1_di" bpmnElement="PARTICIPANT_1" isHorizontal="true">
<omgdc:Bounds x="160" y="70" width="630" height="340" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="SUB_PROCESS_1_di" bpmnElement="SUB_PROCESS_1" isExpanded="true">
<omgdc:Bounds x="250" y="180" width="350" height="200" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="START_EVENT_di" bpmnElement="START_EVENT">
<omgdc:Bounds x="290.3333333333333" y="262" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="PARTICIPANT_2_di" bpmnElement="PARTICIPANT_2" isHorizontal="true">
<omgdc:Bounds x="270" y="470" width="480" height="220" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="TEXT_1_di" bpmnElement="TEXT_1">
<omgdc:Bounds x="840" y="40" width="100" height="30" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="TASK_di" bpmnElement="TASK">
<omgdc:Bounds x="650" y="220" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="TEXT_2_di" bpmnElement="TEXT_2">
<omgdc:Bounds x="810" y="150" width="190" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
133 changes: 122 additions & 11 deletions test/spec/features/snapping/BpmnCreateMoveSnappingSpec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
bootstrapModeler,
getBpmnJS,
inject
} from 'test/TestHelper';

Expand Down Expand Up @@ -32,7 +33,12 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
modelingModule,
moveModule,
rulesModule,
snappingModule
snappingModule,
{
__init__: [ function(dragging) {
dragging.setOptions({ manual: true });
} ]
}
];


Expand Down Expand Up @@ -160,8 +166,6 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
create.start(canvasEvent({ x: 0, y: 0 }), intermediateThrowEvent);

dragging.hover({ element: task, gfx: taskGfx });

dragging.setOptions({ manual: false });
}));


Expand Down Expand Up @@ -251,8 +255,6 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
var process = elementRegistry.get('Process_1'),
processGfx = elementRegistry.getGraphics(process);

dragging.setOptions({ manual: true });

move.start(canvasEventTopLeft({ x: 100, y: 400 }, task), task, true);

dragging.hover({ element: process, gfx: processGfx });
Expand Down Expand Up @@ -303,8 +305,6 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
create.start(canvasEvent({ x: 0, y: 0 }), task);

dragging.hover({ element: sequenceFlow, gfx: sequenceFlowGfx });

dragging.setOptions({ manual: false });
}));


Expand Down Expand Up @@ -340,8 +340,6 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
beforeEach(inject(function(dragging, elementRegistry, move) {
task = elementRegistry.get('Task_1');

dragging.setOptions({ manual: false });

move.start(canvasEvent({ x: 200, y: 165 }), task);
}));

Expand Down Expand Up @@ -380,8 +378,6 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {
beforeEach(inject(function(dragging, elementRegistry, move) {
participant = elementRegistry.get('Participant_2');
participantGfx = elementRegistry.getGraphics(participant);

dragging.setOptions({ manual: true });
}));


Expand Down Expand Up @@ -438,6 +434,121 @@ describe('features/snapping - BpmnCreateMoveSnapping', function() {

});


describe('TRBL snapping', function() {

var diagramXML = require('./BpmnCreateMoveSnapping.trbl-snapping.bpmn');

beforeEach(bootstrapModeler(diagramXML, {
modules: testModules
}));


function get(element) {
return getBpmnJS().invoke(function(elementRegistry) {
return elementRegistry.get(element);
});
}

function absoluteMove(element, toPosition) {

getBpmnJS().invoke(function(elementRegistry, move, dragging, canvas) {

var parent = element.parent;

move.start(canvasEvent({ x: 0, y: 0 }), element);

dragging.hover({
element: parent,
gfx: canvas.getGraphics(parent)
});

dragging.move(canvasEvent({ x: 100, y: 100 }), element);

dragging.move(canvasEvent({
x: toPosition.x - element.x,
y: toPosition.y - element.y
}));

dragging.end();
});

}


it('should snap text annotations', function() {

// given
var annotation = get('TEXT_1');
var otherAnnotation = get('TEXT_2');

// when
absoluteMove(annotation, {
x: otherAnnotation.x + 5,
y: otherAnnotation.y - 5
});

// then
expect(annotation).to.have.position(otherAnnotation);
});


it('should snap task to container', function() {

// given
var task = get('TASK');
var subProcess = get('SUB_PROCESS_1');

// when
absoluteMove(task, {
x: subProcess.x,
y: subProcess.y - 5
});

// then
expect(task).to.have.position(subProcess);
});


it('should snap container to container', function() {

// given
var participant = get('PARTICIPANT_1');
var otherParticipant = get('PARTICIPANT_2');

// when
absoluteMove(participant, {
x: otherParticipant.x + 5,
y: otherParticipant.y
});

// then
expect(participant).to.have.position(otherParticipant);
});


it('should snap container to container right', function() {

// given
var participant = get('PARTICIPANT_1');
var otherParticipant = get('PARTICIPANT_2');

// when
absoluteMove(participant, {
x: otherParticipant.x + otherParticipant.width - participant.width + 5,
y: 5
});

// then
expect(participant).to.have.position({
x: otherParticipant.x + otherParticipant.width - participant.width,
y: 5
});

});

});

});

// helpers //////////
Expand Down

0 comments on commit 3b42519

Please sign in to comment.