bpmn-js 9.0.0-subprocesses.3 → 9.0.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 (44) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/assets/bpmn-js.css +44 -7
  3. package/dist/assets/diagram-js.css +1 -1
  4. package/dist/bpmn-modeler.development.js +2424 -1130
  5. package/dist/bpmn-modeler.production.min.js +8 -8
  6. package/dist/bpmn-navigated-viewer.development.js +990 -317
  7. package/dist/bpmn-navigated-viewer.production.min.js +6 -6
  8. package/dist/bpmn-viewer.development.js +989 -316
  9. package/dist/bpmn-viewer.production.min.js +6 -6
  10. package/lib/BaseViewer.js +1 -1
  11. package/lib/draw/BpmnRenderer.js +8 -7
  12. package/lib/features/auto-resize/BpmnAutoResizeProvider.js +6 -0
  13. package/lib/features/copy-paste/BpmnCopyPaste.js +1 -0
  14. package/lib/features/di-ordering/BpmnDiOrdering.js +15 -11
  15. package/lib/features/drilldown/DrilldownBreadcrumbs.js +122 -0
  16. package/lib/features/drilldown/DrilldownCentering.js +87 -10
  17. package/lib/features/drilldown/DrilldownOverlayBehavior.js +181 -0
  18. package/lib/features/drilldown/SubprocessCompatibility.js +15 -7
  19. package/lib/features/drilldown/index.js +7 -4
  20. package/lib/features/label-editing/LabelEditingProvider.js +1 -1
  21. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +29 -2
  22. package/lib/features/modeling/BpmnFactory.js +5 -1
  23. package/lib/features/modeling/BpmnUpdater.js +43 -1
  24. package/lib/features/modeling/ElementFactory.js +4 -0
  25. package/lib/features/modeling/behavior/CreateParticipantBehavior.js +59 -84
  26. package/lib/features/modeling/behavior/DropOnFlowBehavior.js +2 -2
  27. package/lib/features/modeling/behavior/GroupBehavior.js +6 -18
  28. package/lib/features/modeling/behavior/RemoveEmbeddedLabelBoundsBehavior.js +34 -0
  29. package/lib/features/modeling/behavior/SubProcessPlaneBehavior.js +557 -0
  30. package/lib/features/modeling/behavior/ToggleCollapseConnectionBehaviour.js +74 -0
  31. package/lib/features/modeling/behavior/UnclaimIdBehavior.js +3 -1
  32. package/lib/features/modeling/behavior/index.js +27 -18
  33. package/lib/features/modeling/cmd/SetColorHandler.js +23 -6
  34. package/lib/features/modeling/cmd/UpdateCanvasRootHandler.js +4 -2
  35. package/lib/features/modeling/util/ModelingUtil.js +2 -20
  36. package/lib/features/ordering/BpmnOrderingProvider.js +3 -3
  37. package/lib/features/palette/PaletteProvider.js +1 -1
  38. package/lib/features/popup-menu/ReplaceMenuProvider.js +1 -1
  39. package/lib/import/BpmnImporter.js +15 -9
  40. package/lib/import/Importer.js +130 -10
  41. package/lib/util/DrilldownUtil.js +66 -0
  42. package/lib/util/ModelUtil.js +19 -0
  43. package/package.json +2 -2
  44. package/lib/features/drilldown/DrilldownOverlays.js +0 -110
@@ -0,0 +1,557 @@
1
+ import inherits from 'inherits';
2
+
3
+ import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
4
+
5
+ import { find } from 'min-dash';
6
+ import { isExpanded } from '../../../util/DiUtil';
7
+ import { getBusinessObject, getDi, is } from '../../../util/ModelUtil';
8
+ import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
9
+ import { getBBox } from 'diagram-js/lib/util/Elements';
10
+ import {
11
+ getPlaneIdFromShape,
12
+ getShapeIdFromPlane,
13
+ isPlane,
14
+ toPlaneId
15
+ } from '../../../util/DrilldownUtil';
16
+
17
+
18
+ var LOW_PRIORITY = 400;
19
+ var HIGH_PRIORITY = 600;
20
+
21
+ var DEFAULT_POSITION = {
22
+ x: 180,
23
+ y: 160
24
+ };
25
+
26
+
27
+ /**
28
+ * Creates bpmndi:BPMNPlane elements and canvas planes when collapsed subprocesses are created.
29
+ *
30
+ *
31
+ * @param {Canvas} canvas
32
+ * @param {EventBus} eventBus
33
+ * @param {Modeling} modeling
34
+ * @param {ElementFactory} elementFactory
35
+ * @param {BpmnFactory} bpmnFactory
36
+ * @param {Bpmnjs} bpmnjs
37
+ * @param {ElementRegistry} elementRegistry
38
+ */
39
+ export default function SubProcessPlaneBehavior(
40
+ canvas, eventBus, modeling,
41
+ elementFactory, bpmnFactory, bpmnjs, elementRegistry) {
42
+
43
+ CommandInterceptor.call(this, eventBus);
44
+
45
+ this._canvas = canvas;
46
+ this._eventBus = eventBus;
47
+ this._modeling = modeling;
48
+ this._elementFactory = elementFactory;
49
+ this._bpmnFactory = bpmnFactory;
50
+ this._bpmnjs = bpmnjs;
51
+ this._elementRegistry = elementRegistry;
52
+
53
+ var self = this;
54
+
55
+ function isCollapsedSubProcess(element) {
56
+ return is(element, 'bpmn:SubProcess') && !isExpanded(element);
57
+ }
58
+
59
+ function createRoot(context) {
60
+ var shape = context.shape,
61
+ rootElement = context.newRootElement;
62
+
63
+ var businessObject = getBusinessObject(shape);
64
+
65
+ rootElement = self._addDiagram(rootElement || businessObject);
66
+
67
+ context.newRootElement = canvas.addRootElement(rootElement);
68
+ }
69
+
70
+ function removeRoot(context) {
71
+ var shape = context.shape;
72
+
73
+ var businessObject = getBusinessObject(shape);
74
+ self._removeDiagram(businessObject);
75
+
76
+ var rootElement = context.newRootElement = elementRegistry.get(getPlaneIdFromShape(businessObject));
77
+
78
+ canvas.removeRootElement(rootElement);
79
+ }
80
+
81
+ // add plane elements for newly created sub-processes
82
+ // this ensures we can actually drill down into the element
83
+ this.executed('shape.create', function(context) {
84
+ var shape = context.shape;
85
+ if (!isCollapsedSubProcess(shape)) {
86
+ return;
87
+ }
88
+
89
+ createRoot(context);
90
+ }, true);
91
+
92
+
93
+ this.postExecuted('shape.create', function(context) {
94
+ var shape = context.shape,
95
+ rootElement = context.newRootElement;
96
+
97
+ if (!rootElement || !shape.children) {
98
+ return;
99
+ }
100
+
101
+ self._showRecursively(shape.children);
102
+
103
+ self._moveChildrenToShape(shape, rootElement);
104
+ }, true);
105
+
106
+
107
+ this.reverted('shape.create', function(context) {
108
+ var shape = context.shape;
109
+ if (!isCollapsedSubProcess(shape)) {
110
+ return;
111
+ }
112
+
113
+ removeRoot(context);
114
+ }, true);
115
+
116
+
117
+ this.preExecuted('shape.delete', function(context) {
118
+ var shape = context.shape;
119
+ if (!isCollapsedSubProcess(shape)) {
120
+ return;
121
+ }
122
+
123
+ var attachedRoot = elementRegistry.get(getPlaneIdFromShape(shape));
124
+
125
+ if (!attachedRoot) {
126
+ return;
127
+ }
128
+
129
+ modeling.removeElements(attachedRoot.children.slice());
130
+ }, true);
131
+
132
+
133
+ this.executed('shape.delete', function(context) {
134
+ var shape = context.shape;
135
+ if (!isCollapsedSubProcess(shape)) {
136
+ return;
137
+ }
138
+ removeRoot(context);
139
+ }, true);
140
+
141
+
142
+ this.reverted('shape.delete', function(context) {
143
+ var shape = context.shape;
144
+ if (!isCollapsedSubProcess(shape)) {
145
+ return;
146
+ }
147
+
148
+ createRoot(context);
149
+ }, true);
150
+
151
+
152
+ this.preExecuted('shape.replace', function(context) {
153
+ var oldShape = context.oldShape;
154
+ var newShape = context.newShape;
155
+
156
+ if (!isCollapsedSubProcess(oldShape) || !isCollapsedSubProcess(newShape)) {
157
+ return;
158
+ }
159
+
160
+ // old plane could have content,
161
+ // we remove it so it is not recursively deleted from 'shape.delete'
162
+ context.oldRoot = canvas.removeRootElement(getPlaneIdFromShape(oldShape));
163
+ }, true);
164
+
165
+
166
+ this.postExecuted('shape.replace', function(context) {
167
+ var newShape = context.newShape,
168
+ source = context.oldRoot,
169
+ target = canvas.findRoot(getPlaneIdFromShape(newShape));
170
+
171
+ if (!source || !target) {
172
+ return;
173
+ }
174
+ var elements = source.children;
175
+
176
+ modeling.moveElements(elements, { x: 0, y: 0 }, target);
177
+ }, true);
178
+
179
+
180
+ // rename primary elements when the secondary element changes
181
+ // this ensures rootElement.id = element.id + '_plane'
182
+ this.executed('element.updateProperties', function(context) {
183
+ var shape = context.element;
184
+
185
+ if (!is(shape, 'bpmn:SubProcess')) {
186
+ return;
187
+ }
188
+
189
+ var properties = context.properties;
190
+ var oldProperties = context.oldProperties;
191
+
192
+ var oldId = oldProperties.id,
193
+ newId = properties.id;
194
+
195
+ if (oldId === newId) {
196
+ return;
197
+ }
198
+
199
+ if (isPlane(shape)) {
200
+ elementRegistry.updateId(shape, toPlaneId(newId));
201
+ elementRegistry.updateId(oldId, newId);
202
+
203
+ return;
204
+ }
205
+
206
+ var planeElement = elementRegistry.get(toPlaneId(oldId));
207
+
208
+ if (!planeElement) {
209
+ return;
210
+ }
211
+
212
+ elementRegistry.updateId(toPlaneId(oldId), toPlaneId(newId));
213
+ }, true);
214
+
215
+
216
+ this.reverted('element.updateProperties', function(context) {
217
+ var shape = context.element;
218
+
219
+ if (!is(shape, 'bpmn:SubProcess')) {
220
+ return;
221
+ }
222
+
223
+ var properties = context.properties;
224
+ var oldProperties = context.oldProperties;
225
+
226
+ var oldId = oldProperties.id,
227
+ newId = properties.id;
228
+
229
+ if (oldId === newId) {
230
+ return;
231
+ }
232
+
233
+ if (isPlane(shape)) {
234
+ elementRegistry.updateId(shape, toPlaneId(oldId));
235
+ elementRegistry.updateId(newId, oldId);
236
+
237
+ return;
238
+ }
239
+
240
+ var planeElement = elementRegistry.get(toPlaneId(newId));
241
+
242
+ if (!planeElement) {
243
+ return;
244
+ }
245
+
246
+ elementRegistry.updateId(planeElement, toPlaneId(oldId));
247
+ }, true);
248
+
249
+ // re-throw element.changed to re-render primary shape if associated plane has
250
+ // changed (e.g. bpmn:name property has changed)
251
+ eventBus.on('element.changed', function(context) {
252
+ var element = context.element;
253
+
254
+ if (!isPlane(element)) {
255
+ return;
256
+ }
257
+
258
+ var plane = element;
259
+
260
+ var primaryShape = elementRegistry.get(getShapeIdFromPlane(plane));
261
+
262
+ // do not re-throw if no associated primary shape (e.g. bpmn:Process)
263
+ if (!primaryShape || primaryShape === plane) {
264
+ return;
265
+ }
266
+
267
+ eventBus.fire('element.changed', { element: primaryShape });
268
+ });
269
+
270
+
271
+ // create/remove plane for the subprocess
272
+ this.executed('shape.toggleCollapse', LOW_PRIORITY, function(context) {
273
+ var shape = context.shape;
274
+
275
+ if (!is(shape, 'bpmn:SubProcess')) {
276
+ return;
277
+ }
278
+
279
+ if (!isExpanded(shape)) {
280
+ createRoot(context);
281
+ self._showRecursively(shape.children);
282
+ } else {
283
+ removeRoot(context);
284
+ }
285
+
286
+ }, true);
287
+
288
+
289
+ // create/remove plane for the subprocess
290
+ this.reverted('shape.toggleCollapse', LOW_PRIORITY, function(context) {
291
+ var shape = context.shape;
292
+
293
+ if (!is(shape, 'bpmn:SubProcess')) {
294
+ return;
295
+ }
296
+
297
+ if (!isExpanded(shape)) {
298
+ createRoot(context);
299
+ self._showRecursively(shape.children);
300
+ } else {
301
+ removeRoot(context);
302
+ }
303
+
304
+ }, true);
305
+
306
+ // move elements between planes
307
+ this.postExecuted('shape.toggleCollapse', HIGH_PRIORITY, function(context) {
308
+ var shape = context.shape;
309
+
310
+ if (!is(shape, 'bpmn:SubProcess')) {
311
+ return;
312
+ }
313
+
314
+ var rootElement = context.newRootElement;
315
+
316
+ if (!rootElement) {
317
+ return;
318
+ }
319
+
320
+ if (!isExpanded(shape)) {
321
+
322
+ // collapsed
323
+ self._moveChildrenToShape(shape, rootElement);
324
+
325
+ } else {
326
+ self._moveChildrenToShape(rootElement, shape);
327
+ }
328
+ }, true);
329
+
330
+
331
+ // copy-paste ///////////
332
+
333
+ // add elements in plane to tree
334
+ eventBus.on('copyPaste.createTree', function(context) {
335
+ var element = context.element,
336
+ children = context.children;
337
+
338
+ if (!isCollapsedSubProcess(element)) {
339
+ return;
340
+ }
341
+
342
+ var id = getPlaneIdFromShape(element);
343
+ var parent = elementRegistry.get(id);
344
+
345
+ if (parent) {
346
+
347
+ // do not copy invisible root element
348
+ children.push.apply(children, parent.children);
349
+ }
350
+ });
351
+
352
+ // set plane children as direct children of collapsed shape
353
+ eventBus.on('copyPaste.copyElement', function(context) {
354
+ var descriptor = context.descriptor,
355
+ element = context.element,
356
+ elements = context.elements;
357
+
358
+ var parent = element.parent;
359
+
360
+ var isPlane = is(getDi(parent), 'bpmndi:BPMNPlane');
361
+ if (!isPlane) {
362
+ return;
363
+ }
364
+
365
+ var parentId = getShapeIdFromPlane(parent);
366
+
367
+ var referencedShape = find(elements, function(element) {
368
+ return element.id === parentId;
369
+ });
370
+
371
+ if (!referencedShape) {
372
+ return;
373
+ }
374
+
375
+ descriptor.parent = referencedShape.id;
376
+ });
377
+
378
+ // hide children during pasting
379
+ eventBus.on('copyPaste.pasteElement', function(context) {
380
+ var descriptor = context.descriptor;
381
+
382
+ if (!descriptor.parent) {
383
+ return;
384
+ }
385
+
386
+ if (isCollapsedSubProcess(descriptor.parent) || descriptor.parent.hidden) {
387
+ descriptor.hidden = true;
388
+ }
389
+ });
390
+
391
+ }
392
+
393
+ inherits(SubProcessPlaneBehavior, CommandInterceptor);
394
+
395
+ /**
396
+ * Moves the child elements from source to target.
397
+ *
398
+ * If the target is a plane, the children are moved to the top left corner.
399
+ * Otherwise, the center of the target is used.
400
+ *
401
+ * @param {Object|djs.model.Base} source
402
+ * @param {Object|djs.model.Base} target
403
+ */
404
+ SubProcessPlaneBehavior.prototype._moveChildrenToShape = function(source, target) {
405
+ var modeling = this._modeling;
406
+
407
+ var children = source.children;
408
+ var offset;
409
+
410
+ if (!children) {
411
+ return;
412
+ }
413
+
414
+ // only change plane if there are no visible children, but don't move them
415
+ var visibleChildren = children.filter(function(child) {
416
+ return !child.hidden;
417
+ });
418
+
419
+ if (!visibleChildren.length) {
420
+ modeling.moveElements(children, { x: 0, y: 0 }, target, { autoResize: false });
421
+ return;
422
+ }
423
+
424
+ var childrenBounds = getBBox(visibleChildren);
425
+
426
+ // target is a plane
427
+ if (!target.x) {
428
+ offset = {
429
+ x: DEFAULT_POSITION.x - childrenBounds.x,
430
+ y: DEFAULT_POSITION.y - childrenBounds.y
431
+ };
432
+ }
433
+
434
+ // source is a plane
435
+ else {
436
+
437
+ // move relative to the center of the shape
438
+ var targetMid = getMid(target);
439
+ var childrenMid = getMid(childrenBounds);
440
+
441
+ offset = {
442
+ x: targetMid.x - childrenMid.x,
443
+ y: targetMid.y - childrenMid.y
444
+ };
445
+ }
446
+
447
+ modeling.moveElements(children, offset, target, { autoResize: false });
448
+ };
449
+
450
+ /**
451
+ * Sets `hidden` property on all children of the given shape.
452
+ *
453
+ * @param {Array} elements
454
+ * @param {Boolean} [hidden]
455
+ * @returns {Array} all child elements
456
+ */
457
+ SubProcessPlaneBehavior.prototype._showRecursively = function(elements, hidden) {
458
+ var self = this;
459
+
460
+ var result = [];
461
+ elements.forEach(function(element) {
462
+ element.hidden = !!hidden;
463
+
464
+ result = result.concat(element);
465
+
466
+ if (element.children) {
467
+ result = result.concat(
468
+ self._showRecursively(element.children, element.collapsed || hidden)
469
+ );
470
+ }
471
+ });
472
+
473
+ return result;
474
+ };
475
+
476
+ /**
477
+ * Adds a given rootElement to the bpmnDi diagrams.
478
+ *
479
+ * @param {Object} rootElement
480
+ * @returns {Object} planeElement
481
+ */
482
+ SubProcessPlaneBehavior.prototype._addDiagram = function(planeElement) {
483
+ var bpmnjs = this._bpmnjs;
484
+ var diagrams = bpmnjs.getDefinitions().diagrams;
485
+
486
+ if (!planeElement.businessObject) {
487
+ planeElement = this._createNewDiagram(planeElement);
488
+ }
489
+
490
+ diagrams.push(planeElement.di.$parent);
491
+
492
+ return planeElement;
493
+ };
494
+
495
+
496
+ /**
497
+ * Creates a new plane element for the given sub process.
498
+ *
499
+ * @param {Object} bpmnElement
500
+ *
501
+ * @return {Object} new diagram element
502
+ */
503
+ SubProcessPlaneBehavior.prototype._createNewDiagram = function(bpmnElement) {
504
+ var bpmnFactory = this._bpmnFactory;
505
+ var elementFactory = this._elementFactory;
506
+
507
+ var diPlane = bpmnFactory.create('bpmndi:BPMNPlane', {
508
+ bpmnElement: bpmnElement
509
+ });
510
+ var diDiagram = bpmnFactory.create('bpmndi:BPMNDiagram', {
511
+ plane: diPlane
512
+ });
513
+ diPlane.$parent = diDiagram;
514
+
515
+ // add a virtual element (not being drawn),
516
+ // a copy cat of our BpmnImporter code
517
+ var planeElement = elementFactory.createRoot({
518
+ id: getPlaneIdFromShape(bpmnElement),
519
+ type: bpmnElement.$type,
520
+ di: diPlane,
521
+ businessObject: bpmnElement,
522
+ collapsed: true
523
+ });
524
+
525
+ return planeElement;
526
+ };
527
+
528
+ /**
529
+ * Removes the diagram for a given root element
530
+ *
531
+ * @param {Object} rootElement
532
+ * @returns {Object} removed bpmndi:BPMNDiagram
533
+ */
534
+ SubProcessPlaneBehavior.prototype._removeDiagram = function(rootElement) {
535
+ var bpmnjs = this._bpmnjs;
536
+
537
+ var diagrams = bpmnjs.getDefinitions().diagrams;
538
+
539
+ var removedDiagram = find(diagrams, function(diagram) {
540
+ return diagram.plane.bpmnElement.id === rootElement.id;
541
+ });
542
+
543
+ diagrams.splice(diagrams.indexOf(removedDiagram), 1);
544
+
545
+ return removedDiagram;
546
+ };
547
+
548
+
549
+ SubProcessPlaneBehavior.$inject = [
550
+ 'canvas',
551
+ 'eventBus',
552
+ 'modeling',
553
+ 'elementFactory',
554
+ 'bpmnFactory',
555
+ 'bpmnjs',
556
+ 'elementRegistry'
557
+ ];
@@ -0,0 +1,74 @@
1
+
2
+ import inherits from 'inherits';
3
+
4
+ import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
5
+
6
+ import {
7
+ forEach
8
+ } from 'min-dash';
9
+
10
+ import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
11
+ import { selfAndAllChildren } from 'diagram-js/lib/util/Elements';
12
+
13
+ import { isExpanded } from '../../../util/DiUtil';
14
+
15
+
16
+ export default function ToggleCollapseConnectionBehaviour(
17
+ eventBus, modeling
18
+ ) {
19
+
20
+ CommandInterceptor.call(this, eventBus);
21
+
22
+ this.postExecuted('shape.toggleCollapse', 1500, function(context) {
23
+
24
+ // var shape = context.shape;
25
+ var shape = context.shape;
26
+
27
+ // only change connections when collapsing
28
+ if (isExpanded(shape)) {
29
+ return;
30
+ }
31
+
32
+ var allChildren = selfAndAllChildren(shape);
33
+
34
+ allChildren.forEach(function(child) {
35
+
36
+ // Ensure that the connection array is not modified during iteration
37
+ var incomingConnections = child.incoming.slice(),
38
+ outgoingConnections = child.outgoing.slice();
39
+
40
+ forEach(incomingConnections, function(c) {
41
+ handleConnection(c, true);
42
+ });
43
+
44
+ forEach(outgoingConnections, function(c) {
45
+ handleConnection(c, false);
46
+ });
47
+ });
48
+
49
+
50
+ function handleConnection(c, incoming) {
51
+ if (allChildren.indexOf(c.source) !== -1 && allChildren.indexOf(c.target) !== -1) {
52
+ return;
53
+ }
54
+
55
+ if (incoming) {
56
+ modeling.reconnectEnd(c, shape, getMid(shape));
57
+ } else {
58
+ modeling.reconnectStart(c, shape, getMid(shape));
59
+ }
60
+
61
+ }
62
+
63
+ }, true);
64
+
65
+ }
66
+
67
+ inherits(ToggleCollapseConnectionBehaviour, CommandInterceptor);
68
+
69
+ ToggleCollapseConnectionBehaviour.$inject = [
70
+ 'eventBus',
71
+ 'modeling',
72
+ ];
73
+
74
+
@@ -47,7 +47,9 @@ export default function UnclaimIdBehavior(canvas, injector, moddle, modeling) {
47
47
  var rootElement = canvas.getRootElement(),
48
48
  rootElementBo = rootElement.businessObject;
49
49
 
50
- moddle.ids.unclaim(rootElementBo.id);
50
+ if (is(rootElement, 'bpmn:Collaboration')) {
51
+ moddle.ids.unclaim(rootElementBo.id);
52
+ }
51
53
  });
52
54
  }
53
55