diff --git a/lib/features/modeling/behavior/DropBehavior.js b/lib/features/modeling/behavior/DropBehavior.js deleted file mode 100644 index 1a80dfdf..00000000 --- a/lib/features/modeling/behavior/DropBehavior.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/lib/features/modeling/behavior/ReplaceConnectionBehavior.js b/lib/features/modeling/behavior/ReplaceConnectionBehavior.js new file mode 100644 index 00000000..87a2c2da --- /dev/null +++ b/lib/features/modeling/behavior/ReplaceConnectionBehavior.js @@ -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; diff --git a/lib/features/modeling/behavior/index.js b/lib/features/modeling/behavior/index.js index ca4714af..e27c7eea 100644 --- a/lib/features/modeling/behavior/index.js +++ b/lib/features/modeling/behavior/index.js @@ -3,14 +3,14 @@ module.exports = { 'appendBehavior', 'createBehavior', 'createOnFlowBehavior', - 'dropBehavior', + 'replaceConnectionBehavior', 'removeBehavior', 'modelingFeedback' ], appendBehavior: [ 'type', require('./AppendBehavior') ], - dropBehavior: [ 'type', require('./DropBehavior') ], createBehavior: [ 'type', require('./CreateBehavior') ], + replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ], createOnFlowBehavior: [ 'type', require('./CreateOnFlowBehavior') ], removeBehavior: [ 'type', require('./RemoveBehavior') ], modelingFeedback: [ 'type', require('./ModelingFeedback') ] -}; \ No newline at end of file +}; diff --git a/test/spec/features/modeling/behavior/DropBehavior.association.bpmn b/test/spec/features/modeling/behavior/ReplaceConnectionBehavior.association.bpmn similarity index 100% rename from test/spec/features/modeling/behavior/DropBehavior.association.bpmn rename to test/spec/features/modeling/behavior/ReplaceConnectionBehavior.association.bpmn diff --git a/test/spec/features/modeling/behavior/DropBehavior.message-sequence-flow.bpmn b/test/spec/features/modeling/behavior/ReplaceConnectionBehavior.message-sequence-flow.bpmn similarity index 100% rename from test/spec/features/modeling/behavior/DropBehavior.message-sequence-flow.bpmn rename to test/spec/features/modeling/behavior/ReplaceConnectionBehavior.message-sequence-flow.bpmn diff --git a/test/spec/features/modeling/behavior/DropBehaviorSpec.js b/test/spec/features/modeling/behavior/ReplaceConnectionBehaviorSpec.js similarity index 85% rename from test/spec/features/modeling/behavior/DropBehaviorSpec.js rename to test/spec/features/modeling/behavior/ReplaceConnectionBehaviorSpec.js index e83a9d1e..d3c11f92 100644 --- a/test/spec/features/modeling/behavior/DropBehaviorSpec.js +++ b/test/spec/features/modeling/behavior/ReplaceConnectionBehaviorSpec.js @@ -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 ]; 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 })); - var element; 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() { @@ -186,7 +215,7 @@ describe('features/modeling - drop behavior', function() { describe('should replace SequenceFlow <> MessageFlow', function() { - var processDiagramXML = require('./DropBehavior.association.bpmn'); + var processDiagramXML = require('./ReplaceConnectionBehavior.association.bpmn'); beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); @@ -237,4 +266,4 @@ describe('features/modeling - drop behavior', function() { }); -}); \ No newline at end of file +});