feat(labels): labels can be deleted

Related to camunda/camunda-modeler#243
This commit is contained in:
Philipp Fromme 2018-04-30 11:06:26 +02:00 committed by Nico Rehwaldt
parent 114c81d763
commit 7537757357
25 changed files with 414 additions and 382 deletions

View File

@ -6,6 +6,7 @@ All notable changes to [bpmn-js](https://github.com/bpmn-io/bpmn-js) are documen
___Note:__ Yet to be released changes appear here._
* `FEAT`: external labels can be deleted, clearing the elements name ([#791](https://github.com/bpmn-io/bpmn-js/pull/791))
* `FEAT`: add ability to define default element colors ([#713](https://github.com/bpmn-io/bpmn-js/issues/713))
## 2.0.1

View File

@ -2,6 +2,9 @@ import {
isAny
} from '../modeling/util/ModelingUtil';
import {
isLabel
} from '../../util/LabelUtil';
/**
* Extention of GlobalConnect tool that implements BPMN specific rules about
@ -41,8 +44,4 @@ function nonExistantOrLabel(element) {
return !element || isLabel(element);
}
function isLabel(element) {
return element.labelTarget;
}

View File

@ -10,6 +10,13 @@ import { is } from '../../util/ModelUtil';
import { isAny } from '../modeling/util/ModelingUtil';
import { isExpanded } from '../../util/DiUtil';
import {
getExternalLabelMid,
isLabelExternal,
hasExternalLabel,
isLabel
} from '../../util/LabelUtil';
var SMALL_FONT_SIZE = 11,
SMALL_LINE_HEIGHT = 13,
MEDIUM_FONT_SIZE = 12,
@ -131,9 +138,6 @@ LabelEditingProvider.prototype.activate = function(element) {
assign(context, bounds);
// options
var target = element.label || element;
var options = {};
// tasks
@ -152,7 +156,7 @@ LabelEditingProvider.prototype.activate = function(element) {
}
// external labels
if (target.labelTarget) {
if (isLabelExternal(element)) {
assign(options, {
autoResize: true
});
@ -268,13 +272,12 @@ LabelEditingProvider.prototype.getEditingBBox = function(element) {
});
}
var width = 90 * zoom,
paddingTop = 7 * zoom,
paddingBottom = 4 * zoom;
// external labels for events, data elements, gateways and connections
if (target.labelTarget) {
var width = 90 * zoom,
paddingTop = 7 * zoom,
paddingBottom = 4 * zoom;
assign(bounds, {
width: width,
height: bbox.height + paddingTop + paddingBottom,
@ -290,6 +293,36 @@ LabelEditingProvider.prototype.getEditingBBox = function(element) {
});
}
// external label not yet created
if (isLabelExternal(target)
&& !hasExternalLabel(target)
&& !isLabel(target)) {
var externalLabelMid = getExternalLabelMid(element);
var absoluteBBox = canvas.getAbsoluteBBox({
x: externalLabelMid.x,
y: externalLabelMid.y,
width: 0,
height: 0
});
var height = smallFontSize + paddingTop + paddingBottom;
assign(bounds, {
width: width,
height: height,
x: absoluteBBox.x - width / 2,
y: absoluteBBox.y - height / 2
});
assign(style, {
fontSize: smallFontSize + 'px',
lineHeight: smallLineHeight + 'px',
paddingTop: paddingTop + 'px',
paddingBottom: paddingBottom + 'px'
});
}
// text annotations
if (is(element, 'bpmn:TextAnnotation')) {

View File

@ -33,10 +33,5 @@ export function setLabel(element, text, isExternal) {
semantic[attr] = text;
}
// show external label if not empty
if (isExternal) {
element.hidden = !text;
}
return element;
}

View File

@ -6,7 +6,10 @@ import {
import TextUtil from 'diagram-js/lib/util/Text';
import {
hasExternalLabel
getExternalLabelMid,
isLabelExternal,
hasExternalLabel,
isLabel
} from '../../../util/LabelUtil';
import {
@ -47,6 +50,33 @@ export default function UpdateLabelHandler(modeling) {
return [ label, labelTarget ];
}
function preExecute(ctx) {
var element = ctx.element,
businessObject = element.businessObject,
newLabel = ctx.newLabel;
if (!isLabel(element)
&& isLabelExternal(element)
&& !hasExternalLabel(element)
&& newLabel !== '') {
// create label
var paddingTop = 7;
var labelCenter = getExternalLabelMid(element);
labelCenter = {
x: labelCenter.x,
y: labelCenter.y + paddingTop
};
modeling.createLabel(element, labelCenter, {
id: businessObject.id + '_label',
businessObject: businessObject
});
}
}
function execute(ctx) {
ctx.oldLabel = getLabel(ctx.element);
return setText(ctx.element, ctx.newLabel);
@ -59,10 +89,17 @@ export default function UpdateLabelHandler(modeling) {
function postExecute(ctx) {
var element = ctx.element,
label = element.label || element,
newLabel = ctx.newLabel,
newBounds = ctx.newBounds;
if (isLabel(label) && newLabel.trim() === '') {
modeling.removeShape(label);
return;
}
// ignore internal labels for elements except text annotations
if (!hasExternalLabel(element) && !is(element, 'bpmn:TextAnnotation')) {
if (!isLabelExternal(element) && !is(element, 'bpmn:TextAnnotation')) {
return;
}
@ -89,6 +126,7 @@ export default function UpdateLabelHandler(modeling) {
// API
this.preExecute = preExecute;
this.execute = execute;
this.revert = revert;
this.postExecute = postExecute;

View File

@ -50,7 +50,7 @@ export default function AdaptiveLabelPositioningBehavior(eventBus, modeling) {
function checkLabelAdjustment(element) {
// skip hidden or non-existing labels
// skip non-existing labels
if (!hasExternalLabel(element)) {
return;
}

View File

@ -10,7 +10,7 @@ import {
} from '../../../util/ModelUtil';
import {
hasExternalLabel,
isLabelExternal,
getExternalLabelMid,
} from '../../../util/LabelUtil';
@ -43,16 +43,30 @@ export default function LabelBehavior(eventBus, modeling, bpmnFactory) {
var textUtil = new TextUtil();
// update label if name property was updated
this.postExecute('element.updateProperties', function(e) {
var context = e.context,
element = context.element,
properties = context.properties;
// create external labels on shape creation
if (name in properties) {
modeling.updateLabel(element, name);
}
});
// create label shape after shape/connection was created
this.postExecute([ 'shape.create', 'connection.create' ], function(e) {
var context = e.context;
var element = context.shape || context.connection,
businessObject = element.businessObject;
if (!hasExternalLabel(element)) {
if (!isLabelExternal(element)) {
return;
}
// only create label if name
if (!businessObject.name) {
return;
}
@ -67,19 +81,28 @@ export default function LabelBehavior(eventBus, modeling, bpmnFactory) {
modeling.createLabel(element, labelCenter, {
id: businessObject.id + '_label',
hidden: !businessObject.name,
businessObject: businessObject,
width: labelDimensions.width,
height: labelDimensions.height
});
});
// update label after label shape was deleted
this.postExecute('shape.delete', function(event) {
var context = event.context,
shape = context;
// check if label
if (shape.labelTarget) {
modeling.updateLabel(shape.labelTarget, '');
}
});
// update di information on label creation
this.postExecute([ 'label.create' ], function(event) {
this.executed([ 'label.create' ], function(event) {
var element = event.context.shape,
var context = event.context,
element = context.shape,
businessObject,
di;
@ -111,23 +134,6 @@ export default function LabelBehavior(eventBus, modeling, bpmnFactory) {
});
});
// update label position on connection change
function getHiddenLabelAdjustment(event) {
var context = event.context,
connection = context.connection,
label = connection.label;
var labelPosition = getExternalLabelMid(connection);
return {
x: labelPosition.x - label.x - label.width / 2,
y: labelPosition.y - label.y - label.height / 2
};
}
function getVisibleLabelAdjustment(event) {
var command = event.command,
@ -164,18 +170,13 @@ export default function LabelBehavior(eventBus, modeling, bpmnFactory) {
return;
}
if (label.hidden) {
labelAdjustment = getHiddenLabelAdjustment(event);
} else {
labelAdjustment = getVisibleLabelAdjustment(event);
}
labelAdjustment = getVisibleLabelAdjustment(event);
modeling.moveShape(label, labelAdjustment);
});
// keep label position on shape replace
this.postExecute([ 'shape.replace' ], function(event) {
var context = event.context,
newShape = context.newShape,
@ -183,7 +184,10 @@ export default function LabelBehavior(eventBus, modeling, bpmnFactory) {
var businessObject = getBusinessObject(newShape);
if (businessObject && hasExternalLabel(businessObject)) {
if (businessObject
&& isLabelExternal(businessObject)
&& oldShape.label
&& newShape.label) {
newShape.label.x = oldShape.label.x;
newShape.label.y = oldShape.label.y;
}

View File

@ -12,7 +12,6 @@ import {
import TextUtil from 'diagram-js/lib/util/Text';
var DEFAULT_FLOW = 'default',
NAME = 'name',
ID = 'id',
DI = 'di';
@ -96,13 +95,6 @@ UpdatePropertiesHandler.prototype.execute = function(context) {
}
}
if (NAME in properties && element.label) {
changed.push(element.label);
// show the label
element.label.hidden = !properties[NAME];
}
// update properties
setProperties(businessObject, properties);

View File

@ -2,7 +2,6 @@ import {
find,
some,
every,
filter,
forEach
} from 'min-dash';
@ -17,6 +16,10 @@ import {
isAny
} from '../modeling/util/ModelingUtil';
import {
isLabel
} from '../../util/LabelUtil';
import {
isExpanded,
isEventSubProcess,
@ -165,14 +168,6 @@ BpmnRules.prototype.init = function() {
return canPaste(tree, target);
});
this.addRule([ 'elements.delete' ], function(context) {
// do not allow deletion of labels
return filter(context.elements, function(e) {
return !isLabel(e);
});
});
};
BpmnRules.prototype.canConnectMessageFlow = canConnectMessageFlow;
@ -353,10 +348,6 @@ function isEventBasedTarget(element) {
);
}
function isLabel(element) {
return element.labelTarget;
}
function isConnection(element) {
return element.waypoints;
}

View File

@ -8,7 +8,7 @@ import TextUtil from 'diagram-js/lib/util/Text';
import { is } from '../util/ModelUtil';
import {
hasExternalLabel,
isLabelExternal,
getExternalLabelBounds
} from '../util/LabelUtil';
@ -178,7 +178,7 @@ BpmnImporter.prototype.add = function(semantic, parentElement) {
}));
}
// (optional) LABEL
if (hasExternalLabel(semantic)) {
if (isLabelExternal(semantic) && semantic.name) {
this.addLabel(semantic, element);
}

View File

@ -19,7 +19,7 @@ export var FLOW_LABEL_INDENT = 15;
* @param {BpmnElement} semantic
* @return {Boolean} true if has label
*/
export function hasExternalLabel(semantic) {
export function isLabelExternal(semantic) {
return is(semantic, 'bpmn:Event') ||
is(semantic, 'bpmn:Gateway') ||
is(semantic, 'bpmn:DataStoreReference') ||
@ -28,6 +28,16 @@ export function hasExternalLabel(semantic) {
is(semantic, 'bpmn:MessageFlow');
}
/**
* Returns true if the given element has an external label
*
* @param {djs.model.shape} element
* @return {Boolean} true if has label
*/
export function hasExternalLabel(element) {
return isLabel(element.label);
}
/**
* Get the position for sequence flow labels
*
@ -133,3 +143,7 @@ export function getExternalLabelBounds(semantic, element) {
y: mid.y - size.height / 2
}, size);
}
export function isLabel(element) {
return element && element.labelTarget;
}

View File

@ -0,0 +1,20 @@
<?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:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.14.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1" name="foo" />
<bpmn:task id="Task_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="173" y="102" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="183" y="138" width="17" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1_di" bpmnElement="Task_1">
<dc:Bounds x="353" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

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="1.14.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1" name="KEEP ME">
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
@ -22,7 +22,7 @@
<bpmn:subProcess id="SubProcess_1">
<bpmn:incoming>SequenceFlow_7</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_6</bpmn:outgoing>
<bpmn:startEvent id="StartEvent_2">
<bpmn:startEvent id="StartEvent_2" name="foo">
<bpmn:outgoing>SequenceFlow_4</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_2">
@ -70,8 +70,8 @@
<dc:Bounds x="274" y="12" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1_di" bpmnElement="SequenceFlow_1">
<di:waypoint xsi:type="dc:Point" x="135" y="52" />
<di:waypoint xsi:type="dc:Point" x="274" y="52" />
<di:waypoint x="135" y="52" />
<di:waypoint x="274" y="52" />
<bpmndi:BPMNLabel>
<dc:Bounds x="239" y="42" width="90" height="20" />
</bpmndi:BPMNLabel>
@ -83,8 +83,8 @@
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_2_di" bpmnElement="SequenceFlow_2">
<di:waypoint xsi:type="dc:Point" x="374" y="52" />
<di:waypoint xsi:type="dc:Point" x="501" y="52" />
<di:waypoint x="374" y="52" />
<di:waypoint x="501" y="52" />
<bpmndi:BPMNLabel>
<dc:Bounds x="578" y="42" width="90" height="20" />
</bpmndi:BPMNLabel>
@ -96,8 +96,8 @@
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_3_di" bpmnElement="SequenceFlow_3">
<di:waypoint xsi:type="dc:Point" x="551" y="52" />
<di:waypoint xsi:type="dc:Point" x="696" y="52" />
<di:waypoint x="551" y="52" />
<di:waypoint x="696" y="52" />
<bpmndi:BPMNLabel>
<dc:Bounds x="718" y="42" width="90" height="20" />
</bpmndi:BPMNLabel>
@ -111,15 +111,15 @@
<bpmndi:BPMNShape id="StartEvent_2_di" bpmnElement="StartEvent_2">
<dc:Bounds x="134" y="179" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="107" y="215" width="90" height="20" />
<dc:Bounds x="144" y="215" width="17" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_2_di" bpmnElement="Task_2">
<dc:Bounds x="268" y="157" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_4_di" bpmnElement="SequenceFlow_4">
<di:waypoint xsi:type="dc:Point" x="170" y="197" />
<di:waypoint xsi:type="dc:Point" x="268" y="197" />
<di:waypoint x="170" y="197" />
<di:waypoint x="268" y="197" />
<bpmndi:BPMNLabel>
<dc:Bounds x="174" y="187" width="90" height="20" />
</bpmndi:BPMNLabel>
@ -152,29 +152,29 @@
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_5_di" bpmnElement="SequenceFlow_5">
<di:waypoint xsi:type="dc:Point" x="318" y="237" />
<di:waypoint xsi:type="dc:Point" x="318" y="279" />
<di:waypoint x="318" y="237" />
<di:waypoint x="318" y="279" />
<bpmndi:BPMNLabel>
<dc:Bounds x="273" y="248" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_6_di" bpmnElement="SequenceFlow_6">
<di:waypoint xsi:type="dc:Point" x="451" y="238" />
<di:waypoint xsi:type="dc:Point" x="490" y="238" />
<di:waypoint x="451" y="238" />
<di:waypoint x="490" y="238" />
<bpmndi:BPMNLabel>
<dc:Bounds x="425.5" y="228" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_7_di" bpmnElement="SequenceFlow_7">
<di:waypoint xsi:type="dc:Point" x="280" y="110" />
<di:waypoint xsi:type="dc:Point" x="280" y="138" />
<di:waypoint x="280" y="110" />
<di:waypoint x="280" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="233" y="114" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_8_di" bpmnElement="SequenceFlow_8">
<di:waypoint xsi:type="dc:Point" x="714" y="138" />
<di:waypoint xsi:type="dc:Point" x="714" y="70" />
<di:waypoint x="714" y="138" />
<di:waypoint x="714" y="70" />
<bpmndi:BPMNLabel>
<dc:Bounds x="644.5" y="94" width="90" height="20" />
</bpmndi:BPMNLabel>

View File

@ -63,7 +63,7 @@ describe('features/copy-paste', function() {
expect(tree.getDepthLength(0)).to.equal(1);
expect(tree.getDepthLength(1)).to.equal(3);
expect(tree.getDepthLength(2)).to.equal(15);
expect(tree.getDepthLength(2)).to.equal(12);
expect(subProcess.isExpanded).to.be.true;
}));
@ -245,7 +245,8 @@ describe('features/copy-paste', function() {
);
it('selected elements', inject(integrationTest([ 'SubProcess_1kd6ist' ])));
it.skip('selected elements', inject(integrationTest([ 'SubProcess_1kd6ist' ])));
it('should retain color properties',
inject(function(modeling, copyPaste, canvas, elementRegistry) {
@ -524,7 +525,7 @@ describe('features/copy-paste', function() {
expect(lane.children).to.be.empty;
expect(lane.businessObject.flowNodeRef).to.have.length(2);
expect(participant.children).to.have.length(10);
expect(participant.children).to.have.length(7);
}));

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<semantic:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:semantic="http://www.omg.org/spec/BPMN/20100524/MODEL" id="Definitions" targetNamespace="http://bpmn.io/schema/bpmn">
<semantic:process id="Process">
<semantic:startEvent id="StartEvent" />
<semantic:startEvent id="StartEvent" name="Start 0" />
<semantic:startEvent id="StartEvent_2" name="Start" />
</semantic:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">

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" 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:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.14.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1" />
<bpmn:exclusiveGateway id="ExclusiveGateway_2" />

View File

@ -42,9 +42,11 @@ describe('modeling - label layouting', function() {
// when
var connection = modeling.connect(element1, element2);
modeling.updateLabel(connection, 'foo');
// then
expect(connection.label.x).to.be.equal(472);
expect(connection.label.y).to.be.within(335, 336);
expect(connection.label.x).to.be.within(463, 465);
expect(connection.label.y).to.be.within(335, 340);
}));
@ -57,9 +59,11 @@ describe('modeling - label layouting', function() {
// when
var connection = modeling.connect(element1, element2);
modeling.updateLabel(connection, 'foo');
// then
expect(connection.label.x).to.be.equal(337);
expect(connection.label.y).to.be.within(222, 224);
expect(connection.label.x).to.be.within(328, 330);
expect(connection.label.y).to.be.within(225, 230);
}));
});
@ -75,30 +79,6 @@ describe('modeling - label layouting', function() {
describe('on segment move', function() {
it('label name not set -> move label to waypoints mid', inject(
function(modeling, elementRegistry, connectionSegmentMove, dragging) {
// given
var connection = elementRegistry.get('SequenceFlow_C'),
labelPosition = getLabelPosition(connection);
connection.label.businessObject.name = false;
connection.label.hidden = true;
// when
connectionSegmentMove.start(canvasEvent({ x: 0, y: 0 }), connection, 2);
dragging.move(canvasEvent({ x: 0, y: 50 }));
dragging.end();
// then
expect(connection.label.y - labelPosition.y).to.be.within(13, 16);
expect(connection.label.x - labelPosition.x).to.be.within(-87, -85);
}
));
it('left - no relayout', inject(function(elementRegistry, connectionSegmentMove, dragging) {
// given

View File

@ -30,12 +30,11 @@ describe('features/modeling - update label', function() {
// then
expect(startEvent_1.businessObject.name).to.equal('bar');
expect(startEvent_1.label.hidden).to.be.false;
}
));
it('should change name of start event with hidden label', inject(
it('should create label name of start event', inject(
function(modeling, elementRegistry) {
// given
@ -46,12 +45,12 @@ describe('features/modeling - update label', function() {
// then
expect(startEvent_2.businessObject.name).to.equal('bar');
expect(startEvent_2.label.hidden).to.be.false;
expect(startEvent_2.label).to.exist;
}
));
it('should hide label when setting empty string', inject(
it('should delete label when setting empty string', inject(
function(modeling, elementRegistry) {
// given
@ -62,7 +61,7 @@ describe('features/modeling - update label', function() {
// then
expect(startEvent_1.businessObject.name).to.equal('');
expect(startEvent_1.label.hidden).to.be.true;
expect(startEvent_1.label).not.to.exist;
}
));
@ -79,7 +78,6 @@ describe('features/modeling - update label', function() {
// then
expect(startEvent_1.businessObject.name).to.equal('bar');
expect(startEvent_1.label.hidden).to.be.false;
}
));

View File

@ -165,22 +165,6 @@ describe('features/modeling - update properties', function() {
));
it('setting name', inject(function(elementRegistry, modeling) {
// given
var flowConnection = elementRegistry.get('SequenceFlow_4');
// when
modeling.updateProperties(flowConnection, { name: 'FOO BAR' });
// then
expect(flowConnection.businessObject.name).to.equal('FOO BAR');
// flow label is now shown
expect(flowConnection.label.hidden).to.be.false;
}));
it('updating name', inject(function(elementRegistry, modeling) {
// given
@ -207,9 +191,6 @@ describe('features/modeling - update properties', function() {
// then
expect(flowConnection.businessObject.name).not.to.exist;
// flow label is now hidden
expect(flowConnection.label.hidden).to.be.true;
}));

View File

@ -143,7 +143,7 @@ describe('features/modeling - create participant', function() {
// then
expect(participantShape.children.length).to.equal(0);
expect(processShape.children.length).to.equal(9);
expect(processShape.children.length).to.equal(7);
// children di is wired
expect(startEventDi.$parent).to.eql(rootShapeDi);

View File

@ -6,14 +6,11 @@ import {
import modelingModule from 'lib/features/modeling';
import coreModule from 'lib/core';
import {
getExternalLabelMid
} from 'lib/util/LabelUtil';
describe('behavior - LabelBehavior', function() {
var diagramXML = require('../../../../fixtures/bpmn/basic.bpmn');
var diagramXML =
require('../../../../fixtures/bpmn/features/modeling/behavior/label-behavior.bpmn');
var testModules = [ modelingModule, coreModule ];
@ -22,103 +19,179 @@ describe('behavior - LabelBehavior', function() {
describe('add label', function() {
it('should add to sequence flow', inject(function(elementRegistry, modeling) {
it('should add to sequence flow with name', inject(
function(bpmnFactory, elementRegistry, modeling) {
// given
var startEvent = elementRegistry.get('StartEvent_1'),
task = elementRegistry.get('Task_1');
// given
var startEvent = elementRegistry.get('StartEvent_1'),
task = elementRegistry.get('Task_1'),
businessObject = bpmnFactory.create('bpmn:SequenceFlow', {
name: 'foo'
});
// when
var connection = modeling.connect(startEvent, task);
// when
var connection = modeling.createConnection(startEvent, task, {
type: 'bpmn:SequenceFlow',
businessObject: businessObject
}, startEvent.parent);
// then
expect(connection.label).to.exist;
}));
// then
expect(connection.label).to.exist;
}
));
it('should add to exclusive gateway', inject(function(elementFactory, elementRegistry, modeling) {
it('should NOT add to sequence flow without name', inject(
function(elementRegistry, modeling) {
// given
var parentShape = elementRegistry.get('Process_1'),
newShapeAttrs = { type: 'bpmn:ExclusiveGateway' };
// given
var startEvent = elementRegistry.get('StartEvent_1'),
task = elementRegistry.get('Task_1');
// when
var newShape = modeling.createShape(newShapeAttrs, { x: 50, y: 50 }, parentShape);
// when
var connection = modeling.connect(startEvent, task);
// then
expect(newShape.label).to.exist;
}));
// then
expect(connection.label).not.to.exist;
}
));
it('should not add to task', inject(function(elementFactory, elementRegistry, modeling) {
it('should add to exclusive gateway with name', inject(
function(bpmnFactory, elementFactory, elementRegistry, modeling) {
// given
var parentShape = elementRegistry.get('Process_1'),
newShapeAttrs = { type: 'bpmn:Task' };
// given
var parentShape = elementRegistry.get('Process_1'),
businessObject = bpmnFactory.create('bpmn:ExclusiveGateway', {
name: 'foo'
}),
newShapeAttrs = {
type: 'bpmn:ExclusiveGateway',
businessObject: businessObject
};
// when
var newShape = modeling.createShape(newShapeAttrs, { x: 50, y: 50 }, parentShape);
// when
var newShape = modeling.createShape(newShapeAttrs, { x: 50, y: 50 }, parentShape);
// then
expect(newShape.label).not.to.exist;
}));
// then
expect(newShape.label).to.exist;
}
));
it('should NOT add to exclusive gateway without name', inject(
function(elementFactory, elementRegistry, modeling) {
// given
var parentShape = elementRegistry.get('Process_1'),
newShapeAttrs = {
type: 'bpmn:ExclusiveGateway'
};
// when
var newShape = modeling.createShape(newShapeAttrs, { x: 50, y: 50 }, parentShape);
// then
expect(newShape.label).not.to.exist;
}
));
it('should not add to task', inject(
function(elementFactory, elementRegistry, modeling) {
// given
var parentShape = elementRegistry.get('Process_1'),
newShapeAttrs = { type: 'bpmn:Task' };
// when
var newShape = modeling.createShape(newShapeAttrs, { x: 50, y: 50 }, parentShape);
// then
expect(newShape.label).not.to.exist;
}
));
describe('on append', function() {
it('correctly wired and positioned', inject(function(elementRegistry, modeling, commandStack) {
it('correctly wired and positioned', inject(
function(bpmnFactory, elementRegistry, modeling, commandStack) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
businessObject = bpmnFactory.create('bpmn:EndEvent', {
name: 'foo'
});
// when
var targetShape = modeling.appendShape(startEventShape, {
type: 'bpmn:EndEvent',
businessObject: businessObject
});
var label = targetShape.label;
// then
expect(label).to.exist;
expect(elementRegistry.get(label.id)).to.exist;
expect(label.x).to.within(298, 299);
expect(label.y).to.be.within(141, 142);
expect(label.width).to.be.within(15, 18);
expect(label.height).to.be.within(12, 14);
}
));
it('with di', inject(
function(bpmnFactory, elementRegistry, modeling, commandStack) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
businessObject = bpmnFactory.create('bpmn:EndEvent', {
name: 'foo'
});
// when
var targetShape = modeling.appendShape(startEventShape, {
type: 'bpmn:EndEvent',
businessObject: businessObject
}),
target = targetShape.businessObject;
// then
expect(target.di.label).to.exist;
expect(target.di.label).to.have.bounds(targetShape.label);
}
));
});
it('should add with di', inject(
function(bpmnFactory, elementFactory, elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1');
var startEventShape = elementRegistry.get('StartEvent_1'),
businessObject = bpmnFactory.create('bpmn:SequenceFlow', {
name: 'foo'
});
// when
var targetShape = modeling.appendShape(startEventShape, { type: 'bpmn:EndEvent' });
var label = targetShape.label;
// then
expect(label).to.exist;
expect(elementRegistry.get(label.id)).to.exist;
expect(label.x).to.equal(307);
expect(label.y).to.be.within(141, 142);
expect(label.width).to.be.equal(0);
expect(label.height).to.be.within(12, 14);
}));
it('with di', inject(function(elementRegistry, modeling, commandStack) {
// given
var startEventShape = elementRegistry.get('StartEvent_1');
// when
var targetShape = modeling.appendShape(startEventShape, { type: 'bpmn:EndEvent' }),
var targetShape = modeling.appendShape(startEventShape, {
type: 'bpmn:EndEvent',
businessObject: businessObject
}),
target = targetShape.businessObject;
// then
expect(target.di.label).to.exist;
expect(target.di.label).to.have.bounds(targetShape.label);
}));
});
it('should add with di', inject(function(elementFactory, elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1');
// when
var targetShape = modeling.appendShape(startEventShape, { type: 'bpmn:EndEvent' }),
target = targetShape.businessObject;
// then
expect(target.di.label).to.exist;
expect(target.di.label).to.have.bounds(targetShape.label);
}));
}
));
});
@ -136,143 +209,81 @@ describe('behavior - LabelBehavior', function() {
modeling.moveElements([ labelShape ], { x: 10, y: -10 });
// then
expect(labelShape).to.have.position({ x: 156, y: 128 });
expect(startEvent.di.label).to.have.position({ x: 156, y: 128 });
expect(labelShape.x).to.be.within(193, 194);
expect(labelShape.y).to.equal(128);
expect(startEvent.di.label.bounds.x).to.be.within(193, 194);
expect(startEvent.di.label.bounds.y).to.equal(128);
}));
describe('connection labels', function() {
it('should center position hidden on waypoint change', inject(function(elementRegistry, modeling) {
it('should NOT center position visible', inject(
function(bpmnFactory, elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
taskShape = elementRegistry.get('Task_1');
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
taskShape = elementRegistry.get('Task_1'),
businessObject = bpmnFactory.create('bpmn:SequenceFlow', {
name: 'foo'
});
var sequenceFlowConnection = modeling.createConnection(startEventShape, taskShape, {
type: 'bpmn:SequenceFlow'
}, startEventShape.parent);
var sequenceFlowConnection = modeling.createConnection(startEventShape, taskShape, {
type: 'bpmn:SequenceFlow',
businessObject: businessObject
}, startEventShape.parent);
// when
modeling.updateWaypoints(sequenceFlowConnection, [
sequenceFlowConnection.waypoints[0],
{
x: sequenceFlowConnection.waypoints[0].x,
y: 200
},
{
x: sequenceFlowConnection.waypoints[1].x,
y: 200
},
sequenceFlowConnection.waypoints[1]
]);
var oldLabelPosition = {
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
};
// then
var expected = {
x: getExternalLabelMid(sequenceFlowConnection).x - sequenceFlowConnection.label.width / 2,
y: getExternalLabelMid(sequenceFlowConnection).y - sequenceFlowConnection.label.height / 2
};
// when
sequenceFlowConnection.label.hidden = false;
expect({
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
}).to.eql(expected);
}));
modeling.updateWaypoints(sequenceFlowConnection, [
sequenceFlowConnection.waypoints[0],
{
x: sequenceFlowConnection.waypoints[0].x,
y: 200
},
{
x: sequenceFlowConnection.waypoints[1].x,
y: 200
},
sequenceFlowConnection.waypoints[1]
]);
it('should center position hidden on source move', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
taskShape = elementRegistry.get('Task_1');
var sequenceFlowConnection = modeling.createConnection(startEventShape, taskShape, {
type: 'bpmn:SequenceFlow'
}, startEventShape.parent);
// when
modeling.moveElements([ startEventShape ], { x: 50, y: 0 });
// then
var expected = {
x: getExternalLabelMid(sequenceFlowConnection).x - sequenceFlowConnection.label.width / 2,
y: getExternalLabelMid(sequenceFlowConnection).y - sequenceFlowConnection.label.height / 2
};
expect({
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
}).to.eql(expected);
}));
it('should center position hidden on target move', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
taskShape = elementRegistry.get('Task_1');
var sequenceFlowConnection = modeling.createConnection(startEventShape, taskShape, {
type: 'bpmn:SequenceFlow'
}, startEventShape.parent);
// when
modeling.moveElements([ taskShape ], { x: 50, y: 0 });
// then
var expected = {
x: getExternalLabelMid(sequenceFlowConnection).x - sequenceFlowConnection.label.width / 2,
y: getExternalLabelMid(sequenceFlowConnection).y - sequenceFlowConnection.label.height / 2
};
expect({
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
}).to.eql(expected);
}));
it('should NOT center position visible', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
taskShape = elementRegistry.get('Task_1');
var sequenceFlowConnection = modeling.createConnection(startEventShape, taskShape, {
type: 'bpmn:SequenceFlow'
}, startEventShape.parent);
var oldLabelPosition = {
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
};
// when
sequenceFlowConnection.label.hidden = false;
modeling.updateWaypoints(sequenceFlowConnection, [
sequenceFlowConnection.waypoints[0],
{
x: sequenceFlowConnection.waypoints[0].x,
y: 200
},
{
x: sequenceFlowConnection.waypoints[1].x,
y: 200
},
sequenceFlowConnection.waypoints[1]
]);
// then
expect({
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
}).to.eql(oldLabelPosition);
}));
// then
expect({
x: sequenceFlowConnection.label.x,
y: sequenceFlowConnection.label.y
}).to.eql(oldLabelPosition);
}
));
});
});
describe('delete label', function() {
it('should remove name', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.get('StartEvent_1'),
startEvent = startEventShape.businessObject,
labelShape = startEventShape.label;
// when
modeling.removeShape(labelShape);
// then
expect(startEventShape.label).not.to.exist;
expect(startEvent.name).to.equal('');
}));
});
});

View File

@ -178,7 +178,7 @@ describe('features/modeling - move start event behavior', function() {
var newEndEvent = subProcess.children[0].businessObject;
// then
expect(subProcess.children).to.have.length(2);
expect(subProcess.children).to.have.length(1);
expect(newEndEvent.eventDefinitionTypes).not.to.exist;
})
);
@ -206,7 +206,7 @@ describe('features/modeling - move start event behavior', function() {
})[0];
// then
expect(transaction.children).to.have.length(2);
expect(transaction.children).to.have.length(1);
expect(endEventAfter.businessObject.eventDefinitions).to.exist;
})
);
@ -262,7 +262,7 @@ describe('features/modeling - move start event behavior', function() {
})[0];
// then
expect(transaction.children).to.have.length(2);
expect(transaction.children).to.have.length(1);
expect(endEventAfter.businessObject.eventDefinitions).to.exist;
})
);

View File

@ -360,7 +360,7 @@ describe('features/replace - bpmn replace', function() {
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('should keep interior labels',
it('should keep internal labels',
inject(function(elementRegistry, bpmnReplace) {
// given
@ -379,7 +379,7 @@ describe('features/replace - bpmn replace', function() {
);
it('should keep exterior labels',
it('should keep external labels',
inject(function(elementRegistry, bpmnReplace) {
// given
@ -393,7 +393,6 @@ describe('features/replace - bpmn replace', function() {
var newElement = bpmnReplace.replaceElement(startEvent, newElementData);
// then
expect(newElement.label.hidden).to.equal(false);
expect(newElement.label.labelTarget).to.equal(newElement);
expect(newElement.businessObject.name).to.equal('KEEP ME');
})

View File

@ -1591,29 +1591,4 @@ describe('features/modeling/rules - BpmnRules', function() {
});
describe('labels', function() {
var testXML = require('./BpmnRules.process.bpmn');
beforeEach(bootstrapModeler(testXML, { modules: testModules }));
it('should filter labels', inject(function(elementRegistry, rules) {
// given
var startEventShape = elementRegistry.get('StartEvent_None'),
startEventLabel = startEventShape.label;
// when
var allowed = rules.allowed('elements.delete', {
elements: [ startEventShape, startEventLabel ]
});
// then
expect(allowed).to.eql([ startEventShape ]);
}));
});
});

View File

@ -40,7 +40,7 @@ describe('import - model wiring', function() {
expect(startEventShape.type).to.equal('bpmn:StartEvent');
expect(startEventShape.parent).to.eql(subProcessShape);
expect(subProcessShape.children.length).to.equal(5);
expect(subProcessShape.children.length).to.equal(4);
}));