bpmn-js 9.0.0-subprocesses.3 → 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 (43) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/assets/bpmn-js.css +38 -4
  3. package/dist/assets/diagram-js.css +1 -1
  4. package/dist/bpmn-modeler.development.js +2411 -1110
  5. package/dist/bpmn-modeler.production.min.js +8 -8
  6. package/dist/bpmn-navigated-viewer.development.js +983 -315
  7. package/dist/bpmn-navigated-viewer.production.min.js +6 -6
  8. package/dist/bpmn-viewer.development.js +983 -315
  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 +9 -6
  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/RemoveEmbeddedLabelBoundsBehavior.js +34 -0
  28. package/lib/features/modeling/behavior/SubProcessPlaneBehavior.js +557 -0
  29. package/lib/features/modeling/behavior/ToggleCollapseConnectionBehaviour.js +74 -0
  30. package/lib/features/modeling/behavior/UnclaimIdBehavior.js +3 -1
  31. package/lib/features/modeling/behavior/index.js +27 -18
  32. package/lib/features/modeling/cmd/SetColorHandler.js +23 -6
  33. package/lib/features/modeling/cmd/UpdateCanvasRootHandler.js +4 -2
  34. package/lib/features/modeling/util/ModelingUtil.js +2 -20
  35. package/lib/features/ordering/BpmnOrderingProvider.js +3 -3
  36. package/lib/features/palette/PaletteProvider.js +1 -1
  37. package/lib/features/popup-menu/ReplaceMenuProvider.js +1 -1
  38. package/lib/import/BpmnImporter.js +15 -9
  39. package/lib/import/Importer.js +130 -10
  40. package/lib/util/DrilldownUtil.js +66 -0
  41. package/lib/util/ModelUtil.js +19 -0
  42. package/package.json +2 -2
  43. package/lib/features/drilldown/DrilldownOverlays.js +0 -110
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * bpmn-js - bpmn-viewer v9.0.0-subprocesses.3
2
+ * bpmn-js - bpmn-viewer v9.0.0
3
3
  *
4
4
  * Copyright (c) 2014-present, camunda Services GmbH
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Source Code: https://github.com/bpmn-io/bpmn-js
10
10
  *
11
- * Date: 2021-11-19
11
+ * Date: 2022-02-18
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -207,6 +207,23 @@
207
207
  function some(collection, matcher) {
208
208
  return !!find(collection, matcher);
209
209
  }
210
+ /**
211
+ * Transform a collection into another collection
212
+ * by piping each member through the given fn.
213
+ *
214
+ * @param {Object|Array} collection
215
+ * @param {Function} fn
216
+ *
217
+ * @return {Array} transformed collection
218
+ */
219
+
220
+ function map$1(collection, fn) {
221
+ var result = [];
222
+ forEach(collection, function (val, key) {
223
+ result.push(fn(val, key));
224
+ });
225
+ return result;
226
+ }
210
227
  /**
211
228
  * Create an object pattern matcher.
212
229
  *
@@ -214,7 +231,7 @@
214
231
  *
215
232
  * const matcher = matchPattern({ id: 1 });
216
233
  *
217
- * var element = find(elements, matcher);
234
+ * let element = find(elements, matcher);
218
235
  *
219
236
  * @param {Object} pattern
220
237
  *
@@ -244,8 +261,11 @@
244
261
  }
245
262
 
246
263
  /**
247
- * Debounce fn, calling it only once if
248
- * the given time elapsed between calls.
264
+ * Debounce fn, calling it only once if the given time
265
+ * elapsed between calls.
266
+ *
267
+ * Lodash-style the function exposes methods to `#clear`
268
+ * and `#flush` to control internal behavior.
249
269
  *
250
270
  * @param {Function} fn
251
271
  * @param {Number} timeout
@@ -258,23 +278,39 @@
258
278
  var lastThis;
259
279
  var lastNow;
260
280
 
261
- function fire() {
281
+ function fire(force) {
262
282
  var now = Date.now();
263
- var scheduledDiff = lastNow + timeout - now;
283
+ var scheduledDiff = force ? 0 : lastNow + timeout - now;
264
284
 
265
285
  if (scheduledDiff > 0) {
266
286
  return schedule(scheduledDiff);
267
287
  }
268
288
 
269
289
  fn.apply(lastThis, lastArgs);
270
- timer = lastNow = lastArgs = lastThis = undefined;
290
+ clear();
271
291
  }
272
292
 
273
293
  function schedule(timeout) {
274
294
  timer = setTimeout(fire, timeout);
275
295
  }
276
296
 
277
- return function () {
297
+ function clear() {
298
+ if (timer) {
299
+ clearTimeout(timer);
300
+ }
301
+
302
+ timer = lastNow = lastArgs = lastThis = undefined;
303
+ }
304
+
305
+ function flush() {
306
+ if (timer) {
307
+ fire(true);
308
+ }
309
+
310
+ clear();
311
+ }
312
+
313
+ function callback() {
278
314
  lastNow = Date.now();
279
315
 
280
316
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -287,7 +323,11 @@
287
323
  if (!timer) {
288
324
  schedule(timeout);
289
325
  }
290
- };
326
+ }
327
+
328
+ callback.flush = flush;
329
+ callback.cancel = clear;
330
+ return callback;
291
331
  }
292
332
  /**
293
333
  * Bind function against target <this>.
@@ -476,7 +516,6 @@
476
516
  return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
477
517
  }
478
518
 
479
-
480
519
  /**
481
520
  * Return the business object for a given element.
482
521
  *
@@ -2530,16 +2569,16 @@
2530
2569
  return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
2531
2570
  }
2532
2571
 
2572
+ function renderer(type) {
2573
+ return handlers[type];
2574
+ }
2575
+
2533
2576
  function as(type) {
2534
2577
  return function(parentGfx, element) {
2535
- return handlers[type](parentGfx, element);
2578
+ return renderer(type)(parentGfx, element);
2536
2579
  };
2537
2580
  }
2538
2581
 
2539
- function renderer(type) {
2540
- return handlers[type];
2541
- }
2542
-
2543
2582
  function renderEventContent(element, parentGfx) {
2544
2583
 
2545
2584
  var event = getSemantic(element);
@@ -4020,6 +4059,7 @@
4020
4059
  // extension API, use at your own risk
4021
4060
  this._drawPath = drawPath;
4022
4061
 
4062
+ this._renderer = renderer;
4023
4063
  }
4024
4064
 
4025
4065
 
@@ -4041,7 +4081,7 @@
4041
4081
 
4042
4082
  BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
4043
4083
  var type = element.type;
4044
- var h = this.handlers[type];
4084
+ var h = this._renderer(type);
4045
4085
 
4046
4086
  /* jshint -W040 */
4047
4087
  return h(parentGfx, element);
@@ -4049,7 +4089,7 @@
4049
4089
 
4050
4090
  BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
4051
4091
  var type = element.type;
4052
- var h = this.handlers[type];
4092
+ var h = this._renderer(type);
4053
4093
 
4054
4094
  /* jshint -W040 */
4055
4095
  return h(parentGfx, element);
@@ -5259,6 +5299,13 @@
5259
5299
  return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
5260
5300
  }
5261
5301
 
5302
+ /**
5303
+ * @param {ModdleElement} semantic
5304
+ * @param {ModdleElement} di
5305
+ * @param {Object} [attrs=null]
5306
+ *
5307
+ * @return {Object}
5308
+ */
5262
5309
  function elementData(semantic, di, attrs) {
5263
5310
  return assign({
5264
5311
  id: semantic.id,
@@ -5338,15 +5385,14 @@
5338
5385
  // invisible root element (process, subprocess or collaboration)
5339
5386
  if (is$1(di, 'bpmndi:BPMNPlane')) {
5340
5387
 
5341
- // add a virtual element (not being drawn)
5342
- element = this._elementFactory.createRoot(elementData(semantic, di));
5388
+ var attrs = is$1(semantic, 'bpmn:SubProcess')
5389
+ ? { id: semantic.id + '_plane' }
5390
+ : {};
5343
5391
 
5344
- // for subprocesses, the id is already defined on the collapsed shape
5345
- if (is$1(semantic, 'bpmn:SubProcess')) {
5346
- element.id = element.id + '_plane';
5347
- }
5392
+ // add a virtual element (not being drawn)
5393
+ element = this._elementFactory.createRoot(elementData(semantic, di, attrs));
5348
5394
 
5349
- this._canvas.createPlane(semantic.id, element);
5395
+ this._canvas.addRootElement(element);
5350
5396
  }
5351
5397
 
5352
5398
  // SHAPE
@@ -5382,7 +5428,7 @@
5382
5428
 
5383
5429
  // check whether data store is inside our outside of its semantic parent
5384
5430
  if (!isPointInsideBBox(parentElement, getMid(bounds))) {
5385
- parentElement = this._canvas.findPlane(parentElement).rootElement;
5431
+ parentElement = this._canvas.findRoot(parentElement);
5386
5432
  }
5387
5433
  }
5388
5434
 
@@ -5410,7 +5456,7 @@
5410
5456
  // are rendered correctly across different "hacks" people
5411
5457
  // love to model such as cross participant / sub process
5412
5458
  // associations
5413
- parentElement = this._canvas.findPlane(parentElement).rootElement;
5459
+ parentElement = this._canvas.findRoot(parentElement);
5414
5460
  }
5415
5461
 
5416
5462
  // insert sequence flows behind other flow nodes (cf. #727)
@@ -5644,7 +5690,7 @@
5644
5690
  return isPrimaryButton(event) || isAuxiliaryButton(event);
5645
5691
  }
5646
5692
 
5647
- var LOW_PRIORITY$2 = 500;
5693
+ var LOW_PRIORITY$3 = 500;
5648
5694
 
5649
5695
 
5650
5696
  /**
@@ -5839,7 +5885,7 @@
5839
5885
  eventBus.on([
5840
5886
  'shape.changed',
5841
5887
  'connection.changed'
5842
- ], LOW_PRIORITY$2, function(event) {
5888
+ ], LOW_PRIORITY$3, function(event) {
5843
5889
 
5844
5890
  var element = event.element,
5845
5891
  gfx = event.gfx;
@@ -5847,7 +5893,7 @@
5847
5893
  eventBus.fire('interactionEvents.updateHit', { element: element, gfx: gfx });
5848
5894
  });
5849
5895
 
5850
- eventBus.on('interactionEvents.createHit', LOW_PRIORITY$2, function(event) {
5896
+ eventBus.on('interactionEvents.createHit', LOW_PRIORITY$3, function(event) {
5851
5897
  var element = event.element,
5852
5898
  gfx = event.gfx;
5853
5899
 
@@ -6195,7 +6241,7 @@
6195
6241
  return !!(element && element.isFrame);
6196
6242
  }
6197
6243
 
6198
- var LOW_PRIORITY$1 = 500;
6244
+ var LOW_PRIORITY$2 = 500;
6199
6245
 
6200
6246
 
6201
6247
  /**
@@ -6233,7 +6279,7 @@
6233
6279
 
6234
6280
  // A low priortity is necessary, because outlines of labels have to be updated
6235
6281
  // after the label bounds have been updated in the renderer.
6236
- eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$1, function(event) {
6282
+ eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$2, function(event) {
6237
6283
  var element = event.element,
6238
6284
  gfx = event.gfx;
6239
6285
 
@@ -6330,7 +6376,7 @@
6330
6376
  self.deselect(element);
6331
6377
  });
6332
6378
 
6333
- eventBus.on([ 'diagram.clear', 'plane.set' ], function(e) {
6379
+ eventBus.on([ 'diagram.clear', 'root.set' ], function(e) {
6334
6380
  self.select(null);
6335
6381
  });
6336
6382
  }
@@ -6383,10 +6429,12 @@
6383
6429
 
6384
6430
  var canvas = this._canvas;
6385
6431
 
6432
+ var rootElement = canvas.getRootElement();
6433
+
6386
6434
  elements = elements.filter(function(element) {
6387
- var plane = canvas.findPlane(element);
6435
+ var elementRoot = canvas.findRoot(element);
6388
6436
 
6389
- return plane === canvas.getActivePlane();
6437
+ return rootElement === elementRoot;
6390
6438
  });
6391
6439
 
6392
6440
  // selection may be cleared by passing an empty array or null
@@ -6627,7 +6675,7 @@
6627
6675
  // document wide unique overlay ids
6628
6676
  var ids = new IdGenerator('ov');
6629
6677
 
6630
- var LOW_PRIORITY = 500;
6678
+ var LOW_PRIORITY$1 = 500;
6631
6679
 
6632
6680
 
6633
6681
  /**
@@ -6857,8 +6905,7 @@
6857
6905
  *
6858
6906
  * @see Overlays#get for filter options.
6859
6907
  *
6860
- * @param {string} [id]
6861
- * @param {Object} [filter]
6908
+ * @param {string|object} [filter]
6862
6909
  */
6863
6910
  Overlays.prototype.remove = function(filter) {
6864
6911
 
@@ -6974,6 +7021,7 @@
6974
7021
  }
6975
7022
 
6976
7023
  setPosition(htmlContainer, left || 0, top || 0);
7024
+ this._updateOverlayVisibilty(overlay, this._canvas.viewbox());
6977
7025
  };
6978
7026
 
6979
7027
 
@@ -7057,12 +7105,10 @@
7057
7105
  classes(htmlContainer).add('djs-overlay-' + overlay.type);
7058
7106
  }
7059
7107
 
7060
- var plane = this._canvas.findPlane(element);
7061
- var activePlane = this._canvas.getActivePlane();
7062
- overlay.plane = plane;
7063
- if (plane !== activePlane) {
7064
- setVisible(htmlContainer, false);
7065
- }
7108
+ var elementRoot = this._canvas.findRoot(element);
7109
+ var activeRoot = this._canvas.getRootElement();
7110
+
7111
+ setVisible(htmlContainer, elementRoot === activeRoot);
7066
7112
 
7067
7113
  overlay.htmlContainer = htmlContainer;
7068
7114
 
@@ -7078,14 +7124,14 @@
7078
7124
 
7079
7125
  Overlays.prototype._updateOverlayVisibilty = function(overlay, viewbox) {
7080
7126
  var show = overlay.show,
7081
- plane = overlay.plane,
7127
+ rootElement = this._canvas.findRoot(overlay.element),
7082
7128
  minZoom = show && show.minZoom,
7083
7129
  maxZoom = show && show.maxZoom,
7084
7130
  htmlContainer = overlay.htmlContainer,
7085
- activePlane = this._canvas.getActivePlane(),
7131
+ activeRootElement = this._canvas.getRootElement(),
7086
7132
  visible = true;
7087
7133
 
7088
- if (plane !== activePlane) {
7134
+ if (rootElement !== activeRootElement) {
7089
7135
  visible = false;
7090
7136
  } else if (show) {
7091
7137
  if (
@@ -7196,7 +7242,7 @@
7196
7242
 
7197
7243
  // move integration
7198
7244
 
7199
- eventBus.on('element.changed', LOW_PRIORITY, function(e) {
7245
+ eventBus.on('element.changed', LOW_PRIORITY$1, function(e) {
7200
7246
  var element = e.element;
7201
7247
 
7202
7248
  var container = self._getOverlayContainer(element, true);
@@ -7221,10 +7267,8 @@
7221
7267
  });
7222
7268
 
7223
7269
 
7224
- eventBus.on('plane.set', function(e) {
7225
- forEach(self._overlays, function(el) {
7226
- setVisible(el.htmlContainer, el.plane === e.plane);
7227
- });
7270
+ eventBus.on('root.set', function() {
7271
+ self._updateOverlaysVisibilty(self._canvas.viewbox());
7228
7272
  });
7229
7273
 
7230
7274
  // clear overlays with diagram
@@ -7337,6 +7381,181 @@
7337
7381
  changeSupport: [ 'type', ChangeSupport ]
7338
7382
  };
7339
7383
 
7384
+ var DEFAULT_PRIORITY$1 = 1000;
7385
+
7386
+ /**
7387
+ * A utility that can be used to plug-in into the command execution for
7388
+ * extension and/or validation.
7389
+ *
7390
+ * @param {EventBus} eventBus
7391
+ *
7392
+ * @example
7393
+ *
7394
+ * import inherits from 'inherits';
7395
+ *
7396
+ * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
7397
+ *
7398
+ * function CommandLogger(eventBus) {
7399
+ * CommandInterceptor.call(this, eventBus);
7400
+ *
7401
+ * this.preExecute(function(event) {
7402
+ * console.log('command pre-execute', event);
7403
+ * });
7404
+ * }
7405
+ *
7406
+ * inherits(CommandLogger, CommandInterceptor);
7407
+ *
7408
+ */
7409
+ function CommandInterceptor(eventBus) {
7410
+ this._eventBus = eventBus;
7411
+ }
7412
+
7413
+ CommandInterceptor.$inject = [ 'eventBus' ];
7414
+
7415
+ function unwrapEvent(fn, that) {
7416
+ return function(event) {
7417
+ return fn.call(that || null, event.context, event.command, event);
7418
+ };
7419
+ }
7420
+
7421
+ /**
7422
+ * Register an interceptor for a command execution
7423
+ *
7424
+ * @param {string|Array<string>} [events] list of commands to register on
7425
+ * @param {string} [hook] command hook, i.e. preExecute, executed to listen on
7426
+ * @param {number} [priority] the priority on which to hook into the execution
7427
+ * @param {Function} handlerFn interceptor to be invoked with (event)
7428
+ * @param {boolean} unwrap if true, unwrap the event and pass (context, command, event) to the
7429
+ * listener instead
7430
+ * @param {Object} [that] Pass context (`this`) to the handler function
7431
+ */
7432
+ CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) {
7433
+
7434
+ if (isFunction(hook) || isNumber(hook)) {
7435
+ that = unwrap;
7436
+ unwrap = handlerFn;
7437
+ handlerFn = priority;
7438
+ priority = hook;
7439
+ hook = null;
7440
+ }
7441
+
7442
+ if (isFunction(priority)) {
7443
+ that = unwrap;
7444
+ unwrap = handlerFn;
7445
+ handlerFn = priority;
7446
+ priority = DEFAULT_PRIORITY$1;
7447
+ }
7448
+
7449
+ if (isObject(unwrap)) {
7450
+ that = unwrap;
7451
+ unwrap = false;
7452
+ }
7453
+
7454
+ if (!isFunction(handlerFn)) {
7455
+ throw new Error('handlerFn must be a function');
7456
+ }
7457
+
7458
+ if (!isArray$1(events)) {
7459
+ events = [ events ];
7460
+ }
7461
+
7462
+ var eventBus = this._eventBus;
7463
+
7464
+ forEach(events, function(event) {
7465
+
7466
+ // concat commandStack(.event)?(.hook)?
7467
+ var fullEvent = [ 'commandStack', event, hook ].filter(function(e) { return e; }).join('.');
7468
+
7469
+ eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
7470
+ });
7471
+ };
7472
+
7473
+
7474
+ var hooks = [
7475
+ 'canExecute',
7476
+ 'preExecute',
7477
+ 'preExecuted',
7478
+ 'execute',
7479
+ 'executed',
7480
+ 'postExecute',
7481
+ 'postExecuted',
7482
+ 'revert',
7483
+ 'reverted'
7484
+ ];
7485
+
7486
+ /*
7487
+ * Install hook shortcuts
7488
+ *
7489
+ * This will generate the CommandInterceptor#(preExecute|...|reverted) methods
7490
+ * which will in term forward to CommandInterceptor#on.
7491
+ */
7492
+ forEach(hooks, function(hook) {
7493
+
7494
+ /**
7495
+ * {canExecute|preExecute|preExecuted|execute|executed|postExecute|postExecuted|revert|reverted}
7496
+ *
7497
+ * A named hook for plugging into the command execution
7498
+ *
7499
+ * @param {string|Array<string>} [events] list of commands to register on
7500
+ * @param {number} [priority] the priority on which to hook into the execution
7501
+ * @param {Function} handlerFn interceptor to be invoked with (event)
7502
+ * @param {boolean} [unwrap=false] if true, unwrap the event and pass (context, command, event) to the
7503
+ * listener instead
7504
+ * @param {Object} [that] Pass context (`this`) to the handler function
7505
+ */
7506
+ CommandInterceptor.prototype[hook] = function(events, priority, handlerFn, unwrap, that) {
7507
+
7508
+ if (isFunction(events) || isNumber(events)) {
7509
+ that = unwrap;
7510
+ unwrap = handlerFn;
7511
+ handlerFn = priority;
7512
+ priority = events;
7513
+ events = null;
7514
+ }
7515
+
7516
+ this.on(events, hook, priority, handlerFn, unwrap, that);
7517
+ };
7518
+ });
7519
+
7520
+ /**
7521
+ * A modeling behavior that ensures we set the correct root element
7522
+ * as we undo and redo commands.
7523
+ *
7524
+ * @param {Canvas} canvas
7525
+ * @param {didi.Injector} injector
7526
+ */
7527
+ function RootElementsBehavior(canvas, injector) {
7528
+
7529
+ injector.invoke(CommandInterceptor, this);
7530
+
7531
+ this.executed(function(event) {
7532
+ var context = event.context;
7533
+
7534
+ if (context.rootElement) {
7535
+ canvas.setRootElement(context.rootElement);
7536
+ } else {
7537
+ context.rootElement = canvas.getRootElement();
7538
+ }
7539
+ });
7540
+
7541
+ this.revert(function(event) {
7542
+ var context = event.context;
7543
+
7544
+ if (context.rootElement) {
7545
+ canvas.setRootElement(context.rootElement);
7546
+ }
7547
+ });
7548
+ }
7549
+
7550
+ inherits$1(RootElementsBehavior, CommandInterceptor);
7551
+
7552
+ RootElementsBehavior.$inject = [ 'canvas', 'injector'];
7553
+
7554
+ var RootElementsModule = {
7555
+ __init__: [ 'rootElementsBehavior' ],
7556
+ rootElementsBehavior: [ 'type', RootElementsBehavior ]
7557
+ };
7558
+
7340
7559
  var css_escape = {exports: {}};
7341
7560
 
7342
7561
  /*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
@@ -7459,39 +7678,94 @@
7459
7678
  });
7460
7679
  }
7461
7680
 
7462
- 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>';
7681
+ var planeSuffix = '_plane';
7682
+
7683
+ /**
7684
+ * Get plane ID for a primary shape.
7685
+ *
7686
+ * @param {djs.model.Base|ModdleElement} element
7687
+ *
7688
+ * @returns {String}
7689
+ */
7690
+ function getPlaneIdFromShape(element) {
7691
+ var id = element.id;
7692
+
7693
+ if (is$1(element, 'bpmn:SubProcess')) {
7694
+ return addPlaneSuffix(id);
7695
+ }
7696
+
7697
+ return id;
7698
+ }
7699
+
7700
+ function addPlaneSuffix(id) {
7701
+ return id + planeSuffix;
7702
+ }
7463
7703
 
7464
7704
  var OPEN_CLASS = 'bjs-breadcrumbs-shown';
7465
7705
 
7706
+
7466
7707
  /**
7467
- * Adds Overlays that allow switching planes on collapsed subprocesses.
7708
+ * Adds overlays that allow switching planes on collapsed subprocesses.
7468
7709
  *
7469
7710
  * @param {eventBus} eventBus
7470
7711
  * @param {elementRegistry} elementRegistry
7471
7712
  * @param {overlays} overlays
7472
7713
  * @param {canvas} canvas
7473
7714
  */
7474
- function DrilldownOverlays(eventBus, elementRegistry, overlays, canvas) {
7715
+ function DrilldownBreadcrumbs(eventBus, elementRegistry, overlays, canvas) {
7475
7716
  var breadcrumbs = domify('<ul class="bjs-breadcrumbs"></ul>');
7476
7717
  var container = canvas.getContainer();
7477
7718
  var containerClasses = classes(container);
7478
7719
  container.appendChild(breadcrumbs);
7479
7720
 
7480
- function updateBreadcrumbs(plane) {
7481
- var subProcess = elementRegistry.get(plane.name);
7482
- var parents = getParentChain(subProcess);
7721
+ var boParents = [];
7722
+
7723
+ // update breadcrumbs if name or ID of the primary shape changes
7724
+ eventBus.on('element.changed', function(e) {
7725
+ var shape = e.element,
7726
+ bo = getBusinessObject(shape);
7483
7727
 
7484
- var path = parents.map(function(el) {
7485
- var title = escapeHTML(el.name || el.id);
7728
+ var isPresent = find(boParents, function(el) {
7729
+ return el === bo;
7730
+ });
7731
+
7732
+ if (!isPresent) {
7733
+ return;
7734
+ }
7735
+
7736
+ updateBreadcrumbs();
7737
+ });
7738
+
7739
+ /**
7740
+ * Updates the displayed breadcrumbs. If no element is provided, only the
7741
+ * labels are updated.
7742
+ *
7743
+ * @param {djs.model.Base} [element]
7744
+ */
7745
+ function updateBreadcrumbs(element) {
7746
+ if (element) {
7747
+ boParents = getBoParentChain(element);
7748
+ }
7749
+
7750
+ var path = boParents.map(function(parent) {
7751
+ var title = escapeHTML(parent.name || parent.id);
7486
7752
  var link = domify('<li><span class="bjs-crumb"><a title="' + title + '">' + title + '</a></span></li>');
7487
7753
 
7754
+ var parentPlane = canvas.findRoot(getPlaneIdFromShape(parent)) || canvas.findRoot(parent.id);
7755
+
7756
+ // when the root is a collaboration, the process does not have a corresponding
7757
+ // element in the elementRegisty. Instead, we search for the corresponding participant
7758
+ if (!parentPlane && is$1(parent, 'bpmn:Process')) {
7759
+ var participant = elementRegistry.find(function(element) {
7760
+ var bo = getBusinessObject(element);
7761
+ return bo && bo.processRef && bo.processRef === parent;
7762
+ });
7763
+
7764
+ parentPlane = canvas.findRoot(participant.id);
7765
+ }
7766
+
7488
7767
  link.addEventListener('click', function() {
7489
- if (canvas.getPlane(el.id)) {
7490
- canvas.setActivePlane(el.id);
7491
- } else {
7492
- var plane = canvas.findPlane(el.id);
7493
- canvas.setActivePlane(plane);
7494
- }
7768
+ canvas.setRootElement(parentPlane);
7495
7769
  });
7496
7770
 
7497
7771
  return link;
@@ -7508,50 +7782,26 @@
7508
7782
  });
7509
7783
  }
7510
7784
 
7511
- eventBus.on('plane.set', function(event) {
7512
- var plane = event.plane;
7513
-
7514
- updateBreadcrumbs(plane);
7785
+ eventBus.on('root.set', function(event) {
7786
+ updateBreadcrumbs(event.element);
7515
7787
  });
7516
7788
 
7517
- var createOverlay = function(element) {
7518
- var html = domify('<button class="bjs-drilldown">' + ARROW_DOWN_SVG + '</button>');
7519
-
7520
- html.addEventListener('click', function() {
7521
- canvas.setActivePlane(element.id);
7522
- });
7523
-
7524
- overlays.add(element, {
7525
- position: {
7526
- bottom: -7,
7527
- right: -8
7528
- },
7529
- html: html
7530
- });
7531
- };
7532
-
7533
- var addOverlays = function(elements) {
7534
- elements.forEach(function(element) {
7535
- if (is$1(element, 'bpmn:SubProcess')
7536
- && element.collapsed
7537
- && canvas.getPlane(element.id)) {
7538
- createOverlay(element);
7539
- }
7540
- });
7541
- };
7542
-
7543
- eventBus.on('import.done', function() {
7544
- addOverlays(elementRegistry.filter(function(el) {
7545
- return is$1(el, 'bpmn:SubProcess');
7546
- }));
7547
- });
7548
7789
  }
7549
7790
 
7550
- DrilldownOverlays.$inject = [ 'eventBus', 'elementRegistry', 'overlays', 'canvas' ];
7791
+ DrilldownBreadcrumbs.$inject = [ 'eventBus', 'elementRegistry', 'overlays', 'canvas' ];
7551
7792
 
7552
7793
 
7553
- // helpers
7554
- var getParentChain = function(child) {
7794
+ // helpers //////////
7795
+
7796
+ /**
7797
+ * Returns the parents for the element using the business object chain,
7798
+ * starting with the root element.
7799
+ *
7800
+ * @param {djs.model.Shape} child
7801
+ *
7802
+ * @returns {Array<djs.model.Shape>} parents
7803
+ */
7804
+ function getBoParentChain(child) {
7555
7805
  var bo = getBusinessObject(child);
7556
7806
 
7557
7807
  var parents = [];
@@ -7563,29 +7813,40 @@
7563
7813
  }
7564
7814
 
7565
7815
  return parents.reverse();
7566
- };
7816
+ }
7567
7817
 
7568
7818
  /**
7569
- * Move collapsed subprocesses into view when drilling down. Zoom and scroll
7570
- * are saved in a session.
7819
+ * Move collapsed subprocesses into view when drilling down.
7820
+ *
7821
+ * Zoom and scroll are saved in a session.
7571
7822
  *
7572
7823
  * @param {eventBus} eventBus
7573
7824
  * @param {canvas} canvas
7574
7825
  */
7575
7826
  function DrilldownCentering(eventBus, canvas) {
7576
- var currentPlane = 'base';
7577
- var positionMap = {};
7578
7827
 
7579
- eventBus.on('plane.set', function(event) {
7828
+ var currentRoot = null;
7829
+ var positionMap = new Map();
7830
+
7831
+ eventBus.on('root.set', function(event) {
7832
+ var newRoot = event.element;
7580
7833
  var currentViewbox = canvas.viewbox();
7581
- positionMap[currentPlane] = {
7834
+ var storedViewbox = positionMap.get(newRoot);
7835
+
7836
+ positionMap.set(currentRoot, {
7582
7837
  x: currentViewbox.x,
7583
7838
  y: currentViewbox.y,
7584
7839
  zoom: currentViewbox.scale
7585
- };
7840
+ });
7586
7841
 
7587
- var planeId = event.plane.name;
7588
- var storedViewbox = positionMap[planeId] || { x: 0, y: 0, zoom: 1 };
7842
+ currentRoot = newRoot;
7843
+
7844
+ // current root was replaced with a collaboration, we don't update the viewbox
7845
+ if (is$1(newRoot, 'bpmn:Collaboration') && !storedViewbox) {
7846
+ return;
7847
+ }
7848
+
7849
+ storedViewbox = storedViewbox || { x: 0, y: 0, zoom: 1 };
7589
7850
 
7590
7851
  var dx = (currentViewbox.x - storedViewbox.x) * currentViewbox.scale,
7591
7852
  dy = (currentViewbox.y - storedViewbox.y) * currentViewbox.scale;
@@ -7600,13 +7861,77 @@
7600
7861
  if (storedViewbox.zoom !== currentViewbox.scale) {
7601
7862
  canvas.zoom(storedViewbox.zoom, { x: 0, y: 0 });
7602
7863
  }
7864
+ });
7603
7865
 
7604
- currentPlane = planeId;
7866
+ eventBus.on('diagram.clear', function() {
7867
+ positionMap.clear();
7868
+ currentRoot = null;
7605
7869
  });
7870
+
7606
7871
  }
7607
7872
 
7608
7873
  DrilldownCentering.$inject = [ 'eventBus', 'canvas' ];
7609
7874
 
7875
+
7876
+ /**
7877
+ * ES5 Map implementation. Works.
7878
+ */
7879
+ function Map() {
7880
+
7881
+ this._entries = [];
7882
+
7883
+ this.set = function(key, value) {
7884
+
7885
+ var found = false;
7886
+
7887
+ for (var k in this._entries) {
7888
+ if (this._entries[k][0] === key) {
7889
+ this._entries[k][1] = value;
7890
+
7891
+ found = true;
7892
+
7893
+ break;
7894
+ }
7895
+ }
7896
+
7897
+ if (!found) {
7898
+ this._entries.push([ key, value ]);
7899
+ }
7900
+ };
7901
+
7902
+ this.get = function(key) {
7903
+
7904
+ for (var k in this._entries) {
7905
+ if (this._entries[k][0] === key) {
7906
+ return this._entries[k][1];
7907
+ }
7908
+ }
7909
+
7910
+ return null;
7911
+ };
7912
+
7913
+ this.clear = function() {
7914
+ this._entries.length = 0;
7915
+ };
7916
+
7917
+ this.remove = function(key) {
7918
+
7919
+ var idx = -1;
7920
+
7921
+ for (var k in this._entries) {
7922
+ if (this._entries[k][0] === key) {
7923
+ idx = k;
7924
+
7925
+ break;
7926
+ }
7927
+ }
7928
+
7929
+ if (idx !== -1) {
7930
+ this._entries.splice(idx, 1);
7931
+ }
7932
+ };
7933
+ }
7934
+
7610
7935
  var DEFAULT_POSITION = {
7611
7936
  x: 180,
7612
7937
  y: 160
@@ -7688,6 +8013,15 @@
7688
8013
 
7689
8014
  var newDiagrams = [];
7690
8015
 
8016
+ // create new planes for all collapsed subprocesses, even when they are empty
8017
+ collapsedElements.forEach(function(element) {
8018
+ if (!self._processToDiagramMap[element.id]) {
8019
+ var diagram = self.createDiagram(element);
8020
+ self._processToDiagramMap[element.id] = diagram;
8021
+ newDiagrams.push(diagram);
8022
+ }
8023
+ });
8024
+
7691
8025
  elementsToMove.forEach(function(element) {
7692
8026
  var diElement = element.diElement;
7693
8027
  var parent = element.parent;
@@ -7703,12 +8037,6 @@
7703
8037
  }
7704
8038
 
7705
8039
  var diagram = self._processToDiagramMap[parent.id];
7706
- if (!diagram) {
7707
- diagram = self.createDiagram(parent);
7708
- self._processToDiagramMap[parent.id] = diagram;
7709
- newDiagrams.push(diagram);
7710
- }
7711
-
7712
8040
  self.moveToDiPlane(diElement, diagram.plane);
7713
8041
  });
7714
8042
 
@@ -7775,33 +8103,209 @@
7775
8103
  }
7776
8104
  }
7777
8105
 
7778
- function getPlaneBounds(plane) {
7779
- var planeTrbl = {
7780
- top: Infinity,
7781
- right: -Infinity,
7782
- bottom: -Infinity,
7783
- left: Infinity
7784
- };
8106
+ function getPlaneBounds(plane) {
8107
+ var planeTrbl = {
8108
+ top: Infinity,
8109
+ right: -Infinity,
8110
+ bottom: -Infinity,
8111
+ left: Infinity
8112
+ };
8113
+
8114
+ plane.planeElement.forEach(function(element) {
8115
+ if (!element.bounds) {
8116
+ return;
8117
+ }
8118
+
8119
+ var trbl = asTRBL(element.bounds);
8120
+
8121
+ planeTrbl.top = Math.min(trbl.top, planeTrbl.top);
8122
+ planeTrbl.left = Math.min(trbl.left, planeTrbl.left);
8123
+ });
8124
+
8125
+ return asBounds(planeTrbl);
8126
+ }
8127
+
8128
+ var LOW_PRIORITY = 250;
8129
+ 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>';
8130
+
8131
+ var EMPTY_MARKER = 'bjs-drilldown-empty';
8132
+
8133
+ function DrilldownOverlayBehavior(
8134
+ canvas, eventBus, elementRegistry, overlays
8135
+ ) {
8136
+ CommandInterceptor.call(this, eventBus);
8137
+
8138
+ this._canvas = canvas;
8139
+ this._eventBus = eventBus;
8140
+ this._elementRegistry = elementRegistry;
8141
+ this._overlays = overlays;
8142
+
8143
+ var self = this;
8144
+
8145
+ this.executed('shape.toggleCollapse', LOW_PRIORITY, function(context) {
8146
+ var shape = context.shape;
8147
+
8148
+ // Add overlay to the collapsed shape
8149
+ if (self.canDrillDown(shape)) {
8150
+ self.addOverlay(shape);
8151
+ } else {
8152
+ self.removeOverlay(shape);
8153
+ }
8154
+ }, true);
8155
+
8156
+
8157
+ this.reverted('shape.toggleCollapse', LOW_PRIORITY, function(context) {
8158
+ var shape = context.shape;
8159
+
8160
+ // Add overlay to the collapsed shape
8161
+ if (self.canDrillDown(shape)) {
8162
+ self.addOverlay(shape);
8163
+ } else {
8164
+ self.removeOverlay(shape);
8165
+ }
8166
+ }, true);
8167
+
8168
+
8169
+ this.executed(['shape.create', 'shape.move', 'shape.delete'], LOW_PRIORITY,
8170
+ function(context) {
8171
+ var oldParent = context.oldParent,
8172
+ newParent = context.newParent || context.parent,
8173
+ shape = context.shape;
8174
+
8175
+ // Add overlay to the collapsed shape
8176
+ if (self.canDrillDown(shape)) {
8177
+ self.addOverlay(shape);
8178
+ }
8179
+
8180
+ self.updateDrilldownOverlay(oldParent);
8181
+ self.updateDrilldownOverlay(newParent);
8182
+ self.updateDrilldownOverlay(shape);
8183
+ }, true);
8184
+
8185
+
8186
+ this.reverted(['shape.create', 'shape.move', 'shape.delete'], LOW_PRIORITY,
8187
+ function(context) {
8188
+ var oldParent = context.oldParent,
8189
+ newParent = context.newParent || context.parent,
8190
+ shape = context.shape;
8191
+
8192
+ // Add overlay to the collapsed shape
8193
+ if (self.canDrillDown(shape)) {
8194
+ self.addOverlay(shape);
8195
+ }
8196
+
8197
+ self.updateDrilldownOverlay(oldParent);
8198
+ self.updateDrilldownOverlay(newParent);
8199
+ self.updateDrilldownOverlay(shape);
8200
+ }, true);
8201
+
8202
+
8203
+ eventBus.on('import.done', function() {
8204
+ elementRegistry.filter(function(e) {
8205
+ return self.canDrillDown(e);
8206
+ }).map(function(el) {
8207
+ self.addOverlay(el);
8208
+ });
8209
+ });
8210
+
8211
+ }
8212
+
8213
+ inherits$1(DrilldownOverlayBehavior, CommandInterceptor);
8214
+
8215
+ DrilldownOverlayBehavior.prototype.updateDrilldownOverlay = function(shape) {
8216
+ var canvas = this._canvas;
8217
+
8218
+ if (!shape) {
8219
+ return;
8220
+ }
8221
+
8222
+ var root = canvas.findRoot(shape);
8223
+ if (root) {
8224
+ this.updateOverlayVisibility(root);
8225
+ }
8226
+ };
8227
+
8228
+
8229
+ DrilldownOverlayBehavior.prototype.canDrillDown = function(element) {
8230
+ var canvas = this._canvas;
8231
+ return is$1(element, 'bpmn:SubProcess') && canvas.findRoot(getPlaneIdFromShape(element));
8232
+ };
8233
+
8234
+ /**
8235
+ * Updates visibility of the drilldown overlay. If the plane has no elements,
8236
+ * the drilldown will be only shown when the element is selected.
8237
+ *
8238
+ * @param {djs.model.Shape|djs.model.Root} element collapsed shape or root element
8239
+ */
8240
+ DrilldownOverlayBehavior.prototype.updateOverlayVisibility = function(element) {
8241
+ var overlays = this._overlays;
8242
+
8243
+ var bo = element.businessObject;
8244
+
8245
+ var overlay = overlays.get({ element: bo.id, type: 'drilldown' })[0];
8246
+
8247
+ if (!overlay) {
8248
+ return;
8249
+ }
8250
+
8251
+ var hasContent = bo && bo.flowElements && bo.flowElements.length;
8252
+ classes(overlay.html).toggle(EMPTY_MARKER, !hasContent);
8253
+ };
8254
+
8255
+ /**
8256
+ * Attaches a drilldown button to the given element. We assume that the plane has
8257
+ * the same id as the element.
8258
+ *
8259
+ * @param {djs.model.Shape} element collapsed shape
8260
+ */
8261
+ DrilldownOverlayBehavior.prototype.addOverlay = function(element) {
8262
+ var canvas = this._canvas;
8263
+ var overlays = this._overlays;
8264
+
8265
+ var existingOverlays = overlays.get({ element: element, type: 'drilldown' });
8266
+ if (existingOverlays.length) {
8267
+ this.removeOverlay(element);
8268
+ }
8269
+
8270
+ var button = domify('<button class="bjs-drilldown">' + ARROW_DOWN_SVG + '</button>');
7785
8271
 
7786
- plane.planeElement.forEach(function(element) {
7787
- if (!element.bounds) {
7788
- return;
7789
- }
8272
+ button.addEventListener('click', function() {
8273
+ canvas.setRootElement(canvas.findRoot(getPlaneIdFromShape(element)));
8274
+ });
7790
8275
 
7791
- var trbl = asTRBL(element.bounds);
8276
+ overlays.add(element, 'drilldown', {
8277
+ position: {
8278
+ bottom: -7,
8279
+ right: -8
8280
+ },
8281
+ html: button
8282
+ });
7792
8283
 
7793
- planeTrbl.top = Math.min(trbl.top, planeTrbl.top);
7794
- planeTrbl.left = Math.min(trbl.left, planeTrbl.left);
8284
+ this.updateOverlayVisibility(element);
8285
+ };
8286
+
8287
+ DrilldownOverlayBehavior.prototype.removeOverlay = function(element) {
8288
+ var overlays = this._overlays;
8289
+
8290
+ overlays.remove({
8291
+ element: element,
8292
+ type: 'drilldown'
7795
8293
  });
8294
+ };
7796
8295
 
7797
- return asBounds(planeTrbl);
7798
- }
8296
+ DrilldownOverlayBehavior.$inject = [
8297
+ 'canvas',
8298
+ 'eventBus',
8299
+ 'elementRegistry',
8300
+ 'overlays'
8301
+ ];
7799
8302
 
7800
8303
  var DrilldownModdule = {
7801
- __depends__: [ OverlaysModule, ChangeSupportModule ],
7802
- __init__: [ 'drilldownOverlays', 'drilldownCentering', 'subprocessCompatibility'],
7803
- drilldownOverlays: [ 'type', DrilldownOverlays ],
8304
+ __depends__: [ OverlaysModule, ChangeSupportModule, RootElementsModule ],
8305
+ __init__: [ 'drilldownBreadcrumbs', 'drilldownOverlayBehavior', 'drilldownCentering', 'subprocessCompatibility'],
8306
+ drilldownBreadcrumbs: [ 'type', DrilldownBreadcrumbs ],
7804
8307
  drilldownCentering: [ 'type', DrilldownCentering ],
8308
+ drilldownOverlayBehavior: [ 'type', DrilldownOverlayBehavior ],
7805
8309
  subprocessCompatibility: [ 'type', SubprocessCompatibility ]
7806
8310
  };
7807
8311
 
@@ -8442,7 +8946,6 @@
8442
8946
  }
8443
8947
 
8444
8948
  var BASE_LAYER = 'base';
8445
- var HIDDEN_MARKER = 'djs-element-hidden';
8446
8949
 
8447
8950
  // render plane contents behind utility layers
8448
8951
  var PLANE_LAYER_INDEX = 0;
@@ -8473,6 +8976,12 @@
8473
8976
  this._elementRegistry = elementRegistry;
8474
8977
  this._graphicsFactory = graphicsFactory;
8475
8978
 
8979
+ this._rootsIdx = 0;
8980
+
8981
+ this._layers = {};
8982
+ this._planes = [];
8983
+ this._rootElement = null;
8984
+
8476
8985
  this._init(config || {});
8477
8986
  }
8478
8987
 
@@ -8510,9 +9019,6 @@
8510
9019
 
8511
9020
  var viewport = this._viewport = createGroup(svg, 'viewport');
8512
9021
 
8513
- this._layers = {};
8514
- this._planes = {};
8515
-
8516
9022
  // debounce canvas.viewbox.changed events
8517
9023
  // for smoother diagram interaction
8518
9024
  if (config.deferUpdate !== false) {
@@ -8547,7 +9053,7 @@
8547
9053
  'shape.removed',
8548
9054
  'connection.removed',
8549
9055
  'elements.changed',
8550
- 'plane.set'
9056
+ 'root.set'
8551
9057
  ], function() {
8552
9058
  delete this._cachedViewbox;
8553
9059
  }, this);
@@ -8572,7 +9078,7 @@
8572
9078
  delete this._container;
8573
9079
  delete this._layers;
8574
9080
  delete this._planes;
8575
- delete this._activePlane;
9081
+ delete this._rootElement;
8576
9082
  delete this._viewport;
8577
9083
  };
8578
9084
 
@@ -8587,15 +9093,15 @@
8587
9093
  var type = getType(element);
8588
9094
 
8589
9095
  if (type === 'root') {
8590
- self.setRootElementForPlane(null, self.findPlane(element), true);
9096
+ self.removeRootElement(element);
8591
9097
  } else {
8592
9098
  self._removeElement(element, type);
8593
9099
  }
8594
9100
  });
8595
9101
 
8596
9102
  // remove all planes
8597
- this._activePlane = null;
8598
- this._planes = {};
9103
+ this._planes = [];
9104
+ this._rootElement = null;
8599
9105
 
8600
9106
  // force recomputation of view box
8601
9107
  delete this._cachedViewbox;
@@ -8676,140 +9182,75 @@
8676
9182
 
8677
9183
  };
8678
9184
 
8679
- /**
8680
- * Returns a plane that is used to draw elements on it.
8681
- *
8682
- * @param {string} name
8683
- *
8684
- * @return {Object} plane descriptor with { layer, rootElement, name }
8685
- */
8686
- Canvas.prototype.getPlane = function(name) {
8687
- if (!name) {
8688
- throw new Error('must specify a name');
8689
- }
8690
-
8691
- return this._planes[name];
8692
- };
8693
-
8694
- /**
8695
- * Creates a plane that is used to draw elements on it. If no
8696
- * root element is provided, an implicit root will be used.
8697
- *
8698
- * @param {string} name
8699
- * @param {Object|djs.model.Root} [rootElement] optional root element
8700
- *
8701
- * @return {Object} plane descriptor with { layer, rootElement, name }
8702
- */
8703
- Canvas.prototype.createPlane = function(name, rootElement) {
8704
- if (!name) {
8705
- throw new Error('must specify a name');
8706
- }
8707
-
8708
- if (this._planes[name]) {
8709
- throw new Error('plane ' + name + ' already exists');
8710
- }
8711
-
8712
- if (!rootElement) {
8713
- rootElement = {
8714
- id: '__implicitroot' + name,
8715
- children: [],
8716
- isImplicit: true
8717
- };
8718
- }
8719
-
8720
- var svgLayer = this.getLayer(name, PLANE_LAYER_INDEX);
8721
- classes$1(svgLayer).add(HIDDEN_MARKER);
8722
-
8723
- var plane = this._planes[name] = {
8724
- layer: svgLayer,
8725
- name: name,
8726
- rootElement: null
8727
- };
8728
-
8729
- this.setRootElementForPlane(rootElement, plane);
8730
-
8731
- return plane;
8732
- };
8733
-
8734
- /**
8735
- * Sets the active plane and hides the previously active plane.
8736
- *
8737
- * @param {string|Object} plane
8738
- *
8739
- * @return {Object} plane descriptor with { layer, rootElement, name }
8740
- */
8741
- Canvas.prototype.setActivePlane = function(plane) {
8742
- if (!plane) {
8743
- throw new Error('must specify a plane');
8744
- }
8745
-
8746
- if (typeof plane === 'string') {
8747
- plane = this.getPlane(plane);
8748
- }
8749
9185
 
8750
- // hide previous Plane
8751
- if (this._activePlane) {
8752
- classes$1(this._activePlane.layer).add(HIDDEN_MARKER);
8753
- }
9186
+ Canvas.prototype._removeLayer = function(name) {
8754
9187
 
8755
- this._activePlane = plane;
9188
+ var layer = this._layers[name];
8756
9189
 
8757
- // show current Plane
8758
- classes$1(plane.layer).remove(HIDDEN_MARKER);
9190
+ if (layer) {
9191
+ delete this._layers[name];
8759
9192
 
8760
- if (plane.rootElement) {
8761
- this._elementRegistry.updateGraphics(plane.rootElement, this._svg, true);
9193
+ remove$2(layer.group);
8762
9194
  }
8763
-
8764
- this._eventBus.fire('plane.set', { plane: plane });
8765
-
8766
- return plane;
8767
9195
  };
8768
9196
 
8769
9197
  /**
8770
- * Returns the currently active layer
9198
+ * Returns the currently active layer. Can be null.
8771
9199
  *
8772
- * @returns {SVGElement}
9200
+ * @returns {SVGElement|null}
8773
9201
  */
8774
-
8775
9202
  Canvas.prototype.getActiveLayer = function() {
8776
- return this.getActivePlane().layer;
8777
- };
9203
+ var plane = this._findPlaneForRoot(this.getRootElement());
8778
9204
 
8779
- /**
8780
- * Returns the currently active plane.
8781
- *
8782
- * @return {Object} plane descriptor with { layer, rootElement, name }
8783
- */
8784
- Canvas.prototype.getActivePlane = function() {
8785
- var plane = this._activePlane;
8786
9205
  if (!plane) {
8787
- plane = this.createPlane(BASE_LAYER);
8788
- this.setActivePlane(BASE_LAYER);
9206
+ return null;
8789
9207
  }
8790
9208
 
8791
- return plane;
9209
+ return plane.layer;
8792
9210
  };
8793
9211
 
9212
+
8794
9213
  /**
8795
9214
  * Returns the plane which contains the given element.
8796
9215
  *
8797
9216
  * @param {string|djs.model.Base} element
8798
9217
  *
8799
- * @return {Object} plane descriptor with { layer, rootElement, name }
9218
+ * @return {djs.model.Base} root for element
8800
9219
  */
8801
- Canvas.prototype.findPlane = function(element) {
9220
+ Canvas.prototype.findRoot = function(element) {
8802
9221
  if (typeof element === 'string') {
8803
9222
  element = this._elementRegistry.get(element);
8804
9223
  }
8805
9224
 
8806
- var root = findRoot(element);
9225
+ if (!element) {
9226
+ return;
9227
+ }
9228
+
9229
+ var plane = this._findPlaneForRoot(
9230
+ findRoot(element)
9231
+ ) || {};
9232
+
9233
+ return plane.rootElement;
9234
+ };
9235
+
9236
+ /**
9237
+ * Return a list of all root elements on the diagram.
9238
+ *
9239
+ * @return {djs.model.Root[]}
9240
+ */
9241
+ Canvas.prototype.getRootElements = function() {
9242
+ return this._planes.map(function(plane) {
9243
+ return plane.rootElement;
9244
+ });
9245
+ };
8807
9246
 
9247
+ Canvas.prototype._findPlaneForRoot = function(rootElement) {
8808
9248
  return find(this._planes, function(plane) {
8809
- return plane.rootElement === root;
9249
+ return plane.rootElement === rootElement;
8810
9250
  });
8811
9251
  };
8812
9252
 
9253
+
8813
9254
  /**
8814
9255
  * Returns the html element that encloses the
8815
9256
  * drawing canvas.
@@ -8930,95 +9371,205 @@
8930
9371
  }
8931
9372
  };
8932
9373
 
9374
+ /**
9375
+ * Returns the current root element.
9376
+ *
9377
+ * Supports two different modes for handling root elements:
9378
+ *
9379
+ * 1. if no root element has been added before, an implicit root will be added
9380
+ * and returned. This is used in applications that don't require explicit
9381
+ * root elements.
9382
+ *
9383
+ * 2. when root elements have been added before calling `getRootElement`,
9384
+ * root elements can be null. This is used for applications that want to manage
9385
+ * root elements themselves.
9386
+ *
9387
+ * @returns {Object|djs.model.Root|null} rootElement.
9388
+ */
8933
9389
  Canvas.prototype.getRootElement = function() {
8934
- var plane = this.getActivePlane();
9390
+ var rootElement = this._rootElement;
8935
9391
 
8936
- return plane.rootElement;
9392
+ // can return null if root elements are present but none was set yet
9393
+ if (rootElement || this._planes.length) {
9394
+ return rootElement;
9395
+ }
9396
+
9397
+ return this.setRootElement(this.addRootElement(null));
8937
9398
  };
8938
9399
 
9400
+ /**
9401
+ * Adds a given root element and returns it.
9402
+ *
9403
+ * @param {Object|djs.model.Root} rootElement
9404
+ *
9405
+ * @return {Object|djs.model.Root} rootElement
9406
+ */
8939
9407
 
9408
+ Canvas.prototype.addRootElement = function(rootElement) {
9409
+ var idx = this._rootsIdx++;
8940
9410
 
8941
- // root element handling //////////////////////
9411
+ if (!rootElement) {
9412
+ rootElement = {
9413
+ id: '__implicitroot_' + idx,
9414
+ children: [],
9415
+ isImplicit: true
9416
+ };
9417
+ }
9418
+
9419
+ var layerName = rootElement.layer = 'root-' + idx;
9420
+
9421
+ this._ensureValid('root', rootElement);
9422
+
9423
+ var layer = this.getLayer(layerName, PLANE_LAYER_INDEX);
9424
+
9425
+ attr$1(layer, 'display', 'none');
9426
+
9427
+ this._addRoot(rootElement, layer);
9428
+
9429
+ this._planes.push({
9430
+ rootElement: rootElement,
9431
+ layer: layer
9432
+ });
9433
+
9434
+ return rootElement;
9435
+ };
8942
9436
 
8943
9437
  /**
8944
- * Sets a given element as the new root element for the canvas
8945
- * and returns the new root element.
9438
+ * Removes a given rootElement and returns it.
8946
9439
  *
8947
- * @param {Object|djs.model.Root} element
8948
- * @param {boolean} [override] whether to override the current root element, if any
9440
+ * @param {djs.model.Root|String} rootElement
8949
9441
  *
8950
- * @return {Object|djs.model.Root} new root element
9442
+ * @return {Object|djs.model.Root} rootElement
8951
9443
  */
8952
- Canvas.prototype.setRootElement = function(element, override) {
8953
- var activePlane = this._activePlane;
9444
+ Canvas.prototype.removeRootElement = function(rootElement) {
8954
9445
 
8955
- if (activePlane) {
8956
- return this.setRootElementForPlane(element, activePlane, override);
8957
- } else {
8958
- var basePlane = this.createPlane(BASE_LAYER, element);
9446
+ if (typeof rootElement === 'string') {
9447
+ rootElement = this._elementRegistry.get(rootElement);
9448
+ }
9449
+
9450
+ var plane = this._findPlaneForRoot(rootElement);
9451
+
9452
+ if (!plane) {
9453
+ return;
9454
+ }
9455
+
9456
+ // hook up life-cycle events
9457
+ this._removeRoot(rootElement);
9458
+
9459
+ // clean up layer
9460
+ this._removeLayer(rootElement.layer);
8959
9461
 
8960
- this.setActivePlane(basePlane);
9462
+ // clean up plane
9463
+ this._planes = this._planes.filter(function(plane) {
9464
+ return plane.rootElement !== rootElement;
9465
+ });
8961
9466
 
8962
- return basePlane.rootElement;
9467
+ // clean up active root
9468
+ if (this._rootElement === rootElement) {
9469
+ this._rootElement = null;
8963
9470
  }
9471
+
9472
+ return rootElement;
8964
9473
  };
8965
9474
 
8966
9475
 
9476
+ // root element handling //////////////////////
9477
+
8967
9478
  /**
8968
9479
  * Sets a given element as the new root element for the canvas
8969
9480
  * and returns the new root element.
8970
9481
  *
8971
- * @param {Object|djs.model.Root} element
8972
- * @param {Object|djs.model.Root} plane
8973
- * @param {boolean} [override] whether to override the current root element, if any
9482
+ * @param {Object|djs.model.Root} rootElement
8974
9483
  *
8975
9484
  * @return {Object|djs.model.Root} new root element
8976
9485
  */
8977
- Canvas.prototype.setRootElementForPlane = function(element, plane, override) {
9486
+ Canvas.prototype.setRootElement = function(rootElement, override) {
8978
9487
 
8979
- if (typeof plane === 'string') {
8980
- plane = this.getPlane(plane);
9488
+ if (isDefined(override)) {
9489
+ throw new Error('override not supported');
8981
9490
  }
8982
9491
 
8983
- if (element) {
8984
- this._ensureValid('root', element);
9492
+ if (rootElement === this._rootElement) {
9493
+ return;
8985
9494
  }
8986
9495
 
8987
- var currentRoot = plane.rootElement,
8988
- elementRegistry = this._elementRegistry,
8989
- eventBus = this._eventBus;
9496
+ var plane;
8990
9497
 
8991
- if (currentRoot) {
8992
- if (!override) {
8993
- throw new Error('rootElement already set, need to specify override');
8994
- }
9498
+ if (!rootElement) {
9499
+ throw new Error('rootElement required');
9500
+ }
8995
9501
 
8996
- // simulate element remove event sequence
8997
- eventBus.fire('root.remove', { element: currentRoot });
8998
- eventBus.fire('root.removed', { element: currentRoot });
9502
+ plane = this._findPlaneForRoot(rootElement);
8999
9503
 
9000
- elementRegistry.remove(currentRoot);
9504
+ // give set add semantics for backwards compatibility
9505
+ if (!plane) {
9506
+ rootElement = this.addRootElement(rootElement);
9001
9507
  }
9002
9508
 
9003
- if (element) {
9004
- var gfx = plane.layer;
9509
+ this._setRoot(rootElement);
9510
+
9511
+ return rootElement;
9512
+ };
9005
9513
 
9006
- // resemble element add event sequence
9007
- eventBus.fire('root.add', { element: element });
9008
9514
 
9009
- elementRegistry.add(element, gfx);
9515
+ Canvas.prototype._removeRoot = function(element) {
9516
+ var elementRegistry = this._elementRegistry,
9517
+ eventBus = this._eventBus;
9518
+
9519
+ // simulate element remove event sequence
9520
+ eventBus.fire('root.remove', { element: element });
9521
+ eventBus.fire('root.removed', { element: element });
9522
+
9523
+ elementRegistry.remove(element);
9524
+ };
9525
+
9526
+
9527
+ Canvas.prototype._addRoot = function(element, gfx) {
9528
+ var elementRegistry = this._elementRegistry,
9529
+ eventBus = this._eventBus;
9530
+
9531
+ // resemble element add event sequence
9532
+ eventBus.fire('root.add', { element: element });
9533
+
9534
+ elementRegistry.add(element, gfx);
9535
+
9536
+ eventBus.fire('root.added', { element: element, gfx: gfx });
9537
+ };
9538
+
9539
+
9540
+ Canvas.prototype._setRoot = function(rootElement, layer) {
9010
9541
 
9011
- eventBus.fire('root.added', { element: element, gfx: gfx });
9542
+ var currentRoot = this._rootElement;
9012
9543
 
9013
- // associate SVG with root element when active
9014
- if (plane === this._activePlane) {
9015
- this._elementRegistry.updateGraphics(element, this._svg, true);
9544
+ var currentLayer;
9545
+
9546
+ if (currentRoot) {
9547
+
9548
+ // un-associate previous root element <svg>
9549
+ this._elementRegistry.updateGraphics(currentRoot, null, true);
9550
+
9551
+ // hide previous layer
9552
+ currentLayer = this._findPlaneForRoot(currentRoot).layer;
9553
+
9554
+ attr$1(currentLayer, 'display', 'none');
9555
+ }
9556
+
9557
+ if (rootElement) {
9558
+
9559
+ if (!layer) {
9560
+ layer = this._findPlaneForRoot(rootElement).layer;
9016
9561
  }
9562
+
9563
+ // associate element with <svg>
9564
+ this._elementRegistry.updateGraphics(rootElement, this._svg, true);
9565
+
9566
+ // show root layer
9567
+ attr$1(layer, 'display', null);
9017
9568
  }
9018
9569
 
9019
- plane.rootElement = element;
9570
+ this._rootElement = rootElement;
9020
9571
 
9021
- return element;
9572
+ this._eventBus.fire('root.set', { element: rootElement });
9022
9573
  };
9023
9574
 
9024
9575
  // add functionality //////////////////////
@@ -9029,7 +9580,7 @@
9029
9580
  }
9030
9581
 
9031
9582
  if (this._elementRegistry.get(element.id)) {
9032
- throw new Error('element with id ' + element.id + ' already exists');
9583
+ throw new Error('element <' + element.id + '> already exists');
9033
9584
  }
9034
9585
 
9035
9586
  var requiredAttrs = REQUIRED_MODEL_ATTRS[type];
@@ -9319,6 +9870,7 @@
9319
9870
  innerBox,
9320
9871
  outerBox = this.getSize(),
9321
9872
  matrix,
9873
+ activeLayer,
9322
9874
  transform,
9323
9875
  scale,
9324
9876
  x, y;
@@ -9326,10 +9878,11 @@
9326
9878
  if (!box) {
9327
9879
 
9328
9880
  // compute the inner box based on the
9329
- // diagrams active plane. This allows us to exclude
9881
+ // diagrams active layer. This allows us to exclude
9330
9882
  // external components, such as overlays
9331
9883
 
9332
- innerBox = (this._activePlane && this._activePlane.layer.getBBox()) || {};
9884
+ activeLayer = this._rootElement ? this.getActiveLayer() : null;
9885
+ innerBox = activeLayer && activeLayer.getBBox() || {};
9333
9886
 
9334
9887
  transform = transform$1(viewport);
9335
9888
  matrix = transform ? transform.matrix : createMatrix();
@@ -9412,10 +9965,11 @@
9412
9965
  element = this._elementRegistry.get(element);
9413
9966
  }
9414
9967
 
9415
- // switch to correct Plane
9416
- var targetPlane = this.findPlane(element);
9417
- if (targetPlane !== this._activePlane) {
9418
- this.setActivePlane(targetPlane);
9968
+ // set to correct rootElement
9969
+ var rootElement = this.findRoot(element);
9970
+
9971
+ if (rootElement !== this.getRootElement()) {
9972
+ this.setRootElement(rootElement);
9419
9973
  }
9420
9974
 
9421
9975
  if (!padding) {
@@ -9778,7 +10332,9 @@
9778
10332
  container.gfx = gfx;
9779
10333
  }
9780
10334
 
9781
- attr$1(gfx, ELEMENT_ID, id);
10335
+ if (gfx) {
10336
+ attr$1(gfx, ELEMENT_ID, id);
10337
+ }
9782
10338
 
9783
10339
  return gfx;
9784
10340
  };
@@ -19555,18 +20111,29 @@
19555
20111
 
19556
20112
  var walker = new BpmnTreeWalker(visitor, translate);
19557
20113
 
20114
+
20115
+ bpmnDiagram = bpmnDiagram || (definitions.diagrams && definitions.diagrams[0]);
20116
+
20117
+ var diagramsToImport = getDiagramsToImport(definitions, bpmnDiagram);
20118
+
20119
+ if (!diagramsToImport) {
20120
+ throw new Error(translate('no diagram to display'));
20121
+ }
20122
+
19558
20123
  // traverse BPMN 2.0 document model,
19559
20124
  // starting at definitions
19560
- if (!bpmnDiagram && definitions.diagrams) {
19561
- for (var i = 0; i < definitions.diagrams.length; i++) {
19562
- walker.handleDefinitions(definitions, definitions.diagrams[i]);
19563
- }
19564
- } else {
19565
- walker.handleDefinitions(definitions, bpmnDiagram);
19566
- }
20125
+ forEach(diagramsToImport, function(diagram) {
20126
+ walker.handleDefinitions(definitions, diagram);
20127
+ });
19567
20128
 
19568
- var mainDiagram = bpmnDiagram || definitions.diagrams[0];
19569
- canvas.setActivePlane(mainDiagram.plane.bpmnElement.id);
20129
+ var rootId = bpmnDiagram.plane.bpmnElement.id;
20130
+
20131
+ // we do need to account for different ways we create root elements
20132
+ // each nested imported <root> do have the `_plane` suffix, while
20133
+ // the root <root> is found under the business object ID
20134
+ canvas.setRootElement(
20135
+ canvas.findRoot(rootId + '_plane') || canvas.findRoot(rootId)
20136
+ );
19570
20137
  }
19571
20138
 
19572
20139
  return new Promise(function(resolve, reject) {
@@ -19594,6 +20161,107 @@
19594
20161
  });
19595
20162
  }
19596
20163
 
20164
+ /**
20165
+ * Returns all diagrams in the same hirarchy as the requested diagram.
20166
+ * Includes all parent and sub process diagrams.
20167
+ *
20168
+ * @param {Array} definitions
20169
+ * @param {Object} bpmnDiagram
20170
+ *
20171
+ * @returns {Array<Object>}
20172
+ */
20173
+ function getDiagramsToImport(definitions, bpmnDiagram) {
20174
+ if (!bpmnDiagram) {
20175
+ return;
20176
+ }
20177
+
20178
+ var bpmnElement = bpmnDiagram.plane.bpmnElement,
20179
+ rootElement = bpmnElement;
20180
+
20181
+ if (!is$1(bpmnElement, 'bpmn:Process') && !is$1(bpmnElement, 'bpmn:Collaboration')) {
20182
+ rootElement = findRootProcess(bpmnElement);
20183
+ }
20184
+
20185
+ // in case the process is part of a collaboration, the plane references the
20186
+ // collaboration, not the process
20187
+ var collaboration;
20188
+
20189
+ if (is$1(rootElement, 'bpmn:Collaboration')) {
20190
+ collaboration = rootElement;
20191
+ } else {
20192
+ collaboration = find(definitions.rootElements, function(element) {
20193
+ if (!is$1(element, 'bpmn:Collaboration')) {
20194
+ return;
20195
+ }
20196
+
20197
+ return find(element.participants, function(participant) {
20198
+ return participant.processRef === rootElement;
20199
+ });
20200
+ });
20201
+ }
20202
+
20203
+ var rootElements = [ rootElement ];
20204
+
20205
+ // all collaboration processes can contain sub-diagrams
20206
+ if (collaboration) {
20207
+ rootElements = map$1(collaboration.participants, function(participant) {
20208
+ return participant.processRef;
20209
+ });
20210
+
20211
+ rootElements.push(collaboration);
20212
+ }
20213
+
20214
+ var allChildren = selfAndAllFlowElements(rootElements);
20215
+
20216
+ // if we have multiple diagrams referencing the same element, we
20217
+ // use the first in the file
20218
+ var diagramsToImport = [ bpmnDiagram ];
20219
+ var handledElements = [ bpmnElement ];
20220
+
20221
+ forEach(definitions.diagrams, function(diagram) {
20222
+ var businessObject = diagram.plane.bpmnElement;
20223
+
20224
+ if (
20225
+ allChildren.indexOf(businessObject) !== -1 &&
20226
+ handledElements.indexOf(businessObject) === -1
20227
+ ) {
20228
+ diagramsToImport.push(diagram);
20229
+ handledElements.push(businessObject);
20230
+ }
20231
+ });
20232
+
20233
+
20234
+ return diagramsToImport;
20235
+ }
20236
+
20237
+ function selfAndAllFlowElements(elements) {
20238
+ var result = [];
20239
+
20240
+ forEach(elements, function(element) {
20241
+ if (!element) {
20242
+ return;
20243
+ }
20244
+
20245
+ result.push(element);
20246
+
20247
+ result = result.concat(selfAndAllFlowElements(element.flowElements));
20248
+ });
20249
+
20250
+ return result;
20251
+ }
20252
+
20253
+ function findRootProcess(element) {
20254
+ var parent = element;
20255
+
20256
+ while (parent) {
20257
+ if (is$1(parent, 'bpmn:Process')) {
20258
+ return parent;
20259
+ }
20260
+
20261
+ parent = parent.$parent;
20262
+ }
20263
+ }
20264
+
19597
20265
  /**
19598
20266
  * This file must not be changed or exchanged.
19599
20267
  *
@@ -20084,7 +20752,7 @@
20084
20752
  try {
20085
20753
  var canvas = self.get('canvas');
20086
20754
 
20087
- var contentNode = canvas.getDefaultLayer(),
20755
+ var contentNode = canvas.getActiveLayer(),
20088
20756
  defsNode = query('defs', canvas._svg);
20089
20757
 
20090
20758
  var contents = innerSVG(contentNode),