diff --git a/lib/features/modeling/behavior/DropOnFlowBehavior.js b/lib/features/modeling/behavior/DropOnFlowBehavior.js index 50522cd4..c2bd3161 100644 --- a/lib/features/modeling/behavior/DropOnFlowBehavior.js +++ b/lib/features/modeling/behavior/DropOnFlowBehavior.js @@ -8,6 +8,16 @@ var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var getApproxIntersection = require('diagram-js/lib/util/LineIntersection').getApproxIntersection; +function isPointInsideBBox(bbox, point) { + var x = point.x, + y = point.y; + + return x >= bbox.x && + x <= bbox.x + bbox.width && + y >= bbox.y && + y <= bbox.y + bbox.height; +} + function copy(obj) { return assign({}, obj); } @@ -41,8 +51,15 @@ function DropOnFlow(eventBus, bpmnRules, modeling) { dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : position; - waypointsBefore.push(copy(dockingPoint)); - waypointsAfter.unshift(copy(dockingPoint)); + // if last waypointBefore is inside shape's bounds, ignore docking point + if (!isPointInsideBBox(shape, waypointsBefore[waypointsBefore.length-1])) { + waypointsBefore.push(copy(dockingPoint)); + } + + // if first waypointAfter is inside shape's bounds, ignore docking point + if (!isPointInsideBBox(shape, waypointsAfter[0])) { + waypointsAfter.unshift(copy(dockingPoint)); + } } source = targetFlow.source; diff --git a/test/spec/features/modeling/behavior/DropOnFlowBehaviorSpec.js b/test/spec/features/modeling/behavior/DropOnFlowBehaviorSpec.js index a8b27142..f01fd330 100644 --- a/test/spec/features/modeling/behavior/DropOnFlowBehaviorSpec.js +++ b/test/spec/features/modeling/behavior/DropOnFlowBehaviorSpec.js @@ -150,6 +150,54 @@ describe('modeling/behavior - drop on connection', function() { ])); })); + + it('should connect start -> target -> end (with bendpointBefore inside bbox)', + inject(function(modeling, elementRegistry, elementFactory) { + // given + var taskShape = elementFactory.createShape({ type: 'bpmn:Task' }), + sequenceFlow = elementRegistry.get('SequenceFlow_1'), + originalWaypoints = sequenceFlow.waypoints, + dropPosition = { x: 340, y: 145 }; // 25 pixels below bendpoint + + // when + modeling.createShape(taskShape, dropPosition, sequenceFlow); + + // then + // split target but don't keep insertion point + expect(sequenceFlow).to.have.waypoints(flatten([ + originalWaypoints.slice(0, 1), + { x: 290, y: 120 } + ])); + + expect(sequenceFlow).to.have.endDocking({ x: 340, y: 120 }); + } + )); + + + it('should connect start -> target -> end (with bendpointAfter inside bbox)', + inject(function(modeling, elementRegistry, elementFactory) { + + // given + var taskShape = elementFactory.createShape({ type: 'bpmn:Task' }), + sequenceFlow = elementRegistry.get('SequenceFlow_1'), + originalWaypoints = sequenceFlow.waypoints, + dropPosition = { x: 340, y: 280 }; // 25 pixels above bendpoint + + // when + var newShape = modeling.createShape(taskShape, dropPosition, sequenceFlow), + targetConnection = newShape.outgoing[0]; + + // then + // split target but don't keep insertion point + expect(targetConnection).to.have.waypoints(flatten([ + { x: 390, y: 299 }, + originalWaypoints.slice(3) + ])); + + expect(targetConnection).to.have.startDocking({ x: 340, y: 299 }); + } + )); + }); describe('move', function() {