feat(modeling): retain waypoints with connection on shape deletion

When keeping the connection when the intermittant element,
make sure we keep the waypoints, too.

closes #581
This commit is contained in:
hoferch91 2016-08-17 15:36:13 +02:00 committed by Nico Rehwaldt
parent 4339002b09
commit a8cf097ed0
8 changed files with 553 additions and 98 deletions

View File

@ -2,6 +2,8 @@
var getMid = require('diagram-js/lib/layout/LayoutUtil').getMid;
var lineIntersect = require('./util/LineIntersect');
/**
* Fix broken dockings after DI imports.
@ -74,32 +76,6 @@ module.exports = ImportDockingFix;
/////// helpers //////////////////////////////////
function lineIntersect(l1s, l1e, l2s, l2e) {
// if the lines intersect, the result contains the x and y of the
// intersection (treating the lines as infinite) and booleans for
// whether line segment 1 or line segment 2 contain the point
var denominator, a, b, c, numerator;
denominator = ((l2e.y - l2s.y) * (l1e.x - l1s.x)) - ((l2e.x - l2s.x) * (l1e.y - l1s.y));
if (denominator == 0) {
return null;
}
a = l1s.y - l2s.y;
b = l1s.x - l2s.x;
numerator = ((l2e.x - l2s.x) * a) - ((l2e.y - l2s.y) * b);
c = numerator / denominator;
// if we cast these lines infinitely in
// both directions, they intersect here
return {
x: Math.round(l1s.x + (c * (l1e.x - l1s.x))),
y: Math.round(l1s.y + (c * (l1e.y - l1s.y)))
};
}
function getDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}

View File

@ -4,6 +4,9 @@ var inherits = require('inherits');
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
var lineIntersect = require('./util/LineIntersect');
function RemoveElementBehavior(eventBus, bpmnRules, modeling) {
CommandInterceptor.call(this, eventBus);
@ -13,7 +16,6 @@ function RemoveElementBehavior(eventBus, bpmnRules, modeling) {
* if there is one incoming and one outgoing
* sequence flow
*/
this.preExecute('shape.delete', function(e) {
var shape = e.context.shape;
@ -23,14 +25,17 @@ function RemoveElementBehavior(eventBus, bpmnRules, modeling) {
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);
}
// compute new, combined waypoints
var newWaypoints = getNewWaypoints(inConnection.waypoints, outConnection.waypoints);
modeling.reconnectEnd(inConnection, outConnection.target, newWaypoints);
}
}
});
}
inherits(RemoveElementBehavior, CommandInterceptor);
@ -38,3 +43,32 @@ inherits(RemoveElementBehavior, CommandInterceptor);
RemoveElementBehavior.$inject = [ 'eventBus', 'bpmnRules', 'modeling' ];
module.exports = RemoveElementBehavior;
///////// helpers //////////////////////////////
function getDocking(point) {
return point.original || point;
}
function getNewWaypoints(inWaypoints, outWaypoints) {
var intersection = lineIntersect(
getDocking(inWaypoints[inWaypoints.length - 2]),
getDocking(inWaypoints[inWaypoints.length - 1]),
getDocking(outWaypoints[1]),
getDocking(outWaypoints[0]));
if (intersection) {
return [].concat(
inWaypoints.slice(0, inWaypoints.length - 1),
[ intersection ],
outWaypoints.slice(1));
} else {
return [
getDocking(inWaypoints[0]),
getDocking(outWaypoints[outWaypoints.length - 1])
];
}
}

View File

@ -2,7 +2,7 @@
var GeometricUtil = require('./GeometricUtil');
var getDistance = require('./GeometricUtil').getDistancePointPoint;
var getDistancePointPoint = require('./GeometricUtil').getDistancePointPoint;
var getAttachment = require('./LineAttachmentUtil').getAttachment;
@ -183,8 +183,8 @@ module.exports.getLabelAdjustment = getLabelAdjustment;
function relativePositionMidWaypoint(waypoints, idx) {
var distanceSegment1 = getDistance(waypoints[idx-1], waypoints[idx]),
distanceSegment2 = getDistance(waypoints[idx], waypoints[idx+1]);
var distanceSegment1 = getDistancePointPoint(waypoints[idx-1], waypoints[idx]),
distanceSegment2 = getDistancePointPoint(waypoints[idx], waypoints[idx+1]);
var relativePosition = distanceSegment1 / ( distanceSegment1 + distanceSegment2 );
@ -210,7 +210,8 @@ function getLine(waypoints, idx) {
}
function getRelativeFootPosition(line, foot) {
var length = GeometricUtil.getDistancePointPoint(line[0], line[1]),
lengthToFoot = GeometricUtil.getDistancePointPoint(line[0], foot);
var length = getDistancePointPoint(line[0], line[1]),
lengthToFoot = getDistancePointPoint(line[0], foot);
return lengthToFoot / length;
}

View File

@ -0,0 +1,37 @@
'use strict';
/**
* Returns the intersection between two line segments a and b.
*
* @param {Point} l1s
* @param {Point} l1e
* @param {Point} l2s
* @param {Point} l2e
*
* @return {Point}
*/
module.exports = function lineIntersect(l1s, l1e, l2s, l2e) {
// if the lines intersect, the result contains the x and y of the
// intersection (treating the lines as infinite) and booleans for
// whether line segment 1 or line segment 2 contain the point
var denominator, a, b, c, numerator;
denominator = ((l2e.y - l2s.y) * (l1e.x - l1s.x)) - ((l2e.x - l2s.x) * (l1e.y - l1s.y));
if (denominator == 0) {
return null;
}
a = l1s.y - l2s.y;
b = l1s.x - l2s.x;
numerator = ((l2e.x - l2s.x) * a) - ((l2e.y - l2s.y) * b);
c = numerator / denominator;
// if we cast these lines infinitely in
// both directions, they intersect here
return {
x: Math.round(l1s.x + (c * (l1e.x - l1s.x))),
y: Math.round(l1s.y + (c * (l1e.y - l1s.y)))
};
};

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="0.7.0-dev">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent1">
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
@ -39,101 +39,142 @@
<bpmn:incoming>SequenceFlow5</bpmn:incoming>
</bpmn:intermediateThrowEvent>
<bpmn:sequenceFlow id="SequenceFlow5" sourceRef="Task3" targetRef="IntermediateThrowEvent2" />
<bpmn:startEvent id="StartEvent3">
<bpmn:outgoing>SequenceFlow7</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task4">
<bpmn:incoming>SequenceFlow7</bpmn:incoming>
<bpmn:outgoing>SequenceFlow8</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow7" sourceRef="StartEvent3" targetRef="Task4" />
<bpmn:endEvent id="EndEvent2">
<bpmn:incoming>SequenceFlow8</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow8" sourceRef="Task4" targetRef="EndEvent2" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="StartEvent_1kb6sds_di" bpmnElement="StartEvent1">
<bpmndi:BPMNShape id="StartEvent1_di" bpmnElement="StartEvent1">
<dc:Bounds x="204" y="36" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="177" y="72" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1gm96cu_di" bpmnElement="Task1">
<bpmndi:BPMNShape id="Task1_di" bpmnElement="Task1">
<dc:Bounds x="407" y="14" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0tcm7c4_di" bpmnElement="SequenceFlow1">
<bpmndi:BPMNEdge id="SequenceFlow1_di" bpmnElement="SequenceFlow1">
<di:waypoint xsi:type="dc:Point" x="240" y="54" />
<di:waypoint xsi:type="dc:Point" x="407" y="54" />
<bpmndi:BPMNLabel>
<dc:Bounds x="278.5" y="44" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="EndEvent_19rql6x_di" bpmnElement="EndEvent1">
<bpmndi:BPMNShape id="EndEvent1_di" bpmnElement="EndEvent1">
<dc:Bounds x="649" y="36" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="622" y="72" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0qj8k8s_di" bpmnElement="SequenceFlow2">
<bpmndi:BPMNEdge id="SequenceFlow2_di" bpmnElement="SequenceFlow2">
<di:waypoint xsi:type="dc:Point" x="507" y="54" />
<di:waypoint xsi:type="dc:Point" x="649" y="54" />
<bpmndi:BPMNLabel>
<dc:Bounds x="533" y="44" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="DataStoreReference_0esjm7d_di" bpmnElement="DataStoreReference1">
<dc:Bounds x="642" y="194" width="50" height="50" />
<bpmndi:BPMNShape id="DataStoreReference1_di" bpmnElement="DataStoreReference1">
<dc:Bounds x="642" y="173" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="622" y="244" width="90" height="20" />
<dc:Bounds x="622" y="223" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1109sg9_di" bpmnElement="Task2">
<dc:Bounds x="407" y="179" width="100" height="80" />
<bpmndi:BPMNShape id="Task2_di" bpmnElement="Task2">
<dc:Bounds x="407" y="158" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="IntermediateThrowEvent_0ngofht_di" bpmnElement="IntermediateThrowEvent1">
<dc:Bounds x="204" y="201" width="36" height="36" />
<bpmndi:BPMNShape id="IntermediateThrowEvent1_di" bpmnElement="IntermediateThrowEvent1">
<dc:Bounds x="204" y="180" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="177" y="237" width="90" height="20" />
<dc:Bounds x="177" y="216" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0573259_di" bpmnElement="SequenceFlow3">
<di:waypoint xsi:type="dc:Point" x="240" y="219" />
<di:waypoint xsi:type="dc:Point" x="407" y="219" />
<bpmndi:BPMNEdge id="SequenceFlow3_di" bpmnElement="SequenceFlow3">
<di:waypoint xsi:type="dc:Point" x="240" y="198" />
<di:waypoint xsi:type="dc:Point" x="407" y="198" />
<bpmndi:BPMNLabel>
<dc:Bounds x="278.5" y="209" width="90" height="20" />
<dc:Bounds x="279" y="188" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_1j12zuc_di" bpmnElement="Task3">
<dc:Bounds x="407" y="334" width="100" height="80" />
<bpmndi:BPMNShape id="Task3_di" bpmnElement="Task3">
<dc:Bounds x="407" y="313" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_18wv2tq_di" bpmnElement="SequenceFlow4">
<di:waypoint xsi:type="dc:Point" x="240" y="219" />
<di:waypoint xsi:type="dc:Point" x="324" y="219" />
<di:waypoint xsi:type="dc:Point" x="324" y="374" />
<di:waypoint xsi:type="dc:Point" x="407" y="374" />
<bpmndi:BPMNEdge id="SequenceFlow4_di" bpmnElement="SequenceFlow4">
<di:waypoint xsi:type="dc:Point" x="240" y="198" />
<di:waypoint xsi:type="dc:Point" x="324" y="198" />
<di:waypoint xsi:type="dc:Point" x="324" y="353" />
<di:waypoint xsi:type="dc:Point" x="407" y="353" />
<bpmndi:BPMNLabel>
<dc:Bounds x="279" y="286.5" width="90" height="20" />
<dc:Bounds x="279" y="266" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="StartEvent_00w63ri_di" bpmnElement="StartEvent2">
<dc:Bounds x="439" y="522" width="36" height="36" />
<bpmndi:BPMNShape id="StartEvent2_di" bpmnElement="StartEvent2">
<dc:Bounds x="439" y="501" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="412" y="558" width="90" height="20" />
<dc:Bounds x="412" y="537" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0y0xyjt_di" bpmnElement="SequenceFlow6">
<di:waypoint xsi:type="dc:Point" x="457" y="522" />
<di:waypoint xsi:type="dc:Point" x="457" y="414" />
<bpmndi:BPMNEdge id="SequenceFlow6_di" bpmnElement="SequenceFlow6">
<di:waypoint xsi:type="dc:Point" x="457" y="501" />
<di:waypoint xsi:type="dc:Point" x="457" y="393" />
<bpmndi:BPMNLabel>
<dc:Bounds x="412" y="458" width="90" height="20" />
<dc:Bounds x="412" y="437" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="IntermediateThrowEvent_174hln1_di" bpmnElement="IntermediateThrowEvent2">
<dc:Bounds x="649" y="356" width="36" height="36" />
<bpmndi:BPMNShape id="IntermediateThrowEvent2_di" bpmnElement="IntermediateThrowEvent2">
<dc:Bounds x="649" y="335" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="622" y="392" width="90" height="20" />
<dc:Bounds x="622" y="371" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0ydw9jn_di" bpmnElement="SequenceFlow5">
<di:waypoint xsi:type="dc:Point" x="507" y="374" />
<di:waypoint xsi:type="dc:Point" x="649" y="374" />
<bpmndi:BPMNEdge id="SequenceFlow5_di" bpmnElement="SequenceFlow5">
<di:waypoint xsi:type="dc:Point" x="507" y="353" />
<di:waypoint xsi:type="dc:Point" x="649" y="353" />
<bpmndi:BPMNLabel>
<dc:Bounds x="533" y="364" width="90" height="20" />
<dc:Bounds x="533" y="343" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="DataOutputAssociation_020a5n1_di" bpmnElement="DataOutputAssociation1">
<di:waypoint xsi:type="dc:Point" x="507" y="219" />
<di:waypoint xsi:type="dc:Point" x="642" y="219" />
<bpmndi:BPMNEdge id="DataOutputAssociation1_di" bpmnElement="DataOutputAssociation1">
<di:waypoint xsi:type="dc:Point" x="507" y="198" />
<di:waypoint xsi:type="dc:Point" x="642" y="198" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="StartEvent3_di" bpmnElement="StartEvent3">
<dc:Bounds x="813" y="11" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="786" y="47" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task4_di" bpmnElement="Task4">
<dc:Bounds x="781" y="169" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow7_di" bpmnElement="SequenceFlow7">
<di:waypoint xsi:type="dc:Point" x="831" y="47" />
<di:waypoint xsi:type="dc:Point" x="831" y="169" />
<bpmndi:BPMNLabel>
<dc:Bounds x="801" y="98" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="EndEvent2_di" bpmnElement="EndEvent2">
<dc:Bounds x="813" y="370" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="786" y="406" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow8_di" bpmnElement="SequenceFlow8">
<di:waypoint xsi:type="dc:Point" x="831" y="249" />
<di:waypoint xsi:type="dc:Point" x="831" y="370" />
<bpmndi:BPMNLabel>
<dc:Bounds x="801" y="299.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="0.7.0-dev">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:task id="Task_1">
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="Task_1" targetRef="Task_2" />
<bpmn:task id="Task_2">
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_2</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_10">
<bpmn:outgoing>SequenceFlow_7</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_11">
<bpmn:incoming>SequenceFlow_7</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_8</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_12">
<bpmn:incoming>SequenceFlow_8</bpmn:incoming>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_8" sourceRef="Task_11" targetRef="Task_12" />
<bpmn:task id="Task_4">
<bpmn:incoming>SequenceFlow_Diagonal</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_3</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_5">
<bpmn:incoming>SequenceFlow_3</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_4</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_3" sourceRef="Task_4" targetRef="Task_5" />
<bpmn:task id="Task_6">
<bpmn:incoming>SequenceFlow_4</bpmn:incoming>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_4" sourceRef="Task_5" targetRef="Task_6" />
<bpmn:task id="Task_7">
<bpmn:outgoing>SequenceFlow_5</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_8">
<bpmn:incoming>SequenceFlow_5</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_6</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_5" sourceRef="Task_7" targetRef="Task_8" />
<bpmn:task id="Task_3">
<bpmn:incoming>SequenceFlow_2</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_Diagonal</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="Task_2" targetRef="Task_3" />
<bpmn:task id="Task_9">
<bpmn:incoming>SequenceFlow_6</bpmn:incoming>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_6" sourceRef="Task_8" targetRef="Task_9" />
<bpmn:sequenceFlow id="SequenceFlow_7" sourceRef="Task_10" targetRef="Task_11" />
<bpmn:sequenceFlow id="SequenceFlow_Diagonal" sourceRef="Task_3" targetRef="Task_4" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Task_0z8xi1c_di" bpmnElement="Task_1">
<dc:Bounds x="29.704295704295674" y="43.7112887112887" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1u9fztm_di" bpmnElement="SequenceFlow_1">
<di:waypoint xsi:type="dc:Point" x="130" y="84" />
<di:waypoint xsi:type="dc:Point" x="185" y="84" />
<bpmndi:BPMNLabel>
<dc:Bounds x="112.5" y="59" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0hnbe82_di" bpmnElement="Task_2">
<dc:Bounds x="184.70429570429565" y="44" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_099efka_di" bpmnElement="Task_10">
<dc:Bounds x="442" y="290" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_002sy2a_di" bpmnElement="Task_11">
<dc:Bounds x="589" y="290" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_01u3tfu_di" bpmnElement="Task_12">
<dc:Bounds x="589" y="167" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0t8ndvz_di" bpmnElement="SequenceFlow_8">
<di:waypoint xsi:type="dc:Point" x="639" y="290" />
<di:waypoint xsi:type="dc:Point" x="639" y="247" />
<bpmndi:BPMNLabel>
<dc:Bounds x="609" y="259" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0vbnxvm_di" bpmnElement="Task_4">
<dc:Bounds x="31" y="180.5840707964602" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1fuoxk1_di" bpmnElement="Task_5">
<dc:Bounds x="31" y="297.5840707964602" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1vwmwqi_di" bpmnElement="SequenceFlow_3">
<di:waypoint xsi:type="dc:Point" x="81" y="261" />
<di:waypoint xsi:type="dc:Point" x="81" y="298" />
<bpmndi:BPMNLabel>
<dc:Bounds x="51" y="269.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_09cntqi_di" bpmnElement="Task_6">
<dc:Bounds x="170.0480404551201" y="298" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1tyq2xs_di" bpmnElement="SequenceFlow_4">
<di:waypoint xsi:type="dc:Point" x="131" y="338" />
<di:waypoint xsi:type="dc:Point" x="170" y="338" />
<bpmndi:BPMNLabel>
<dc:Bounds x="105.5" y="313" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_1jxiw7a_di" bpmnElement="Task_7">
<dc:Bounds x="449" y="165" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_0pr4fwc_di" bpmnElement="Task_8">
<dc:Bounds x="449" y="47" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_13zcj99_di" bpmnElement="SequenceFlow_5">
<di:waypoint xsi:type="dc:Point" x="499" y="165" />
<di:waypoint xsi:type="dc:Point" x="499" y="127" />
<bpmndi:BPMNLabel>
<dc:Bounds x="469" y="136" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0lhi5mw_di" bpmnElement="Task_3">
<dc:Bounds x="185" y="162.44707740916272" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1y03bir_di" bpmnElement="SequenceFlow_2">
<di:waypoint xsi:type="dc:Point" x="235" y="124" />
<di:waypoint xsi:type="dc:Point" x="235" y="162" />
<bpmndi:BPMNLabel>
<dc:Bounds x="205" y="133" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0bq0d9m_di" bpmnElement="Task_9">
<dc:Bounds x="588.8672985781991" y="47" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0k5d9gz_di" bpmnElement="SequenceFlow_6">
<di:waypoint xsi:type="dc:Point" x="549" y="87" />
<di:waypoint xsi:type="dc:Point" x="589" y="87" />
<bpmndi:BPMNLabel>
<dc:Bounds x="524" y="62" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1473jag_di" bpmnElement="SequenceFlow_7">
<di:waypoint xsi:type="dc:Point" x="542" y="330" />
<di:waypoint xsi:type="dc:Point" x="589" y="330" />
<bpmndi:BPMNLabel>
<dc:Bounds x="520.5" y="305" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_Diagonal_di" bpmnElement="SequenceFlow_Diagonal">
<di:waypoint xsi:type="dc:Point" x="185" y="184" />
<di:waypoint xsi:type="dc:Point" x="131" y="198" />
<bpmndi:BPMNLabel>
<dc:Bounds x="113" y="166" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -5,36 +5,198 @@
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() {
describe('parallel connections', function() {
var processDiagramXML = require('./RemoveElementBehavior.bpmn');
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
it('horizontal', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task1');
// when
modeling.removeShape(task);
// then
var sequenceFlow1 = elementRegistry.get('SequenceFlow1');
var waypoints = sequenceFlow1.waypoints;
// SequenceFlow2 should be deleted
expect(elementRegistry.get(task.id)).to.be.undefined;
expect(sequenceFlow1).to.not.be.undefined;
expect(elementRegistry.get('SequenceFlow2')).to.be.undefined;
// source and target have one connection each
expect(elementRegistry.get('StartEvent1').outgoing.length).to.be.equal(1);
expect(elementRegistry.get('EndEvent1').incoming.length).to.be.equal(1);
// connection has two horizontally equal waypoints
expect(waypoints).to.have.length(2);
expect(waypoints[0].y).to.eql(waypoints[1].y);
}));
it('vertical', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task4');
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow7').waypoints;
// connection has two vertically equal waypoints
expect(waypoints).to.have.length(2);
expect(waypoints[0].x).to.eql(waypoints[1].x);
}));
});
describe('perpendicular connections', function() {
var gatewayDiagramXML = require('./RemoveElementBehavior.perpendicular.bpmn');
beforeEach(bootstrapModeler(gatewayDiagramXML, { modules: testModules }));
it('right-down', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task_2');
var mid = {
x : task.x + task.width / 2,
y : task.y + task.height / 2
};
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow_1').waypoints;
expect(waypoints).to.have.length(3);
var intersec = waypoints[1];
expect(intersec).to.eql(point(mid));
}));
it('right-up', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task_11');
var mid = {
x : task.x + task.width / 2,
y : task.y + task.height / 2
};
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow_7').waypoints;
expect(waypoints).to.have.length(3);
var intersec = waypoints[1];
expect(intersec).to.eql(point(mid));
}));
it('down-right', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task_5');
var mid = {
x : task.x + task.width / 2,
y : task.y + task.height / 2
};
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow_3').waypoints;
expect(waypoints).to.have.length(3);
var intersec = waypoints[1];
expect(intersec).to.eql(point(mid));
}));
it('up-right', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task_8');
var mid = {
x : task.x + task.width / 2,
y : task.y + task.height / 2
};
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow_5').waypoints;
expect(waypoints).to.have.length(3);
var intersec = waypoints[1];
expect(intersec).to.eql(point(mid));
}));
it('diagonal', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task_4');
var mid = {
x: task.x + task.width / 2,
y: 211
};
// when
modeling.removeShape(task);
// then
var waypoints = elementRegistry.get('SequenceFlow_Diagonal').waypoints;
expect(waypoints).to.have.length(3);
var intersec = waypoints[1];
expect(intersec).to.eql(point(mid));
}));
});
});
describe('do not combine sequence flows ', 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) {
it('remove all if there are more than one incoming or outgoing', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task3');
@ -54,7 +216,7 @@ describe('features/modeling - remove element behavior', function() {
}));
it('should not combine not allowed connection', inject(function(modeling, elementRegistry) {
it('when connection is not allowed', inject(function(modeling, elementRegistry) {
// given
var task = elementRegistry.get('Task2');
@ -75,3 +237,15 @@ describe('features/modeling - remove element behavior', function() {
});
});
////////////////////////// helper /////////////////////////////////
function point(p) {
return {
x: p.x,
y: p.y
};
}

View File

@ -0,0 +1,33 @@
'use strict';
require('../../../../../TestHelper');
var intersection = require('lib/features/modeling/behavior/util/LineIntersect');
describe('modeling/behavior/util - LineIntersect', function() {
it('should compute intersections', function() {
expect(intersection(
{ x: 10, y: 20 }, { x: 50, y: 50 },
{ x: 10, y: 50 }, { x: 50, y: 50 }
)).to.eql({ x: 50, y: 50 });
expect(intersection(
{ x: 10, y: 20 }, { x: 10, y: 50 },
{ x: 10, y: 50 }, { x: 50, y: 50 }
)).to.eql({ x: 10, y: 50 });
expect(intersection(
{ x: 50, y: 50 }, { x: 10, y: 40 },
{ x: 10, y: 50 }, { x: 50, y: 50 }
)).to.eql({ x: 50, y: 50 });
expect(intersection(
{ x: 0, y: 0 }, { x: 100, y: 100 },
{ x: 40, y: 0 }, { x: 30, y: 10 }
)).to.eql({ x: 20, y: 20 });
});
});