fix(snapping): snap sequence flows mid -> mid
With the latest version of bpmn-js it is possible to draw point top point connections between elements. This restores the mid -> mid connection snapping for sequence flows. Closes #588
This commit is contained in:
parent
28f7145b32
commit
7fdd9bc611
|
@ -2,7 +2,11 @@
|
|||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var forEach = require('lodash/collection/forEach');
|
||||
var abs = Math.abs;
|
||||
|
||||
var forEach = require('lodash/collection/forEach'),
|
||||
filter = require('lodash/collection/filter'),
|
||||
assign = require('lodash/object/assign');
|
||||
|
||||
var getBoundingBox = require('diagram-js/lib/util/Elements').getBBox;
|
||||
|
||||
|
@ -88,6 +92,10 @@ function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistry) {
|
|||
return bpmnRules.canAttach([ shape ], target, null, position) === 'attach';
|
||||
}
|
||||
|
||||
function canConnect(source, target) {
|
||||
return bpmnRules.canConnect(source, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Snap boundary events to elements border
|
||||
*/
|
||||
|
@ -129,11 +137,38 @@ function BpmnSnapping(eventBus, canvas, bpmnRules, elementRegistry) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Snap sequence flows.
|
||||
*/
|
||||
eventBus.on([
|
||||
'connect.move',
|
||||
'connect.hover',
|
||||
'connect.end'
|
||||
], HIGH_PRIORITY, function(event) {
|
||||
var context = event.context,
|
||||
source = context.source,
|
||||
target = context.target;
|
||||
|
||||
var abs = Math.abs;
|
||||
var connection = canConnect(source, target) || {};
|
||||
|
||||
var filter = require('lodash/collection/filter'),
|
||||
assign = require('lodash/object/assign');
|
||||
if (!context.initialSourcePosition) {
|
||||
context.initialSourcePosition = context.sourcePosition;
|
||||
}
|
||||
|
||||
if (target && connection.type === 'bpmn:SequenceFlow') {
|
||||
|
||||
// snap source
|
||||
context.sourcePosition = mid(source);
|
||||
|
||||
// snap target
|
||||
assign(event, mid(target));
|
||||
} else {
|
||||
|
||||
// otherwise reset source snap
|
||||
context.sourcePosition = context.initialSourcePosition;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
eventBus.on([
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="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" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.1.1">
|
||||
<bpmn:collaboration id="Collaboration_1">
|
||||
<bpmn:participant id="Participant_1" processRef="Process_1" />
|
||||
<bpmn:participant id="Participant_2" processRef="Process_1e043dv" />
|
||||
</bpmn:collaboration>
|
||||
<bpmn:process id="Process_1" isExecutable="false">
|
||||
<bpmn:startEvent id="StartEvent_1" />
|
||||
<bpmn:task id="Task_1" />
|
||||
</bpmn:process>
|
||||
<bpmn:process id="Process_1e043dv" isExecutable="false">
|
||||
<bpmn:task id="Task_2" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
|
||||
<bpmndi:BPMNShape id="Participant_1sh90bv_di" bpmnElement="Participant_1">
|
||||
<dc:Bounds x="50" y="58" width="370" height="120" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="100" y="100" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="73" y="136" width="90" height="20" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Task_005jq1a_di" bpmnElement="Task_1">
|
||||
<dc:Bounds x="300" y="78" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Participant_1lvgmm2_di" bpmnElement="Participant_2">
|
||||
<dc:Bounds x="50" y="185" width="370" height="113" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Task_0ythg78_di" bpmnElement="Task_2">
|
||||
<dc:Bounds x="240" y="200" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -12,7 +12,8 @@ var coreModule = require('../../../../lib/core'),
|
|||
createModule = require('diagram-js/lib/features/create'),
|
||||
resizeModule = require('diagram-js/lib/features/resize'),
|
||||
moveModule = require('diagram-js/lib/features/move'),
|
||||
rulesModule = require('../../../../lib/features/rules');
|
||||
rulesModule = require('../../../../lib/features/rules'),
|
||||
connectModule = require('diagram-js/lib/features/connect');
|
||||
|
||||
|
||||
describe('features/snapping - BpmnSnapping', function() {
|
||||
|
@ -23,7 +24,8 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
modelingModule,
|
||||
createModule,
|
||||
rulesModule,
|
||||
moveModule
|
||||
moveModule,
|
||||
connectModule
|
||||
];
|
||||
|
||||
describe('on Boundary Events', function() {
|
||||
|
@ -541,4 +543,214 @@ describe('features/snapping - BpmnSnapping', function() {
|
|||
|
||||
});
|
||||
|
||||
|
||||
describe('on connect', function() {
|
||||
|
||||
var diagramXML = require('./BpmnSnapping.connect.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||
|
||||
|
||||
it('should snap sequence flow on global connect', inject(function(connect, dragging, elementRegistry) {
|
||||
|
||||
// given
|
||||
var startEvent = elementRegistry.get('StartEvent_1'),
|
||||
task = elementRegistry.get('Task_1');
|
||||
|
||||
var mid = {
|
||||
x: startEvent.x + startEvent.width / 2,
|
||||
y: startEvent.y + startEvent.height / 2
|
||||
};
|
||||
|
||||
// when
|
||||
connect.start(canvasEvent({ x: mid.x + 10, y: mid.y + 10 }), startEvent);
|
||||
|
||||
dragging.hover({
|
||||
element: task,
|
||||
gfx: elementRegistry.getGraphics(task)
|
||||
});
|
||||
|
||||
dragging.move(canvasEvent({
|
||||
x: task.x + task.width / 2,
|
||||
y: task.y + task.height / 2
|
||||
}));
|
||||
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
var expected = [
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: startEvent.x + startEvent.width / 2,
|
||||
y: startEvent.y + startEvent.height / 2
|
||||
},
|
||||
x: startEvent.x + startEvent.width,
|
||||
y: startEvent.y + startEvent.height / 2
|
||||
},
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: task.x + task.width / 2,
|
||||
y: task.y + task.height / 2
|
||||
},
|
||||
x: task.x,
|
||||
y: task.y + task.height / 2
|
||||
}
|
||||
];
|
||||
|
||||
expect(startEvent.outgoing[0].waypoints).to.eql(expected);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('should snap sequence flow on connect', inject(function(connect, dragging, elementRegistry) {
|
||||
|
||||
// given
|
||||
var startEvent = elementRegistry.get('StartEvent_1'),
|
||||
task = elementRegistry.get('Task_1');
|
||||
|
||||
var mid = { x: task.x + task.width / 2, y: task.y + task.height / 2 };
|
||||
|
||||
// when
|
||||
connect.start(canvasEvent({ x: 0, y: 0 }), startEvent);
|
||||
|
||||
dragging.hover({
|
||||
element: task,
|
||||
gfx: elementRegistry.getGraphics(task)
|
||||
});
|
||||
|
||||
dragging.move(canvasEvent({ x: mid.x + 10, y: mid.y + 10 }));
|
||||
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
var expected = [
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: startEvent.x + startEvent.width / 2,
|
||||
y: startEvent.y + startEvent.height / 2
|
||||
},
|
||||
x: startEvent.x + startEvent.width,
|
||||
y: startEvent.y + startEvent.height / 2
|
||||
},
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: task.x + task.width / 2,
|
||||
y: task.y + task.height / 2
|
||||
},
|
||||
x: task.x,
|
||||
y: task.y + task.height / 2
|
||||
}
|
||||
];
|
||||
|
||||
expect(startEvent.outgoing[0].waypoints).to.eql(expected);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT snap message flow on global connect', inject(function(connect, dragging, elementRegistry) {
|
||||
|
||||
// given
|
||||
var task1 = elementRegistry.get('Task_1'),
|
||||
task2 = elementRegistry.get('Task_2');
|
||||
|
||||
var task1Mid = { x: task1.x + task1.width / 2, y: task1.y + task1.height / 2 },
|
||||
task2Mid = { x: task2.x + task2.width / 2, y: task2.y + task2.height / 2 };
|
||||
|
||||
// when
|
||||
connect.start(null, task1, { x: 320, y: task1Mid.y + 20 });
|
||||
|
||||
dragging.hover({
|
||||
element: task2,
|
||||
gfx: elementRegistry.getGraphics(task2)
|
||||
});
|
||||
|
||||
dragging.move(canvasEvent({
|
||||
x: 320,
|
||||
y: task2Mid.y - 20
|
||||
}));
|
||||
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
var expected = [
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: 320,
|
||||
y: task1Mid.y + 20
|
||||
},
|
||||
x: 320,
|
||||
y: task1.y + task1.height
|
||||
},
|
||||
{
|
||||
original:
|
||||
{
|
||||
x: 320,
|
||||
y: task2Mid.y - 20
|
||||
},
|
||||
x: 320,
|
||||
y: task2.y
|
||||
}
|
||||
];
|
||||
|
||||
expect(task1.outgoing[0].waypoints).to.eql(expected);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT snap message flow on connect', inject(function(connect, dragging, elementRegistry) {
|
||||
|
||||
// given
|
||||
var task1 = elementRegistry.get('Task_1'),
|
||||
task2 = elementRegistry.get('Task_2');
|
||||
|
||||
var task1Mid = { x: task1.x + task1.width / 2, y: task1.y + task1.height / 2 },
|
||||
task2Mid = { x: task2.x + task2.width / 2, y: task2.y + task2.height / 2 };
|
||||
|
||||
// when
|
||||
connect.start(canvasEvent({ x: 0, y: 0 }), task1);
|
||||
|
||||
dragging.hover({
|
||||
element: task2,
|
||||
gfx: elementRegistry.getGraphics(task2)
|
||||
});
|
||||
|
||||
dragging.move(canvasEvent({
|
||||
x: task2Mid.x + 20,
|
||||
y: task2Mid.y - 20
|
||||
}));
|
||||
|
||||
dragging.end();
|
||||
|
||||
// then
|
||||
expect(task1.outgoing[0].waypoints.length).to.equal(4);
|
||||
|
||||
expect(task1.outgoing[0].waypoints[0]).to.eql({
|
||||
original:
|
||||
{
|
||||
x: task1Mid.x,
|
||||
y: task1Mid.y
|
||||
},
|
||||
x: task1Mid.x,
|
||||
y: task1.y + task1.height
|
||||
});
|
||||
|
||||
expect(task1.outgoing[0].waypoints[3]).to.eql({
|
||||
original:
|
||||
{
|
||||
x: task2Mid.x + 20,
|
||||
y: task2Mid.y - 20
|
||||
},
|
||||
x: task2Mid.x + 20,
|
||||
y: task2.y
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue