fix(drop-on-flow-behavior): handle shape created with bounds

* take into account that shapes can be created with position OR bounds

Fixes #1178
This commit is contained in:
Philipp Fromme 2019-08-29 11:55:34 +02:00 committed by merge-me[bot]
parent c9e9f002c9
commit e1d8a67527
2 changed files with 77 additions and 17 deletions

View File

@ -2,10 +2,13 @@ import inherits from 'inherits';
import {
assign,
filter,
find,
filter
isNumber
} from 'min-dash';
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
import {
@ -22,7 +25,7 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
* dropping an element on a flow.
*/
function insertShape(shape, targetFlow, position) {
function insertShape(shape, targetFlow, positionOrBounds) {
var waypoints = targetFlow.waypoints,
waypointsBefore,
waypointsAfter,
@ -34,7 +37,15 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
oldOutgoing = shape.outgoing.slice(),
oldIncoming = shape.incoming.slice();
var intersection = getApproxIntersection(waypoints, position);
var mid;
if (isNumber(positionOrBounds.width)) {
mid = getMid(positionOrBounds);
} else {
mid = positionOrBounds;
}
var intersection = getApproxIntersection(waypoints, mid);
if (intersection) {
waypointsBefore = waypoints.slice(0, intersection.index);
@ -45,7 +56,7 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
return;
}
dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : position;
dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : mid;
// if last waypointBefore is inside shape's bounds, ignore docking point
if (!isPointInsideBBox(shape, waypointsBefore[waypointsBefore.length-1])) {
@ -64,7 +75,7 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
if (bpmnRules.canConnect(source, shape, targetFlow)) {
// reconnect source -> inserted shape
modeling.reconnectEnd(targetFlow, shape, waypointsBefore || position);
modeling.reconnectEnd(targetFlow, shape, waypointsBefore || mid);
incomingConnection = targetFlow;
}
@ -74,7 +85,7 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
if (!incomingConnection) {
// reconnect inserted shape -> end
modeling.reconnectStart(targetFlow, shape, waypointsAfter || position);
modeling.reconnectStart(targetFlow, shape, waypointsAfter || mid);
outgoingConnection = targetFlow;
} else {
@ -165,10 +176,10 @@ export default function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
var shape = context.shape,
targetFlow = context.targetFlow,
position = context.position;
positionOrBounds = context.position;
if (targetFlow) {
insertShape(shape, targetFlow, position);
insertShape(shape, targetFlow, positionOrBounds);
}
}, true);
}
@ -198,11 +209,3 @@ function copy(obj) {
return assign({}, obj);
}
function getMid(bounds) {
return {
x: Math.round(bounds.x + bounds.width / 2),
y: Math.round(bounds.y + bounds.height / 2)
};
}

View File

@ -17,6 +17,8 @@ import {
createCanvasEvent as canvasEvent
} from '../../../../util/MockEvents';
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
describe('modeling/behavior - drop on connection', function() {
@ -60,7 +62,6 @@ describe('modeling/behavior - drop on connection', function() {
);
// then
var targetConnection = newShape.outgoing[0];
// new incoming connection
@ -215,6 +216,62 @@ describe('modeling/behavior - drop on connection', function() {
}
));
it('should handle shape created with bounds', inject(
function(elementFactory, elementRegistry, modeling) {
// given
var intermediateThrowEvent = elementFactory.createShape({
type: 'bpmn:IntermediateThrowEvent'
});
var startEvent = elementRegistry.get('StartEvent'),
sequenceFlow = elementRegistry.get('SequenceFlow_1'),
task = elementRegistry.get('Task_1');
var originalWaypoints = sequenceFlow.waypoints;
var dropBounds = { x: 322, y: 102, width: 36, height: 36 }; // first bendpoint
// when
var newShape = modeling.createShape(
intermediateThrowEvent,
dropBounds,
sequenceFlow
);
// then
var targetConnection = newShape.outgoing[0];
// new incoming connection
expect(newShape.incoming.length).to.equal(1);
expect(newShape.incoming[0]).to.eql(sequenceFlow);
// new outgoing connection
expect(newShape.outgoing.length).to.equal(1);
expect(targetConnection).to.exist;
expect(targetConnection.type).to.equal('bpmn:SequenceFlow');
expect(startEvent.outgoing[0]).to.equal(newShape.incoming[0]);
expect(task.incoming[1]).to.equal(newShape.outgoing[0]);
// split target at insertion point
expect(sequenceFlow).to.have.waypoints(flatten([
originalWaypoints.slice(0, 1),
{ x: 322, y: 120 }
]));
expect(sequenceFlow).to.have.endDocking(getMid(dropBounds));
expect(targetConnection).to.have.waypoints(flatten([
{ x: 340, y: 138 },
originalWaypoints.slice(2)
]));
expect(targetConnection).to.have.startDocking(getMid(dropBounds));
}
));
});