bpmn-js 8.8.1 → 9.0.0-subprocesses.2

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/assets/bpmn-js.css +57 -0
  3. package/dist/assets/diagram-js.css +2 -0
  4. package/dist/bpmn-modeler.development.js +1289 -795
  5. package/dist/bpmn-modeler.production.min.js +8 -7
  6. package/dist/bpmn-navigated-viewer.development.js +20635 -19973
  7. package/dist/bpmn-navigated-viewer.production.min.js +22 -20
  8. package/dist/bpmn-viewer.development.js +19836 -19174
  9. package/dist/bpmn-viewer.production.min.js +22 -20
  10. package/lib/BaseViewer.js +0 -13
  11. package/lib/Viewer.js +3 -1
  12. package/lib/draw/BpmnRenderUtil.js +6 -4
  13. package/lib/draw/BpmnRenderer.js +363 -296
  14. package/lib/features/context-pad/ContextPadProvider.js +1 -1
  15. package/lib/features/copy-paste/BpmnCopyPaste.js +13 -13
  16. package/lib/features/copy-paste/ModdleCopy.js +15 -3
  17. package/lib/features/di-ordering/BpmnDiOrdering.js +2 -3
  18. package/lib/features/drilldown/DrilldownCentering.js +41 -0
  19. package/lib/features/drilldown/DrilldownOverlays.js +109 -0
  20. package/lib/features/drilldown/SubprocessCompatibility.js +193 -0
  21. package/lib/features/drilldown/index.js +14 -0
  22. package/lib/features/label-editing/LabelEditingPreview.js +3 -3
  23. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +2 -1
  24. package/lib/features/modeling/BpmnFactory.js +8 -8
  25. package/lib/features/modeling/BpmnUpdater.js +35 -27
  26. package/lib/features/modeling/ElementFactory.js +60 -37
  27. package/lib/features/modeling/behavior/DataStoreBehavior.js +3 -1
  28. package/lib/features/modeling/behavior/IsHorizontalFix.js +7 -4
  29. package/lib/features/modeling/behavior/LabelBehavior.js +8 -7
  30. package/lib/features/modeling/behavior/ToggleElementCollapseBehaviour.js +6 -6
  31. package/lib/features/modeling/cmd/UpdateCanvasRootHandler.js +8 -6
  32. package/lib/features/modeling/cmd/UpdatePropertiesHandler.js +19 -12
  33. package/lib/features/modeling/cmd/UpdateSemanticParentHandler.js +5 -3
  34. package/lib/features/palette/PaletteProvider.js +3 -1
  35. package/lib/features/popup-menu/ReplaceMenuProvider.js +5 -5
  36. package/lib/features/popup-menu/util/TypeUtil.js +1 -1
  37. package/lib/features/replace/BpmnReplace.js +29 -29
  38. package/lib/import/BpmnImporter.js +27 -22
  39. package/lib/import/BpmnTreeWalker.js +19 -17
  40. package/lib/import/Importer.js +17 -6
  41. package/lib/util/CompatibilityUtil.js +21 -1
  42. package/lib/util/DiUtil.js +10 -3
  43. package/lib/util/LabelUtil.js +2 -3
  44. package/lib/util/ModelUtil.js +11 -0
  45. package/package.json +2 -2
  46. package/test/matchers/BoundsMatchers.js +10 -10
  47. package/test/matchers/ConnectionMatchers.js +5 -5
  48. package/test/util/MockEvents.js +10 -2
@@ -197,7 +197,7 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
197
197
  }
198
198
 
199
199
 
200
- if (isAny(businessObject, [ 'bpmn:Lane', 'bpmn:Participant' ]) && isExpanded(businessObject)) {
200
+ if (isAny(businessObject, [ 'bpmn:Lane', 'bpmn:Participant' ]) && isExpanded(element)) {
201
201
 
202
202
  var childLanes = getChildLanes(element);
203
203
 
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  getBusinessObject,
3
+ getDi,
3
4
  is
4
5
  } from '../../util/ModelUtil';
5
6
 
@@ -45,23 +46,13 @@ export default function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) {
45
46
  element = context.element;
46
47
 
47
48
  var businessObject = descriptor.oldBusinessObject = getBusinessObject(element);
49
+ var di = descriptor.oldDi = getDi(element);
48
50
 
49
51
  descriptor.type = element.type;
50
52
 
51
53
  copyProperties(businessObject, descriptor, 'name');
52
54
 
53
- descriptor.di = {};
54
-
55
- // colors will be set to DI
56
- copyProperties(businessObject.di, descriptor.di, [
57
- 'fill',
58
- 'stroke',
59
- 'background-color',
60
- 'border-color',
61
- 'color'
62
- ]);
63
-
64
- copyProperties(businessObject.di, descriptor, 'isExpanded');
55
+ copyProperties(di, descriptor, 'isExpanded');
65
56
 
66
57
  if (isLabel(descriptor)) {
67
58
  return descriptor;
@@ -135,11 +126,13 @@ export default function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) {
135
126
  var cache = context.cache,
136
127
  descriptor = context.descriptor,
137
128
  oldBusinessObject = descriptor.oldBusinessObject,
138
- newBusinessObject;
129
+ oldDi = descriptor.oldDi,
130
+ newBusinessObject, newDi;
139
131
 
140
132
  // do NOT copy business object if external label
141
133
  if (isLabel(descriptor)) {
142
134
  descriptor.businessObject = getBusinessObject(cache[ descriptor.labelTarget ]);
135
+ descriptor.di = getDi(cache[ descriptor.labelTarget ]);
143
136
 
144
137
  return;
145
138
  }
@@ -151,6 +144,13 @@ export default function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) {
151
144
  newBusinessObject
152
145
  );
153
146
 
147
+ newDi = bpmnFactory.create(oldDi.$type);
148
+
149
+ descriptor.di = moddleCopy.copyElement(
150
+ oldDi,
151
+ newDi
152
+ );
153
+
154
154
  // resolve references e.g. default sequence flow
155
155
  resolveReferences(descriptor, cache);
156
156
 
@@ -220,9 +220,9 @@ ModdleCopy.prototype.copyProperty = function(property, parent, propertyName) {
220
220
  return;
221
221
  }
222
222
 
223
- // disallow copying IDs if already assigned
224
- if (propertyDescriptor.isId && this._moddle.ids.assigned(property)) {
225
- return;
223
+ // copy id
224
+ if (propertyDescriptor.isId) {
225
+ return this._copyId(property, parent);
226
226
  }
227
227
 
228
228
  // copy arrays
@@ -263,6 +263,18 @@ ModdleCopy.prototype.copyProperty = function(property, parent, propertyName) {
263
263
  return property;
264
264
  };
265
265
 
266
+ ModdleCopy.prototype._copyId = function(id, element) {
267
+
268
+ // disallow if already taken
269
+ if (this._moddle.ids.assigned(id)) {
270
+ return;
271
+ } else {
272
+
273
+ this._moddle.ids.claim(id, element);
274
+ return id;
275
+ }
276
+ };
277
+
266
278
  // helpers //////////
267
279
 
268
280
  export function getPropertyNames(descriptor, keepDefaultProperties) {
@@ -1,5 +1,4 @@
1
- import { getDi } from '../../draw/BpmnRenderUtil';
2
- import { getBusinessObject } from '../../util/ModelUtil';
1
+ import { getDi } from '../../util/ModelUtil';
3
2
 
4
3
  import {
5
4
  filter,
@@ -17,7 +16,7 @@ export default function BpmnDiOrdering(eventBus, canvas) {
17
16
 
18
17
  function orderDi() {
19
18
  var root = canvas.getRootElement(),
20
- rootDi = getBusinessObject(root).di,
19
+ rootDi = getDi(root),
21
20
  elements,
22
21
  diElements;
23
22
 
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Move collapsed subprocesses into view when drilling down. Zoom and scroll
3
+ * are saved in a session.
4
+ *
5
+ * @param {eventBus} eventBus
6
+ * @param {canvas} canvas
7
+ */
8
+ export default function DrilldownCentering(eventBus, canvas) {
9
+ var currentPlane = 'base';
10
+ var positionMap = {};
11
+
12
+ eventBus.on('plane.set', function(event) {
13
+ var currentViewbox = canvas.viewbox();
14
+ positionMap[currentPlane] = {
15
+ x: currentViewbox.x,
16
+ y: currentViewbox.y,
17
+ zoom: currentViewbox.scale
18
+ };
19
+
20
+ var planeId = event.plane.name;
21
+ var storedViewbox = positionMap[planeId] || { x: 0, y: 0, zoom: 1 };
22
+
23
+ var dx = (currentViewbox.x - storedViewbox.x) * currentViewbox.scale,
24
+ dy = (currentViewbox.y - storedViewbox.y) * currentViewbox.scale;
25
+
26
+ if (dx !== 0 || dy !== 0) {
27
+ canvas.scroll({
28
+ dx: dx,
29
+ dy: dy
30
+ });
31
+ }
32
+
33
+ if (storedViewbox.zoom !== currentViewbox.scale) {
34
+ canvas.zoom(storedViewbox.zoom, { x: 0, y: 0 });
35
+ }
36
+
37
+ currentPlane = planeId;
38
+ });
39
+ }
40
+
41
+ DrilldownCentering.$inject = [ 'eventBus', 'canvas' ];
@@ -0,0 +1,109 @@
1
+ import { domify } from 'min-dom';
2
+
3
+ import { escapeHTML } from 'diagram-js/lib/util/EscapeUtil';
4
+ import { getBusinessObject, is } from '../../util/ModelUtil';
5
+
6
+ var ARROW_DOWN_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4.81801948,3.50735931 L10.4996894,9.1896894 L10.5,4 L12,4 L12,12 L4,12 L4,10.5 L9.6896894,10.4996894 L3.75735931,4.56801948 C3.46446609,4.27512627 3.46446609,3.80025253 3.75735931,3.50735931 C4.05025253,3.21446609 4.52512627,3.21446609 4.81801948,3.50735931 Z"/></svg>';
7
+
8
+ /**
9
+ * Adds Overlays that allow switching planes on collapsed subprocesses.
10
+ *
11
+ * @param {eventBus} eventBus
12
+ * @param {elementRegistry} elementRegistry
13
+ * @param {overlays} overlays
14
+ * @param {canvas} canvas
15
+ */
16
+ export default function DrilldownOverlays(eventBus, elementRegistry, overlays, canvas) {
17
+ var breadcrumbs = domify('<ul class="bjs-breadcrumbs djs-element-hidden"></ul>');
18
+ var container = canvas.getContainer();
19
+ container.appendChild(breadcrumbs);
20
+
21
+ function updateBreadcrumbs(plane) {
22
+ var subProcess = elementRegistry.get(plane.name);
23
+ var parents = getParentChain(subProcess);
24
+
25
+ var path = parents.map(function(el) {
26
+ var title = escapeHTML(el.name || el.id);
27
+ var link = domify('<li><span class="bjs-crumb"><a title="' + title + '">' + title + '</a></span></li>');
28
+
29
+ link.addEventListener('click', function() {
30
+ if (canvas.getPlane(el.id)) {
31
+ canvas.setActivePlane(el.id);
32
+ } else {
33
+ var plane = canvas.findPlane(el.id);
34
+ canvas.setActivePlane(plane);
35
+ }
36
+ });
37
+
38
+ return link;
39
+ });
40
+
41
+ breadcrumbs.innerHTML = '';
42
+
43
+ if (path.length > 1) {
44
+ breadcrumbs.classList.remove('djs-element-hidden');
45
+ } else {
46
+ breadcrumbs.classList.add('djs-element-hidden');
47
+ }
48
+
49
+ path.forEach(function(el) {
50
+ breadcrumbs.appendChild(el);
51
+ });
52
+ }
53
+
54
+ eventBus.on('plane.set', function(event) {
55
+ var plane = event.plane;
56
+
57
+ updateBreadcrumbs(plane);
58
+ });
59
+
60
+ var createOverlay = function(element) {
61
+ var html = domify('<button class="bjs-drilldown">' + ARROW_DOWN_SVG + '</button>');
62
+
63
+ html.addEventListener('click', function() {
64
+ canvas.setActivePlane(element.id);
65
+ });
66
+
67
+ overlays.add(element, {
68
+ position: {
69
+ bottom: -7,
70
+ right: -8
71
+ },
72
+ html: html
73
+ });
74
+ };
75
+
76
+ var addOverlays = function(elements) {
77
+ elements.forEach(function(element) {
78
+ if (is(element, 'bpmn:SubProcess')
79
+ && element.collapsed
80
+ && canvas.getPlane(element.id)) {
81
+ createOverlay(element);
82
+ }
83
+ });
84
+ };
85
+
86
+ eventBus.on('import.done', function() {
87
+ addOverlays(elementRegistry.filter(function(el) {
88
+ return is(el, 'bpmn:SubProcess');
89
+ }));
90
+ });
91
+ }
92
+
93
+ DrilldownOverlays.$inject = [ 'eventBus', 'elementRegistry', 'overlays', 'canvas' ];
94
+
95
+
96
+ // helpers
97
+ var getParentChain = function(child) {
98
+ var bo = getBusinessObject(child);
99
+
100
+ var parents = [];
101
+
102
+ for (var element = bo; element; element = element.$parent) {
103
+ if (is(element, 'bpmn:SubProcess') || is(element, 'bpmn:Process')) {
104
+ parents.push(element);
105
+ }
106
+ }
107
+
108
+ return parents.reverse();
109
+ };
@@ -0,0 +1,193 @@
1
+
2
+ import { asBounds, asTRBL } from 'diagram-js/lib/layout/LayoutUtil';
3
+ import { is } from '../../util/ModelUtil';
4
+
5
+ var DEFAULT_POSITION = {
6
+ x: 180,
7
+ y: 160
8
+ };
9
+
10
+ /**
11
+ * Hook into `import.render.start` and create new planes for diagrams with
12
+ * collapsed subprocesses and all dis on the same plane.
13
+ *
14
+ * @param {eventBus} eventBus
15
+ * @param {moddle} moddle
16
+ */
17
+ export default function SubprocessCompatibility(eventBus, moddle) {
18
+ this._eventBus = eventBus;
19
+ this._moddle = moddle;
20
+
21
+ var self = this;
22
+
23
+ eventBus.on('import.render.start', 1500, function(e, context) {
24
+ self.handleImport(context.definitions);
25
+ });
26
+ }
27
+
28
+ SubprocessCompatibility.prototype.handleImport = function(definitions) {
29
+ if (!definitions.diagrams) {
30
+ return;
31
+ }
32
+
33
+ var self = this;
34
+ this._definitions = definitions;
35
+ this._processToDiagramMap = {};
36
+
37
+ definitions.diagrams.forEach(function(diagram) {
38
+ if (!diagram.plane || !diagram.plane.bpmnElement) {
39
+ return;
40
+ }
41
+
42
+ self._processToDiagramMap[diagram.plane.bpmnElement.id] = diagram;
43
+ });
44
+
45
+ var newDiagrams = [];
46
+ definitions.diagrams.forEach(function(diagram) {
47
+ var createdDiagrams = self.createNewDiagrams(diagram.plane);
48
+ Array.prototype.push.apply(newDiagrams, createdDiagrams);
49
+ });
50
+
51
+ newDiagrams.forEach(function(diagram) {
52
+ self.movePlaneElementsToOrigin(diagram.plane);
53
+ });
54
+ };
55
+
56
+
57
+ /**
58
+ * Moves all DI elements from collapsed subprocesses to a new plane.
59
+ *
60
+ * @param {Object} plane
61
+ * @return {Array} new diagrams created for the collapsed subprocesses
62
+ */
63
+ SubprocessCompatibility.prototype.createNewDiagrams = function(plane) {
64
+ var self = this;
65
+
66
+ var collapsedElements = [];
67
+ var elementsToMove = [];
68
+
69
+ plane.get('planeElement').forEach(function(diElement) {
70
+ var bo = diElement.bpmnElement;
71
+ var parent = bo.$parent;
72
+
73
+ if (is(bo, 'bpmn:SubProcess') && !diElement.isExpanded) {
74
+ collapsedElements.push(bo);
75
+ }
76
+
77
+ if (is(parent, 'bpmn:SubProcess') && parent !== plane.bpmnElement) {
78
+
79
+ // don't change the array while we iterate over it
80
+ elementsToMove.push({ diElement: diElement, parent: parent });
81
+ }
82
+ });
83
+
84
+ var newDiagrams = [];
85
+
86
+ elementsToMove.forEach(function(element) {
87
+ var diElement = element.diElement;
88
+ var parent = element.parent;
89
+
90
+ // parent is expanded, get nearest collapsed parent
91
+ while (parent && !collapsedElements.includes(parent)) {
92
+ parent = parent.$parent;
93
+ }
94
+
95
+ // false positive, all parents are expanded
96
+ if (!parent) {
97
+ return;
98
+ }
99
+
100
+ var diagram = self._processToDiagramMap[parent.id];
101
+ if (!diagram) {
102
+ diagram = self.createDiagram(parent);
103
+ self._processToDiagramMap[parent.id] = diagram;
104
+ newDiagrams.push(diagram);
105
+ }
106
+
107
+ self.moveToDiPlane(diElement, diagram.plane);
108
+ });
109
+
110
+ return newDiagrams;
111
+ };
112
+
113
+ SubprocessCompatibility.prototype.movePlaneElementsToOrigin = function(plane) {
114
+ var elements = plane.get('planeElement');
115
+
116
+ // get bounding box of all elements
117
+ var planeBounds = getPlaneBounds(plane);
118
+
119
+ var offset = {
120
+ x: planeBounds.x - DEFAULT_POSITION.x,
121
+ y: planeBounds.y - DEFAULT_POSITION.y
122
+ };
123
+
124
+ elements.forEach(function(diElement) {
125
+ if (diElement.waypoint) {
126
+ diElement.waypoint.forEach(function(waypoint) {
127
+ waypoint.x = waypoint.x - offset.x;
128
+ waypoint.y = waypoint.y - offset.y;
129
+ });
130
+ } else if (diElement.bounds) {
131
+ diElement.bounds.x = diElement.bounds.x - offset.x;
132
+ diElement.bounds.y = diElement.bounds.y - offset.y;
133
+ }
134
+ });
135
+ };
136
+
137
+
138
+ SubprocessCompatibility.prototype.moveToDiPlane = function(diElement, newPlane) {
139
+ var containingDiagram = findRootDiagram(diElement);
140
+
141
+ // remove DI from old Plane and add it to the new one
142
+ var parentPlaneElement = containingDiagram.plane.get('planeElement');
143
+ parentPlaneElement.splice(parentPlaneElement.indexOf(diElement), 1);
144
+ newPlane.get('planeElement').push(diElement);
145
+ };
146
+
147
+
148
+ SubprocessCompatibility.prototype.createDiagram = function(bo) {
149
+ var plane = this._moddle.create('bpmndi:BPMNPlane', { bpmnElement: bo });
150
+ var diagram = this._moddle.create('bpmndi:BPMNDiagram', {
151
+ plane: plane
152
+ });
153
+ plane.$parent = diagram;
154
+ plane.bpmnElement = bo;
155
+ diagram.$parent = this._definitions;
156
+ this._definitions.diagrams.push(diagram);
157
+ return diagram;
158
+ };
159
+
160
+ SubprocessCompatibility.$inject = [ 'eventBus', 'moddle' ];
161
+
162
+
163
+ // helpers
164
+
165
+ function findRootDiagram(element) {
166
+ if (is(element, 'bpmndi:BPMNDiagram')) {
167
+ return element;
168
+ } else {
169
+ return findRootDiagram(element.$parent);
170
+ }
171
+ }
172
+
173
+ function getPlaneBounds(plane) {
174
+ var planeTrbl = {
175
+ top: Infinity,
176
+ right: -Infinity,
177
+ bottom: -Infinity,
178
+ left: Infinity
179
+ };
180
+
181
+ plane.planeElement.forEach(function(element) {
182
+ if (!element.bounds) {
183
+ return;
184
+ }
185
+
186
+ var trbl = asTRBL(element.bounds);
187
+
188
+ planeTrbl.top = Math.min(trbl.top, planeTrbl.top);
189
+ planeTrbl.left = Math.min(trbl.left, planeTrbl.left);
190
+ });
191
+
192
+ return asBounds(planeTrbl);
193
+ }
@@ -0,0 +1,14 @@
1
+ import OverlaysModule from 'diagram-js/lib/features/overlays';
2
+ import ChangeSupportModule from 'diagram-js/lib/features/change-support';
3
+
4
+ import DrilldownOverlays from './DrilldownOverlays';
5
+ import DrilldownCentering from './DrilldownCentering';
6
+ import SubprocessCompatibility from './SubprocessCompatibility';
7
+
8
+ export default {
9
+ __depends__: [ OverlaysModule, ChangeSupportModule ],
10
+ __init__: [ 'drilldownOverlays', 'drilldownCentering', 'subprocessCompatibility'],
11
+ drilldownOverlays: [ 'type', DrilldownOverlays ],
12
+ drilldownCentering: [ 'type', DrilldownCentering ],
13
+ subprocessCompatibility: [ 'type', SubprocessCompatibility ]
14
+ };
@@ -6,7 +6,7 @@ import {
6
6
  } from 'tiny-svg';
7
7
 
8
8
  import {
9
- getBusinessObject,
9
+ getDi,
10
10
  is
11
11
  } from '../../util/ModelUtil';
12
12
 
@@ -132,7 +132,7 @@ LabelEditingPreview.$inject = [
132
132
  // helpers ///////////////////
133
133
 
134
134
  function getStrokeColor(element, defaultColor) {
135
- var bo = getBusinessObject(element);
135
+ var di = getDi(element);
136
136
 
137
- return bo.di.get('stroke') || defaultColor || 'black';
137
+ return di.get('stroke') || defaultColor || 'black';
138
138
  }
@@ -67,7 +67,8 @@ export default function UpdateLabelHandler(modeling, textRenderer) {
67
67
 
68
68
  modeling.createLabel(element, labelCenter, {
69
69
  id: businessObject.id + '_label',
70
- businessObject: businessObject
70
+ businessObject: businessObject,
71
+ di: element.di
71
72
  });
72
73
  }
73
74
  }
@@ -83,11 +83,10 @@ BpmnFactory.prototype.createDiLabel = function() {
83
83
  };
84
84
 
85
85
 
86
- BpmnFactory.prototype.createDiShape = function(semantic, bounds, attrs) {
87
-
86
+ BpmnFactory.prototype.createDiShape = function(semantic, attrs) {
88
87
  return this.create('bpmndi:BPMNShape', assign({
89
88
  bpmnElement: semantic,
90
- bounds: this.createDiBounds(bounds)
89
+ bounds: this.createDiBounds()
91
90
  }, attrs));
92
91
  };
93
92
 
@@ -110,14 +109,15 @@ BpmnFactory.prototype.createDiWaypoint = function(point) {
110
109
  };
111
110
 
112
111
 
113
- BpmnFactory.prototype.createDiEdge = function(semantic, waypoints, attrs) {
112
+ BpmnFactory.prototype.createDiEdge = function(semantic, attrs) {
114
113
  return this.create('bpmndi:BPMNEdge', assign({
115
- bpmnElement: semantic
114
+ bpmnElement: semantic,
115
+ waypoints: this.createDiWaypoints([])
116
116
  }, attrs));
117
117
  };
118
118
 
119
- BpmnFactory.prototype.createDiPlane = function(semantic) {
120
- return this.create('bpmndi:BPMNPlane', {
119
+ BpmnFactory.prototype.createDiPlane = function(semantic, attrs) {
120
+ return this.create('bpmndi:BPMNPlane', assign({
121
121
  bpmnElement: semantic
122
- });
122
+ }, attrs));
123
123
  };