bpmn-js 0.20.7 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/draw/BpmnRenderer.js +1 -1
- package/lib/features/copy-paste/BpmnCopyPaste.js +18 -24
- package/lib/features/label-editing/LabelEditingPreview.js +122 -0
- package/lib/features/label-editing/LabelEditingProvider.js +154 -55
- package/lib/features/label-editing/cmd/UpdateLabelHandler.js +10 -6
- package/lib/features/label-editing/index.js +8 -3
- package/lib/features/modeling/behavior/DropOnFlowBehavior.js +50 -16
- package/lib/features/snapping/BpmnSnapping.js +22 -6
- package/package.json +4 -4
- package/test/TestHelper.js +1 -1
- package/test/fixtures/bpmn/features/label-editing/labels.bpmn +132 -202
- package/test/spec/features/copy-paste/BpmnCopyPasteSpec.js +10 -5
- package/test/spec/features/label-editing/LabelEditingPreviewSpec.js +133 -0
- package/test/spec/features/label-editing/LabelEditingProviderSpec.js +207 -172
- package/test/spec/features/modeling/LabelBoundsSpec.js +3 -1
- package/test/spec/features/modeling/behavior/DropOnFlowBehavior.bpmn +5 -1
- package/test/spec/features/modeling/behavior/DropOnFlowBehaviorSpec.js +174 -1
- package/test/spec/features/snapping/BpmnSnapping.sequenceFlow.bpmn +41 -0
- package/test/spec/features/snapping/BpmnSnappingSpec.js +66 -0
package/lib/draw/BpmnRenderer.js
CHANGED
|
@@ -1551,7 +1551,7 @@ function BpmnRenderer(eventBus, styles, pathMap, canvas, priority) {
|
|
|
1551
1551
|
});
|
|
1552
1552
|
|
|
1553
1553
|
var text = getSemantic(element).text || '';
|
|
1554
|
-
renderLabel(parentGfx, text, { box: element, align: 'left-
|
|
1554
|
+
renderLabel(parentGfx, text, { box: element, align: 'left-top', padding: 5 });
|
|
1555
1555
|
|
|
1556
1556
|
return textElement;
|
|
1557
1557
|
},
|
|
@@ -37,17 +37,9 @@ function BpmnCopyPaste(
|
|
|
37
37
|
var helper = new ModelCloneHelper(eventBus);
|
|
38
38
|
|
|
39
39
|
copyPaste.registerDescriptor(function(element, descriptor) {
|
|
40
|
-
var businessObject = getBusinessObject(element)
|
|
41
|
-
newBusinessObject = bpmnFactory.create(businessObject.$type);
|
|
40
|
+
var businessObject = descriptor.oldBusinessObject = getBusinessObject(element);
|
|
42
41
|
|
|
43
|
-
var
|
|
44
|
-
colors = {};
|
|
45
|
-
|
|
46
|
-
properties = filter(properties, function(property) {
|
|
47
|
-
return IGNORED_PROPERTIES.indexOf(property.replace(/bpmn:/, '')) === -1;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
descriptor.businessObject = helper.clone(businessObject, newBusinessObject, properties);
|
|
42
|
+
var colors = {};
|
|
51
43
|
|
|
52
44
|
descriptor.type = element.type;
|
|
53
45
|
|
|
@@ -79,11 +71,22 @@ function BpmnCopyPaste(
|
|
|
79
71
|
createdElements = context.createdElements,
|
|
80
72
|
parent = descriptor.parent,
|
|
81
73
|
rootElement = canvas.getRootElement(),
|
|
82
|
-
|
|
74
|
+
oldBusinessObject = descriptor.oldBusinessObject,
|
|
75
|
+
newBusinessObject,
|
|
83
76
|
source,
|
|
84
77
|
target,
|
|
85
78
|
canConnect;
|
|
86
79
|
|
|
80
|
+
newBusinessObject = bpmnFactory.create(oldBusinessObject.$type);
|
|
81
|
+
|
|
82
|
+
var properties = getProperties(oldBusinessObject.$descriptor);
|
|
83
|
+
|
|
84
|
+
properties = filter(properties, function(property) {
|
|
85
|
+
return IGNORED_PROPERTIES.indexOf(property.replace(/bpmn:/, '')) === -1;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
descriptor.businessObject = helper.clone(oldBusinessObject, newBusinessObject, properties);
|
|
89
|
+
|
|
87
90
|
if (descriptor.type === 'label') {
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
@@ -119,19 +122,17 @@ function BpmnCopyPaste(
|
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
businessObject = descriptor.businessObject;
|
|
123
|
-
|
|
124
125
|
// remove the id or else we cannot paste multiple times
|
|
125
|
-
delete
|
|
126
|
+
delete newBusinessObject.id;
|
|
126
127
|
|
|
127
128
|
// assign an ID
|
|
128
|
-
bpmnFactory._ensureId(
|
|
129
|
+
bpmnFactory._ensureId(newBusinessObject);
|
|
129
130
|
|
|
130
131
|
if (descriptor.type === 'bpmn:Participant' && descriptor.processRef) {
|
|
131
|
-
descriptor.processRef =
|
|
132
|
+
descriptor.processRef = newBusinessObject.processRef = bpmnFactory.create('bpmn:Process');
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
setProperties(
|
|
135
|
+
setProperties(newBusinessObject, descriptor, [
|
|
135
136
|
'isExpanded',
|
|
136
137
|
'triggeredByEvent'
|
|
137
138
|
]);
|
|
@@ -141,13 +142,6 @@ function BpmnCopyPaste(
|
|
|
141
142
|
]);
|
|
142
143
|
});
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
eventBus.on('commandStack.elements.paste.postExecuted', function() {
|
|
146
|
-
// temporarily disable multi paste until #686
|
|
147
|
-
// is addressed
|
|
148
|
-
clipboard.clear();
|
|
149
|
-
});
|
|
150
|
-
|
|
151
145
|
}
|
|
152
146
|
|
|
153
147
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var svgAppend = require('tiny-svg/lib/append'),
|
|
2
|
+
svgAttr = require('tiny-svg/lib/attr'),
|
|
3
|
+
svgCreate = require('tiny-svg/lib/create'),
|
|
4
|
+
svgRemove = require('tiny-svg/lib/remove');
|
|
5
|
+
|
|
6
|
+
var getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
|
|
7
|
+
is = require('../../util/ModelUtil').is;
|
|
8
|
+
|
|
9
|
+
var translate = require('diagram-js/lib/util/SvgTransformUtil').translate;
|
|
10
|
+
|
|
11
|
+
var MARKER_HIDDEN = 'djs-element-hidden',
|
|
12
|
+
MARKER_LABEL_HIDDEN = 'djs-label-hidden';
|
|
13
|
+
|
|
14
|
+
function getStrokeColor(element, defaultColor) {
|
|
15
|
+
var bo = getBusinessObject(element);
|
|
16
|
+
|
|
17
|
+
return bo.di.get('stroke') || defaultColor || 'black';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function LabelEditingPreview(eventBus, canvas, elementRegistry, pathMap) {
|
|
21
|
+
var self = this;
|
|
22
|
+
|
|
23
|
+
var defaultLayer = canvas.getDefaultLayer();
|
|
24
|
+
|
|
25
|
+
var element, absoluteElementBBox, gfx;
|
|
26
|
+
|
|
27
|
+
eventBus.on('directEditing.activate', function(context) {
|
|
28
|
+
var activeProvider = context.active;
|
|
29
|
+
|
|
30
|
+
element = activeProvider.element.label || activeProvider.element;
|
|
31
|
+
|
|
32
|
+
// text annotation
|
|
33
|
+
if (is(element, 'bpmn:TextAnnotation')) {
|
|
34
|
+
absoluteElementBBox = canvas.getAbsoluteBBox(element);
|
|
35
|
+
|
|
36
|
+
gfx = svgCreate('g');
|
|
37
|
+
|
|
38
|
+
var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
|
|
39
|
+
xScaleFactor: 1,
|
|
40
|
+
yScaleFactor: 1,
|
|
41
|
+
containerWidth: element.width,
|
|
42
|
+
containerHeight: element.height,
|
|
43
|
+
position: {
|
|
44
|
+
mx: 0.0,
|
|
45
|
+
my: 0.0
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
var path = self.path = svgCreate('path');
|
|
50
|
+
|
|
51
|
+
svgAttr(path, {
|
|
52
|
+
d: textPathData,
|
|
53
|
+
strokeWidth: 2,
|
|
54
|
+
stroke: getStrokeColor(element)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
svgAppend(gfx, path);
|
|
58
|
+
|
|
59
|
+
svgAppend(defaultLayer, gfx);
|
|
60
|
+
|
|
61
|
+
translate(gfx, element.x, element.y);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (is(element, 'bpmn:TextAnnotation') ||
|
|
65
|
+
element.labelTarget) {
|
|
66
|
+
canvas.addMarker(element, MARKER_HIDDEN);
|
|
67
|
+
} else if (is(element, 'bpmn:Task') ||
|
|
68
|
+
is(element, 'bpmn:CallActivity') ||
|
|
69
|
+
is(element, 'bpmn:SubProcess') ||
|
|
70
|
+
is(element, 'bpmn:Participant')) {
|
|
71
|
+
canvas.addMarker(element, MARKER_LABEL_HIDDEN);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
eventBus.on('directEditing.resize', function(context) {
|
|
76
|
+
|
|
77
|
+
// text annotation
|
|
78
|
+
if (is(element, 'bpmn:TextAnnotation')) {
|
|
79
|
+
var height = context.height,
|
|
80
|
+
dy = context.dy;
|
|
81
|
+
|
|
82
|
+
var newElementHeight = Math.max(element.height / absoluteElementBBox.height * (height + dy), 0);
|
|
83
|
+
|
|
84
|
+
var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
|
|
85
|
+
xScaleFactor: 1,
|
|
86
|
+
yScaleFactor: 1,
|
|
87
|
+
containerWidth: element.width,
|
|
88
|
+
containerHeight: newElementHeight,
|
|
89
|
+
position: {
|
|
90
|
+
mx: 0.0,
|
|
91
|
+
my: 0.0
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
svgAttr(self.path, {
|
|
96
|
+
d: textPathData
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
eventBus.on([ 'directEditing.complete', 'directEditing.cancel' ], function(context) {
|
|
102
|
+
var activeProvider = context.active;
|
|
103
|
+
|
|
104
|
+
if (activeProvider) {
|
|
105
|
+
canvas.removeMarker(activeProvider.element.label || activeProvider.element, MARKER_HIDDEN);
|
|
106
|
+
canvas.removeMarker(element, MARKER_LABEL_HIDDEN);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
element = undefined;
|
|
110
|
+
absoluteElementBBox = undefined;
|
|
111
|
+
|
|
112
|
+
if (gfx) {
|
|
113
|
+
svgRemove(gfx);
|
|
114
|
+
|
|
115
|
+
gfx = undefined;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
LabelEditingPreview.$inject = [ 'eventBus', 'canvas', 'elementRegistry', 'pathMap' ];
|
|
121
|
+
|
|
122
|
+
module.exports = LabelEditingPreview;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var assign = require('lodash/object/assign');
|
|
4
|
+
|
|
3
5
|
var UpdateLabelHandler = require('./cmd/UpdateLabelHandler');
|
|
4
6
|
|
|
5
7
|
var LabelUtil = require('./LabelUtil');
|
|
@@ -7,10 +9,12 @@ var LabelUtil = require('./LabelUtil');
|
|
|
7
9
|
var is = require('../../util/ModelUtil').is,
|
|
8
10
|
isExpanded = require('../../util/DiUtil').isExpanded;
|
|
9
11
|
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
+
var SMALL_FONT_SIZE = 11,
|
|
13
|
+
SMALL_LINE_HEIGHT = 13,
|
|
14
|
+
MEDIUM_FONT_SIZE = 12,
|
|
15
|
+
MEDIUM_LINE_HEIGHT = 14;
|
|
12
16
|
|
|
13
|
-
function LabelEditingProvider(eventBus, canvas, directEditing, commandStack) {
|
|
17
|
+
function LabelEditingProvider(eventBus, canvas, directEditing, commandStack, resizeHandles) {
|
|
14
18
|
|
|
15
19
|
this._canvas = canvas;
|
|
16
20
|
this._commandStack = commandStack;
|
|
@@ -22,19 +26,20 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack) {
|
|
|
22
26
|
// listen to dblclick on non-root elements
|
|
23
27
|
eventBus.on('element.dblclick', function(event) {
|
|
24
28
|
directEditing.activate(event.element);
|
|
29
|
+
|
|
30
|
+
resizeHandles.removeResizers();
|
|
25
31
|
});
|
|
26
32
|
|
|
27
33
|
// complete on followup canvas operation
|
|
28
|
-
eventBus.on([ 'element.mousedown', 'drag.init', 'canvas.viewbox.
|
|
34
|
+
eventBus.on([ 'element.mousedown', 'drag.init', 'canvas.viewbox.changing' ], function(event) {
|
|
29
35
|
directEditing.complete();
|
|
30
36
|
});
|
|
31
37
|
|
|
32
38
|
// cancel on command stack changes
|
|
33
|
-
eventBus.on([ 'commandStack.changed' ], function() {
|
|
39
|
+
eventBus.on([ 'commandStack.changed' ], function(e) {
|
|
34
40
|
directEditing.cancel();
|
|
35
41
|
});
|
|
36
42
|
|
|
37
|
-
|
|
38
43
|
if ('ontouchstart' in document.documentElement) {
|
|
39
44
|
// we deactivate automatic label editing on mobile devices
|
|
40
45
|
// as it breaks the user interaction workflow
|
|
@@ -42,10 +47,9 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack) {
|
|
|
42
47
|
// TODO(nre): we should temporarily focus the edited element here
|
|
43
48
|
// and release the focused viewport after the direct edit operation is finished
|
|
44
49
|
} else {
|
|
45
|
-
eventBus.on('create.end', 500, function(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
canExecute = e.context.canExecute;
|
|
50
|
+
eventBus.on('create.end', 500, function(event) {
|
|
51
|
+
var element = event.shape,
|
|
52
|
+
canExecute = event.context.canExecute;
|
|
49
53
|
|
|
50
54
|
if (!canExecute) {
|
|
51
55
|
return;
|
|
@@ -53,14 +57,15 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack) {
|
|
|
53
57
|
|
|
54
58
|
if (is(element, 'bpmn:Task') || is(element, 'bpmn:TextAnnotation') ||
|
|
55
59
|
(is(element, 'bpmn:SubProcess') && !isExpanded(element))) {
|
|
56
|
-
|
|
57
60
|
directEditing.activate(element);
|
|
61
|
+
|
|
62
|
+
resizeHandles.removeResizers();
|
|
58
63
|
}
|
|
59
64
|
});
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
LabelEditingProvider.$inject = [ 'eventBus', 'canvas', 'directEditing', 'commandStack' ];
|
|
68
|
+
LabelEditingProvider.$inject = [ 'eventBus', 'canvas', 'directEditing', 'commandStack', 'resizeHandles' ];
|
|
64
69
|
|
|
65
70
|
module.exports = LabelEditingProvider;
|
|
66
71
|
|
|
@@ -70,21 +75,62 @@ module.exports = LabelEditingProvider;
|
|
|
70
75
|
*
|
|
71
76
|
* @param {djs.model.Base} element
|
|
72
77
|
*
|
|
73
|
-
* @return {Object} an object with properties bounds (position and size) and
|
|
78
|
+
* @return {Object} an object with properties bounds (position and size), text and options
|
|
74
79
|
*/
|
|
75
80
|
LabelEditingProvider.prototype.activate = function(element) {
|
|
76
81
|
|
|
82
|
+
// text
|
|
77
83
|
var text = LabelUtil.getLabel(element);
|
|
78
84
|
|
|
79
85
|
if (text === undefined) {
|
|
80
86
|
return;
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
var
|
|
89
|
+
var context = {
|
|
90
|
+
text: text
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// bounds
|
|
94
|
+
var bounds = this.getEditingBBox(element);
|
|
95
|
+
|
|
96
|
+
assign(context, bounds);
|
|
97
|
+
|
|
98
|
+
// options
|
|
99
|
+
var target = element.label || element;
|
|
100
|
+
|
|
101
|
+
var options = {};
|
|
84
102
|
|
|
85
|
-
|
|
103
|
+
// tasks
|
|
104
|
+
if (is(element, 'bpmn:Task') ||
|
|
105
|
+
is(element, 'bpmn:Participant') ||
|
|
106
|
+
is(element, 'bpmn:Lane') ||
|
|
107
|
+
(is(element, 'bpmn:CallActivity') && !isExpanded(element)) ||
|
|
108
|
+
(is(element, 'bpmn:SubProcess') && !isExpanded(element))) {
|
|
109
|
+
assign(options, {
|
|
110
|
+
centerVertically: true
|
|
111
|
+
});
|
|
112
|
+
}
|
|
86
113
|
|
|
87
|
-
|
|
114
|
+
// external labels
|
|
115
|
+
if (target.labelTarget) {
|
|
116
|
+
assign(options, {
|
|
117
|
+
autoResize: true
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// text annotations
|
|
122
|
+
if (is(element, 'bpmn:TextAnnotation')) {
|
|
123
|
+
assign(options, {
|
|
124
|
+
resizable: true,
|
|
125
|
+
autoResize: true
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
assign(context, {
|
|
130
|
+
options: options
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return context;
|
|
88
134
|
};
|
|
89
135
|
|
|
90
136
|
|
|
@@ -110,17 +156,36 @@ LabelEditingProvider.prototype.getEditingBBox = function(element) {
|
|
|
110
156
|
// default position
|
|
111
157
|
var bounds = { x: bbox.x, y: bbox.y };
|
|
112
158
|
|
|
113
|
-
var
|
|
114
|
-
|
|
159
|
+
var zoom = canvas.zoom();
|
|
160
|
+
|
|
161
|
+
// take zoom into account
|
|
162
|
+
var smallFontSize = SMALL_FONT_SIZE * zoom,
|
|
163
|
+
smallLineHeight = SMALL_LINE_HEIGHT * zoom,
|
|
164
|
+
mediumFontSize = MEDIUM_FONT_SIZE * zoom,
|
|
165
|
+
mediumLineHeight = MEDIUM_LINE_HEIGHT * zoom;
|
|
166
|
+
|
|
167
|
+
var style = {};
|
|
115
168
|
|
|
116
169
|
// adjust for expanded pools AND lanes
|
|
117
|
-
if ((is(element, 'bpmn:Participant') && isExpanded(element))
|
|
170
|
+
if ((is(element, 'bpmn:Participant') && isExpanded(element))
|
|
171
|
+
|| is(element, 'bpmn:Lane')) {
|
|
172
|
+
|
|
173
|
+
assign(bounds, {
|
|
174
|
+
width: bbox.height,
|
|
175
|
+
height: 30 * zoom,
|
|
176
|
+
x: bbox.x - bbox.height / 2 + (15 * zoom),
|
|
177
|
+
y: mid.y - (30 * zoom) / 2
|
|
178
|
+
});
|
|
118
179
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
180
|
+
assign(style, {
|
|
181
|
+
fontSize: mediumFontSize + 'px',
|
|
182
|
+
lineHeight: mediumLineHeight + 'px',
|
|
183
|
+
paddingTop: (7 * zoom) + 'px',
|
|
184
|
+
paddingBottom: (7 * zoom) + 'px',
|
|
185
|
+
paddingLeft: (5 * zoom) + 'px',
|
|
186
|
+
paddingRight: (5 * zoom) + 'px',
|
|
187
|
+
transform: 'rotate(-90deg)'
|
|
188
|
+
});
|
|
124
189
|
}
|
|
125
190
|
|
|
126
191
|
|
|
@@ -131,63 +196,97 @@ LabelEditingProvider.prototype.getEditingBBox = function(element) {
|
|
|
131
196
|
(is(element, 'bpmn:SubProcess') && !isExpanded(element)) ||
|
|
132
197
|
(is(element, 'bpmn:Participant') && !isExpanded(element))
|
|
133
198
|
) {
|
|
199
|
+
assign(bounds, {
|
|
200
|
+
width: bbox.width,
|
|
201
|
+
height: bbox.height
|
|
202
|
+
});
|
|
134
203
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
bounds.height = bbox.height;
|
|
144
|
-
} else {
|
|
145
|
-
bounds.width = bbox.width / zoom;
|
|
146
|
-
bounds.height = bbox.height / zoom;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// centering overlapping text box size at low zoom levels
|
|
150
|
-
if (zoom < 1) {
|
|
151
|
-
bounds.x = bbox.x - (bounds.width / 2 - bbox.width / 2);
|
|
152
|
-
bounds.y = bbox.y - (bounds.height / 2 - bbox.height / 2);
|
|
153
|
-
}
|
|
154
|
-
|
|
204
|
+
assign(style, {
|
|
205
|
+
fontSize: mediumFontSize + 'px',
|
|
206
|
+
lineHeight: mediumLineHeight + 'px',
|
|
207
|
+
paddingTop: (7 * zoom) + 'px',
|
|
208
|
+
paddingBottom: (7 * zoom) + 'px',
|
|
209
|
+
paddingLeft: (5 * zoom) + 'px',
|
|
210
|
+
paddingRight: (5 * zoom) + 'px'
|
|
211
|
+
});
|
|
155
212
|
}
|
|
156
213
|
|
|
157
214
|
|
|
158
215
|
// internal labels for expanded sub processes
|
|
159
216
|
if (is(element, 'bpmn:SubProcess') && isExpanded(element)) {
|
|
217
|
+
assign(bounds, {
|
|
218
|
+
width: bbox.width,
|
|
219
|
+
x: bbox.x
|
|
220
|
+
});
|
|
160
221
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
222
|
+
assign(style, {
|
|
223
|
+
fontSize: mediumFontSize + 'px',
|
|
224
|
+
lineHeight: mediumLineHeight + 'px',
|
|
225
|
+
paddingTop: (7 * zoom) + 'px',
|
|
226
|
+
paddingBottom: (7 * zoom) + 'px',
|
|
227
|
+
paddingLeft: (5 * zoom) + 'px',
|
|
228
|
+
paddingRight: (5 * zoom) + 'px'
|
|
229
|
+
});
|
|
164
230
|
}
|
|
165
231
|
|
|
166
232
|
|
|
167
233
|
// external labels for events, data elements, gateways and connections
|
|
168
234
|
if (target.labelTarget) {
|
|
235
|
+
var width = 90 * zoom,
|
|
236
|
+
paddingTop = 7 * zoom,
|
|
237
|
+
paddingBottom = 4 * zoom;
|
|
238
|
+
|
|
239
|
+
assign(bounds, {
|
|
240
|
+
width: width,
|
|
241
|
+
height: bbox.height + paddingTop + paddingBottom,
|
|
242
|
+
x: mid.x - width / 2,
|
|
243
|
+
y: bbox.y - paddingTop
|
|
244
|
+
});
|
|
169
245
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
246
|
+
assign(style, {
|
|
247
|
+
fontSize: smallFontSize + 'px',
|
|
248
|
+
lineHeight: smallLineHeight + 'px',
|
|
249
|
+
paddingTop: paddingTop + 'px',
|
|
250
|
+
paddingBottom: paddingBottom + 'px'
|
|
251
|
+
});
|
|
173
252
|
}
|
|
174
253
|
|
|
175
254
|
|
|
176
255
|
// text annotations
|
|
177
256
|
if (is(element, 'bpmn:TextAnnotation')) {
|
|
178
|
-
bounds
|
|
179
|
-
|
|
257
|
+
assign(bounds, {
|
|
258
|
+
width: bbox.width,
|
|
259
|
+
height: bbox.height,
|
|
260
|
+
minWidth: 30 * zoom,
|
|
261
|
+
minHeight: 10 * zoom
|
|
262
|
+
});
|
|
180
263
|
|
|
181
|
-
style
|
|
264
|
+
assign(style, {
|
|
265
|
+
textAlign: 'left',
|
|
266
|
+
paddingTop: (7 * zoom) + 'px',
|
|
267
|
+
paddingBottom: (7 * zoom) + 'px',
|
|
268
|
+
paddingLeft: (5 * zoom) + 'px',
|
|
269
|
+
paddingRight: (5 * zoom) + 'px',
|
|
270
|
+
fontSize: mediumFontSize + 'px',
|
|
271
|
+
lineHeight: mediumLineHeight + 'px'
|
|
272
|
+
});
|
|
182
273
|
}
|
|
183
274
|
|
|
184
275
|
return { bounds: bounds, style: style };
|
|
185
276
|
};
|
|
186
277
|
|
|
187
278
|
|
|
188
|
-
LabelEditingProvider.prototype.update = function(element, newLabel) {
|
|
279
|
+
LabelEditingProvider.prototype.update = function(element, newLabel, activeContextText, bounds) {
|
|
280
|
+
var absoluteElementBBox = this._canvas.getAbsoluteBBox(element);
|
|
281
|
+
|
|
189
282
|
this._commandStack.execute('element.updateLabel', {
|
|
190
283
|
element: element,
|
|
191
|
-
newLabel: newLabel
|
|
284
|
+
newLabel: newLabel,
|
|
285
|
+
bounds: {
|
|
286
|
+
x: element.x,
|
|
287
|
+
y: element.y,
|
|
288
|
+
width: element.width / absoluteElementBBox.width * bounds.width,
|
|
289
|
+
height: element.height / absoluteElementBBox.height * bounds.height
|
|
290
|
+
}
|
|
192
291
|
});
|
|
193
292
|
};
|
|
@@ -6,7 +6,8 @@ var TextUtil = require('diagram-js/lib/util/Text');
|
|
|
6
6
|
|
|
7
7
|
var hasExternalLabel = require('../../../util/LabelUtil').hasExternalLabel;
|
|
8
8
|
|
|
9
|
-
var getBusinessObject = require('../../../util/ModelUtil').getBusinessObject
|
|
9
|
+
var getBusinessObject = require('../../../util/ModelUtil').getBusinessObject,
|
|
10
|
+
is = require('../../../util/ModelUtil').is;
|
|
10
11
|
|
|
11
12
|
var NULL_DIMENSIONS = {
|
|
12
13
|
width: 0,
|
|
@@ -52,14 +53,17 @@ function UpdateLabelHandler(modeling) {
|
|
|
52
53
|
|
|
53
54
|
function postExecute(ctx) {
|
|
54
55
|
var element = ctx.element,
|
|
55
|
-
label = element.label || element
|
|
56
|
+
label = element.label || element,
|
|
57
|
+
bounds = ctx.bounds;
|
|
56
58
|
|
|
57
|
-
// ignore internal labels
|
|
58
|
-
if (!hasExternalLabel(element)) {
|
|
59
|
+
// ignore internal labels for elements except text annotations
|
|
60
|
+
if (!hasExternalLabel(element) && !is(element, 'bpmn:TextAnnotation')) {
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
var
|
|
64
|
+
var bo = getBusinessObject(label);
|
|
65
|
+
|
|
66
|
+
var text = bo.name || bo.text;
|
|
63
67
|
|
|
64
68
|
if (!text) {
|
|
65
69
|
return;
|
|
@@ -67,7 +71,7 @@ function UpdateLabelHandler(modeling) {
|
|
|
67
71
|
|
|
68
72
|
// get layouted text bounds and resize external
|
|
69
73
|
// external label accordingly
|
|
70
|
-
var newBounds = getLayoutedBounds(label, text, textUtil);
|
|
74
|
+
var newBounds = is(element, 'bpmn:TextAnnotation') ? bounds : getLayoutedBounds(label, text, textUtil);
|
|
71
75
|
|
|
72
76
|
modeling.resizeShape(label, newBounds, NULL_DIMENSIONS);
|
|
73
77
|
}
|
|
@@ -2,8 +2,13 @@ module.exports = {
|
|
|
2
2
|
__depends__: [
|
|
3
3
|
require('diagram-js/lib/command'),
|
|
4
4
|
require('diagram-js/lib/features/change-support'),
|
|
5
|
+
require('diagram-js/lib/features/resize'),
|
|
5
6
|
require('diagram-js-direct-editing')
|
|
6
7
|
],
|
|
7
|
-
__init__: [
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
__init__: [
|
|
9
|
+
'labelEditingProvider',
|
|
10
|
+
'labelEditingPreview'
|
|
11
|
+
],
|
|
12
|
+
labelEditingProvider: [ 'type', require('./LabelEditingProvider') ],
|
|
13
|
+
labelEditingPreview: [ 'type', require('./LabelEditingPreview') ]
|
|
14
|
+
};
|
|
@@ -2,12 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
var inherits = require('inherits');
|
|
4
4
|
|
|
5
|
-
var assign = require('lodash/object/assign')
|
|
5
|
+
var assign = require('lodash/object/assign'),
|
|
6
|
+
find = require('lodash/collection/find');
|
|
6
7
|
|
|
7
8
|
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
|
|
8
9
|
|
|
9
10
|
var getApproxIntersection = require('diagram-js/lib/util/LineIntersection').getApproxIntersection;
|
|
10
11
|
|
|
12
|
+
function isPointInsideBBox(bbox, point) {
|
|
13
|
+
var x = point.x,
|
|
14
|
+
y = point.y;
|
|
15
|
+
|
|
16
|
+
return x >= bbox.x &&
|
|
17
|
+
x <= bbox.x + bbox.width &&
|
|
18
|
+
y >= bbox.y &&
|
|
19
|
+
y <= bbox.y + bbox.height;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
function copy(obj) {
|
|
12
23
|
return assign({}, obj);
|
|
13
24
|
}
|
|
@@ -41,8 +52,15 @@ function DropOnFlow(eventBus, bpmnRules, modeling) {
|
|
|
41
52
|
|
|
42
53
|
dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : position;
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
// if last waypointBefore is inside shape's bounds, ignore docking point
|
|
56
|
+
if (!isPointInsideBBox(shape, waypointsBefore[waypointsBefore.length-1])) {
|
|
57
|
+
waypointsBefore.push(copy(dockingPoint));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// if first waypointAfter is inside shape's bounds, ignore docking point
|
|
61
|
+
if (!isPointInsideBBox(shape, waypointsAfter[0])) {
|
|
62
|
+
waypointsAfter.unshift(copy(dockingPoint));
|
|
63
|
+
}
|
|
46
64
|
}
|
|
47
65
|
|
|
48
66
|
source = targetFlow.source;
|
|
@@ -68,24 +86,40 @@ function DropOnFlow(eventBus, bpmnRules, modeling) {
|
|
|
68
86
|
|
|
69
87
|
this.preExecute('elements.move', function(context) {
|
|
70
88
|
|
|
71
|
-
var
|
|
89
|
+
var newParent = context.newParent,
|
|
72
90
|
shapes = context.shapes,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
delta = context.delta;
|
|
91
|
+
delta = context.delta,
|
|
92
|
+
shape = shapes[0];
|
|
76
93
|
|
|
77
|
-
if (
|
|
94
|
+
if (!shape || !newParent) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
78
97
|
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
// if the new parent is a connection,
|
|
99
|
+
// change it to the new parent's parent
|
|
100
|
+
if (newParent && newParent.waypoints) {
|
|
101
|
+
context.newParent = newParent = newParent.parent;
|
|
102
|
+
}
|
|
81
103
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
var shapeMid = getMid(shape);
|
|
105
|
+
var newShapeMid = {
|
|
106
|
+
x: shapeMid.x + delta.x,
|
|
107
|
+
y: shapeMid.y + delta.y
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// find a connection which intersects with the
|
|
111
|
+
// element's mid point
|
|
112
|
+
var connection = find(newParent.children, function(element) {
|
|
113
|
+
var canInsert = bpmnRules.canInsert(shapes, element);
|
|
114
|
+
|
|
115
|
+
return canInsert && getApproxIntersection(element.waypoints, newShapeMid);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (connection) {
|
|
119
|
+
context.targetFlow = connection;
|
|
120
|
+
context.position = newShapeMid;
|
|
88
121
|
}
|
|
122
|
+
|
|
89
123
|
}, true);
|
|
90
124
|
|
|
91
125
|
this.postExecuted('elements.move', function(context) {
|