diff --git a/lib/features/modeling/behavior/RemoveElementBehavior.js b/lib/features/modeling/behavior/RemoveElementBehavior.js new file mode 100644 index 00000000..d775816b --- /dev/null +++ b/lib/features/modeling/behavior/RemoveElementBehavior.js @@ -0,0 +1,40 @@ +'use strict'; + +var inherits = require('inherits'); + +var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); + +function RemoveElementBehavior(eventBus, bpmnRules, modeling) { + + CommandInterceptor.call(this, eventBus); + + /** + * Combine sequence flows when deleting an element + * if there is one incoming and one outgoing + * sequence flow + */ + + this.preExecute('shape.delete', function(e) { + + var shape = e.context.shape; + + if (shape.incoming.length == 1 && shape.outgoing.length == 1) { + + var inConnection = shape.incoming[0], + outConnection = shape.outgoing[0]; + + var docking = outConnection.waypoints[outConnection.waypoints.length - 1]; + + if (bpmnRules.canConnect(inConnection.source, outConnection.target, inConnection)) { + modeling.reconnectEnd(inConnection, outConnection.target, docking); + } + + } + }); +} + +inherits(RemoveElementBehavior, CommandInterceptor); + +RemoveElementBehavior.$inject = [ 'eventBus', 'bpmnRules', 'modeling' ]; + +module.exports = RemoveElementBehavior; diff --git a/lib/features/modeling/behavior/index.js b/lib/features/modeling/behavior/index.js index 2e55b8ca..cb76e49d 100644 --- a/lib/features/modeling/behavior/index.js +++ b/lib/features/modeling/behavior/index.js @@ -14,7 +14,8 @@ module.exports = { 'replaceElementBehaviour', 'resizeLaneBehavior', 'unsetDefaultFlowBehavior', - 'updateFlowNodeRefsBehavior' + 'updateFlowNodeRefsBehavior', + 'removeElementBehavior' ], appendBehavior: [ 'type', require('./AppendBehavior') ], createBoundaryEventBehavior: [ 'type', require('./CreateBoundaryEventBehavior') ], @@ -30,5 +31,6 @@ module.exports = { replaceElementBehaviour: [ 'type', require('./ReplaceElementBehaviour') ], resizeLaneBehavior: [ 'type', require('./ResizeLaneBehavior') ], unsetDefaultFlowBehavior: [ 'type', require('./UnsetDefaultFlowBehavior') ], - updateFlowNodeRefsBehavior: [ 'type', require('./UpdateFlowNodeRefsBehavior') ] + updateFlowNodeRefsBehavior: [ 'type', require('./UpdateFlowNodeRefsBehavior') ], + removeElementBehavior: [ 'type', require('./RemoveElementBehavior') ] }; diff --git a/test/spec/features/modeling/behavior/RemoveElementBehavior.bpmn b/test/spec/features/modeling/behavior/RemoveElementBehavior.bpmn new file mode 100644 index 00000000..6260c87f --- /dev/null +++ b/test/spec/features/modeling/behavior/RemoveElementBehavior.bpmn @@ -0,0 +1,140 @@ + + + + + SequenceFlow1 + + + SequenceFlow1 + SequenceFlow2 + + + + SequenceFlow2 + + + + + SequenceFlow3 + + DataStoreReference1 + + + + SequenceFlow3 + SequenceFlow4 + + + + SequenceFlow4 + SequenceFlow6 + SequenceFlow5 + + + + SequenceFlow6 + + + + SequenceFlow5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/features/modeling/behavior/RemoveElementBehaviorSpec.js b/test/spec/features/modeling/behavior/RemoveElementBehaviorSpec.js new file mode 100644 index 00000000..b08fe005 --- /dev/null +++ b/test/spec/features/modeling/behavior/RemoveElementBehaviorSpec.js @@ -0,0 +1,77 @@ +'use strict'; + +/* global bootstrapModeler, inject */ + +var modelingModule = require('../../../../../lib/features/modeling'), + coreModule = require('../../../../../lib/core'); + +describe('features/modeling - remove element behavior', function() { + + var testModules = [ coreModule, modelingModule ]; + + describe('combine sequence flow when deleting element', function() { + + var processDiagramXML = require('./RemoveElementBehavior.bpmn'); + + beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); + + it('should combine sequence flows on remove', inject(function(modeling, elementRegistry) { + + // given + var task = elementRegistry.get('Task1'); + + // when + modeling.removeShape(task); + + // then + expect(elementRegistry.get(task.id)).to.be.undefined; + expect(elementRegistry.get('SequenceFlow1')).to.not.be.undefined; + expect(elementRegistry.get('SequenceFlow2')).to.be.undefined; + + expect(elementRegistry.get('StartEvent1').outgoing.length).to.be.equal(1); + expect(elementRegistry.get('EndEvent1').incoming.length).to.be.equal(1); + + })); + + + it('should remove all sequence flows', inject(function(modeling, elementRegistry) { + + // given + var task = elementRegistry.get('Task3'); + + // when + modeling.removeShape(task); + + // then + expect(elementRegistry.get(task.id)).to.be.undefined; + expect(elementRegistry.get('SequenceFlow4')).to.be.undefined; + expect(elementRegistry.get('SequenceFlow5')).to.be.undefined; + expect(elementRegistry.get('SequenceFlow6')).to.be.undefined; + + expect(elementRegistry.get('StartEvent2').outgoing).to.be.empty; + expect(elementRegistry.get('StartEvent2').incoming).to.be.empty; + + })); + + + it('should not combine not allowed connection', inject(function(modeling, elementRegistry) { + + // given + var task = elementRegistry.get('Task2'); + + // when + modeling.removeShape(task); + + // then + expect(elementRegistry.get(task.id)).to.be.undefined; + expect(elementRegistry.get('SequenceFlow3')).to.be.undefined; + expect(elementRegistry.get('DataOutputAssociation1')).to.be.undefined; + + expect(elementRegistry.get('DataStoreReference1').incoming).to.be.empty; + expect(elementRegistry.get('IntermediateThrowEvent1').outgoing.length).to.be.eql(1); + + })); + + }); + +});