feat(layout): add straight layouting for message flows
This commit adds a straight layouting strategy for message flows. Other than that it makes sure connection attachments are being remembered during reconnection / shape move. Closes #249 Closes #179
This commit is contained in:
parent
373b8c6293
commit
6eceb0926b
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var assign = require('lodash/object/assign');
|
||||
|
||||
var BaseLayouter = require('diagram-js/lib/layout/BaseLayouter'),
|
||||
LayoutUtil = require('diagram-js/lib/layout/LayoutUtil'),
|
||||
ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout');
|
||||
|
||||
var is = require('./ModelingUtil').is;
|
||||
|
||||
|
||||
function BpmnLayouter() {}
|
||||
|
||||
inherits(BpmnLayouter, BaseLayouter);
|
||||
|
||||
module.exports = BpmnLayouter;
|
||||
|
||||
|
||||
function getAttachment(waypoints, idx, shape) {
|
||||
var point = waypoints && waypoints[idx];
|
||||
|
||||
return point ? (point.original || point) : LayoutUtil.getMidPoint(shape);
|
||||
}
|
||||
|
||||
|
||||
BpmnLayouter.prototype.layoutConnection = function(connection, hints) {
|
||||
var source = connection.source,
|
||||
target = connection.target,
|
||||
waypoints = connection.waypoints,
|
||||
start,
|
||||
end;
|
||||
|
||||
var layoutManhattan,
|
||||
updatedWaypoints;
|
||||
|
||||
start = getAttachment(waypoints, 0, source);
|
||||
end = getAttachment(waypoints, waypoints && waypoints.length - 1, target);
|
||||
|
||||
// manhattan layout sequence / message flows
|
||||
if (is(connection, 'bpmn:MessageFlow')) {
|
||||
layoutManhattan = {
|
||||
preferStraight: true,
|
||||
preferVertical: true
|
||||
};
|
||||
}
|
||||
|
||||
if (is(connection, 'bpmn:SequenceFlow')) {
|
||||
layoutManhattan = {};
|
||||
}
|
||||
|
||||
if (layoutManhattan) {
|
||||
|
||||
layoutManhattan = assign(layoutManhattan, hints);
|
||||
|
||||
updatedWaypoints =
|
||||
ManhattanLayout.repairConnection(
|
||||
source, target, start, end,
|
||||
waypoints,
|
||||
layoutManhattan);
|
||||
}
|
||||
|
||||
return updatedWaypoints || [ start, end ];
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var BaseLayouter = require('diagram-js/lib/features/modeling/Layouter'),
|
||||
LayoutUtil = require('diagram-js/lib/layout/Util'),
|
||||
ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout');
|
||||
|
||||
|
||||
function Layouter() {}
|
||||
|
||||
inherits(Layouter, BaseLayouter);
|
||||
|
||||
module.exports = Layouter;
|
||||
|
||||
|
||||
Layouter.prototype.getConnectionWaypoints = function(connection) {
|
||||
var source = connection.source,
|
||||
start = LayoutUtil.getMidPoint(source),
|
||||
target = connection.target,
|
||||
end = LayoutUtil.getMidPoint(target);
|
||||
|
||||
var bo = connection.businessObject;
|
||||
|
||||
// manhattan layout sequence / message flows
|
||||
if (bo.$instanceOf('bpmn:SequenceFlow') ||
|
||||
bo.$instanceOf('bpmn:MessageFlow')) {
|
||||
|
||||
var waypoints = ManhattanLayout.repairConnection(source, target, start, end, connection.waypoints);
|
||||
|
||||
if (waypoints) {
|
||||
return waypoints;
|
||||
}
|
||||
}
|
||||
|
||||
return [ start, end ];
|
||||
};
|
|
@ -12,6 +12,6 @@ module.exports = {
|
|||
elementFactory: [ 'type', require('./ElementFactory') ],
|
||||
modeling: [ 'type', require('./Modeling') ],
|
||||
labelSupport: [ 'type', require('./LabelSupport') ],
|
||||
layouter: [ 'type', require('./Layouter') ],
|
||||
layouter: [ 'type', require('./BpmnLayouter') ],
|
||||
connectionDocking: [ 'type', require('diagram-js/lib/layout/CroppingConnectionDocking') ]
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?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="_pHDz0KojEeOJhIBv1RySdg" targetNamespace="http://bpmn.io/schema/bpmn">
|
||||
<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="_pHDz0KojEeOJhIBv1RySdg" exporter="camunda modeler" exporterVersion="2.6.0" targetNamespace="http://bpmn.io/schema/bpmn">
|
||||
<bpmn2:collaboration id="_Collaboration_2">
|
||||
<bpmn2:participant id="Participant_2" name="Pool" processRef="Process_1"/>
|
||||
<bpmn2:participant id="Participant_1" name="Pool" processRef="Process_2"/>
|
||||
<bpmn2:messageFlow id="MessageFlow_1" name="" sourceRef="Task_1" targetRef="Participant_1"/>
|
||||
<bpmn2:messageFlow id="MessageFlow_1" name="" sourceRef="Task_2" targetRef="Participant_1"/>
|
||||
<bpmn2:messageFlow id="MessageFlow_2" name="" sourceRef="Participant_1" targetRef="Participant_2"/>
|
||||
<bpmn2:messageFlow id="MessageFlow_4" name="" sourceRef="Task_1" targetRef="StartEvent_1"/>
|
||||
<bpmn2:messageFlow id="MessageFlow_5" name="" sourceRef="EndEvent_1" targetRef="Participant_1"/>
|
||||
|
@ -13,6 +13,7 @@
|
|||
<bpmn2:endEvent id="EndEvent_1">
|
||||
<bpmn2:messageEventDefinition id="MessageEventDefinition_2"/>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:task id="Task_2"/>
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="Process_2" isExecutable="false">
|
||||
<bpmn2:startEvent id="StartEvent_1">
|
||||
|
@ -34,20 +35,18 @@
|
|||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task_1">
|
||||
<dc:Bounds height="80.0" width="100.0" x="404.0" y="135.0"/>
|
||||
<dc:Bounds height="80.0" width="100.0" x="360.0" y="134.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_MessageFlow_1" bpmnElement="MessageFlow_1" sourceElement="_BPMNShape_Task_3" targetElement="_BPMNShape_Participant_3">
|
||||
<di:waypoint xsi:type="dc:Point" x="454.0" y="215.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="454.0" y="370.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="370.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="415.0"/>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_MessageFlow_1" bpmnElement="MessageFlow_1" sourceElement="_BPMNShape_Task_4" targetElement="_BPMNShape_Participant_3">
|
||||
<di:waypoint xsi:type="dc:Point" x="590.0" y="214.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="590.0" y="415.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="6.0" width="6.0" x="451.0" y="316.0"/>
|
||||
<dc:Bounds height="6.0" width="6.0" x="522.0" y="314.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_MessageFlow_2" bpmnElement="MessageFlow_2" sourceElement="_BPMNShape_Participant_3" targetElement="_BPMNShape_Participant_2">
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="415.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="386.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="506.0" y="415.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="506.0" y="386.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="506.0" y="386.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="506.0" y="300.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
|
@ -55,12 +54,12 @@
|
|||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_MessageFlow_4" bpmnElement="MessageFlow_4" sourceElement="_BPMNShape_Task_3" targetElement="_BPMNShape_StartEvent_3">
|
||||
<di:waypoint xsi:type="dc:Point" x="454.0" y="215.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="454.0" y="387.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="390.0" y="214.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="390.0" y="387.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="318.0" y="387.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="318.0" y="448.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="6.0" width="6.0" x="451.0" y="322.0"/>
|
||||
<dc:Bounds height="6.0" width="6.0" x="427.0" y="321.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_2" bpmnElement="EndEvent_1">
|
||||
|
@ -71,13 +70,14 @@
|
|||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="BPMNEdge_MessageFlow_5" bpmnElement="MessageFlow_5" sourceElement="_BPMNShape_EndEvent_2" targetElement="_BPMNShape_Participant_3">
|
||||
<di:waypoint xsi:type="dc:Point" x="671.0" y="214.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="671.0" y="332.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="332.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="522.0" y="415.0"/>
|
||||
<di:waypoint xsi:type="dc:Point" x="671.0" y="415.0"/>
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds height="6.0" width="6.0" x="630.0" y="332.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_Task_4" bpmnElement="Task_2">
|
||||
<dc:Bounds height="80.0" width="100.0" x="516.0" y="134.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
|
@ -36,8 +36,9 @@ describe('features/modeling - layout connection', function() {
|
|||
// then
|
||||
|
||||
// expect cropped, repaired connection
|
||||
// that was not actually modified
|
||||
expect(sequenceFlowConnection.waypoints).toDeepEqual([
|
||||
{ original: { x: 553, y: 341 }, x: 578, y: 341 },
|
||||
{ original: { x: 578, y: 341 }, x: 578, y: 341 },
|
||||
{ x: 934, y: 341 },
|
||||
{ x: 934, y: 436 },
|
||||
{ original: { x: 832, y: 436 }, x: 832, y: 436 }
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
'use strict';
|
||||
|
||||
var Matchers = require('../../../Matchers'),
|
||||
TestHelper = require('../../../TestHelper');
|
||||
|
||||
/* global bootstrapModeler, inject */
|
||||
|
||||
|
||||
var modelingModule = require('../../../../lib/features/modeling'),
|
||||
coreModule = require('../../../../lib/core');
|
||||
|
||||
|
||||
describe('features/modeling - layout message flows', function() {
|
||||
|
||||
beforeEach(Matchers.addDeepEquals);
|
||||
|
||||
|
||||
var diagramXML = require('../../../fixtures/bpmn/collaboration-message-flows.bpmn');
|
||||
|
||||
var testModules = [ coreModule, modelingModule ];
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||
|
||||
|
||||
it('should layout manhattan after Task move', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var taskShape = elementRegistry.get('Task_1'),
|
||||
messageFlowConnection = elementRegistry.get('MessageFlow_4');
|
||||
|
||||
// when
|
||||
modeling.moveShapes([ taskShape ], { x: 30, y: 20 });
|
||||
|
||||
// then
|
||||
|
||||
// expect cropped, repaired manhattan connection
|
||||
expect(messageFlowConnection.waypoints).toDeepEqual([
|
||||
{ original: { x: 420, y: 234 }, x: 420, y: 234 },
|
||||
{ x: 420, y: 387 },
|
||||
{ x: 318, y: 387 },
|
||||
{ original: { x: 318, y: 448 }, x: 318, y: 448 }
|
||||
]);
|
||||
}));
|
||||
|
||||
|
||||
it('should layout straight after Task move', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var taskShape = elementRegistry.get('Task_2'),
|
||||
messageFlowConnection = elementRegistry.get('MessageFlow_1');
|
||||
|
||||
// when
|
||||
modeling.moveShapes([ taskShape ], { x: 20, y: -20 });
|
||||
|
||||
// then
|
||||
|
||||
// expect cropped, repaired manhattan connection
|
||||
expect(messageFlowConnection.waypoints).toDeepEqual([
|
||||
{ original: { x: 610, y: 194 }, x: 610, y: 194 },
|
||||
{ original: { x: 610, y: 415 }, x: 610, y: 415 }
|
||||
]);
|
||||
}));
|
||||
|
||||
|
||||
it('should layout straight after Participant move', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var participantShape = elementRegistry.get('Participant_1'),
|
||||
messageFlowConnection = elementRegistry.get('MessageFlow_5');
|
||||
|
||||
// when
|
||||
modeling.moveShapes([ participantShape ], { x: 100, y: 50 });
|
||||
|
||||
// then
|
||||
|
||||
// expect cropped, repaired manhattan connection
|
||||
expect(messageFlowConnection.waypoints).toDeepEqual([
|
||||
{ original: { x: 671, y: 214 }, x: 671, y: 214 },
|
||||
{ original: { x: 671, y: 465 }, x: 671, y: 465 }
|
||||
]);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
it('should layout manhattan after Participant move beyond EndEvent bounds',
|
||||
inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var participantShape = elementRegistry.get('Participant_1'),
|
||||
messageFlowConnection = elementRegistry.get('MessageFlow_5');
|
||||
|
||||
// when
|
||||
modeling.moveShapes([ participantShape ], { x: -200, y: 0 });
|
||||
|
||||
// then
|
||||
|
||||
// expect cropped, repaired manhattan connection
|
||||
expect(messageFlowConnection.waypoints).toDeepEqual([
|
||||
{ original: { x: 671, y: 214 }, x: 671, y: 214 },
|
||||
{ x: 671, y: 315 },
|
||||
{ x: 471, y: 315 },
|
||||
{ original: { x: 471, y: 415 }, x: 471, y: 415 }
|
||||
]);
|
||||
}));
|
||||
|
||||
});
|
|
@ -47,10 +47,10 @@ describe('features/modeling - move shape', function() {
|
|||
|
||||
// expect flow layout
|
||||
expect(sequenceFlowElement.waypoints).toDeepEqual([
|
||||
{ original: { x: 370, y: 310 }, x: 388, y: 310 },
|
||||
{ original: { x: 388, y: 310 }, x: 388, y: 310 },
|
||||
{ x: 404, y: 310 },
|
||||
{ x: 404, y: 260 },
|
||||
{ original: { x: 470, y: 260 }, x: 420, y: 260 }
|
||||
{ original: { x: 420, y: 260 }, x: 420, y: 260 }
|
||||
]);
|
||||
|
||||
expect(sequenceFlow.di.waypoint).toDeepEqual([
|
||||
|
|
Loading…
Reference in New Issue