fix(modeling): message flow updating correctly after changing source

Closes #267
This commit is contained in:
pedesen 2015-07-20 11:59:41 +02:00 committed by Nico Rehwaldt
parent 3f90a77a7b
commit 8c6c920482
6 changed files with 135 additions and 97 deletions

View File

@ -1,89 +0,0 @@
'use strict';
var forEach = require('lodash/collection/forEach'),
inherits = require('inherits');
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
var is = require('../../../util/ModelUtil').is,
getSharedParent = require('../ModelingUtil').getSharedParent;
function DropBehavior(eventBus, modeling, bpmnRules) {
CommandInterceptor.call(this, eventBus);
// remove sequence flows that should not be allowed
// after a move operation
this.postExecute('shapes.move', function(context) {
var closure = context.closure,
allConnections = closure.allConnections;
forEach(allConnections, function(c) {
var source = c.source,
target = c.target;
var replacementType,
remove;
/**
* Check if incoming or outgoing connections
* can stay or could be substituted with an
* appropriate replacement.
*
* This holds true for SequenceFlow <> MessageFlow.
*/
if (is(c, 'bpmn:SequenceFlow')) {
if (!bpmnRules.canConnectSequenceFlow(source, target)) {
remove = true;
}
if (bpmnRules.canConnectMessageFlow(source, target)) {
replacementType = 'bpmn:MessageFlow';
}
}
// transform message flows into sequence flows, if possible
if (is(c, 'bpmn:MessageFlow')) {
if (!bpmnRules.canConnectMessageFlow(source, target)) {
remove = true;
}
if (bpmnRules.canConnectSequenceFlow(source, target)) {
replacementType = 'bpmn:SequenceFlow';
}
}
if (is(c, 'bpmn:Association') && !bpmnRules.canConnectAssociation(source, target)) {
remove = true;
}
// remove invalid connection
if (remove) {
modeling.removeConnection(c);
}
// replace SequenceFlow <> MessageFlow
if (replacementType) {
modeling.createConnection(source, target, {
type: replacementType,
waypoints: c.waypoints.slice()
}, getSharedParent(source, target));
}
});
}, true);
}
inherits(DropBehavior, CommandInterceptor);
DropBehavior.$inject = [ 'eventBus', 'modeling', 'bpmnRules' ];
module.exports = DropBehavior;

View File

@ -0,0 +1,98 @@
'use strict';
var forEach = require('lodash/collection/forEach'),
inherits = require('inherits');
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
var is = require('../../../util/ModelUtil').is,
getSharedParent = require('../ModelingUtil').getSharedParent;
function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules) {
CommandInterceptor.call(this, eventBus);
function replaceConnection(connection) {
var source = connection.source,
target = connection.target;
var replacementType,
remove;
/**
* Check if incoming or outgoing connections
* can stay or could be substituted with an
* appropriate replacement.
*
* This holds true for SequenceFlow <> MessageFlow.
*/
if (is(connection, 'bpmn:SequenceFlow')) {
if (!bpmnRules.canConnectSequenceFlow(source, target)) {
remove = true;
}
if (bpmnRules.canConnectMessageFlow(source, target)) {
replacementType = 'bpmn:MessageFlow';
}
}
// transform message flows into sequence flows, if possible
if (is(connection, 'bpmn:MessageFlow')) {
if (!bpmnRules.canConnectMessageFlow(source, target)) {
remove = true;
}
if (bpmnRules.canConnectSequenceFlow(source, target)) {
replacementType = 'bpmn:SequenceFlow';
}
}
if (is(connection, 'bpmn:Association') && !bpmnRules.canConnectAssociation(source, target)) {
remove = true;
}
// remove invalid connection
if (remove) {
modeling.removeConnection(connection);
}
// replace SequenceFlow <> MessageFlow
if (replacementType) {
modeling.createConnection(source, target, {
type: replacementType,
waypoints: connection.waypoints.slice()
}, getSharedParent(source, target));
}
}
this.postExecute('shapes.move', function(context) {
var closure = context.closure,
allConnections = closure.allConnections;
forEach(allConnections, replaceConnection);
}, true);
this.postExecute([
'connection.reconnectStart',
'connection.reconnectEnd'
], function(event){
var connection = event.context.connection;
replaceConnection(connection);
});
}
inherits(ReplaceConnectionBehavior, CommandInterceptor);
ReplaceConnectionBehavior.$inject = [ 'eventBus', 'modeling', 'bpmnRules' ];
module.exports = ReplaceConnectionBehavior;

View File

@ -3,13 +3,13 @@ module.exports = {
'appendBehavior', 'appendBehavior',
'createBehavior', 'createBehavior',
'createOnFlowBehavior', 'createOnFlowBehavior',
'dropBehavior', 'replaceConnectionBehavior',
'removeBehavior', 'removeBehavior',
'modelingFeedback' 'modelingFeedback'
], ],
appendBehavior: [ 'type', require('./AppendBehavior') ], appendBehavior: [ 'type', require('./AppendBehavior') ],
dropBehavior: [ 'type', require('./DropBehavior') ],
createBehavior: [ 'type', require('./CreateBehavior') ], createBehavior: [ 'type', require('./CreateBehavior') ],
replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ],
createOnFlowBehavior: [ 'type', require('./CreateOnFlowBehavior') ], createOnFlowBehavior: [ 'type', require('./CreateOnFlowBehavior') ],
removeBehavior: [ 'type', require('./RemoveBehavior') ], removeBehavior: [ 'type', require('./RemoveBehavior') ],
modelingFeedback: [ 'type', require('./ModelingFeedback') ] modelingFeedback: [ 'type', require('./ModelingFeedback') ]

View File

@ -27,18 +27,17 @@ function expectNotConnected(source, target, connectionOrType) {
} }
describe('features/modeling - drop behavior', function() { describe('features/modeling - replace connection', function() {
var testModules = [ coreModule, modelingModule ]; var testModules = [ coreModule, modelingModule ];
describe('should replace SequenceFlow <> MessageFlow', function() { describe('should replace SequenceFlow <> MessageFlow', function() {
var processDiagramXML = require('./DropBehavior.message-sequence-flow.bpmn'); var processDiagramXML = require('./ReplaceConnectionBehavior.message-sequence-flow.bpmn');
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
var element; var element;
beforeEach(inject(function(elementRegistry) { beforeEach(inject(function(elementRegistry) {
@ -47,6 +46,36 @@ describe('features/modeling - drop behavior', function() {
}; };
})); }));
describe('after reconnecting', function(){
it('sequence flow to another task', inject(function(elementRegistry, modeling){
var task4Shape = element('Task_4');
var connection = element('SequenceFlow_1');
var newWaypoints = [connection.waypoints[0], {x: task4Shape.x+30, y: task4Shape.y}];
modeling.reconnectEnd(connection, task4Shape, newWaypoints);
expectConnected(element('Task_2'), task4Shape, 'bpmn:MessageFlow');
}));
it('message flow to another task', inject(function(elementRegistry, modeling){
var task4Shape = element('Task_4');
var connection = element('MessageFlow_1');
var newWaypoints = [connection.waypoints[0], {x: task4Shape.x, y: task4Shape.y+20}];
modeling.reconnectEnd(connection, task4Shape, newWaypoints);
expectConnected(element('Task_3'), task4Shape, 'bpmn:SequenceFlow');
}));
});
describe('moving single shape', function() { describe('moving single shape', function() {
@ -186,7 +215,7 @@ describe('features/modeling - drop behavior', function() {
describe('should replace SequenceFlow <> MessageFlow', function() { describe('should replace SequenceFlow <> MessageFlow', function() {
var processDiagramXML = require('./DropBehavior.association.bpmn'); var processDiagramXML = require('./ReplaceConnectionBehavior.association.bpmn');
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));