bpmn-js 9.0.0-subprocesses.0 → 9.0.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/dist/assets/bpmn-js.css +113 -0
  3. package/dist/assets/diagram-js.css +82 -78
  4. package/dist/bpmn-modeler.development.js +3402 -2196
  5. package/dist/bpmn-modeler.production.min.js +9 -8
  6. package/dist/bpmn-navigated-viewer.development.js +21207 -20345
  7. package/dist/bpmn-navigated-viewer.production.min.js +22 -20
  8. package/dist/bpmn-viewer.development.js +20401 -19562
  9. package/dist/bpmn-viewer.production.min.js +22 -20
  10. package/lib/BaseViewer.js +1 -1
  11. package/lib/Modeler.js +1 -4
  12. package/lib/Viewer.js +2 -2
  13. package/lib/draw/BpmnRenderer.js +8 -7
  14. package/lib/draw/PathMap.js +2 -2
  15. package/lib/features/auto-resize/BpmnAutoResizeProvider.js +9 -6
  16. package/lib/features/copy-paste/BpmnCopyPaste.js +1 -0
  17. package/lib/features/copy-paste/ModdleCopy.js +19 -2
  18. package/lib/features/di-ordering/BpmnDiOrdering.js +15 -11
  19. package/lib/features/drilldown/DrilldownBreadcrumbs.js +122 -0
  20. package/lib/features/drilldown/DrilldownCentering.js +118 -0
  21. package/lib/features/drilldown/DrilldownOverlayBehavior.js +181 -0
  22. package/lib/features/drilldown/SubprocessCompatibility.js +196 -0
  23. package/lib/features/drilldown/index.js +17 -0
  24. package/lib/features/label-editing/LabelEditingProvider.js +1 -1
  25. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +29 -2
  26. package/lib/features/modeling/BpmnFactory.js +12 -8
  27. package/lib/features/modeling/BpmnUpdater.js +43 -6
  28. package/lib/features/modeling/ElementFactory.js +31 -13
  29. package/lib/features/modeling/behavior/CreateParticipantBehavior.js +59 -84
  30. package/lib/features/modeling/behavior/DropOnFlowBehavior.js +2 -2
  31. package/lib/features/modeling/behavior/RemoveEmbeddedLabelBoundsBehavior.js +34 -0
  32. package/lib/features/modeling/behavior/ResizeBehavior.js +129 -3
  33. package/lib/features/modeling/behavior/SubProcessPlaneBehavior.js +557 -0
  34. package/lib/features/modeling/behavior/ToggleCollapseConnectionBehaviour.js +74 -0
  35. package/lib/features/modeling/behavior/UnclaimIdBehavior.js +3 -1
  36. package/lib/features/modeling/behavior/index.js +27 -18
  37. package/lib/features/modeling/behavior/util/ResizeUtil.js +1 -132
  38. package/lib/features/modeling/cmd/SetColorHandler.js +23 -6
  39. package/lib/features/modeling/cmd/UpdateCanvasRootHandler.js +4 -2
  40. package/lib/features/modeling/util/ModelingUtil.js +2 -20
  41. package/lib/features/ordering/BpmnOrderingProvider.js +3 -3
  42. package/lib/features/palette/PaletteProvider.js +1 -1
  43. package/lib/features/popup-menu/ReplaceMenuProvider.js +1 -1
  44. package/lib/features/replace/BpmnReplace.js +38 -16
  45. package/lib/import/BpmnImporter.js +19 -13
  46. package/lib/import/BpmnTreeWalker.js +2 -2
  47. package/lib/import/Importer.js +134 -14
  48. package/lib/util/DiUtil.js +1 -0
  49. package/lib/util/DrilldownUtil.js +66 -0
  50. package/lib/util/ModelUtil.js +19 -0
  51. package/package.json +2 -2
  52. package/test/util/MockEvents.js +10 -2
  53. package/lib/features/collapsed-subprocesses/DeleteBehaviour.js +0 -65
  54. package/lib/features/collapsed-subprocesses/ToggleCollapseBehaviour.js +0 -133
  55. package/lib/features/collapsed-subprocesses/diagramFactory.js +0 -56
  56. package/lib/features/collapsed-subprocesses/index.js +0 -12
  57. package/lib/features/collapsed-subprocesses-navigation/CollapsedSubprocessNavigation.js +0 -198
  58. package/lib/features/collapsed-subprocesses-navigation/index.js +0 -7
package/lib/BaseViewer.js CHANGED
@@ -439,7 +439,7 @@ BaseViewer.prototype.saveSVG = wrapForCompatibility(function saveSVG(options) {
439
439
  try {
440
440
  var canvas = self.get('canvas');
441
441
 
442
- var contentNode = canvas.getDefaultLayer(),
442
+ var contentNode = canvas.getActiveLayer(),
443
443
  defsNode = domQuery('defs', canvas._svg);
444
444
 
445
445
  var contents = innerSVG(contentNode),
package/lib/Modeler.js CHANGED
@@ -35,8 +35,6 @@ import ResizeModule from 'diagram-js/lib/features/resize';
35
35
  import SnappingModule from './features/snapping';
36
36
  import SearchModule from './features/search';
37
37
 
38
- import CollapsedSubprocessModule from './features/collapsed-subprocesses';
39
-
40
38
  import {
41
39
  wrapForCompatibility
42
40
  } from './util/CompatibilityUtil';
@@ -176,8 +174,7 @@ Modeler.prototype._interactionModules = [
176
174
  KeyboardMoveModule,
177
175
  MoveCanvasModule,
178
176
  TouchModule,
179
- ZoomScrollModule,
180
- CollapsedSubprocessModule
177
+ ZoomScrollModule
181
178
  ];
182
179
 
183
180
  Modeler.prototype._modelingModules = [
package/lib/Viewer.js CHANGED
@@ -4,7 +4,7 @@ import CoreModule from './core';
4
4
  import TranslateModule from 'diagram-js/lib/i18n/translate';
5
5
  import SelectionModule from 'diagram-js/lib/features/selection';
6
6
  import OverlaysModule from 'diagram-js/lib/features/overlays';
7
- import CollapsedSubprocessNavigationModule from './features/collapsed-subprocesses-navigation';
7
+ import DrilldownModdule from './features/drilldown';
8
8
 
9
9
  import BaseViewer from './BaseViewer';
10
10
 
@@ -68,7 +68,7 @@ Viewer.prototype._modules = [
68
68
  TranslateModule,
69
69
  SelectionModule,
70
70
  OverlaysModule,
71
- CollapsedSubprocessNavigationModule
71
+ DrilldownModdule
72
72
  ];
73
73
 
74
74
  // default moddle extensions the viewer is composed of
@@ -382,16 +382,16 @@ export default function BpmnRenderer(
382
382
  return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
383
383
  }
384
384
 
385
+ function renderer(type) {
386
+ return handlers[type];
387
+ }
388
+
385
389
  function as(type) {
386
390
  return function(parentGfx, element) {
387
- return handlers[type](parentGfx, element);
391
+ return renderer(type)(parentGfx, element);
388
392
  };
389
393
  }
390
394
 
391
- function renderer(type) {
392
- return handlers[type];
393
- }
394
-
395
395
  function renderEventContent(element, parentGfx) {
396
396
 
397
397
  var event = getSemantic(element);
@@ -1872,6 +1872,7 @@ export default function BpmnRenderer(
1872
1872
  // extension API, use at your own risk
1873
1873
  this._drawPath = drawPath;
1874
1874
 
1875
+ this._renderer = renderer;
1875
1876
  }
1876
1877
 
1877
1878
 
@@ -1893,7 +1894,7 @@ BpmnRenderer.prototype.canRender = function(element) {
1893
1894
 
1894
1895
  BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
1895
1896
  var type = element.type;
1896
- var h = this.handlers[type];
1897
+ var h = this._renderer(type);
1897
1898
 
1898
1899
  /* jshint -W040 */
1899
1900
  return h(parentGfx, element);
@@ -1901,7 +1902,7 @@ BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
1901
1902
 
1902
1903
  BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
1903
1904
  var type = element.type;
1904
- var h = this.handlers[type];
1905
+ var h = this._renderer(type);
1905
1906
 
1906
1907
  /* jshint -W040 */
1907
1908
  return h(parentGfx, element);
@@ -444,8 +444,8 @@ export default function PathMap() {
444
444
 
445
445
  // helpers //////////////////////
446
446
 
447
- // copied from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js
448
- var tokenRegex = /\{([^}]+)\}/g,
447
+ // copied and adjusted from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js
448
+ var tokenRegex = /\{([^{}]+)\}/g,
449
449
  objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties
450
450
 
451
451
  function replacer(all, key, obj) {
@@ -1,4 +1,4 @@
1
- import { getDi, is } from '../../util/ModelUtil';
1
+ import { is } from '../../util/ModelUtil';
2
2
 
3
3
  import inherits from 'inherits';
4
4
 
@@ -32,11 +32,14 @@ BpmnAutoResizeProvider.$inject = [
32
32
  * @return {boolean}
33
33
  */
34
34
  BpmnAutoResizeProvider.prototype.canResize = function(elements, target) {
35
- if (
36
- !is(target, 'bpmn:Participant') &&
37
- !is(target, 'bpmn:Lane') &&
38
- (!is(target, 'bpmn:SubProcess') || is(getDi(target), 'bpmndi:BPMNPlane'))
39
- ) {
35
+
36
+ // do not resize plane elements:
37
+ // root elements, collapsed sub-processes
38
+ if (is(target.di, 'bpmndi:BPMNPlane')) {
39
+ return false;
40
+ }
41
+
42
+ if (!is(target, 'bpmn:Participant') && !is(target, 'bpmn:Lane') && !(is(target, 'bpmn:SubProcess'))) {
40
43
  return false;
41
44
  }
42
45
 
@@ -145,6 +145,7 @@ export default function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) {
145
145
  );
146
146
 
147
147
  newDi = bpmnFactory.create(oldDi.$type);
148
+ newDi.bpmnElement = newBusinessObject;
148
149
 
149
150
  descriptor.di = moddleCopy.copyElement(
150
151
  oldDi,
@@ -215,11 +215,16 @@ ModdleCopy.prototype.copyProperty = function(property, parent, propertyName) {
215
215
 
216
216
  var propertyDescriptor = this._moddle.getPropertyDescriptor(parent, propertyName);
217
217
 
218
- // do NOT copy Ids and references
219
- if (propertyDescriptor.isId || propertyDescriptor.isReference) {
218
+ // do NOT copy references
219
+ if (propertyDescriptor.isReference) {
220
220
  return;
221
221
  }
222
222
 
223
+ // copy id
224
+ if (propertyDescriptor.isId) {
225
+ return this._copyId(property, parent);
226
+ }
227
+
223
228
  // copy arrays
224
229
  if (isArray(property)) {
225
230
  return reduce(property, function(childProperties, childProperty) {
@@ -258,6 +263,18 @@ ModdleCopy.prototype.copyProperty = function(property, parent, propertyName) {
258
263
  return property;
259
264
  };
260
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
+
261
278
  // helpers //////////
262
279
 
263
280
  export function getPropertyNames(descriptor, keepDefaultProperties) {
@@ -2,6 +2,7 @@ import { getDi } from '../../util/ModelUtil';
2
2
 
3
3
  import {
4
4
  filter,
5
+ forEach,
5
6
  map
6
7
  } from 'min-dash';
7
8
 
@@ -15,21 +16,24 @@ export default function BpmnDiOrdering(eventBus, canvas) {
15
16
  eventBus.on('saveXML.start', HIGH_PRIORITY, orderDi);
16
17
 
17
18
  function orderDi() {
18
- var root = canvas.getRootElement(),
19
- rootDi = getDi(root),
20
- elements,
21
- diElements;
19
+ var rootElements = canvas.getRootElements();
22
20
 
23
- elements = selfAndAllChildren([ root ], false);
21
+ forEach(rootElements, function(root) {
22
+ var rootDi = getDi(root),
23
+ elements,
24
+ diElements;
24
25
 
25
- // only bpmndi:Shape and bpmndi:Edge can be direct children of bpmndi:Plane
26
- elements = filter(elements, function(element) {
27
- return element !== root && !element.labelTarget;
28
- });
26
+ elements = selfAndAllChildren([ root ], false);
27
+
28
+ // only bpmndi:Shape and bpmndi:Edge can be direct children of bpmndi:Plane
29
+ elements = filter(elements, function(element) {
30
+ return element !== root && !element.labelTarget;
31
+ });
29
32
 
30
- diElements = map(elements, getDi);
33
+ diElements = map(elements, getDi);
31
34
 
32
- rootDi.set('planeElement', diElements);
35
+ rootDi.set('planeElement', diElements);
36
+ });
33
37
  }
34
38
  }
35
39
 
@@ -0,0 +1,122 @@
1
+ import { domify, classes } from 'min-dom';
2
+ import { find } from 'min-dash';
3
+
4
+ import { escapeHTML } from 'diagram-js/lib/util/EscapeUtil';
5
+ import { getBusinessObject, is } from '../../util/ModelUtil';
6
+ import {
7
+ getPlaneIdFromShape
8
+ } from '../../util/DrilldownUtil';
9
+
10
+ var OPEN_CLASS = 'bjs-breadcrumbs-shown';
11
+
12
+
13
+ /**
14
+ * Adds overlays that allow switching planes on collapsed subprocesses.
15
+ *
16
+ * @param {eventBus} eventBus
17
+ * @param {elementRegistry} elementRegistry
18
+ * @param {overlays} overlays
19
+ * @param {canvas} canvas
20
+ */
21
+ export default function DrilldownBreadcrumbs(eventBus, elementRegistry, overlays, canvas) {
22
+ var breadcrumbs = domify('<ul class="bjs-breadcrumbs"></ul>');
23
+ var container = canvas.getContainer();
24
+ var containerClasses = classes(container);
25
+ container.appendChild(breadcrumbs);
26
+
27
+ var boParents = [];
28
+
29
+ // update breadcrumbs if name or ID of the primary shape changes
30
+ eventBus.on('element.changed', function(e) {
31
+ var shape = e.element,
32
+ bo = getBusinessObject(shape);
33
+
34
+ var isPresent = find(boParents, function(el) {
35
+ return el === bo;
36
+ });
37
+
38
+ if (!isPresent) {
39
+ return;
40
+ }
41
+
42
+ updateBreadcrumbs();
43
+ });
44
+
45
+ /**
46
+ * Updates the displayed breadcrumbs. If no element is provided, only the
47
+ * labels are updated.
48
+ *
49
+ * @param {djs.model.Base} [element]
50
+ */
51
+ function updateBreadcrumbs(element) {
52
+ if (element) {
53
+ boParents = getBoParentChain(element);
54
+ }
55
+
56
+ var path = boParents.map(function(parent) {
57
+ var title = escapeHTML(parent.name || parent.id);
58
+ var link = domify('<li><span class="bjs-crumb"><a title="' + title + '">' + title + '</a></span></li>');
59
+
60
+ var parentPlane = canvas.findRoot(getPlaneIdFromShape(parent)) || canvas.findRoot(parent.id);
61
+
62
+ // when the root is a collaboration, the process does not have a corresponding
63
+ // element in the elementRegisty. Instead, we search for the corresponding participant
64
+ if (!parentPlane && is(parent, 'bpmn:Process')) {
65
+ var participant = elementRegistry.find(function(element) {
66
+ var bo = getBusinessObject(element);
67
+ return bo && bo.processRef && bo.processRef === parent;
68
+ });
69
+
70
+ parentPlane = canvas.findRoot(participant.id);
71
+ }
72
+
73
+ link.addEventListener('click', function() {
74
+ canvas.setRootElement(parentPlane);
75
+ });
76
+
77
+ return link;
78
+ });
79
+
80
+ breadcrumbs.innerHTML = '';
81
+
82
+ // show breadcrumbs and expose state to .djs-container
83
+ var visible = path.length > 1;
84
+ containerClasses.toggle(OPEN_CLASS, visible);
85
+
86
+ path.forEach(function(el) {
87
+ breadcrumbs.appendChild(el);
88
+ });
89
+ }
90
+
91
+ eventBus.on('root.set', function(event) {
92
+ updateBreadcrumbs(event.element);
93
+ });
94
+
95
+ }
96
+
97
+ DrilldownBreadcrumbs.$inject = [ 'eventBus', 'elementRegistry', 'overlays', 'canvas' ];
98
+
99
+
100
+ // helpers //////////
101
+
102
+ /**
103
+ * Returns the parents for the element using the business object chain,
104
+ * starting with the root element.
105
+ *
106
+ * @param {djs.model.Shape} child
107
+ *
108
+ * @returns {Array<djs.model.Shape>} parents
109
+ */
110
+ function getBoParentChain(child) {
111
+ var bo = getBusinessObject(child);
112
+
113
+ var parents = [];
114
+
115
+ for (var element = bo; element; element = element.$parent) {
116
+ if (is(element, 'bpmn:SubProcess') || is(element, 'bpmn:Process')) {
117
+ parents.push(element);
118
+ }
119
+ }
120
+
121
+ return parents.reverse();
122
+ }
@@ -0,0 +1,118 @@
1
+ import { is } from '../../util/ModelUtil';
2
+
3
+ /**
4
+ * Move collapsed subprocesses into view when drilling down.
5
+ *
6
+ * Zoom and scroll are saved in a session.
7
+ *
8
+ * @param {eventBus} eventBus
9
+ * @param {canvas} canvas
10
+ */
11
+ export default function DrilldownCentering(eventBus, canvas) {
12
+
13
+ var currentRoot = null;
14
+ var positionMap = new Map();
15
+
16
+ eventBus.on('root.set', function(event) {
17
+ var newRoot = event.element;
18
+ var currentViewbox = canvas.viewbox();
19
+ var storedViewbox = positionMap.get(newRoot);
20
+
21
+ positionMap.set(currentRoot, {
22
+ x: currentViewbox.x,
23
+ y: currentViewbox.y,
24
+ zoom: currentViewbox.scale
25
+ });
26
+
27
+ currentRoot = newRoot;
28
+
29
+ // current root was replaced with a collaboration, we don't update the viewbox
30
+ if (is(newRoot, 'bpmn:Collaboration') && !storedViewbox) {
31
+ return;
32
+ }
33
+
34
+ storedViewbox = storedViewbox || { x: 0, y: 0, zoom: 1 };
35
+
36
+ var dx = (currentViewbox.x - storedViewbox.x) * currentViewbox.scale,
37
+ dy = (currentViewbox.y - storedViewbox.y) * currentViewbox.scale;
38
+
39
+ if (dx !== 0 || dy !== 0) {
40
+ canvas.scroll({
41
+ dx: dx,
42
+ dy: dy
43
+ });
44
+ }
45
+
46
+ if (storedViewbox.zoom !== currentViewbox.scale) {
47
+ canvas.zoom(storedViewbox.zoom, { x: 0, y: 0 });
48
+ }
49
+ });
50
+
51
+ eventBus.on('diagram.clear', function() {
52
+ positionMap.clear();
53
+ currentRoot = null;
54
+ });
55
+
56
+ }
57
+
58
+ DrilldownCentering.$inject = [ 'eventBus', 'canvas' ];
59
+
60
+
61
+ /**
62
+ * ES5 Map implementation. Works.
63
+ */
64
+ function Map() {
65
+
66
+ this._entries = [];
67
+
68
+ this.set = function(key, value) {
69
+
70
+ var found = false;
71
+
72
+ for (var k in this._entries) {
73
+ if (this._entries[k][0] === key) {
74
+ this._entries[k][1] = value;
75
+
76
+ found = true;
77
+
78
+ break;
79
+ }
80
+ }
81
+
82
+ if (!found) {
83
+ this._entries.push([ key, value ]);
84
+ }
85
+ };
86
+
87
+ this.get = function(key) {
88
+
89
+ for (var k in this._entries) {
90
+ if (this._entries[k][0] === key) {
91
+ return this._entries[k][1];
92
+ }
93
+ }
94
+
95
+ return null;
96
+ };
97
+
98
+ this.clear = function() {
99
+ this._entries.length = 0;
100
+ };
101
+
102
+ this.remove = function(key) {
103
+
104
+ var idx = -1;
105
+
106
+ for (var k in this._entries) {
107
+ if (this._entries[k][0] === key) {
108
+ idx = k;
109
+
110
+ break;
111
+ }
112
+ }
113
+
114
+ if (idx !== -1) {
115
+ this._entries.splice(idx, 1);
116
+ }
117
+ };
118
+ }
@@ -0,0 +1,181 @@
1
+ import inherits from 'inherits';
2
+
3
+ import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
4
+ import { is } from '../../util/ModelUtil';
5
+ import { classes, domify } from 'min-dom';
6
+ import { getPlaneIdFromShape } from '../../util/DrilldownUtil';
7
+
8
+ var LOW_PRIORITY = 250;
9
+ 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>';
10
+
11
+ var EMPTY_MARKER = 'bjs-drilldown-empty';
12
+
13
+ export default function DrilldownOverlayBehavior(
14
+ canvas, eventBus, elementRegistry, overlays
15
+ ) {
16
+ CommandInterceptor.call(this, eventBus);
17
+
18
+ this._canvas = canvas;
19
+ this._eventBus = eventBus;
20
+ this._elementRegistry = elementRegistry;
21
+ this._overlays = overlays;
22
+
23
+ var self = this;
24
+
25
+ this.executed('shape.toggleCollapse', LOW_PRIORITY, function(context) {
26
+ var shape = context.shape;
27
+
28
+ // Add overlay to the collapsed shape
29
+ if (self.canDrillDown(shape)) {
30
+ self.addOverlay(shape);
31
+ } else {
32
+ self.removeOverlay(shape);
33
+ }
34
+ }, true);
35
+
36
+
37
+ this.reverted('shape.toggleCollapse', LOW_PRIORITY, function(context) {
38
+ var shape = context.shape;
39
+
40
+ // Add overlay to the collapsed shape
41
+ if (self.canDrillDown(shape)) {
42
+ self.addOverlay(shape);
43
+ } else {
44
+ self.removeOverlay(shape);
45
+ }
46
+ }, true);
47
+
48
+
49
+ this.executed(['shape.create', 'shape.move', 'shape.delete'], LOW_PRIORITY,
50
+ function(context) {
51
+ var oldParent = context.oldParent,
52
+ newParent = context.newParent || context.parent,
53
+ shape = context.shape;
54
+
55
+ // Add overlay to the collapsed shape
56
+ if (self.canDrillDown(shape)) {
57
+ self.addOverlay(shape);
58
+ }
59
+
60
+ self.updateDrilldownOverlay(oldParent);
61
+ self.updateDrilldownOverlay(newParent);
62
+ self.updateDrilldownOverlay(shape);
63
+ }, true);
64
+
65
+
66
+ this.reverted(['shape.create', 'shape.move', 'shape.delete'], LOW_PRIORITY,
67
+ function(context) {
68
+ var oldParent = context.oldParent,
69
+ newParent = context.newParent || context.parent,
70
+ shape = context.shape;
71
+
72
+ // Add overlay to the collapsed shape
73
+ if (self.canDrillDown(shape)) {
74
+ self.addOverlay(shape);
75
+ }
76
+
77
+ self.updateDrilldownOverlay(oldParent);
78
+ self.updateDrilldownOverlay(newParent);
79
+ self.updateDrilldownOverlay(shape);
80
+ }, true);
81
+
82
+
83
+ eventBus.on('import.done', function() {
84
+ elementRegistry.filter(function(e) {
85
+ return self.canDrillDown(e);
86
+ }).map(function(el) {
87
+ self.addOverlay(el);
88
+ });
89
+ });
90
+
91
+ }
92
+
93
+ inherits(DrilldownOverlayBehavior, CommandInterceptor);
94
+
95
+ DrilldownOverlayBehavior.prototype.updateDrilldownOverlay = function(shape) {
96
+ var canvas = this._canvas;
97
+
98
+ if (!shape) {
99
+ return;
100
+ }
101
+
102
+ var root = canvas.findRoot(shape);
103
+ if (root) {
104
+ this.updateOverlayVisibility(root);
105
+ }
106
+ };
107
+
108
+
109
+ DrilldownOverlayBehavior.prototype.canDrillDown = function(element) {
110
+ var canvas = this._canvas;
111
+ return is(element, 'bpmn:SubProcess') && canvas.findRoot(getPlaneIdFromShape(element));
112
+ };
113
+
114
+ /**
115
+ * Updates visibility of the drilldown overlay. If the plane has no elements,
116
+ * the drilldown will be only shown when the element is selected.
117
+ *
118
+ * @param {djs.model.Shape|djs.model.Root} element collapsed shape or root element
119
+ */
120
+ DrilldownOverlayBehavior.prototype.updateOverlayVisibility = function(element) {
121
+ var overlays = this._overlays;
122
+
123
+ var bo = element.businessObject;
124
+
125
+ var overlay = overlays.get({ element: bo.id, type: 'drilldown' })[0];
126
+
127
+ if (!overlay) {
128
+ return;
129
+ }
130
+
131
+ var hasContent = bo && bo.flowElements && bo.flowElements.length;
132
+ classes(overlay.html).toggle(EMPTY_MARKER, !hasContent);
133
+ };
134
+
135
+ /**
136
+ * Attaches a drilldown button to the given element. We assume that the plane has
137
+ * the same id as the element.
138
+ *
139
+ * @param {djs.model.Shape} element collapsed shape
140
+ */
141
+ DrilldownOverlayBehavior.prototype.addOverlay = function(element) {
142
+ var canvas = this._canvas;
143
+ var overlays = this._overlays;
144
+
145
+ var existingOverlays = overlays.get({ element: element, type: 'drilldown' });
146
+ if (existingOverlays.length) {
147
+ this.removeOverlay(element);
148
+ }
149
+
150
+ var button = domify('<button class="bjs-drilldown">' + ARROW_DOWN_SVG + '</button>');
151
+
152
+ button.addEventListener('click', function() {
153
+ canvas.setRootElement(canvas.findRoot(getPlaneIdFromShape(element)));
154
+ });
155
+
156
+ overlays.add(element, 'drilldown', {
157
+ position: {
158
+ bottom: -7,
159
+ right: -8
160
+ },
161
+ html: button
162
+ });
163
+
164
+ this.updateOverlayVisibility(element);
165
+ };
166
+
167
+ DrilldownOverlayBehavior.prototype.removeOverlay = function(element) {
168
+ var overlays = this._overlays;
169
+
170
+ overlays.remove({
171
+ element: element,
172
+ type: 'drilldown'
173
+ });
174
+ };
175
+
176
+ DrilldownOverlayBehavior.$inject = [
177
+ 'canvas',
178
+ 'eventBus',
179
+ 'elementRegistry',
180
+ 'overlays'
181
+ ];