feat(label-editing): enable direct editing for group labels

* Adds external label for Groups
* Modifies referenced categoryValue

Closes #955
This commit is contained in:
Niklas Kiefer 2019-05-22 08:45:12 +02:00 committed by merge-me[bot]
parent f6f9ac29f2
commit fb3398fa39
10 changed files with 89 additions and 15 deletions

View File

@ -279,7 +279,7 @@ LabelEditingProvider.prototype.getEditingBBox = function(element) {
paddingTop = 7 * zoom, paddingTop = 7 * zoom,
paddingBottom = 4 * zoom; paddingBottom = 4 * zoom;
// external labels for events, data elements, gateways and connections // external labels for events, data elements, gateways, groups and connections
if (target.labelTarget) { if (target.labelTarget) {
assign(bounds, { assign(bounds, {
width: width, width: width,

View File

@ -16,6 +16,21 @@ function getLabelAttr(semantic) {
if (is(semantic, 'bpmn:TextAnnotation')) { if (is(semantic, 'bpmn:TextAnnotation')) {
return 'text'; return 'text';
} }
if (is(semantic, 'bpmn:Group')) {
return 'categoryValueRef';
}
}
function getCategoryValue(semantic) {
var categoryValueRef = semantic['categoryValueRef'];
if (!categoryValueRef) {
return '';
}
return categoryValueRef.value || '';
} }
export function getLabel(element) { export function getLabel(element) {
@ -23,6 +38,12 @@ export function getLabel(element) {
attr = getLabelAttr(semantic); attr = getLabelAttr(semantic);
if (attr) { if (attr) {
if (attr === 'categoryValueRef') {
return getCategoryValue(semantic);
}
return semantic[attr] || ''; return semantic[attr] || '';
} }
} }
@ -33,7 +54,13 @@ export function setLabel(element, text, isExternal) {
attr = getLabelAttr(semantic); attr = getLabelAttr(semantic);
if (attr) { if (attr) {
semantic[attr] = text;
if (attr === 'categoryValueRef') {
semantic['categoryValueRef'].value = text;
} else {
semantic[attr] = text;
}
} }
return element; return element;

View File

@ -11,7 +11,6 @@ import {
} from '../../../util/LabelUtil'; } from '../../../util/LabelUtil';
import { import {
getBusinessObject,
is is
} from '../../../util/ModelUtil'; } from '../../../util/ModelUtil';
@ -103,9 +102,7 @@ export default function UpdateLabelHandler(modeling, textRenderer) {
return; return;
} }
var bo = getBusinessObject(label); var text = getLabel(label);
var text = bo.name || bo.text;
// don't resize without text // don't resize without text
if (!text) { if (!text) {

View File

@ -255,7 +255,7 @@ function isTextAnnotation(element) {
} }
function isGroup(element) { function isGroup(element) {
return is(element, 'bpmn:Group'); return is(element, 'bpmn:Group') && !element.labelTarget;
} }
function isCompensationBoundary(element) { function isCompensationBoundary(element) {

View File

@ -17,6 +17,10 @@ import {
isExpanded isExpanded
} from '../util/DiUtil'; } from '../util/DiUtil';
import {
getLabel
} from '../features/label-editing/LabelUtil';
import { import {
elementToString elementToString
} from './Util'; } from './Util';
@ -182,7 +186,7 @@ BpmnImporter.prototype.add = function(semantic, parentElement) {
})); }));
} }
// (optional) LABEL // (optional) LABEL
if (isLabelExternal(semantic) && semantic.name) { if (isLabelExternal(semantic) && getLabel(element)) {
this.addLabel(semantic, element); this.addLabel(semantic, element);
} }
@ -239,7 +243,7 @@ BpmnImporter.prototype.addLabel = function(semantic, element) {
bounds = getExternalLabelBounds(semantic, element); bounds = getExternalLabelBounds(semantic, element);
text = semantic.name; text = getLabel(element);
if (text) { if (text) {
// get corrected bounds from actual layouted text // get corrected bounds from actual layouted text
@ -250,7 +254,7 @@ BpmnImporter.prototype.addLabel = function(semantic, element) {
id: semantic.id + '_label', id: semantic.id + '_label',
labelTarget: element, labelTarget: element,
type: 'label', type: 'label',
hidden: element.hidden || !semantic.name, hidden: element.hidden || !getLabel(element),
x: Math.round(bounds.x), x: Math.round(bounds.x),
y: Math.round(bounds.y), y: Math.round(bounds.y),
width: Math.round(bounds.width), width: Math.round(bounds.width),

View File

@ -27,7 +27,8 @@ export function isLabelExternal(semantic) {
is(semantic, 'bpmn:DataInput') || is(semantic, 'bpmn:DataInput') ||
is(semantic, 'bpmn:DataOutput') || is(semantic, 'bpmn:DataOutput') ||
is(semantic, 'bpmn:SequenceFlow') || is(semantic, 'bpmn:SequenceFlow') ||
is(semantic, 'bpmn:MessageFlow'); is(semantic, 'bpmn:MessageFlow') ||
is(semantic, 'bpmn:Group');
} }
/** /**
@ -97,6 +98,11 @@ export function getExternalLabelMid(element) {
if (element.waypoints) { if (element.waypoints) {
return getFlowLabelPosition(element.waypoints); return getFlowLabelPosition(element.waypoints);
} else if (is(element, 'bpmn:Group')) {
return {
x: element.x + element.width / 2,
y: element.y + DEFAULT_LABEL_SIZE.height / 2
};
} else { } else {
return { return {
x: element.x + element.width / 2, x: element.x + element.width / 2,

View File

@ -67,7 +67,12 @@
<bpmn:dataObject id="DataObject_1rq8hb8" /> <bpmn:dataObject id="DataObject_1rq8hb8" />
<bpmn:dataStoreReference id="DataStoreReference_1" /> <bpmn:dataStoreReference id="DataStoreReference_1" />
<bpmn:association id="Association_0ckvfj2" sourceRef="SubProcess_1" targetRef="TextAnnotation_1" /> <bpmn:association id="Association_0ckvfj2" sourceRef="SubProcess_1" targetRef="TextAnnotation_1" />
<bpmn:group id="Group_1" categoryValueRef="CategoryValue_1" />
<bpmn:group id="Group_2" />
</bpmn:process> </bpmn:process>
<bpmn:category id="Category_1">
<bpmn:categoryValue id="CategoryValue_1" value="FOO" />
</bpmn:category>
<bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1o0amh9"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1o0amh9">
<bpmndi:BPMNShape id="Participant_15tkgjw_di" bpmnElement="Participant_1"> <bpmndi:BPMNShape id="Participant_15tkgjw_di" bpmnElement="Participant_1">
@ -184,17 +189,26 @@
<dc:Bounds x="161" y="646" width="600" height="250" /> <dc:Bounds x="161" y="646" width="600" height="250" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataOutput_di" bpmnElement="DataOutput"> <bpmndi:BPMNShape id="DataOutput_di" bpmnElement="DataOutput">
<dc:Bounds x="265" y="150" width="34" height="40"/> <dc:Bounds x="265" y="150" width="34" height="40" />
<bpmndi:BPMNLabel> <bpmndi:BPMNLabel>
<dc:Bounds height="12" width="30" x="265" y="195"/> <dc:Bounds x="265" y="195" width="30" height="12" />
</bpmndi:BPMNLabel> </bpmndi:BPMNLabel>
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataInput_di" bpmnElement="DataInput"> <bpmndi:BPMNShape id="DataInput_di" bpmnElement="DataInput">
<dc:Bounds x="220" y="150" width="34" height="40"/> <dc:Bounds x="220" y="150" width="34" height="40" />
<bpmndi:BPMNLabel> <bpmndi:BPMNLabel>
<dc:Bounds height="12" width="30" x="220" y="200"/> <dc:Bounds x="220" y="200" width="30" height="12" />
</bpmndi:BPMNLabel> </bpmndi:BPMNLabel>
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Group_1_di" bpmnElement="Group_1">
<dc:Bounds x="195" y="390" width="225" height="190" />
<bpmndi:BPMNLabel>
<dc:Bounds x="296" y="397" width="24" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Group_2_di" bpmnElement="Group_2">
<dc:Bounds x="555" y="390" width="85" height="200" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>
</bpmn:definitions> </bpmn:definitions>

View File

@ -411,6 +411,11 @@ describe('features - label-editing', function() {
it('data output', directEdit('DataOutput')); it('data output', directEdit('DataOutput'));
it('group', directEdit('Group_1'));
it('group via label', directEdit('Group_1_label'));
}); });
}); });

View File

@ -7,7 +7,11 @@
<bpmn:textAnnotation id="TextAnnotation_1"> <bpmn:textAnnotation id="TextAnnotation_1">
<bpmn:text></bpmn:text> <bpmn:text></bpmn:text>
</bpmn:textAnnotation> </bpmn:textAnnotation>
<bpmn:group id="Group_1" categoryValueRef="CategoryValue_1" />
</bpmn:process> </bpmn:process>
<bpmn:category id="Category_1">
<bpmn:categoryValue id="CategoryValue_1" />
</bpmn:category>
<bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
@ -25,6 +29,9 @@
<bpmndi:BPMNShape id="TextAnnotation_1_di" bpmnElement="TextAnnotation_1"> <bpmndi:BPMNShape id="TextAnnotation_1_di" bpmnElement="TextAnnotation_1">
<dc:Bounds x="426" y="220" width="100" height="30" /> <dc:Bounds x="426" y="220" width="100" height="30" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Group_1_di" bpmnElement="Group_1">
<dc:Bounds x="165" y="190" width="150" height="120" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>
</bpmn:definitions> </bpmn:definitions>

View File

@ -134,6 +134,20 @@ describe('features/modeling - update label', function() {
)); ));
it('should change value of group', inject(function(modeling, elementRegistry) {
// given
var group_1 = elementRegistry.get('Group_1');
// when
modeling.updateLabel(group_1, 'foo');
// then
expect(group_1.businessObject.categoryValueRef.value).to.equal('foo');
expect(group_1.label).to.exist;
}));
it('should propertly fire events.changed after event name change', inject( it('should propertly fire events.changed after event name change', inject(
function(modeling, elementRegistry, eventBus) { function(modeling, elementRegistry, eventBus) {