feat(modeling): adjust label location based on free space
Reacts on connection create, layout, reconnect and waypoint update to find a suitable place for the label and reposition it. Closes #738
This commit is contained in:
parent
a830c1e1e0
commit
5761e01ffe
|
@ -0,0 +1,189 @@
|
|||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var getOrientation = require('diagram-js/lib/layout/LayoutUtil').getOrientation,
|
||||
getMid = require('diagram-js/lib/layout/LayoutUtil').getMid,
|
||||
asTRBL = require('diagram-js/lib/layout/LayoutUtil').asTRBL,
|
||||
substract = require('diagram-js/lib/util/Math').substract;
|
||||
|
||||
var LabelUtil = require('../../../util/LabelUtil');
|
||||
|
||||
var hasExternalLabel = LabelUtil.hasExternalLabel;
|
||||
|
||||
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
|
||||
|
||||
|
||||
/**
|
||||
* A component that makes sure that external labels are added
|
||||
* together with respective elements and properly updated (DI wise)
|
||||
* during move.
|
||||
*
|
||||
* @param {EventBus} eventBus
|
||||
* @param {Modeling} modeling
|
||||
*/
|
||||
function AdaptiveLabelPositioningBehavior(eventBus, modeling) {
|
||||
|
||||
CommandInterceptor.call(this, eventBus);
|
||||
|
||||
this.postExecuted([
|
||||
'connection.create',
|
||||
'connection.layout',
|
||||
'connection.reconnectEnd',
|
||||
'connection.reconnectStart',
|
||||
'connection.updateWaypoints'
|
||||
], function(event) {
|
||||
|
||||
var context = event.context,
|
||||
connection = context.connection;
|
||||
|
||||
var source = connection.source,
|
||||
target = connection.target;
|
||||
|
||||
checkLabelAdjustment(source);
|
||||
checkLabelAdjustment(target);
|
||||
});
|
||||
|
||||
|
||||
function checkLabelAdjustment(element) {
|
||||
|
||||
// skip hidden or non-existing labels
|
||||
if (!hasExternalLabel(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var optimalPosition = getOptimalPosition(element);
|
||||
|
||||
// no optimal position found
|
||||
if (!optimalPosition) {
|
||||
return;
|
||||
}
|
||||
|
||||
adjustLabelPosition(element, optimalPosition);
|
||||
}
|
||||
|
||||
var ELEMENT_LABEL_DISTANCE = 10;
|
||||
|
||||
function adjustLabelPosition(element, orientation) {
|
||||
|
||||
var elementMid = getMid(element),
|
||||
label = element.label,
|
||||
labelMid = getMid(label);
|
||||
|
||||
var elementTrbl = asTRBL(element);
|
||||
|
||||
var newLabelMid;
|
||||
|
||||
switch (orientation) {
|
||||
case 'top':
|
||||
newLabelMid = {
|
||||
x: elementMid.x,
|
||||
y: elementTrbl.top - ELEMENT_LABEL_DISTANCE - label.height / 2
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case 'left':
|
||||
|
||||
newLabelMid = {
|
||||
x: elementTrbl.left - ELEMENT_LABEL_DISTANCE - label.width / 2,
|
||||
y: elementMid.y
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case 'bottom':
|
||||
|
||||
newLabelMid = {
|
||||
x: elementMid.x,
|
||||
y: elementTrbl.bottom + ELEMENT_LABEL_DISTANCE + label.height / 2
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case 'right':
|
||||
|
||||
newLabelMid = {
|
||||
x: elementTrbl.right + ELEMENT_LABEL_DISTANCE + label.width / 2,
|
||||
y: elementMid.y
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
var delta = substract(newLabelMid, labelMid);
|
||||
|
||||
modeling.moveShape(label, delta);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
inherits(AdaptiveLabelPositioningBehavior, CommandInterceptor);
|
||||
|
||||
AdaptiveLabelPositioningBehavior.$inject = [
|
||||
'eventBus',
|
||||
'modeling'
|
||||
];
|
||||
|
||||
module.exports = AdaptiveLabelPositioningBehavior;
|
||||
|
||||
/**
|
||||
* Return the optimal label position around an element
|
||||
* or _undefined_, if none was found.
|
||||
*
|
||||
* @param {Shape} element
|
||||
*
|
||||
* @return {String} positioning identifier
|
||||
*/
|
||||
function getOptimalPosition(element) {
|
||||
|
||||
var labelMid = getMid(element.label);
|
||||
|
||||
var elementMid = getMid(element);
|
||||
|
||||
var labelOrientation = getApproximateOrientation(elementMid, labelMid);
|
||||
|
||||
if (!isAligned(labelOrientation)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var takenAlignments = [].concat(
|
||||
element.incoming.map(function(c) {
|
||||
return c.waypoints[c.waypoints.length - 2 ];
|
||||
}),
|
||||
element.outgoing.map(function(c) {
|
||||
return c.waypoints[1];
|
||||
})
|
||||
).map(function(point) {
|
||||
return getApproximateOrientation(elementMid, point);
|
||||
});
|
||||
|
||||
var freeAlignments = ALIGNMENTS.filter(function(alignment) {
|
||||
|
||||
return takenAlignments.indexOf(alignment) === -1;
|
||||
});
|
||||
|
||||
// NOTHING TO DO; label already aligned a.O.K.
|
||||
if (freeAlignments.indexOf(labelOrientation) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
return freeAlignments[0];
|
||||
}
|
||||
|
||||
var ALIGNMENTS = [
|
||||
'top',
|
||||
'bottom',
|
||||
'left',
|
||||
'right'
|
||||
];
|
||||
|
||||
function getApproximateOrientation(p0, p1) {
|
||||
return getOrientation(p1, p0, 5);
|
||||
}
|
||||
|
||||
function isAligned(orientation) {
|
||||
return ALIGNMENTS.indexOf(orientation) !== -1;
|
||||
}
|
|
@ -1,44 +1,46 @@
|
|||
module.exports = {
|
||||
__init__: [
|
||||
'adaptiveLabelPositioningBehavior',
|
||||
'appendBehavior',
|
||||
'copyPasteBehavior',
|
||||
'createBoundaryEventBehavior',
|
||||
'createDataObjectBehavior',
|
||||
'dropOnFlowBehavior',
|
||||
'createParticipantBehavior',
|
||||
'dataInputAssociationBehavior',
|
||||
'deleteLaneBehavior',
|
||||
'dropOnFlowBehavior',
|
||||
'importDockingFix',
|
||||
'labelBehavior',
|
||||
'modelingFeedback',
|
||||
'removeElementBehavior',
|
||||
'removeParticipantBehavior',
|
||||
'replaceConnectionBehavior',
|
||||
'replaceElementBehaviour',
|
||||
'resizeLaneBehavior',
|
||||
'unsetDefaultFlowBehavior',
|
||||
'updateFlowNodeRefsBehavior',
|
||||
'removeElementBehavior',
|
||||
'toggleElementCollapseBehaviour',
|
||||
'unclaimIdBehavior',
|
||||
'toggleElementCollapseBehaviour'
|
||||
'unsetDefaultFlowBehavior',
|
||||
'updateFlowNodeRefsBehavior'
|
||||
],
|
||||
adaptiveLabelPositioningBehavior: [ 'type', require('./AdaptiveLabelPositioningBehavior') ],
|
||||
appendBehavior: [ 'type', require('./AppendBehavior') ],
|
||||
copyPasteBehavior: [ 'type', require('./CopyPasteBehavior') ],
|
||||
createBoundaryEventBehavior: [ 'type', require('./CreateBoundaryEventBehavior') ],
|
||||
createDataObjectBehavior: [ 'type', require('./CreateDataObjectBehavior') ],
|
||||
dropOnFlowBehavior: [ 'type', require('./DropOnFlowBehavior') ],
|
||||
createParticipantBehavior: [ 'type', require('./CreateParticipantBehavior') ],
|
||||
dataInputAssociationBehavior: [ 'type', require('./DataInputAssociationBehavior') ],
|
||||
deleteLaneBehavior: [ 'type', require('./DeleteLaneBehavior') ],
|
||||
dropOnFlowBehavior: [ 'type', require('./DropOnFlowBehavior') ],
|
||||
importDockingFix: [ 'type', require('./ImportDockingFix') ],
|
||||
labelBehavior: [ 'type', require('./LabelBehavior') ],
|
||||
modelingFeedback: [ 'type', require('./ModelingFeedback') ],
|
||||
removeParticipantBehavior: [ 'type', require('./RemoveParticipantBehavior') ],
|
||||
replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ],
|
||||
removeParticipantBehavior: [ 'type', require('./RemoveParticipantBehavior') ],
|
||||
replaceElementBehaviour: [ 'type', require('./ReplaceElementBehaviour') ],
|
||||
resizeLaneBehavior: [ 'type', require('./ResizeLaneBehavior') ],
|
||||
unsetDefaultFlowBehavior: [ 'type', require('./UnsetDefaultFlowBehavior') ],
|
||||
updateFlowNodeRefsBehavior: [ 'type', require('./UpdateFlowNodeRefsBehavior') ],
|
||||
removeElementBehavior: [ 'type', require('./RemoveElementBehavior') ],
|
||||
toggleElementCollapseBehaviour : [ 'type', require('./ToggleElementCollapseBehaviour') ],
|
||||
unclaimIdBehavior: [ 'type', require('./UnclaimIdBehavior') ],
|
||||
toggleElementCollapseBehaviour : [ 'type', require('./ToggleElementCollapseBehaviour') ]
|
||||
updateFlowNodeRefsBehavior: [ 'type', require('./UpdateFlowNodeRefsBehavior') ],
|
||||
unsetDefaultFlowBehavior: [ 'type', require('./UnsetDefaultFlowBehavior') ]
|
||||
};
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="sid-38422fae-e03e-43a3-bef4-bd33b32041b2" targetNamespace="http://bpmn.io/bpmn" exporter="http://bpmn.io" exporterVersion="0.10.1">
|
||||
<process id="Process_1" isExecutable="false">
|
||||
<exclusiveGateway id="LabelBottom" name="BOTTOM" />
|
||||
<exclusiveGateway id="LabelLeft" name="LEFT" />
|
||||
<exclusiveGateway id="LabelTop" name="TOP">
|
||||
<outgoing>SequenceFlow_1</outgoing>
|
||||
</exclusiveGateway>
|
||||
<exclusiveGateway id="LabelRight" name="RIGHT">
|
||||
<outgoing>SequenceFlow_2</outgoing>
|
||||
</exclusiveGateway>
|
||||
<exclusiveGateway id="LabelBottomLeft" name="BOTTOM_LEFT" />
|
||||
<exclusiveGateway id="LabelBottom_2" name="BOTTOM_2">
|
||||
<incoming>SequenceFlow_2</incoming>
|
||||
</exclusiveGateway>
|
||||
<exclusiveGateway id="LabelBottom_3" name="BOTTOM_3">
|
||||
<incoming>SequenceFlow_1</incoming>
|
||||
</exclusiveGateway>
|
||||
<sequenceFlow id="SequenceFlow_1" name="1" sourceRef="LabelTop" targetRef="LabelBottom_3" />
|
||||
<sequenceFlow id="SequenceFlow_2" name="2" sourceRef="LabelRight" targetRef="LabelBottom_2" />
|
||||
<exclusiveGateway id="LabelImpossible" name="IMPOSSIBLE">
|
||||
<incoming>SequenceFlow_1qmllcx</incoming>
|
||||
<incoming>SequenceFlow_0s993e4</incoming>
|
||||
<incoming>SequenceFlow_022at7e</incoming>
|
||||
</exclusiveGateway>
|
||||
<task id="Task">
|
||||
<outgoing>SequenceFlow_1qmllcx</outgoing>
|
||||
<outgoing>SequenceFlow_0s993e4</outgoing>
|
||||
<outgoing>SequenceFlow_022at7e</outgoing>
|
||||
</task>
|
||||
<sequenceFlow id="SequenceFlow_1qmllcx" sourceRef="Task" targetRef="LabelImpossible" />
|
||||
<sequenceFlow id="SequenceFlow_0s993e4" sourceRef="Task" targetRef="LabelImpossible" />
|
||||
<sequenceFlow id="SequenceFlow_022at7e" sourceRef="Task" targetRef="LabelImpossible" />
|
||||
</process>
|
||||
<bpmndi:BPMNDiagram id="BpmnDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BpmnPlane_1" bpmnElement="Process_1">
|
||||
<bpmndi:BPMNShape id="LabelBottom_di" bpmnElement="LabelBottom" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="113" y="89" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="107" y="129" width="49" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelLeft_di" bpmnElement="LabelLeft" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="309" y="82" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="263" y="101" width="30" height="24" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelTop_di" bpmnElement="LabelTop" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="309" y="225" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="322" y="198" width="24" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelRight_di" bpmnElement="LabelRight" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="106" y="225" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="168" y="244" width="37" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelBottomLeft_di" bpmnElement="LabelBottomLeft" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="532" y="82" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="487" y="146" width="83" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelBottom_2_di" bpmnElement="LabelBottom_2" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="106" y="370" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="101" y="424" width="61" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="LabelBottom_3_di" bpmnElement="LabelBottom_3" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="309" y="370" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="304" y="424" width="61" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_1_di" bpmnElement="SequenceFlow_1">
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="334" y="275" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="334" y="370" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="346" y="317" width="7" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_2_di" bpmnElement="SequenceFlow_2">
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="131" y="275" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="131" y="370" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="142" y="317" width="8" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="LabelImpossible_di" bpmnElement="LabelImpossible" isMarkerVisible="true">
|
||||
<omgdc:Bounds x="633" y="308" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="694" y="327" width="68" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Task_di" bpmnElement="Task">
|
||||
<omgdc:Bounds x="776" y="293" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_1qmllcx_di" bpmnElement="SequenceFlow_1qmllcx">
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="826" y="293" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="826" y="202" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="658" y="202" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="658" y="308" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="742" y="181" width="0" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_0s993e4_di" bpmnElement="SequenceFlow_0s993e4">
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="826" y="373" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="826" y="424" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="658" y="424" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="658" y="358" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="742" y="403" width="0" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_022at7e_di" bpmnElement="SequenceFlow_022at7e">
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="845" y="373" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="845" y="453" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="594" y="453" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="594" y="333" />
|
||||
<omgdi:waypoint xsi:type="omgdc:Point" x="633" y="333" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<omgdc:Bounds x="719.5" y="432" width="0" height="12" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</definitions>
|
|
@ -0,0 +1,241 @@
|
|||
'use strict';
|
||||
|
||||
require('../../../../TestHelper');
|
||||
|
||||
/* global bootstrapModeler, inject */
|
||||
|
||||
var getOrientation = require('diagram-js/lib/layout/LayoutUtil').getOrientation;
|
||||
|
||||
var modelingModule = require('../../../../../lib/features/modeling'),
|
||||
coreModule = require('../../../../../lib/core');
|
||||
|
||||
|
||||
describe('modeling/behavior - AdaptiveLabelPositioningBehavior', function() {
|
||||
|
||||
var diagramXML = require('./AdaptiveLabelPositioningBehavior.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(diagramXML, {
|
||||
modules: [
|
||||
modelingModule,
|
||||
coreModule
|
||||
]
|
||||
}));
|
||||
|
||||
|
||||
function expectLabelOrientation(element, expectedOrientation) {
|
||||
|
||||
var label = element.label;
|
||||
|
||||
// assume
|
||||
expect(label).to.exist;
|
||||
|
||||
// when
|
||||
var orientation = getOrientation(label, element);
|
||||
|
||||
// then
|
||||
expect(orientation).to.eql(expectedOrientation);
|
||||
}
|
||||
|
||||
|
||||
describe('on connect', function() {
|
||||
|
||||
it('should move label from LEFT to TOP', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelBottom'),
|
||||
target = elementRegistry.get('LabelLeft');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'bottom');
|
||||
expectLabelOrientation(target, 'top');
|
||||
}));
|
||||
|
||||
|
||||
it('should move label from BOTTOM to TOP', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelBottom'),
|
||||
target = elementRegistry.get('LabelRight');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'top');
|
||||
expectLabelOrientation(target, 'right');
|
||||
}));
|
||||
|
||||
|
||||
it('should move label from RIGHT to TOP', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelRight'),
|
||||
target = elementRegistry.get('LabelTop');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'top');
|
||||
expectLabelOrientation(target, 'top');
|
||||
}));
|
||||
|
||||
|
||||
it('should move label from TOP to LEFT', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelTop'),
|
||||
target = elementRegistry.get('LabelLeft');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'left');
|
||||
expectLabelOrientation(target, 'left');
|
||||
}));
|
||||
|
||||
|
||||
it('should move label from TOP to LEFT', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelTop'),
|
||||
target = elementRegistry.get('LabelLeft');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'left');
|
||||
expectLabelOrientation(target, 'left');
|
||||
}));
|
||||
|
||||
|
||||
it('should move label from TOP to LEFT (inverse)', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelLeft'),
|
||||
target = elementRegistry.get('LabelTop');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(target, 'left');
|
||||
expectLabelOrientation(source, 'left');
|
||||
}));
|
||||
|
||||
|
||||
it('should keep unaligned labels AS IS', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelBottomLeft'),
|
||||
target = elementRegistry.get('LabelTop');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'bottom');
|
||||
expectLabelOrientation(target, 'top');
|
||||
}));
|
||||
|
||||
|
||||
it('should keep label where it is, if no options', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelImpossible'),
|
||||
target = elementRegistry.get('Task');
|
||||
|
||||
// when
|
||||
modeling.connect(source, target);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'right');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('on reconnect', function() {
|
||||
|
||||
it('should move label from TOP to BOTTOM', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var connection = elementRegistry.get('SequenceFlow_1'),
|
||||
source = elementRegistry.get('LabelTop'),
|
||||
target = elementRegistry.get('LabelLeft');
|
||||
|
||||
// when
|
||||
modeling.reconnectEnd(connection, target, { x: target.x + target.width / 2, y: target.y });
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'bottom');
|
||||
expectLabelOrientation(target, 'left');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('on target move / layout', function() {
|
||||
|
||||
it('should move label from TOP to BOTTOM', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var source = elementRegistry.get('LabelTop'),
|
||||
target = elementRegistry.get('LabelBottom_3');
|
||||
|
||||
// when
|
||||
modeling.moveElements([ source ], { x: 0, y: 300 });
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'bottom');
|
||||
expectLabelOrientation(target, 'top');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('on waypoints update', function() {
|
||||
|
||||
it('should move label from RIGHT to TOP', inject(function(elementRegistry, modeling) {
|
||||
|
||||
// given
|
||||
var connection = elementRegistry.get('SequenceFlow_2'),
|
||||
source = elementRegistry.get('LabelRight'),
|
||||
target = elementRegistry.get('LabelBottom');
|
||||
|
||||
// when
|
||||
modeling.updateWaypoints(connection, [
|
||||
{
|
||||
original: { x: 131, y: 248 },
|
||||
x: 131,
|
||||
y: 248
|
||||
},
|
||||
{
|
||||
x: 250,
|
||||
y: 248
|
||||
},
|
||||
{
|
||||
x: 250,
|
||||
y: 394
|
||||
},
|
||||
{
|
||||
original: { x: 131, y: 394 },
|
||||
x: 131,
|
||||
y: 394
|
||||
},
|
||||
]);
|
||||
|
||||
// then
|
||||
expectLabelOrientation(source, 'top');
|
||||
expectLabelOrientation(target, 'bottom');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
Loading…
Reference in New Issue