UNPKG

560 kBJavaScriptView Raw
1/*!
2 * bpmn-js - bpmn-viewer v17.3.0
3 *
4 * Copyright (c) 2014-present, camunda Services GmbH
5 *
6 * Released under the bpmn.io license
7 * http://bpmn.io/license
8 *
9 * Source Code: https://github.com/bpmn-io/bpmn-js
10 *
11 * Date: 2024-04-17
12 */
13(function (global, factory) {
14 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
15 typeof define === 'function' && define.amd ? define(factory) :
16 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.BpmnJS = factory());
17})(this, (function () { 'use strict';
18
19 function e(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}));}
20
21 /**
22 * Flatten array, one level deep.
23 *
24 * @template T
25 *
26 * @param {T[][]} arr
27 *
28 * @return {T[]}
29 */
30
31 const nativeToString$1 = Object.prototype.toString;
32 const nativeHasOwnProperty$1 = Object.prototype.hasOwnProperty;
33
34 function isUndefined$2(obj) {
35 return obj === undefined;
36 }
37
38 function isDefined(obj) {
39 return obj !== undefined;
40 }
41
42 function isNil(obj) {
43 return obj == null;
44 }
45
46 function isArray$2(obj) {
47 return nativeToString$1.call(obj) === '[object Array]';
48 }
49
50 function isObject(obj) {
51 return nativeToString$1.call(obj) === '[object Object]';
52 }
53
54 function isNumber(obj) {
55 return nativeToString$1.call(obj) === '[object Number]';
56 }
57
58 /**
59 * @param {any} obj
60 *
61 * @return {boolean}
62 */
63 function isFunction(obj) {
64 const tag = nativeToString$1.call(obj);
65
66 return (
67 tag === '[object Function]' ||
68 tag === '[object AsyncFunction]' ||
69 tag === '[object GeneratorFunction]' ||
70 tag === '[object AsyncGeneratorFunction]' ||
71 tag === '[object Proxy]'
72 );
73 }
74
75 function isString(obj) {
76 return nativeToString$1.call(obj) === '[object String]';
77 }
78
79 /**
80 * Return true, if target owns a property with the given key.
81 *
82 * @param {Object} target
83 * @param {String} key
84 *
85 * @return {Boolean}
86 */
87 function has$1(target, key) {
88 return nativeHasOwnProperty$1.call(target, key);
89 }
90
91 /**
92 * @template T
93 * @typedef { (
94 * ((e: T) => boolean) |
95 * ((e: T, idx: number) => boolean) |
96 * ((e: T, key: string) => boolean) |
97 * string |
98 * number
99 * ) } Matcher
100 */
101
102 /**
103 * @template T
104 * @template U
105 *
106 * @typedef { (
107 * ((e: T) => U) | string | number
108 * ) } Extractor
109 */
110
111
112 /**
113 * @template T
114 * @typedef { (val: T, key: any) => boolean } MatchFn
115 */
116
117 /**
118 * @template T
119 * @typedef { T[] } ArrayCollection
120 */
121
122 /**
123 * @template T
124 * @typedef { { [key: string]: T } } StringKeyValueCollection
125 */
126
127 /**
128 * @template T
129 * @typedef { { [key: number]: T } } NumberKeyValueCollection
130 */
131
132 /**
133 * @template T
134 * @typedef { StringKeyValueCollection<T> | NumberKeyValueCollection<T> } KeyValueCollection
135 */
136
137 /**
138 * @template T
139 * @typedef { KeyValueCollection<T> | ArrayCollection<T> } Collection
140 */
141
142 /**
143 * Find element in collection.
144 *
145 * @template T
146 * @param {Collection<T>} collection
147 * @param {Matcher<T>} matcher
148 *
149 * @return {Object}
150 */
151 function find(collection, matcher) {
152
153 const matchFn = toMatcher(matcher);
154
155 let match;
156
157 forEach$1(collection, function(val, key) {
158 if (matchFn(val, key)) {
159 match = val;
160
161 return false;
162 }
163 });
164
165 return match;
166
167 }
168
169
170 /**
171 * Find element index in collection.
172 *
173 * @template T
174 * @param {Collection<T>} collection
175 * @param {Matcher<T>} matcher
176 *
177 * @return {number}
178 */
179 function findIndex(collection, matcher) {
180
181 const matchFn = toMatcher(matcher);
182
183 let idx = isArray$2(collection) ? -1 : undefined;
184
185 forEach$1(collection, function(val, key) {
186 if (matchFn(val, key)) {
187 idx = key;
188
189 return false;
190 }
191 });
192
193 return idx;
194 }
195
196
197 /**
198 * Filter elements in collection.
199 *
200 * @template T
201 * @param {Collection<T>} collection
202 * @param {Matcher<T>} matcher
203 *
204 * @return {T[]} result
205 */
206 function filter(collection, matcher) {
207
208 const matchFn = toMatcher(matcher);
209
210 let result = [];
211
212 forEach$1(collection, function(val, key) {
213 if (matchFn(val, key)) {
214 result.push(val);
215 }
216 });
217
218 return result;
219 }
220
221
222 /**
223 * Iterate over collection; returning something
224 * (non-undefined) will stop iteration.
225 *
226 * @template T
227 * @param {Collection<T>} collection
228 * @param { ((item: T, idx: number) => (boolean|void)) | ((item: T, key: string) => (boolean|void)) } iterator
229 *
230 * @return {T} return result that stopped the iteration
231 */
232 function forEach$1(collection, iterator) {
233
234 let val,
235 result;
236
237 if (isUndefined$2(collection)) {
238 return;
239 }
240
241 const convertKey = isArray$2(collection) ? toNum$1 : identity$1;
242
243 for (let key in collection) {
244
245 if (has$1(collection, key)) {
246 val = collection[key];
247
248 result = iterator(val, convertKey(key));
249
250 if (result === false) {
251 return val;
252 }
253 }
254 }
255 }
256
257
258 /**
259 * Reduce collection, returning a single result.
260 *
261 * @template T
262 * @template V
263 *
264 * @param {Collection<T>} collection
265 * @param {(result: V, entry: T, index: any) => V} iterator
266 * @param {V} result
267 *
268 * @return {V} result returned from last iterator
269 */
270 function reduce(collection, iterator, result) {
271
272 forEach$1(collection, function(value, idx) {
273 result = iterator(result, value, idx);
274 });
275
276 return result;
277 }
278
279
280 /**
281 * Return true if every element in the collection
282 * matches the criteria.
283 *
284 * @param {Object|Array} collection
285 * @param {Function} matcher
286 *
287 * @return {Boolean}
288 */
289 function every(collection, matcher) {
290
291 return !!reduce(collection, function(matches, val, key) {
292 return matches && matcher(val, key);
293 }, true);
294 }
295
296
297 /**
298 * Return true if some elements in the collection
299 * match the criteria.
300 *
301 * @param {Object|Array} collection
302 * @param {Function} matcher
303 *
304 * @return {Boolean}
305 */
306 function some(collection, matcher) {
307
308 return !!find(collection, matcher);
309 }
310
311
312 /**
313 * Transform a collection into another collection
314 * by piping each member through the given fn.
315 *
316 * @param {Object|Array} collection
317 * @param {Function} fn
318 *
319 * @return {Array} transformed collection
320 */
321 function map$1(collection, fn) {
322
323 let result = [];
324
325 forEach$1(collection, function(val, key) {
326 result.push(fn(val, key));
327 });
328
329 return result;
330 }
331
332
333 /**
334 * Create an object pattern matcher.
335 *
336 * @example
337 *
338 * ```javascript
339 * const matcher = matchPattern({ id: 1 });
340 *
341 * let element = find(elements, matcher);
342 * ```
343 *
344 * @template T
345 *
346 * @param {T} pattern
347 *
348 * @return { (el: any) => boolean } matcherFn
349 */
350 function matchPattern(pattern) {
351
352 return function(el) {
353
354 return every(pattern, function(val, key) {
355 return el[key] === val;
356 });
357
358 };
359 }
360
361
362 /**
363 * @template T
364 * @param {Matcher<T>} matcher
365 *
366 * @return {MatchFn<T>}
367 */
368 function toMatcher(matcher) {
369 return isFunction(matcher) ? matcher : (e) => {
370 return e === matcher;
371 };
372 }
373
374
375 function identity$1(arg) {
376 return arg;
377 }
378
379 function toNum$1(arg) {
380 return Number(arg);
381 }
382
383 /* global setTimeout clearTimeout */
384
385 /**
386 * @typedef { {
387 * (...args: any[]): any;
388 * flush: () => void;
389 * cancel: () => void;
390 * } } DebouncedFunction
391 */
392
393 /**
394 * Debounce fn, calling it only once if the given time
395 * elapsed between calls.
396 *
397 * Lodash-style the function exposes methods to `#clear`
398 * and `#flush` to control internal behavior.
399 *
400 * @param {Function} fn
401 * @param {Number} timeout
402 *
403 * @return {DebouncedFunction} debounced function
404 */
405 function debounce(fn, timeout) {
406
407 let timer;
408
409 let lastArgs;
410 let lastThis;
411
412 let lastNow;
413
414 function fire(force) {
415
416 let now = Date.now();
417
418 let scheduledDiff = force ? 0 : (lastNow + timeout) - now;
419
420 if (scheduledDiff > 0) {
421 return schedule(scheduledDiff);
422 }
423
424 fn.apply(lastThis, lastArgs);
425
426 clear();
427 }
428
429 function schedule(timeout) {
430 timer = setTimeout(fire, timeout);
431 }
432
433 function clear() {
434 if (timer) {
435 clearTimeout(timer);
436 }
437
438 timer = lastNow = lastArgs = lastThis = undefined;
439 }
440
441 function flush() {
442 if (timer) {
443 fire(true);
444 }
445
446 clear();
447 }
448
449 /**
450 * @type { DebouncedFunction }
451 */
452 function callback(...args) {
453 lastNow = Date.now();
454
455 lastArgs = args;
456 lastThis = this;
457
458 // ensure an execution is scheduled
459 if (!timer) {
460 schedule(timeout);
461 }
462 }
463
464 callback.flush = flush;
465 callback.cancel = clear;
466
467 return callback;
468 }
469
470 /**
471 * Bind function against target <this>.
472 *
473 * @param {Function} fn
474 * @param {Object} target
475 *
476 * @return {Function} bound function
477 */
478 function bind$2(fn, target) {
479 return fn.bind(target);
480 }
481
482 /**
483 * Convenience wrapper for `Object.assign`.
484 *
485 * @param {Object} target
486 * @param {...Object} others
487 *
488 * @return {Object} the target
489 */
490 function assign$1(target, ...others) {
491 return Object.assign(target, ...others);
492 }
493
494 /**
495 * Sets a nested property of a given object to the specified value.
496 *
497 * This mutates the object and returns it.
498 *
499 * @template T
500 *
501 * @param {T} target The target of the set operation.
502 * @param {(string|number)[]} path The path to the nested value.
503 * @param {any} value The value to set.
504 *
505 * @return {T}
506 */
507 function set$1(target, path, value) {
508
509 let currentTarget = target;
510
511 forEach$1(path, function(key, idx) {
512
513 if (typeof key !== 'number' && typeof key !== 'string') {
514 throw new Error('illegal key type: ' + typeof key + '. Key should be of type number or string.');
515 }
516
517 if (key === 'constructor') {
518 throw new Error('illegal key: constructor');
519 }
520
521 if (key === '__proto__') {
522 throw new Error('illegal key: __proto__');
523 }
524
525 let nextKey = path[idx + 1];
526 let nextTarget = currentTarget[key];
527
528 if (isDefined(nextKey) && isNil(nextTarget)) {
529 nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : [];
530 }
531
532 if (isUndefined$2(nextKey)) {
533 if (isUndefined$2(value)) {
534 delete currentTarget[key];
535 } else {
536 currentTarget[key] = value;
537 }
538 } else {
539 currentTarget = nextTarget;
540 }
541 });
542
543 return target;
544 }
545
546 /**
547 * Pick properties from the given target.
548 *
549 * @template T
550 * @template {any[]} V
551 *
552 * @param {T} target
553 * @param {V} properties
554 *
555 * @return Pick<T, V>
556 */
557 function pick(target, properties) {
558
559 let result = {};
560
561 let obj = Object(target);
562
563 forEach$1(properties, function(prop) {
564
565 if (prop in obj) {
566 result[prop] = target[prop];
567 }
568 });
569
570 return result;
571 }
572
573 /**
574 * Pick all target properties, excluding the given ones.
575 *
576 * @template T
577 * @template {any[]} V
578 *
579 * @param {T} target
580 * @param {V} properties
581 *
582 * @return {Omit<T, V>} target
583 */
584 function omit(target, properties) {
585
586 let result = {};
587
588 let obj = Object(target);
589
590 forEach$1(obj, function(prop, key) {
591
592 if (properties.indexOf(key) === -1) {
593 result[key] = prop;
594 }
595 });
596
597 return result;
598 }
599
600 var DEFAULT_RENDER_PRIORITY$1 = 1000;
601
602 /**
603 * @typedef {import('../core/Types').ElementLike} Element
604 * @typedef {import('../core/Types').ConnectionLike} Connection
605 * @typedef {import('../core/Types').ShapeLike} Shape
606 *
607 * @typedef {import('../core/EventBus').default} EventBus
608 */
609
610 /**
611 * The base implementation of shape and connection renderers.
612 *
613 * @param {EventBus} eventBus
614 * @param {number} [renderPriority=1000]
615 */
616 function BaseRenderer(eventBus, renderPriority) {
617 var self = this;
618
619 renderPriority = renderPriority || DEFAULT_RENDER_PRIORITY$1;
620
621 eventBus.on([ 'render.shape', 'render.connection' ], renderPriority, function(evt, context) {
622 var type = evt.type,
623 element = context.element,
624 visuals = context.gfx,
625 attrs = context.attrs;
626
627 if (self.canRender(element)) {
628 if (type === 'render.shape') {
629 return self.drawShape(visuals, element, attrs);
630 } else {
631 return self.drawConnection(visuals, element, attrs);
632 }
633 }
634 });
635
636 eventBus.on([ 'render.getShapePath', 'render.getConnectionPath' ], renderPriority, function(evt, element) {
637 if (self.canRender(element)) {
638 if (evt.type === 'render.getShapePath') {
639 return self.getShapePath(element);
640 } else {
641 return self.getConnectionPath(element);
642 }
643 }
644 });
645 }
646
647 /**
648 * Checks whether an element can be rendered.
649 *
650 * @param {Element} element The element to be rendered.
651 *
652 * @return {boolean} Whether the element can be rendered.
653 */
654 BaseRenderer.prototype.canRender = function(element) {};
655
656 /**
657 * Draws a shape.
658 *
659 * @param {SVGElement} visuals The SVG element to draw the shape into.
660 * @param {Shape} shape The shape to be drawn.
661 *
662 * @return {SVGElement} The SVG element of the shape drawn.
663 */
664 BaseRenderer.prototype.drawShape = function(visuals, shape) {};
665
666 /**
667 * Draws a connection.
668 *
669 * @param {SVGElement} visuals The SVG element to draw the connection into.
670 * @param {Connection} connection The connection to be drawn.
671 *
672 * @return {SVGElement} The SVG element of the connection drawn.
673 */
674 BaseRenderer.prototype.drawConnection = function(visuals, connection) {};
675
676 /**
677 * Gets the SVG path of the graphical representation of a shape.
678 *
679 * @param {Shape} shape The shape.
680 *
681 * @return {string} The SVG path of the shape.
682 */
683 BaseRenderer.prototype.getShapePath = function(shape) {};
684
685 /**
686 * Gets the SVG path of the graphical representation of a connection.
687 *
688 * @param {Connection} connection The connection.
689 *
690 * @return {string} The SVG path of the connection.
691 */
692 BaseRenderer.prototype.getConnectionPath = function(connection) {};
693
694 /**
695 * @typedef { import('../model/Types').Element } Element
696 * @typedef { import('../model/Types').ModdleElement } ModdleElement
697 */
698
699 /**
700 * Is an element of the given BPMN type?
701 *
702 * @param {Element|ModdleElement} element
703 * @param {string} type
704 *
705 * @return {boolean}
706 */
707 function is$1(element, type) {
708 var bo = getBusinessObject(element);
709
710 return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
711 }
712
713
714 /**
715 * Return true if element has any of the given types.
716 *
717 * @param {Element|ModdleElement} element
718 * @param {string[]} types
719 *
720 * @return {boolean}
721 */
722 function isAny(element, types) {
723 return some(types, function(t) {
724 return is$1(element, t);
725 });
726 }
727
728 /**
729 * Return the business object for a given element.
730 *
731 * @param {Element|ModdleElement} element
732 *
733 * @return {ModdleElement}
734 */
735 function getBusinessObject(element) {
736 return (element && element.businessObject) || element;
737 }
738
739 /**
740 * Return the di object for a given element.
741 *
742 * @param {Element} element
743 *
744 * @return {ModdleElement}
745 */
746 function getDi(element) {
747 return element && element.di;
748 }
749
750 /**
751 * @typedef {import('../model/Types').Element} Element
752 * @typedef {import('../model/Types').ModdleElement} ModdleElement
753 */
754
755 /**
756 * @param {Element} element
757 * @param {ModdleElement} [di]
758 *
759 * @return {boolean}
760 */
761 function isExpanded(element, di) {
762
763 if (is$1(element, 'bpmn:CallActivity')) {
764 return false;
765 }
766
767 if (is$1(element, 'bpmn:SubProcess')) {
768 di = di || getDi(element);
769
770 if (di && is$1(di, 'bpmndi:BPMNPlane')) {
771 return true;
772 }
773
774 return di && !!di.isExpanded;
775 }
776
777 if (is$1(element, 'bpmn:Participant')) {
778 return !!getBusinessObject(element).processRef;
779 }
780
781 return true;
782 }
783
784 /**
785 * @param {Element} element
786 *
787 * @return {boolean}
788 */
789 function isHorizontal(element) {
790
791 if (!is$1(element, 'bpmn:Participant') && !is$1(element, 'bpmn:Lane')) {
792 return undefined;
793 }
794
795 var isHorizontal = getDi(element).isHorizontal;
796
797 if (isHorizontal === undefined) {
798 return true;
799 }
800
801 return isHorizontal;
802 }
803
804 /**
805 * @param {Element} element
806 *
807 * @return {boolean}
808 */
809 function isEventSubProcess(element) {
810 return element && !!getBusinessObject(element).triggeredByEvent;
811 }
812
813 /**
814 * Checks whether a value is an instance of Connection.
815 *
816 * @param {any} value
817 *
818 * @return {boolean}
819 */
820 function isConnection(value) {
821 return isObject(value) && has$1(value, 'waypoints');
822 }
823
824 /**
825 * Checks whether a value is an instance of Label.
826 *
827 * @param {any} value
828 *
829 * @return {boolean}
830 */
831 function isLabel(value) {
832 return isObject(value) && has$1(value, 'labelTarget');
833 }
834
835 /**
836 * @typedef {import('diagram-js/lib/util/Types').Point} Point
837 * @typedef {import('diagram-js/lib/util/Types').Rect} Rect
838 *
839 * @typedef {import('../model/Types').Element} Element
840 * @typedef {import('../model/Types').ModdleElement} ModdleElement
841 */
842
843 var DEFAULT_LABEL_SIZE$1 = {
844 width: 90,
845 height: 20
846 };
847
848 var FLOW_LABEL_INDENT = 15;
849
850
851 /**
852 * Return true if the given semantic has an external label.
853 *
854 * @param {Element} semantic
855 *
856 * @return {boolean}
857 */
858 function isLabelExternal(semantic) {
859 return is$1(semantic, 'bpmn:Event') ||
860 is$1(semantic, 'bpmn:Gateway') ||
861 is$1(semantic, 'bpmn:DataStoreReference') ||
862 is$1(semantic, 'bpmn:DataObjectReference') ||
863 is$1(semantic, 'bpmn:DataInput') ||
864 is$1(semantic, 'bpmn:DataOutput') ||
865 is$1(semantic, 'bpmn:SequenceFlow') ||
866 is$1(semantic, 'bpmn:MessageFlow') ||
867 is$1(semantic, 'bpmn:Group');
868 }
869
870 /**
871 * Get the position of a sequence flow label.
872 *
873 * @param {Point[]} waypoints
874 *
875 * @return {Point}
876 */
877 function getFlowLabelPosition(waypoints) {
878
879 // get the waypoints mid
880 var mid = waypoints.length / 2 - 1;
881
882 var first = waypoints[Math.floor(mid)];
883 var second = waypoints[Math.ceil(mid + 0.01)];
884
885 // get position
886 var position = getWaypointsMid(waypoints);
887
888 // calculate angle
889 var angle = Math.atan((second.y - first.y) / (second.x - first.x));
890
891 var x = position.x,
892 y = position.y;
893
894 if (Math.abs(angle) < Math.PI / 2) {
895 y -= FLOW_LABEL_INDENT;
896 } else {
897 x += FLOW_LABEL_INDENT;
898 }
899
900 return { x: x, y: y };
901 }
902
903
904 /**
905 * Get the middle of a number of waypoints.
906 *
907 * @param {Point[]} waypoints
908 *
909 * @return {Point}
910 */
911 function getWaypointsMid(waypoints) {
912
913 var mid = waypoints.length / 2 - 1;
914
915 var first = waypoints[Math.floor(mid)];
916 var second = waypoints[Math.ceil(mid + 0.01)];
917
918 return {
919 x: first.x + (second.x - first.x) / 2,
920 y: first.y + (second.y - first.y) / 2
921 };
922 }
923
924 /**
925 * Get the middle of the external label of an element.
926 *
927 * @param {Element} element
928 *
929 * @return {Point}
930 */
931 function getExternalLabelMid(element) {
932
933 if (element.waypoints) {
934 return getFlowLabelPosition(element.waypoints);
935 } else if (is$1(element, 'bpmn:Group')) {
936 return {
937 x: element.x + element.width / 2,
938 y: element.y + DEFAULT_LABEL_SIZE$1.height / 2
939 };
940 } else {
941 return {
942 x: element.x + element.width / 2,
943 y: element.y + element.height + DEFAULT_LABEL_SIZE$1.height / 2
944 };
945 }
946 }
947
948
949 /**
950 * Return the bounds of an elements label, parsed from the elements DI or
951 * generated from its bounds.
952 *
953 * @param {ModdleElement} di
954 * @param {Element} element
955 *
956 * @return {Rect}
957 */
958 function getExternalLabelBounds(di, element) {
959
960 var mid,
961 size,
962 bounds,
963 label = di.label;
964
965 if (label && label.bounds) {
966 bounds = label.bounds;
967
968 size = {
969 width: Math.max(DEFAULT_LABEL_SIZE$1.width, bounds.width),
970 height: bounds.height
971 };
972
973 mid = {
974 x: bounds.x + bounds.width / 2,
975 y: bounds.y + bounds.height / 2
976 };
977 } else {
978
979 mid = getExternalLabelMid(element);
980
981 size = DEFAULT_LABEL_SIZE$1;
982 }
983
984 return assign$1({
985 x: mid.x - size.width / 2,
986 y: mid.y - size.height / 2
987 }, size);
988 }
989
990 /**
991 * @param {ModdleElement} semantic
992 *
993 * @returns {string}
994 */
995 function getLabelAttr(semantic) {
996 if (
997 is$1(semantic, 'bpmn:FlowElement') ||
998 is$1(semantic, 'bpmn:Participant') ||
999 is$1(semantic, 'bpmn:Lane') ||
1000 is$1(semantic, 'bpmn:SequenceFlow') ||
1001 is$1(semantic, 'bpmn:MessageFlow') ||
1002 is$1(semantic, 'bpmn:DataInput') ||
1003 is$1(semantic, 'bpmn:DataOutput')
1004 ) {
1005 return 'name';
1006 }
1007
1008 if (is$1(semantic, 'bpmn:TextAnnotation')) {
1009 return 'text';
1010 }
1011
1012 if (is$1(semantic, 'bpmn:Group')) {
1013 return 'categoryValueRef';
1014 }
1015 }
1016
1017 /**
1018 * @param {ModdleElement} semantic
1019 *
1020 * @returns {string}
1021 */
1022 function getCategoryValue(semantic) {
1023 var categoryValueRef = semantic['categoryValueRef'];
1024
1025 if (!categoryValueRef) {
1026 return '';
1027 }
1028
1029
1030 return categoryValueRef.value || '';
1031 }
1032
1033 /**
1034 * @param {Element} element
1035 *
1036 * @return {string}
1037 */
1038 function getLabel(element) {
1039 var semantic = element.businessObject,
1040 attr = getLabelAttr(semantic);
1041
1042 if (attr) {
1043
1044 if (attr === 'categoryValueRef') {
1045
1046 return getCategoryValue(semantic);
1047 }
1048
1049 return semantic[attr] || '';
1050 }
1051 }
1052
1053 function ensureImported(element, target) {
1054
1055 if (element.ownerDocument !== target.ownerDocument) {
1056 try {
1057
1058 // may fail on webkit
1059 return target.ownerDocument.importNode(element, true);
1060 } catch (e) {
1061
1062 // ignore
1063 }
1064 }
1065
1066 return element;
1067 }
1068
1069 /**
1070 * appendTo utility
1071 */
1072
1073 /**
1074 * Append a node to a target element and return the appended node.
1075 *
1076 * @param {SVGElement} element
1077 * @param {SVGElement} target
1078 *
1079 * @return {SVGElement} the appended node
1080 */
1081 function appendTo(element, target) {
1082 return target.appendChild(ensureImported(element, target));
1083 }
1084
1085 /**
1086 * append utility
1087 */
1088
1089 /**
1090 * Append a node to an element
1091 *
1092 * @param {SVGElement} element
1093 * @param {SVGElement} node
1094 *
1095 * @return {SVGElement} the element
1096 */
1097 function append(target, node) {
1098 appendTo(node, target);
1099 return target;
1100 }
1101
1102 /**
1103 * attribute accessor utility
1104 */
1105
1106 var LENGTH_ATTR = 2;
1107
1108 var CSS_PROPERTIES = {
1109 'alignment-baseline': 1,
1110 'baseline-shift': 1,
1111 'clip': 1,
1112 'clip-path': 1,
1113 'clip-rule': 1,
1114 'color': 1,
1115 'color-interpolation': 1,
1116 'color-interpolation-filters': 1,
1117 'color-profile': 1,
1118 'color-rendering': 1,
1119 'cursor': 1,
1120 'direction': 1,
1121 'display': 1,
1122 'dominant-baseline': 1,
1123 'enable-background': 1,
1124 'fill': 1,
1125 'fill-opacity': 1,
1126 'fill-rule': 1,
1127 'filter': 1,
1128 'flood-color': 1,
1129 'flood-opacity': 1,
1130 'font': 1,
1131 'font-family': 1,
1132 'font-size': LENGTH_ATTR,
1133 'font-size-adjust': 1,
1134 'font-stretch': 1,
1135 'font-style': 1,
1136 'font-variant': 1,
1137 'font-weight': 1,
1138 'glyph-orientation-horizontal': 1,
1139 'glyph-orientation-vertical': 1,
1140 'image-rendering': 1,
1141 'kerning': 1,
1142 'letter-spacing': 1,
1143 'lighting-color': 1,
1144 'marker': 1,
1145 'marker-end': 1,
1146 'marker-mid': 1,
1147 'marker-start': 1,
1148 'mask': 1,
1149 'opacity': 1,
1150 'overflow': 1,
1151 'pointer-events': 1,
1152 'shape-rendering': 1,
1153 'stop-color': 1,
1154 'stop-opacity': 1,
1155 'stroke': 1,
1156 'stroke-dasharray': 1,
1157 'stroke-dashoffset': 1,
1158 'stroke-linecap': 1,
1159 'stroke-linejoin': 1,
1160 'stroke-miterlimit': 1,
1161 'stroke-opacity': 1,
1162 'stroke-width': LENGTH_ATTR,
1163 'text-anchor': 1,
1164 'text-decoration': 1,
1165 'text-rendering': 1,
1166 'unicode-bidi': 1,
1167 'visibility': 1,
1168 'word-spacing': 1,
1169 'writing-mode': 1
1170 };
1171
1172
1173 function getAttribute(node, name) {
1174 if (CSS_PROPERTIES[name]) {
1175 return node.style[name];
1176 } else {
1177 return node.getAttributeNS(null, name);
1178 }
1179 }
1180
1181 function setAttribute(node, name, value) {
1182 var hyphenated = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1183
1184 var type = CSS_PROPERTIES[hyphenated];
1185
1186 if (type) {
1187
1188 // append pixel unit, unless present
1189 if (type === LENGTH_ATTR && typeof value === 'number') {
1190 value = String(value) + 'px';
1191 }
1192
1193 node.style[hyphenated] = value;
1194 } else {
1195 node.setAttributeNS(null, name, value);
1196 }
1197 }
1198
1199 function setAttributes(node, attrs) {
1200
1201 var names = Object.keys(attrs), i, name;
1202
1203 for (i = 0, name; (name = names[i]); i++) {
1204 setAttribute(node, name, attrs[name]);
1205 }
1206 }
1207
1208 /**
1209 * Gets or sets raw attributes on a node.
1210 *
1211 * @param {SVGElement} node
1212 * @param {Object} [attrs]
1213 * @param {String} [name]
1214 * @param {String} [value]
1215 *
1216 * @return {String}
1217 */
1218 function attr$1(node, name, value) {
1219 if (typeof name === 'string') {
1220 if (value !== undefined) {
1221 setAttribute(node, name, value);
1222 } else {
1223 return getAttribute(node, name);
1224 }
1225 } else {
1226 setAttributes(node, name);
1227 }
1228
1229 return node;
1230 }
1231
1232 /**
1233 * Taken from https://github.com/component/classes
1234 *
1235 * Without the component bits.
1236 */
1237
1238 /**
1239 * toString reference.
1240 */
1241
1242 const toString$1 = Object.prototype.toString;
1243
1244 /**
1245 * Wrap `el` in a `ClassList`.
1246 *
1247 * @param {Element} el
1248 * @return {ClassList}
1249 * @api public
1250 */
1251
1252 function classes$1(el) {
1253 return new ClassList$1(el);
1254 }
1255
1256 function ClassList$1(el) {
1257 if (!el || !el.nodeType) {
1258 throw new Error('A DOM element reference is required');
1259 }
1260 this.el = el;
1261 this.list = el.classList;
1262 }
1263
1264 /**
1265 * Add class `name` if not already present.
1266 *
1267 * @param {String} name
1268 * @return {ClassList}
1269 * @api public
1270 */
1271
1272 ClassList$1.prototype.add = function(name) {
1273 this.list.add(name);
1274 return this;
1275 };
1276
1277 /**
1278 * Remove class `name` when present, or
1279 * pass a regular expression to remove
1280 * any which match.
1281 *
1282 * @param {String|RegExp} name
1283 * @return {ClassList}
1284 * @api public
1285 */
1286
1287 ClassList$1.prototype.remove = function(name) {
1288 if ('[object RegExp]' == toString$1.call(name)) {
1289 return this.removeMatching(name);
1290 }
1291
1292 this.list.remove(name);
1293 return this;
1294 };
1295
1296 /**
1297 * Remove all classes matching `re`.
1298 *
1299 * @param {RegExp} re
1300 * @return {ClassList}
1301 * @api private
1302 */
1303
1304 ClassList$1.prototype.removeMatching = function(re) {
1305 const arr = this.array();
1306 for (let i = 0; i < arr.length; i++) {
1307 if (re.test(arr[i])) {
1308 this.remove(arr[i]);
1309 }
1310 }
1311 return this;
1312 };
1313
1314 /**
1315 * Toggle class `name`, can force state via `force`.
1316 *
1317 * For browsers that support classList, but do not support `force` yet,
1318 * the mistake will be detected and corrected.
1319 *
1320 * @param {String} name
1321 * @param {Boolean} force
1322 * @return {ClassList}
1323 * @api public
1324 */
1325
1326 ClassList$1.prototype.toggle = function(name, force) {
1327 if ('undefined' !== typeof force) {
1328 if (force !== this.list.toggle(name, force)) {
1329 this.list.toggle(name); // toggle again to correct
1330 }
1331 } else {
1332 this.list.toggle(name);
1333 }
1334 return this;
1335 };
1336
1337 /**
1338 * Return an array of classes.
1339 *
1340 * @return {Array}
1341 * @api public
1342 */
1343
1344 ClassList$1.prototype.array = function() {
1345 return Array.from(this.list);
1346 };
1347
1348 /**
1349 * Check if class `name` is present.
1350 *
1351 * @param {String} name
1352 * @return {ClassList}
1353 * @api public
1354 */
1355
1356 ClassList$1.prototype.has =
1357 ClassList$1.prototype.contains = function(name) {
1358 return this.list.contains(name);
1359 };
1360
1361 function remove$2(element) {
1362 var parent = element.parentNode;
1363
1364 if (parent) {
1365 parent.removeChild(element);
1366 }
1367
1368 return element;
1369 }
1370
1371 /**
1372 * Clear utility
1373 */
1374
1375 /**
1376 * Removes all children from the given element
1377 *
1378 * @param {DOMElement} element
1379 * @return {DOMElement} the element (for chaining)
1380 */
1381 function clear$1(element) {
1382 var child;
1383
1384 while ((child = element.firstChild)) {
1385 remove$2(child);
1386 }
1387
1388 return element;
1389 }
1390
1391 var ns = {
1392 svg: 'http://www.w3.org/2000/svg'
1393 };
1394
1395 /**
1396 * DOM parsing utility
1397 */
1398
1399 var SVG_START = '<svg xmlns="' + ns.svg + '"';
1400
1401 function parse$1(svg) {
1402
1403 var unwrap = false;
1404
1405 // ensure we import a valid svg document
1406 if (svg.substring(0, 4) === '<svg') {
1407 if (svg.indexOf(ns.svg) === -1) {
1408 svg = SVG_START + svg.substring(4);
1409 }
1410 } else {
1411
1412 // namespace svg
1413 svg = SVG_START + '>' + svg + '</svg>';
1414 unwrap = true;
1415 }
1416
1417 var parsed = parseDocument(svg);
1418
1419 if (!unwrap) {
1420 return parsed;
1421 }
1422
1423 var fragment = document.createDocumentFragment();
1424
1425 var parent = parsed.firstChild;
1426
1427 while (parent.firstChild) {
1428 fragment.appendChild(parent.firstChild);
1429 }
1430
1431 return fragment;
1432 }
1433
1434 function parseDocument(svg) {
1435
1436 var parser;
1437
1438 // parse
1439 parser = new DOMParser();
1440 parser.async = false;
1441
1442 return parser.parseFromString(svg, 'text/xml');
1443 }
1444
1445 /**
1446 * Create utility for SVG elements
1447 */
1448
1449
1450 /**
1451 * Create a specific type from name or SVG markup.
1452 *
1453 * @param {String} name the name or markup of the element
1454 * @param {Object} [attrs] attributes to set on the element
1455 *
1456 * @returns {SVGElement}
1457 */
1458 function create$1(name, attrs) {
1459 var element;
1460
1461 if (name.charAt(0) === '<') {
1462 element = parse$1(name).firstChild;
1463 element = document.importNode(element, true);
1464 } else {
1465 element = document.createElementNS(ns.svg, name);
1466 }
1467
1468 if (attrs) {
1469 attr$1(element, attrs);
1470 }
1471
1472 return element;
1473 }
1474
1475 /**
1476 * Geometry helpers
1477 */
1478
1479 // fake node used to instantiate svg geometry elements
1480 var node = null;
1481
1482 function getNode() {
1483 if (node === null) {
1484 node = create$1('svg');
1485 }
1486
1487 return node;
1488 }
1489
1490 function extend$1(object, props) {
1491 var i, k, keys = Object.keys(props);
1492
1493 for (i = 0; (k = keys[i]); i++) {
1494 object[k] = props[k];
1495 }
1496
1497 return object;
1498 }
1499
1500 /**
1501 * Create matrix via args.
1502 *
1503 * @example
1504 *
1505 * createMatrix({ a: 1, b: 1 });
1506 * createMatrix();
1507 * createMatrix(1, 2, 0, 0, 30, 20);
1508 *
1509 * @return {SVGMatrix}
1510 */
1511 function createMatrix(a, b, c, d, e, f) {
1512 var matrix = getNode().createSVGMatrix();
1513
1514 switch (arguments.length) {
1515 case 0:
1516 return matrix;
1517 case 1:
1518 return extend$1(matrix, a);
1519 case 6:
1520 return extend$1(matrix, {
1521 a: a,
1522 b: b,
1523 c: c,
1524 d: d,
1525 e: e,
1526 f: f
1527 });
1528 }
1529 }
1530
1531 function createTransform(matrix) {
1532 if (matrix) {
1533 return getNode().createSVGTransformFromMatrix(matrix);
1534 } else {
1535 return getNode().createSVGTransform();
1536 }
1537 }
1538
1539 /**
1540 * Serialization util
1541 */
1542
1543 var TEXT_ENTITIES = /([&<>]{1})/g;
1544 var ATTR_ENTITIES = /([\n\r"]{1})/g;
1545
1546 var ENTITY_REPLACEMENT = {
1547 '&': '&amp;',
1548 '<': '&lt;',
1549 '>': '&gt;',
1550 '"': '\''
1551 };
1552
1553 function escape$1(str, pattern) {
1554
1555 function replaceFn(match, entity) {
1556 return ENTITY_REPLACEMENT[entity] || entity;
1557 }
1558
1559 return str.replace(pattern, replaceFn);
1560 }
1561
1562 function serialize(node, output) {
1563
1564 var i, len, attrMap, attrNode, childNodes;
1565
1566 switch (node.nodeType) {
1567
1568 // TEXT
1569 case 3:
1570
1571 // replace special XML characters
1572 output.push(escape$1(node.textContent, TEXT_ENTITIES));
1573 break;
1574
1575 // ELEMENT
1576 case 1:
1577 output.push('<', node.tagName);
1578
1579 if (node.hasAttributes()) {
1580 attrMap = node.attributes;
1581 for (i = 0, len = attrMap.length; i < len; ++i) {
1582 attrNode = attrMap.item(i);
1583 output.push(' ', attrNode.name, '="', escape$1(attrNode.value, ATTR_ENTITIES), '"');
1584 }
1585 }
1586
1587 if (node.hasChildNodes()) {
1588 output.push('>');
1589 childNodes = node.childNodes;
1590 for (i = 0, len = childNodes.length; i < len; ++i) {
1591 serialize(childNodes.item(i), output);
1592 }
1593 output.push('</', node.tagName, '>');
1594 } else {
1595 output.push('/>');
1596 }
1597 break;
1598
1599 // COMMENT
1600 case 8:
1601 output.push('<!--', escape$1(node.nodeValue, TEXT_ENTITIES), '-->');
1602 break;
1603
1604 // CDATA
1605 case 4:
1606 output.push('<![CDATA[', node.nodeValue, ']]>');
1607 break;
1608
1609 default:
1610 throw new Error('unable to handle node ' + node.nodeType);
1611 }
1612
1613 return output;
1614 }
1615
1616 /**
1617 * innerHTML like functionality for SVG elements.
1618 * based on innerSVG (https://code.google.com/p/innersvg)
1619 */
1620
1621
1622 function set(element, svg) {
1623
1624 var parsed = parse$1(svg);
1625
1626 // clear element contents
1627 clear$1(element);
1628
1629 if (!svg) {
1630 return;
1631 }
1632
1633 if (!isFragment(parsed)) {
1634
1635 // extract <svg> from parsed document
1636 parsed = parsed.documentElement;
1637 }
1638
1639 var nodes = slice$1(parsed.childNodes);
1640
1641 // import + append each node
1642 for (var i = 0; i < nodes.length; i++) {
1643 appendTo(nodes[i], element);
1644 }
1645
1646 }
1647
1648 function get(element) {
1649 var child = element.firstChild,
1650 output = [];
1651
1652 while (child) {
1653 serialize(child, output);
1654 child = child.nextSibling;
1655 }
1656
1657 return output.join('');
1658 }
1659
1660 function isFragment(node) {
1661 return node.nodeName === '#document-fragment';
1662 }
1663
1664 function innerSVG(element, svg) {
1665
1666 if (svg !== undefined) {
1667
1668 try {
1669 set(element, svg);
1670 } catch (e) {
1671 throw new Error('error parsing SVG: ' + e.message);
1672 }
1673
1674 return element;
1675 } else {
1676 return get(element);
1677 }
1678 }
1679
1680
1681 function slice$1(arr) {
1682 return Array.prototype.slice.call(arr);
1683 }
1684
1685 /**
1686 * transform accessor utility
1687 */
1688
1689 function wrapMatrix(transformList, transform) {
1690 if (transform instanceof SVGMatrix) {
1691 return transformList.createSVGTransformFromMatrix(transform);
1692 }
1693
1694 return transform;
1695 }
1696
1697
1698 function setTransforms(transformList, transforms) {
1699 var i, t;
1700
1701 transformList.clear();
1702
1703 for (i = 0; (t = transforms[i]); i++) {
1704 transformList.appendItem(wrapMatrix(transformList, t));
1705 }
1706 }
1707
1708 /**
1709 * Get or set the transforms on the given node.
1710 *
1711 * @param {SVGElement} node
1712 * @param {SVGTransform|SVGMatrix|Array<SVGTransform|SVGMatrix>} [transforms]
1713 *
1714 * @return {SVGTransform} the consolidated transform
1715 */
1716 function transform$1(node, transforms) {
1717 var transformList = node.transform.baseVal;
1718
1719 if (transforms) {
1720
1721 if (!Array.isArray(transforms)) {
1722 transforms = [ transforms ];
1723 }
1724
1725 setTransforms(transformList, transforms);
1726 }
1727
1728 return transformList.consolidate();
1729 }
1730
1731 /**
1732 * @typedef {(string|number)[]} Component
1733 *
1734 * @typedef {import('../util/Types').Point} Point
1735 */
1736
1737 /**
1738 * @param {Component[] | Component[][]} elements
1739 *
1740 * @return {string}
1741 */
1742 function componentsToPath(elements) {
1743 return elements.flat().join(',').replace(/,?([A-z]),?/g, '$1');
1744 }
1745
1746 /**
1747 * @param {Point} point
1748 *
1749 * @return {Component[]}
1750 */
1751 function move(point) {
1752 return [ 'M', point.x, point.y ];
1753 }
1754
1755 /**
1756 * @param {Point} point
1757 *
1758 * @return {Component[]}
1759 */
1760 function lineTo(point) {
1761 return [ 'L', point.x, point.y ];
1762 }
1763
1764 /**
1765 * @param {Point} p1
1766 * @param {Point} p2
1767 * @param {Point} p3
1768 *
1769 * @return {Component[]}
1770 */
1771 function curveTo(p1, p2, p3) {
1772 return [ 'C', p1.x, p1.y, p2.x, p2.y, p3.x, p3.y ];
1773 }
1774
1775 /**
1776 * @param {Point[]} waypoints
1777 * @param {number} [cornerRadius]
1778 * @return {Component[][]}
1779 */
1780 function drawPath(waypoints, cornerRadius) {
1781 const pointCount = waypoints.length;
1782
1783 const path = [ move(waypoints[0]) ];
1784
1785 for (let i = 1; i < pointCount; i++) {
1786
1787 const pointBefore = waypoints[i - 1];
1788 const point = waypoints[i];
1789 const pointAfter = waypoints[i + 1];
1790
1791 if (!pointAfter || !cornerRadius) {
1792 path.push(lineTo(point));
1793
1794 continue;
1795 }
1796
1797 const effectiveRadius = Math.min(
1798 cornerRadius,
1799 vectorLength(point.x - pointBefore.x, point.y - pointBefore.y),
1800 vectorLength(pointAfter.x - point.x, pointAfter.y - point.y)
1801 );
1802
1803 if (!effectiveRadius) {
1804 path.push(lineTo(point));
1805
1806 continue;
1807 }
1808
1809 const beforePoint = getPointAtLength(point, pointBefore, effectiveRadius);
1810 const beforePoint2 = getPointAtLength(point, pointBefore, effectiveRadius * .5);
1811
1812 const afterPoint = getPointAtLength(point, pointAfter, effectiveRadius);
1813 const afterPoint2 = getPointAtLength(point, pointAfter, effectiveRadius * .5);
1814
1815 path.push(lineTo(beforePoint));
1816 path.push(curveTo(beforePoint2, afterPoint2, afterPoint));
1817 }
1818
1819 return path;
1820 }
1821
1822 function getPointAtLength(start, end, length) {
1823
1824 const deltaX = end.x - start.x;
1825 const deltaY = end.y - start.y;
1826
1827 const totalLength = vectorLength(deltaX, deltaY);
1828
1829 const percent = length / totalLength;
1830
1831 return {
1832 x: start.x + deltaX * percent,
1833 y: start.y + deltaY * percent
1834 };
1835 }
1836
1837 function vectorLength(x, y) {
1838 return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
1839 }
1840
1841 /**
1842 * @param {Point[]} points
1843 * @param {number|Object} [attrs]
1844 * @param {number} [radius]
1845 *
1846 * @return {SVGElement}
1847 */
1848 function createLine(points, attrs, radius) {
1849
1850 if (isNumber(attrs)) {
1851 radius = attrs;
1852 attrs = null;
1853 }
1854
1855 if (!attrs) {
1856 attrs = {};
1857 }
1858
1859 const line = create$1('path', attrs);
1860
1861 if (isNumber(radius)) {
1862 line.dataset.cornerRadius = String(radius);
1863 }
1864
1865 return updateLine(line, points);
1866 }
1867
1868 /**
1869 * @param {SVGElement} gfx
1870 * @param {Point[]} points
1871 *
1872 * @return {SVGElement}
1873 */
1874 function updateLine(gfx, points) {
1875
1876 const cornerRadius = parseInt(gfx.dataset.cornerRadius, 10) || 0;
1877
1878 attr$1(gfx, {
1879 d: componentsToPath(drawPath(points, cornerRadius))
1880 });
1881
1882 return gfx;
1883 }
1884
1885 var black = 'hsl(225, 10%, 15%)';
1886 var white = 'white';
1887
1888 // element utils //////////////////////
1889
1890 /**
1891 * Checks if eventDefinition of the given element matches with semantic type.
1892 *
1893 * @param {ModdleElement} event
1894 * @param {string} eventDefinitionType
1895 *
1896 * @return {boolean}
1897 */
1898 function isTypedEvent(event, eventDefinitionType) {
1899 return some(event.eventDefinitions, function(definition) {
1900 return definition.$type === eventDefinitionType;
1901 });
1902 }
1903
1904 /**
1905 * Check if element is a throw event.
1906 *
1907 * @param {ModdleElement} event
1908 *
1909 * @return {boolean}
1910 */
1911 function isThrowEvent(event) {
1912 return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent');
1913 }
1914
1915 /**
1916 * Check if element is a throw event.
1917 *
1918 * @param {ModdleElement} element
1919 *
1920 * @return {boolean}
1921 */
1922 function isCollection(element) {
1923 var dataObject = element.dataObjectRef;
1924
1925 return element.isCollection || (dataObject && dataObject.isCollection);
1926 }
1927
1928
1929 // color access //////////////////////
1930
1931 /**
1932 * @param {Element} element
1933 * @param {string} [defaultColor]
1934 * @param {string} [overrideColor]
1935 *
1936 * @return {string}
1937 */
1938 function getFillColor(element, defaultColor, overrideColor) {
1939 var di = getDi(element);
1940
1941 return overrideColor || di.get('color:background-color') || di.get('bioc:fill') || defaultColor || white;
1942 }
1943
1944 /**
1945 * @param {Element} element
1946 * @param {string} [defaultColor]
1947 * @param {string} [overrideColor]
1948 *
1949 * @return {string}
1950 */
1951 function getStrokeColor(element, defaultColor, overrideColor) {
1952 var di = getDi(element);
1953
1954 return overrideColor || di.get('color:border-color') || di.get('bioc:stroke') || defaultColor || black;
1955 }
1956
1957 /**
1958 * @param {Element} element
1959 * @param {string} [defaultColor]
1960 * @param {string} [defaultStrokeColor]
1961 * @param {string} [overrideColor]
1962 *
1963 * @return {string}
1964 */
1965 function getLabelColor(element, defaultColor, defaultStrokeColor, overrideColor) {
1966 var di = getDi(element),
1967 label = di.get('label');
1968
1969 return overrideColor || (label && label.get('color:color')) || defaultColor ||
1970 getStrokeColor(element, defaultStrokeColor);
1971 }
1972
1973 // cropping path customizations //////////////////////
1974
1975 /**
1976 * @param {ShapeLike} shape
1977 *
1978 * @return {string} path
1979 */
1980 function getCirclePath(shape) {
1981
1982 var cx = shape.x + shape.width / 2,
1983 cy = shape.y + shape.height / 2,
1984 radius = shape.width / 2;
1985
1986 var circlePath = [
1987 [ 'M', cx, cy ],
1988 [ 'm', 0, -radius ],
1989 [ 'a', radius, radius, 0, 1, 1, 0, 2 * radius ],
1990 [ 'a', radius, radius, 0, 1, 1, 0, -2 * radius ],
1991 [ 'z' ]
1992 ];
1993
1994 return componentsToPath(circlePath);
1995 }
1996
1997 /**
1998 * @param {ShapeLike} shape
1999 * @param {number} [borderRadius]
2000 *
2001 * @return {string} path
2002 */
2003 function getRoundRectPath(shape, borderRadius) {
2004
2005 var x = shape.x,
2006 y = shape.y,
2007 width = shape.width,
2008 height = shape.height;
2009
2010 var roundRectPath = [
2011 [ 'M', x + borderRadius, y ],
2012 [ 'l', width - borderRadius * 2, 0 ],
2013 [ 'a', borderRadius, borderRadius, 0, 0, 1, borderRadius, borderRadius ],
2014 [ 'l', 0, height - borderRadius * 2 ],
2015 [ 'a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, borderRadius ],
2016 [ 'l', borderRadius * 2 - width, 0 ],
2017 [ 'a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, -borderRadius ],
2018 [ 'l', 0, borderRadius * 2 - height ],
2019 [ 'a', borderRadius, borderRadius, 0, 0, 1, borderRadius, -borderRadius ],
2020 [ 'z' ]
2021 ];
2022
2023 return componentsToPath(roundRectPath);
2024 }
2025
2026 /**
2027 * @param {ShapeLike} shape
2028 *
2029 * @return {string} path
2030 */
2031 function getDiamondPath(shape) {
2032
2033 var width = shape.width,
2034 height = shape.height,
2035 x = shape.x,
2036 y = shape.y,
2037 halfWidth = width / 2,
2038 halfHeight = height / 2;
2039
2040 var diamondPath = [
2041 [ 'M', x + halfWidth, y ],
2042 [ 'l', halfWidth, halfHeight ],
2043 [ 'l', -halfWidth, halfHeight ],
2044 [ 'l', -halfWidth, -halfHeight ],
2045 [ 'z' ]
2046 ];
2047
2048 return componentsToPath(diamondPath);
2049 }
2050
2051 /**
2052 * @param {ShapeLike} shape
2053 *
2054 * @return {string} path
2055 */
2056 function getRectPath(shape) {
2057 var x = shape.x,
2058 y = shape.y,
2059 width = shape.width,
2060 height = shape.height;
2061
2062 var rectPath = [
2063 [ 'M', x, y ],
2064 [ 'l', width, 0 ],
2065 [ 'l', 0, height ],
2066 [ 'l', -width, 0 ],
2067 [ 'z' ]
2068 ];
2069
2070 return componentsToPath(rectPath);
2071 }
2072
2073 /**
2074 * Get width and height from element or overrides.
2075 *
2076 * @param {Dimensions|Rect|ShapeLike} bounds
2077 * @param {Object} overrides
2078 *
2079 * @returns {Dimensions}
2080 */
2081 function getBounds(bounds, overrides = {}) {
2082 return {
2083 width: getWidth(bounds, overrides),
2084 height: getHeight(bounds, overrides)
2085 };
2086 }
2087
2088 /**
2089 * Get width from element or overrides.
2090 *
2091 * @param {Dimensions|Rect|ShapeLike} bounds
2092 * @param {Object} overrides
2093 *
2094 * @returns {number}
2095 */
2096 function getWidth(bounds, overrides = {}) {
2097 return has$1(overrides, 'width') ? overrides.width : bounds.width;
2098 }
2099
2100 /**
2101 * Get height from element or overrides.
2102 *
2103 * @param {Dimensions|Rect|ShapeLike} bounds
2104 * @param {Object} overrides
2105 *
2106 * @returns {number}
2107 */
2108 function getHeight(bounds, overrides = {}) {
2109 return has$1(overrides, 'height') ? overrides.height : bounds.height;
2110 }
2111
2112 function _mergeNamespaces$1(n, m) {
2113 m.forEach(function (e) {
2114 e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
2115 if (k !== 'default' && !(k in n)) {
2116 var d = Object.getOwnPropertyDescriptor(e, k);
2117 Object.defineProperty(n, k, d.get ? d : {
2118 enumerable: true,
2119 get: function () { return e[k]; }
2120 });
2121 }
2122 });
2123 });
2124 return Object.freeze(n);
2125 }
2126
2127 /**
2128 * Flatten array, one level deep.
2129 *
2130 * @param {Array<?>} arr
2131 *
2132 * @return {Array<?>}
2133 */
2134
2135 const nativeToString = Object.prototype.toString;
2136 const nativeHasOwnProperty = Object.prototype.hasOwnProperty;
2137
2138 function isUndefined$1(obj) {
2139 return obj === undefined;
2140 }
2141
2142 function isArray$1(obj) {
2143 return nativeToString.call(obj) === '[object Array]';
2144 }
2145
2146 /**
2147 * Return true, if target owns a property with the given key.
2148 *
2149 * @param {Object} target
2150 * @param {String} key
2151 *
2152 * @return {Boolean}
2153 */
2154 function has(target, key) {
2155 return nativeHasOwnProperty.call(target, key);
2156 }
2157
2158
2159 /**
2160 * Iterate over collection; returning something
2161 * (non-undefined) will stop iteration.
2162 *
2163 * @param {Array|Object} collection
2164 * @param {Function} iterator
2165 *
2166 * @return {Object} return result that stopped the iteration
2167 */
2168 function forEach(collection, iterator) {
2169
2170 let val,
2171 result;
2172
2173 if (isUndefined$1(collection)) {
2174 return;
2175 }
2176
2177 const convertKey = isArray$1(collection) ? toNum : identity;
2178
2179 for (let key in collection) {
2180
2181 if (has(collection, key)) {
2182 val = collection[key];
2183
2184 result = iterator(val, convertKey(key));
2185
2186 if (result === false) {
2187 return val;
2188 }
2189 }
2190 }
2191 }
2192
2193
2194 function identity(arg) {
2195 return arg;
2196 }
2197
2198 function toNum(arg) {
2199 return Number(arg);
2200 }
2201
2202 /**
2203 * Assigns style attributes in a style-src compliant way.
2204 *
2205 * @param {Element} element
2206 * @param {...Object} styleSources
2207 *
2208 * @return {Element} the element
2209 */
2210 function assign(element, ...styleSources) {
2211 const target = element.style;
2212
2213 forEach(styleSources, function(style) {
2214 if (!style) {
2215 return;
2216 }
2217
2218 forEach(style, function(value, key) {
2219 target[key] = value;
2220 });
2221 });
2222
2223 return element;
2224 }
2225
2226 /**
2227 * Set attribute `name` to `val`, or get attr `name`.
2228 *
2229 * @param {Element} el
2230 * @param {String} name
2231 * @param {String} [val]
2232 * @api public
2233 */
2234 function attr(el, name, val) {
2235
2236 // get
2237 if (arguments.length == 2) {
2238 return el.getAttribute(name);
2239 }
2240
2241 // remove
2242 if (val === null) {
2243 return el.removeAttribute(name);
2244 }
2245
2246 // set
2247 el.setAttribute(name, val);
2248
2249 return el;
2250 }
2251
2252 /**
2253 * Taken from https://github.com/component/classes
2254 *
2255 * Without the component bits.
2256 */
2257
2258 /**
2259 * toString reference.
2260 */
2261
2262 const toString = Object.prototype.toString;
2263
2264 /**
2265 * Wrap `el` in a `ClassList`.
2266 *
2267 * @param {Element} el
2268 * @return {ClassList}
2269 * @api public
2270 */
2271
2272 function classes(el) {
2273 return new ClassList(el);
2274 }
2275
2276 /**
2277 * Initialize a new ClassList for `el`.
2278 *
2279 * @param {Element} el
2280 * @api private
2281 */
2282
2283 function ClassList(el) {
2284 if (!el || !el.nodeType) {
2285 throw new Error('A DOM element reference is required');
2286 }
2287 this.el = el;
2288 this.list = el.classList;
2289 }
2290
2291 /**
2292 * Add class `name` if not already present.
2293 *
2294 * @param {String} name
2295 * @return {ClassList}
2296 * @api public
2297 */
2298
2299 ClassList.prototype.add = function(name) {
2300 this.list.add(name);
2301 return this;
2302 };
2303
2304 /**
2305 * Remove class `name` when present, or
2306 * pass a regular expression to remove
2307 * any which match.
2308 *
2309 * @param {String|RegExp} name
2310 * @return {ClassList}
2311 * @api public
2312 */
2313
2314 ClassList.prototype.remove = function(name) {
2315 if ('[object RegExp]' == toString.call(name)) {
2316 return this.removeMatching(name);
2317 }
2318
2319 this.list.remove(name);
2320 return this;
2321 };
2322
2323 /**
2324 * Remove all classes matching `re`.
2325 *
2326 * @param {RegExp} re
2327 * @return {ClassList}
2328 * @api private
2329 */
2330
2331 ClassList.prototype.removeMatching = function(re) {
2332 const arr = this.array();
2333 for (let i = 0; i < arr.length; i++) {
2334 if (re.test(arr[i])) {
2335 this.remove(arr[i]);
2336 }
2337 }
2338 return this;
2339 };
2340
2341 /**
2342 * Toggle class `name`, can force state via `force`.
2343 *
2344 * For browsers that support classList, but do not support `force` yet,
2345 * the mistake will be detected and corrected.
2346 *
2347 * @param {String} name
2348 * @param {Boolean} force
2349 * @return {ClassList}
2350 * @api public
2351 */
2352
2353 ClassList.prototype.toggle = function(name, force) {
2354 if ('undefined' !== typeof force) {
2355 if (force !== this.list.toggle(name, force)) {
2356 this.list.toggle(name); // toggle again to correct
2357 }
2358 } else {
2359 this.list.toggle(name);
2360 }
2361 return this;
2362 };
2363
2364 /**
2365 * Return an array of classes.
2366 *
2367 * @return {Array}
2368 * @api public
2369 */
2370
2371 ClassList.prototype.array = function() {
2372 return Array.from(this.list);
2373 };
2374
2375 /**
2376 * Check if class `name` is present.
2377 *
2378 * @param {String} name
2379 * @return {ClassList}
2380 * @api public
2381 */
2382
2383 ClassList.prototype.has =
2384 ClassList.prototype.contains = function(name) {
2385 return this.list.contains(name);
2386 };
2387
2388 /**
2389 * Remove all children from the given element.
2390 */
2391 function clear(el) {
2392
2393 var c;
2394
2395 while (el.childNodes.length) {
2396 c = el.childNodes[0];
2397 el.removeChild(c);
2398 }
2399
2400 return el;
2401 }
2402
2403 /**
2404 * @param { HTMLElement } element
2405 * @param { String } selector
2406 *
2407 * @return { boolean }
2408 */
2409 function matches(element, selector) {
2410 return element && typeof element.matches === 'function' && element.matches(selector);
2411 }
2412
2413 /**
2414 * Closest
2415 *
2416 * @param {Element} el
2417 * @param {String} selector
2418 * @param {Boolean} checkYourSelf (optional)
2419 */
2420 function closest(element, selector, checkYourSelf) {
2421 var currentElem = checkYourSelf ? element : element.parentNode;
2422
2423 while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE &&
2424 currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) {
2425
2426 if (matches(currentElem, selector)) {
2427 return currentElem;
2428 }
2429
2430 currentElem = currentElem.parentNode;
2431 }
2432
2433 return matches(currentElem, selector) ? currentElem : null;
2434 }
2435
2436 var componentEvent = {};
2437
2438 var bind$1, unbind$1, prefix$6;
2439
2440 function detect () {
2441 bind$1 = window.addEventListener ? 'addEventListener' : 'attachEvent';
2442 unbind$1 = window.removeEventListener ? 'removeEventListener' : 'detachEvent';
2443 prefix$6 = bind$1 !== 'addEventListener' ? 'on' : '';
2444 }
2445
2446 /**
2447 * Bind `el` event `type` to `fn`.
2448 *
2449 * @param {Element} el
2450 * @param {String} type
2451 * @param {Function} fn
2452 * @param {Boolean} capture
2453 * @return {Function}
2454 * @api public
2455 */
2456
2457 var bind_1 = componentEvent.bind = function(el, type, fn, capture){
2458 if (!bind$1) detect();
2459 el[bind$1](prefix$6 + type, fn, capture || false);
2460 return fn;
2461 };
2462
2463 /**
2464 * Unbind `el` event `type`'s callback `fn`.
2465 *
2466 * @param {Element} el
2467 * @param {String} type
2468 * @param {Function} fn
2469 * @param {Boolean} capture
2470 * @return {Function}
2471 * @api public
2472 */
2473
2474 var unbind_1 = componentEvent.unbind = function(el, type, fn, capture){
2475 if (!unbind$1) detect();
2476 el[unbind$1](prefix$6 + type, fn, capture || false);
2477 return fn;
2478 };
2479
2480 var event = /*#__PURE__*/_mergeNamespaces$1({
2481 __proto__: null,
2482 bind: bind_1,
2483 unbind: unbind_1,
2484 'default': componentEvent
2485 }, [componentEvent]);
2486
2487 /**
2488 * Module dependencies.
2489 */
2490
2491 /**
2492 * Delegate event `type` to `selector`
2493 * and invoke `fn(e)`. A callback function
2494 * is returned which may be passed to `.unbind()`.
2495 *
2496 * @param {Element} el
2497 * @param {String} selector
2498 * @param {String} type
2499 * @param {Function} fn
2500 * @param {Boolean} capture
2501 * @return {Function}
2502 * @api public
2503 */
2504
2505 // Some events don't bubble, so we want to bind to the capture phase instead
2506 // when delegating.
2507 var forceCaptureEvents = [ 'focus', 'blur' ];
2508
2509 function bind(el, selector, type, fn, capture) {
2510 if (forceCaptureEvents.indexOf(type) !== -1) {
2511 capture = true;
2512 }
2513
2514 return event.bind(el, type, function(e) {
2515 var target = e.target || e.srcElement;
2516 e.delegateTarget = closest(target, selector, true);
2517 if (e.delegateTarget) {
2518 fn.call(el, e);
2519 }
2520 }, capture);
2521 }
2522
2523 /**
2524 * Unbind event `type`'s callback `fn`.
2525 *
2526 * @param {Element} el
2527 * @param {String} type
2528 * @param {Function} fn
2529 * @param {Boolean} capture
2530 * @api public
2531 */
2532 function unbind(el, type, fn, capture) {
2533 if (forceCaptureEvents.indexOf(type) !== -1) {
2534 capture = true;
2535 }
2536
2537 return event.unbind(el, type, fn, capture);
2538 }
2539
2540 var delegate = {
2541 bind,
2542 unbind
2543 };
2544
2545 /**
2546 * Expose `parse`.
2547 */
2548
2549 var domify = parse;
2550
2551 /**
2552 * Tests for browser support.
2553 */
2554
2555 var innerHTMLBug = false;
2556 var bugTestDiv;
2557 if (typeof document !== 'undefined') {
2558 bugTestDiv = document.createElement('div');
2559 // Setup
2560 bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
2561 // Make sure that link elements get serialized correctly by innerHTML
2562 // This requires a wrapper element in IE
2563 innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
2564 bugTestDiv = undefined;
2565 }
2566
2567 /**
2568 * Wrap map from jquery.
2569 */
2570
2571 var map = {
2572 legend: [1, '<fieldset>', '</fieldset>'],
2573 tr: [2, '<table><tbody>', '</tbody></table>'],
2574 col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
2575 // for script/link/style tags to work in IE6-8, you have to wrap
2576 // in a div with a non-whitespace character in front, ha!
2577 _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
2578 };
2579
2580 map.td =
2581 map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
2582
2583 map.option =
2584 map.optgroup = [1, '<select multiple="multiple">', '</select>'];
2585
2586 map.thead =
2587 map.tbody =
2588 map.colgroup =
2589 map.caption =
2590 map.tfoot = [1, '<table>', '</table>'];
2591
2592 map.polyline =
2593 map.ellipse =
2594 map.polygon =
2595 map.circle =
2596 map.text =
2597 map.line =
2598 map.path =
2599 map.rect =
2600 map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
2601
2602 /**
2603 * Parse `html` and return a DOM Node instance, which could be a TextNode,
2604 * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
2605 * instance, depending on the contents of the `html` string.
2606 *
2607 * @param {String} html - HTML string to "domify"
2608 * @param {Document} doc - The `document` instance to create the Node for
2609 * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
2610 * @api private
2611 */
2612
2613 function parse(html, doc) {
2614 if ('string' != typeof html) throw new TypeError('String expected');
2615
2616 // default to the global `document` object
2617 if (!doc) doc = document;
2618
2619 // tag name
2620 var m = /<([\w:]+)/.exec(html);
2621 if (!m) return doc.createTextNode(html);
2622
2623 html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
2624
2625 var tag = m[1];
2626
2627 // body support
2628 if (tag == 'body') {
2629 var el = doc.createElement('html');
2630 el.innerHTML = html;
2631 return el.removeChild(el.lastChild);
2632 }
2633
2634 // wrap map
2635 var wrap = Object.prototype.hasOwnProperty.call(map, tag) ? map[tag] : map._default;
2636 var depth = wrap[0];
2637 var prefix = wrap[1];
2638 var suffix = wrap[2];
2639 var el = doc.createElement('div');
2640 el.innerHTML = prefix + html + suffix;
2641 while (depth--) el = el.lastChild;
2642
2643 // one element
2644 if (el.firstChild == el.lastChild) {
2645 return el.removeChild(el.firstChild);
2646 }
2647
2648 // several elements
2649 var fragment = doc.createDocumentFragment();
2650 while (el.firstChild) {
2651 fragment.appendChild(el.removeChild(el.firstChild));
2652 }
2653
2654 return fragment;
2655 }
2656
2657 var domify$1 = domify;
2658
2659 function query(selector, el) {
2660 el = el || document;
2661
2662 return el.querySelector(selector);
2663 }
2664
2665 function all(selector, el) {
2666 el = el || document;
2667
2668 return el.querySelectorAll(selector);
2669 }
2670
2671 function remove$1(el) {
2672 el.parentNode && el.parentNode.removeChild(el);
2673 }
2674
2675 /**
2676 * @param {SVGElement} gfx
2677 * @param {number} x
2678 * @param {number} y
2679 * @param {number} [angle]
2680 * @param {number} [amount]
2681 */
2682 function transform(gfx, x, y, angle, amount) {
2683 var translate = createTransform();
2684 translate.setTranslate(x, y);
2685
2686 var rotate = createTransform();
2687 rotate.setRotate(angle || 0, 0, 0);
2688
2689 var scale = createTransform();
2690 scale.setScale(amount || 1, amount || 1);
2691
2692 transform$1(gfx, [ translate, rotate, scale ]);
2693 }
2694
2695
2696 /**
2697 * @param {SVGElement} gfx
2698 * @param {number} x
2699 * @param {number} y
2700 */
2701 function translate$1(gfx, x, y) {
2702 var translate = createTransform();
2703 translate.setTranslate(x, y);
2704
2705 transform$1(gfx, translate);
2706 }
2707
2708
2709 /**
2710 * @param {SVGElement} gfx
2711 * @param {number} angle
2712 */
2713 function rotate(gfx, angle) {
2714 var rotate = createTransform();
2715 rotate.setRotate(angle, 0, 0);
2716
2717 transform$1(gfx, rotate);
2718 }
2719
2720 function createCommonjsModule(fn, module) {
2721 return module = { exports: {} }, fn(module, module.exports), module.exports;
2722 }
2723
2724 var hat_1 = createCommonjsModule(function (module) {
2725 var hat = module.exports = function (bits, base) {
2726 if (!base) base = 16;
2727 if (bits === undefined) bits = 128;
2728 if (bits <= 0) return '0';
2729
2730 var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
2731 for (var i = 2; digits === Infinity; i *= 2) {
2732 digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
2733 }
2734
2735 var rem = digits - Math.floor(digits);
2736
2737 var res = '';
2738
2739 for (var i = 0; i < Math.floor(digits); i++) {
2740 var x = Math.floor(Math.random() * base).toString(base);
2741 res = x + res;
2742 }
2743
2744 if (rem) {
2745 var b = Math.pow(base, rem);
2746 var x = Math.floor(Math.random() * b).toString(base);
2747 res = x + res;
2748 }
2749
2750 var parsed = parseInt(res, base);
2751 if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
2752 return hat(bits, base)
2753 }
2754 else return res;
2755 };
2756
2757 hat.rack = function (bits, base, expandBy) {
2758 var fn = function (data) {
2759 var iters = 0;
2760 do {
2761 if (iters ++ > 10) {
2762 if (expandBy) bits += expandBy;
2763 else throw new Error('too many ID collisions, use more bits')
2764 }
2765
2766 var id = hat(bits, base);
2767 } while (Object.hasOwnProperty.call(hats, id));
2768
2769 hats[id] = data;
2770 return id;
2771 };
2772 var hats = fn.hats = {};
2773
2774 fn.get = function (id) {
2775 return fn.hats[id];
2776 };
2777
2778 fn.set = function (id, value) {
2779 fn.hats[id] = value;
2780 return fn;
2781 };
2782
2783 fn.bits = bits || 128;
2784 fn.base = base || 16;
2785 return fn;
2786 };
2787 });
2788
2789 /**
2790 * Create a new id generator / cache instance.
2791 *
2792 * You may optionally provide a seed that is used internally.
2793 *
2794 * @param {Seed} seed
2795 */
2796 function Ids(seed) {
2797 if (!(this instanceof Ids)) {
2798 return new Ids(seed);
2799 }
2800 seed = seed || [128, 36, 1];
2801 this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed;
2802 }
2803
2804 /**
2805 * Generate a next id.
2806 *
2807 * @param {Object} [element] element to bind the id to
2808 *
2809 * @return {String} id
2810 */
2811 Ids.prototype.next = function (element) {
2812 return this._seed(element || true);
2813 };
2814
2815 /**
2816 * Generate a next id with a given prefix.
2817 *
2818 * @param {Object} [element] element to bind the id to
2819 *
2820 * @return {String} id
2821 */
2822 Ids.prototype.nextPrefixed = function (prefix, element) {
2823 var id;
2824 do {
2825 id = prefix + this.next(true);
2826 } while (this.assigned(id));
2827
2828 // claim {prefix}{random}
2829 this.claim(id, element);
2830
2831 // return
2832 return id;
2833 };
2834
2835 /**
2836 * Manually claim an existing id.
2837 *
2838 * @param {String} id
2839 * @param {String} [element] element the id is claimed by
2840 */
2841 Ids.prototype.claim = function (id, element) {
2842 this._seed.set(id, element || true);
2843 };
2844
2845 /**
2846 * Returns true if the given id has already been assigned.
2847 *
2848 * @param {String} id
2849 * @return {Boolean}
2850 */
2851 Ids.prototype.assigned = function (id) {
2852 return this._seed.get(id) || false;
2853 };
2854
2855 /**
2856 * Unclaim an id.
2857 *
2858 * @param {String} id the id to unclaim
2859 */
2860 Ids.prototype.unclaim = function (id) {
2861 delete this._seed.hats[id];
2862 };
2863
2864 /**
2865 * Clear all claimed ids.
2866 */
2867 Ids.prototype.clear = function () {
2868 var hats = this._seed.hats,
2869 id;
2870 for (id in hats) {
2871 this.unclaim(id);
2872 }
2873 };
2874
2875 var rendererIds = new Ids();
2876
2877 var ELEMENT_LABEL_DISTANCE = 10,
2878 INNER_OUTER_DIST = 3,
2879 PARTICIPANT_STROKE_WIDTH = 1.5,
2880 TASK_BORDER_RADIUS = 10;
2881
2882 var DEFAULT_OPACITY = 0.95,
2883 FULL_OPACITY = 1,
2884 LOW_OPACITY = 0.25;
2885
2886 /**
2887 * @typedef { Partial<{
2888 * defaultFillColor: string,
2889 * defaultStrokeColor: string,
2890 * defaultLabelColor: string
2891 * }> } BpmnRendererConfig
2892 *
2893 * @typedef { Partial<{
2894 * fill: string,
2895 * stroke: string,
2896 * width: string,
2897 * height: string
2898 * }> } Attrs
2899 */
2900
2901 /**
2902 * @typedef { import('../model/Types').Element } Element
2903 */
2904
2905 /**
2906 * A renderer for BPMN elements
2907 *
2908 * @param {BpmnRendererConfig} config
2909 * @param {import('diagram-js/lib/core/EventBus').default} eventBus
2910 * @param {import('diagram-js/lib/draw/Styles').default} styles
2911 * @param {import('./PathMap').default} pathMap
2912 * @param {import('diagram-js/lib/core/Canvas').default} canvas
2913 * @param {import('./TextRenderer').default} textRenderer
2914 * @param {number} [priority]
2915 */
2916 function BpmnRenderer(
2917 config, eventBus, styles, pathMap,
2918 canvas, textRenderer, priority) {
2919
2920 BaseRenderer.call(this, eventBus, priority);
2921
2922 var defaultFillColor = config && config.defaultFillColor,
2923 defaultStrokeColor = config && config.defaultStrokeColor,
2924 defaultLabelColor = config && config.defaultLabelColor;
2925
2926 var rendererId = rendererIds.next();
2927
2928 var markers = {};
2929
2930 function shapeStyle(attrs) {
2931 return styles.computeStyle(attrs, {
2932 strokeLinecap: 'round',
2933 strokeLinejoin: 'round',
2934 stroke: black,
2935 strokeWidth: 2,
2936 fill: 'white'
2937 });
2938 }
2939
2940 function lineStyle(attrs) {
2941 return styles.computeStyle(attrs, [ 'no-fill' ], {
2942 strokeLinecap: 'round',
2943 strokeLinejoin: 'round',
2944 stroke: black,
2945 strokeWidth: 2
2946 });
2947 }
2948
2949 function addMarker(id, options) {
2950 var {
2951 ref = { x: 0, y: 0 },
2952 scale = 1,
2953 element
2954 } = options;
2955
2956 var marker = create$1('marker', {
2957 id: id,
2958 viewBox: '0 0 20 20',
2959 refX: ref.x,
2960 refY: ref.y,
2961 markerWidth: 20 * scale,
2962 markerHeight: 20 * scale,
2963 orient: 'auto'
2964 });
2965
2966 append(marker, element);
2967
2968 var defs = query('defs', canvas._svg);
2969
2970 if (!defs) {
2971 defs = create$1('defs');
2972
2973 append(canvas._svg, defs);
2974 }
2975
2976 append(defs, marker);
2977
2978 markers[id] = marker;
2979 }
2980
2981 function colorEscape(str) {
2982
2983 // only allow characters and numbers
2984 return str.replace(/[^0-9a-zA-Z]+/g, '_');
2985 }
2986
2987 function marker(type, fill, stroke) {
2988 var id = type + '-' + colorEscape(fill) + '-' + colorEscape(stroke) + '-' + rendererId;
2989
2990 if (!markers[id]) {
2991 createMarker(id, type, fill, stroke);
2992 }
2993
2994 return 'url(#' + id + ')';
2995 }
2996
2997 function createMarker(id, type, fill, stroke) {
2998
2999 if (type === 'sequenceflow-end') {
3000 var sequenceflowEnd = create$1('path', {
3001 d: 'M 1 5 L 11 10 L 1 15 Z',
3002 ...shapeStyle({
3003 fill: stroke,
3004 stroke: stroke,
3005 strokeWidth: 1
3006 })
3007 });
3008
3009 addMarker(id, {
3010 element: sequenceflowEnd,
3011 ref: { x: 11, y: 10 },
3012 scale: 0.5
3013 });
3014 }
3015
3016 if (type === 'messageflow-start') {
3017 var messageflowStart = create$1('circle', {
3018 cx: 6,
3019 cy: 6,
3020 r: 3.5,
3021 ...shapeStyle({
3022 fill,
3023 stroke: stroke,
3024 strokeWidth: 1,
3025
3026 // fix for safari / chrome / firefox bug not correctly
3027 // resetting stroke dash array
3028 strokeDasharray: [ 10000, 1 ]
3029 })
3030 });
3031
3032 addMarker(id, {
3033 element: messageflowStart,
3034 ref: { x: 6, y: 6 }
3035 });
3036 }
3037
3038 if (type === 'messageflow-end') {
3039 var messageflowEnd = create$1('path', {
3040 d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z',
3041 ...shapeStyle({
3042 fill,
3043 stroke: stroke,
3044 strokeWidth: 1,
3045
3046 // fix for safari / chrome / firefox bug not correctly
3047 // resetting stroke dash array
3048 strokeDasharray: [ 10000, 1 ]
3049 })
3050 });
3051
3052 addMarker(id, {
3053 element: messageflowEnd,
3054 ref: { x: 8.5, y: 5 }
3055 });
3056 }
3057
3058 if (type === 'association-start') {
3059 var associationStart = create$1('path', {
3060 d: 'M 11 5 L 1 10 L 11 15',
3061 ...lineStyle({
3062 fill: 'none',
3063 stroke,
3064 strokeWidth: 1.5,
3065
3066 // fix for safari / chrome / firefox bug not correctly
3067 // resetting stroke dash array
3068 strokeDasharray: [ 10000, 1 ]
3069 })
3070 });
3071
3072 addMarker(id, {
3073 element: associationStart,
3074 ref: { x: 1, y: 10 },
3075 scale: 0.5
3076 });
3077 }
3078
3079 if (type === 'association-end') {
3080 var associationEnd = create$1('path', {
3081 d: 'M 1 5 L 11 10 L 1 15',
3082 ...lineStyle({
3083 fill: 'none',
3084 stroke,
3085 strokeWidth: 1.5,
3086
3087 // fix for safari / chrome / firefox bug not correctly
3088 // resetting stroke dash array
3089 strokeDasharray: [ 10000, 1 ]
3090 })
3091 });
3092
3093 addMarker(id, {
3094 element: associationEnd,
3095 ref: { x: 11, y: 10 },
3096 scale: 0.5
3097 });
3098 }
3099
3100 if (type === 'conditional-flow-marker') {
3101 var conditionalFlowMarker = create$1('path', {
3102 d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z',
3103 ...shapeStyle({
3104 fill,
3105 stroke: stroke
3106 })
3107 });
3108
3109 addMarker(id, {
3110 element: conditionalFlowMarker,
3111 ref: { x: -1, y: 10 },
3112 scale: 0.5
3113 });
3114 }
3115
3116 if (type === 'conditional-default-flow-marker') {
3117 var defaultFlowMarker = create$1('path', {
3118 d: 'M 6 4 L 10 16',
3119 ...shapeStyle({
3120 stroke: stroke
3121 })
3122 });
3123
3124 addMarker(id, {
3125 element: defaultFlowMarker,
3126 ref: { x: 0, y: 10 },
3127 scale: 0.5
3128 });
3129 }
3130 }
3131
3132 function drawCircle(parentGfx, width, height, offset, attrs = {}) {
3133
3134 if (isObject(offset)) {
3135 attrs = offset;
3136 offset = 0;
3137 }
3138
3139 offset = offset || 0;
3140
3141 attrs = shapeStyle(attrs);
3142
3143 var cx = width / 2,
3144 cy = height / 2;
3145
3146 var circle = create$1('circle', {
3147 cx: cx,
3148 cy: cy,
3149 r: Math.round((width + height) / 4 - offset),
3150 ...attrs
3151 });
3152
3153 append(parentGfx, circle);
3154
3155 return circle;
3156 }
3157
3158 function drawRect(parentGfx, width, height, r, offset, attrs) {
3159
3160 if (isObject(offset)) {
3161 attrs = offset;
3162 offset = 0;
3163 }
3164
3165 offset = offset || 0;
3166
3167 attrs = shapeStyle(attrs);
3168
3169 var rect = create$1('rect', {
3170 x: offset,
3171 y: offset,
3172 width: width - offset * 2,
3173 height: height - offset * 2,
3174 rx: r,
3175 ry: r,
3176 ...attrs
3177 });
3178
3179 append(parentGfx, rect);
3180
3181 return rect;
3182 }
3183
3184 function drawDiamond(parentGfx, width, height, attrs) {
3185
3186 var x_2 = width / 2;
3187 var y_2 = height / 2;
3188
3189 var points = [
3190 { x: x_2, y: 0 },
3191 { x: width, y: y_2 },
3192 { x: x_2, y: height },
3193 { x: 0, y: y_2 }
3194 ];
3195
3196 var pointsString = points.map(function(point) {
3197 return point.x + ',' + point.y;
3198 }).join(' ');
3199
3200 attrs = shapeStyle(attrs);
3201
3202 var polygon = create$1('polygon', {
3203 ...attrs,
3204 points: pointsString
3205 });
3206
3207 append(parentGfx, polygon);
3208
3209 return polygon;
3210 }
3211
3212 /**
3213 * @param {SVGElement} parentGfx
3214 * @param {Point[]} waypoints
3215 * @param {any} attrs
3216 * @param {number} [radius]
3217 *
3218 * @return {SVGElement}
3219 */
3220 function drawLine(parentGfx, waypoints, attrs, radius) {
3221 attrs = lineStyle(attrs);
3222
3223 var line = createLine(waypoints, attrs, radius);
3224
3225 append(parentGfx, line);
3226
3227 return line;
3228 }
3229
3230 /**
3231 * @param {SVGElement} parentGfx
3232 * @param {Point[]} waypoints
3233 * @param {any} attrs
3234 *
3235 * @return {SVGElement}
3236 */
3237 function drawConnectionSegments(parentGfx, waypoints, attrs) {
3238 return drawLine(parentGfx, waypoints, attrs, 5);
3239 }
3240
3241 function drawPath(parentGfx, d, attrs) {
3242 attrs = lineStyle(attrs);
3243
3244 var path = create$1('path', {
3245 ...attrs,
3246 d
3247 });
3248
3249 append(parentGfx, path);
3250
3251 return path;
3252 }
3253
3254 function drawMarker(type, parentGfx, path, attrs) {
3255 return drawPath(parentGfx, path, assign$1({ 'data-marker': type }, attrs));
3256 }
3257
3258 function renderer(type) {
3259 return handlers[type];
3260 }
3261
3262 function as(type) {
3263 return function(parentGfx, element, attrs) {
3264 return renderer(type)(parentGfx, element, attrs);
3265 };
3266 }
3267
3268 var eventIconRenderers = {
3269 'bpmn:MessageEventDefinition': function(parentGfx, element, attrs = {}, isThrowing) {
3270 var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
3271 xScaleFactor: 0.9,
3272 yScaleFactor: 0.9,
3273 containerWidth: element.width,
3274 containerHeight: element.height,
3275 position: {
3276 mx: 0.235,
3277 my: 0.315
3278 }
3279 });
3280
3281 var fill = isThrowing
3282 ? getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3283 : getFillColor(element, defaultFillColor, attrs.fill);
3284
3285 var stroke = isThrowing
3286 ? getFillColor(element, defaultFillColor, attrs.fill)
3287 : getStrokeColor(element, defaultStrokeColor, attrs.stroke);
3288
3289 var messagePath = drawPath(parentGfx, pathData, {
3290 fill,
3291 stroke,
3292 strokeWidth: 1
3293 });
3294
3295 return messagePath;
3296 },
3297 'bpmn:TimerEventDefinition': function(parentGfx, element, attrs = {}) {
3298 var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
3299 fill: getFillColor(element, defaultFillColor, attrs.fill),
3300 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3301 strokeWidth: 2
3302 });
3303
3304 var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
3305 xScaleFactor: 0.75,
3306 yScaleFactor: 0.75,
3307 containerWidth: element.width,
3308 containerHeight: element.height,
3309 position: {
3310 mx: 0.5,
3311 my: 0.5
3312 }
3313 });
3314
3315 drawPath(parentGfx, pathData, {
3316 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3317 strokeWidth: 2
3318 });
3319
3320 for (var i = 0; i < 12; i++) {
3321 var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
3322 xScaleFactor: 0.75,
3323 yScaleFactor: 0.75,
3324 containerWidth: element.width,
3325 containerHeight: element.height,
3326 position: {
3327 mx: 0.5,
3328 my: 0.5
3329 }
3330 });
3331
3332 var width = element.width / 2,
3333 height = element.height / 2;
3334
3335 drawPath(parentGfx, linePathData, {
3336 strokeWidth: 1,
3337 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3338 transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')'
3339 });
3340 }
3341
3342 return circle;
3343 },
3344 'bpmn:EscalationEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3345 var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
3346 xScaleFactor: 1,
3347 yScaleFactor: 1,
3348 containerWidth: event.width,
3349 containerHeight: event.height,
3350 position: {
3351 mx: 0.5,
3352 my: 0.2
3353 }
3354 });
3355
3356 var fill = isThrowing
3357 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3358 : getFillColor(event, defaultFillColor, attrs.fill);
3359
3360 return drawPath(parentGfx, pathData, {
3361 fill,
3362 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3363 strokeWidth: 1
3364 });
3365 },
3366 'bpmn:ConditionalEventDefinition': function(parentGfx, event, attrs = {}) {
3367 var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
3368 xScaleFactor: 1,
3369 yScaleFactor: 1,
3370 containerWidth: event.width,
3371 containerHeight: event.height,
3372 position: {
3373 mx: 0.5,
3374 my: 0.222
3375 }
3376 });
3377
3378 return drawPath(parentGfx, pathData, {
3379 fill: getFillColor(event, defaultFillColor, attrs.fill),
3380 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3381 strokeWidth: 1
3382 });
3383 },
3384 'bpmn:LinkEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3385 var pathData = pathMap.getScaledPath('EVENT_LINK', {
3386 xScaleFactor: 1,
3387 yScaleFactor: 1,
3388 containerWidth: event.width,
3389 containerHeight: event.height,
3390 position: {
3391 mx: 0.57,
3392 my: 0.263
3393 }
3394 });
3395
3396 var fill = isThrowing
3397 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3398 : getFillColor(event, defaultFillColor, attrs.fill);
3399
3400 return drawPath(parentGfx, pathData, {
3401 fill,
3402 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3403 strokeWidth: 1
3404 });
3405 },
3406 'bpmn:ErrorEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3407 var pathData = pathMap.getScaledPath('EVENT_ERROR', {
3408 xScaleFactor: 1.1,
3409 yScaleFactor: 1.1,
3410 containerWidth: event.width,
3411 containerHeight: event.height,
3412 position: {
3413 mx: 0.2,
3414 my: 0.722
3415 }
3416 });
3417
3418 var fill = isThrowing
3419 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3420 : getFillColor(event, defaultFillColor, attrs.fill);
3421
3422 return drawPath(parentGfx, pathData, {
3423 fill,
3424 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3425 strokeWidth: 1
3426 });
3427 },
3428 'bpmn:CancelEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3429 var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
3430 xScaleFactor: 1.0,
3431 yScaleFactor: 1.0,
3432 containerWidth: event.width,
3433 containerHeight: event.height,
3434 position: {
3435 mx: 0.638,
3436 my: -0.055
3437 }
3438 });
3439
3440 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor, attrs.stroke) : 'none';
3441
3442 var path = drawPath(parentGfx, pathData, {
3443 fill,
3444 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3445 strokeWidth: 1
3446 });
3447
3448 rotate(path, 45);
3449
3450 return path;
3451 },
3452 'bpmn:CompensateEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3453 var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
3454 xScaleFactor: 1,
3455 yScaleFactor: 1,
3456 containerWidth: event.width,
3457 containerHeight: event.height,
3458 position: {
3459 mx: 0.22,
3460 my: 0.5
3461 }
3462 });
3463
3464 var fill = isThrowing
3465 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3466 : getFillColor(event, defaultFillColor, attrs.fill);
3467
3468 return drawPath(parentGfx, pathData, {
3469 fill,
3470 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3471 strokeWidth: 1
3472 });
3473 },
3474 'bpmn:SignalEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3475 var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
3476 xScaleFactor: 0.9,
3477 yScaleFactor: 0.9,
3478 containerWidth: event.width,
3479 containerHeight: event.height,
3480 position: {
3481 mx: 0.5,
3482 my: 0.2
3483 }
3484 });
3485
3486 var fill = isThrowing
3487 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3488 : getFillColor(event, defaultFillColor, attrs.fill);
3489
3490 return drawPath(parentGfx, pathData, {
3491 strokeWidth: 1,
3492 fill,
3493 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3494 });
3495 },
3496 'bpmn:MultipleEventDefinition': function(parentGfx, event, attrs = {}, isThrowing) {
3497 var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
3498 xScaleFactor: 1.1,
3499 yScaleFactor: 1.1,
3500 containerWidth: event.width,
3501 containerHeight: event.height,
3502 position: {
3503 mx: 0.222,
3504 my: 0.36
3505 }
3506 });
3507
3508 var fill = isThrowing
3509 ? getStrokeColor(event, defaultStrokeColor, attrs.stroke)
3510 : getFillColor(event, defaultFillColor, attrs.fill);
3511
3512 return drawPath(parentGfx, pathData, {
3513 fill,
3514 strokeWidth: 1
3515 });
3516 },
3517 'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event, attrs = {}) {
3518 var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
3519 xScaleFactor: 1.2,
3520 yScaleFactor: 1.2,
3521 containerWidth: event.width,
3522 containerHeight: event.height,
3523 position: {
3524 mx: 0.458,
3525 my: 0.194
3526 }
3527 });
3528
3529 return drawPath(parentGfx, pathData, {
3530 fill: getFillColor(event, defaultFillColor, attrs.fill),
3531 stroke: getStrokeColor(event, defaultStrokeColor, attrs.stroke),
3532 strokeWidth: 1
3533 });
3534 },
3535 'bpmn:TerminateEventDefinition': function(parentGfx, element, attrs = {}) {
3536 var circle = drawCircle(parentGfx, element.width, element.height, 8, {
3537 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3538 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3539 strokeWidth: 4
3540 });
3541
3542 return circle;
3543 }
3544 };
3545
3546 function renderEventIcon(element, parentGfx, attrs = {}) {
3547 var semantic = getBusinessObject(element),
3548 isThrowing = isThrowEvent(semantic);
3549
3550 if (semantic.get('eventDefinitions') && semantic.get('eventDefinitions').length > 1) {
3551 if (semantic.get('parallelMultiple')) {
3552 return eventIconRenderers[ 'bpmn:ParallelMultipleEventDefinition' ](parentGfx, element, attrs, isThrowing);
3553 }
3554 else {
3555 return eventIconRenderers[ 'bpmn:MultipleEventDefinition' ](parentGfx, element, attrs, isThrowing);
3556 }
3557 }
3558
3559 if (isTypedEvent(semantic, 'bpmn:MessageEventDefinition')) {
3560 return eventIconRenderers[ 'bpmn:MessageEventDefinition' ](parentGfx, element, attrs, isThrowing);
3561 }
3562
3563 if (isTypedEvent(semantic, 'bpmn:TimerEventDefinition')) {
3564 return eventIconRenderers[ 'bpmn:TimerEventDefinition' ](parentGfx, element, attrs, isThrowing);
3565 }
3566
3567 if (isTypedEvent(semantic, 'bpmn:ConditionalEventDefinition')) {
3568 return eventIconRenderers[ 'bpmn:ConditionalEventDefinition' ](parentGfx, element, attrs, isThrowing);
3569 }
3570
3571 if (isTypedEvent(semantic, 'bpmn:SignalEventDefinition')) {
3572 return eventIconRenderers[ 'bpmn:SignalEventDefinition' ](parentGfx, element, attrs, isThrowing);
3573 }
3574
3575 if (isTypedEvent(semantic, 'bpmn:EscalationEventDefinition')) {
3576 return eventIconRenderers[ 'bpmn:EscalationEventDefinition' ](parentGfx, element, attrs, isThrowing);
3577 }
3578
3579 if (isTypedEvent(semantic, 'bpmn:LinkEventDefinition')) {
3580 return eventIconRenderers[ 'bpmn:LinkEventDefinition' ](parentGfx, element, attrs, isThrowing);
3581 }
3582
3583 if (isTypedEvent(semantic, 'bpmn:ErrorEventDefinition')) {
3584 return eventIconRenderers[ 'bpmn:ErrorEventDefinition' ](parentGfx, element, attrs, isThrowing);
3585 }
3586
3587 if (isTypedEvent(semantic, 'bpmn:CancelEventDefinition')) {
3588 return eventIconRenderers[ 'bpmn:CancelEventDefinition' ](parentGfx, element, attrs, isThrowing);
3589 }
3590
3591 if (isTypedEvent(semantic, 'bpmn:CompensateEventDefinition')) {
3592 return eventIconRenderers[ 'bpmn:CompensateEventDefinition' ](parentGfx, element, attrs, isThrowing);
3593 }
3594
3595 if (isTypedEvent(semantic, 'bpmn:TerminateEventDefinition')) {
3596 return eventIconRenderers[ 'bpmn:TerminateEventDefinition' ](parentGfx, element, attrs, isThrowing);
3597 }
3598
3599 return null;
3600 }
3601
3602 var taskMarkerRenderers = {
3603 'ParticipantMultiplicityMarker': function(parentGfx, element, attrs = {}) {
3604 var width = getWidth(element, attrs),
3605 height = getHeight(element, attrs);
3606
3607 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
3608 xScaleFactor: 1,
3609 yScaleFactor: 1,
3610 containerWidth: width,
3611 containerHeight: height,
3612 position: {
3613 mx: ((width / 2 - 6) / width),
3614 my: (height - 15) / height
3615 }
3616 });
3617
3618 drawMarker('participant-multiplicity', parentGfx, markerPath, {
3619 strokeWidth: 2,
3620 fill: getFillColor(element, defaultFillColor, attrs.fill),
3621 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3622 });
3623 },
3624 'SubProcessMarker': function(parentGfx, element, attrs = {}) {
3625 var markerRect = drawRect(parentGfx, 14, 14, 0, {
3626 strokeWidth: 1,
3627 fill: getFillColor(element, defaultFillColor, attrs.fill),
3628 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3629 });
3630
3631 translate$1(markerRect, element.width / 2 - 7.5, element.height - 20);
3632
3633 var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
3634 xScaleFactor: 1.5,
3635 yScaleFactor: 1.5,
3636 containerWidth: element.width,
3637 containerHeight: element.height,
3638 position: {
3639 mx: (element.width / 2 - 7.5) / element.width,
3640 my: (element.height - 20) / element.height
3641 }
3642 });
3643
3644 drawMarker('sub-process', parentGfx, markerPath, {
3645 fill: getFillColor(element, defaultFillColor, attrs.fill),
3646 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3647 });
3648 },
3649 'ParallelMarker': function(parentGfx, element, attrs) {
3650 var width = getWidth(element, attrs),
3651 height = getHeight(element, attrs);
3652
3653 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
3654 xScaleFactor: 1,
3655 yScaleFactor: 1,
3656 containerWidth: width,
3657 containerHeight: height,
3658 position: {
3659 mx: ((width / 2 + attrs.parallel) / width),
3660 my: (height - 20) / height
3661 }
3662 });
3663
3664 drawMarker('parallel', parentGfx, markerPath, {
3665 fill: getFillColor(element, defaultFillColor, attrs.fill),
3666 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3667 });
3668 },
3669 'SequentialMarker': function(parentGfx, element, attrs) {
3670 var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
3671 xScaleFactor: 1,
3672 yScaleFactor: 1,
3673 containerWidth: element.width,
3674 containerHeight: element.height,
3675 position: {
3676 mx: ((element.width / 2 + attrs.seq) / element.width),
3677 my: (element.height - 19) / element.height
3678 }
3679 });
3680
3681 drawMarker('sequential', parentGfx, markerPath, {
3682 fill: getFillColor(element, defaultFillColor, attrs.fill),
3683 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3684 });
3685 },
3686 'CompensationMarker': function(parentGfx, element, attrs) {
3687 var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
3688 xScaleFactor: 1,
3689 yScaleFactor: 1,
3690 containerWidth: element.width,
3691 containerHeight: element.height,
3692 position: {
3693 mx: ((element.width / 2 + attrs.compensation) / element.width),
3694 my: (element.height - 13) / element.height
3695 }
3696 });
3697
3698 drawMarker('compensation', parentGfx, markerMath, {
3699 strokeWidth: 1,
3700 fill: getFillColor(element, defaultFillColor, attrs.fill),
3701 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3702 });
3703 },
3704 'LoopMarker': function(parentGfx, element, attrs) {
3705 var width = getWidth(element, attrs),
3706 height = getHeight(element, attrs);
3707
3708 var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
3709 xScaleFactor: 1,
3710 yScaleFactor: 1,
3711 containerWidth: width,
3712 containerHeight: height,
3713 position: {
3714 mx: ((width / 2 + attrs.loop) / width),
3715 my: (height - 7) / height
3716 }
3717 });
3718
3719 drawMarker('loop', parentGfx, markerPath, {
3720 strokeWidth: 1.5,
3721 fill: 'none',
3722 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3723 strokeMiterlimit: 0.5
3724 });
3725 },
3726 'AdhocMarker': function(parentGfx, element, attrs) {
3727 var width = getWidth(element, attrs),
3728 height = getHeight(element, attrs);
3729
3730 var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
3731 xScaleFactor: 1,
3732 yScaleFactor: 1,
3733 containerWidth: width,
3734 containerHeight: height,
3735 position: {
3736 mx: ((width / 2 + attrs.adhoc) / width),
3737 my: (height - 15) / height
3738 }
3739 });
3740
3741 drawMarker('adhoc', parentGfx, markerPath, {
3742 strokeWidth: 1,
3743 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
3744 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3745 });
3746 }
3747 };
3748
3749 function renderTaskMarker(type, parentGfx, element, attrs) {
3750 taskMarkerRenderers[ type ](parentGfx, element, attrs);
3751 }
3752
3753 function renderTaskMarkers(parentGfx, element, taskMarkers, attrs = {}) {
3754 attrs = {
3755 fill: attrs.fill,
3756 stroke: attrs.stroke,
3757 width: getWidth(element, attrs),
3758 height: getHeight(element, attrs)
3759 };
3760
3761 var semantic = getBusinessObject(element);
3762
3763 var subprocess = taskMarkers && taskMarkers.includes('SubProcessMarker');
3764
3765 if (subprocess) {
3766 attrs = {
3767 ...attrs,
3768 seq: -21,
3769 parallel: -22,
3770 compensation: -42,
3771 loop: -18,
3772 adhoc: 10
3773 };
3774 } else {
3775 attrs = {
3776 ...attrs,
3777 seq: -5,
3778 parallel: -6,
3779 compensation: -27,
3780 loop: 0,
3781 adhoc: 10
3782 };
3783 }
3784
3785 forEach$1(taskMarkers, function(marker) {
3786 renderTaskMarker(marker, parentGfx, element, attrs);
3787 });
3788
3789 if (semantic.get('isForCompensation')) {
3790 renderTaskMarker('CompensationMarker', parentGfx, element, attrs);
3791 }
3792
3793 if (is$1(semantic, 'bpmn:AdHocSubProcess')) {
3794 renderTaskMarker('AdhocMarker', parentGfx, element, attrs);
3795 }
3796
3797 var loopCharacteristics = semantic.get('loopCharacteristics'),
3798 isSequential = loopCharacteristics && loopCharacteristics.get('isSequential');
3799
3800 if (loopCharacteristics) {
3801
3802 if (isSequential === undefined) {
3803 renderTaskMarker('LoopMarker', parentGfx, element, attrs);
3804 }
3805
3806 if (isSequential === false) {
3807 renderTaskMarker('ParallelMarker', parentGfx, element, attrs);
3808 }
3809
3810 if (isSequential === true) {
3811 renderTaskMarker('SequentialMarker', parentGfx, element, attrs);
3812 }
3813 }
3814 }
3815
3816 function renderLabel(parentGfx, label, attrs = {}) {
3817 attrs = assign$1({
3818 size: {
3819 width: 100
3820 }
3821 }, attrs);
3822
3823 var text = textRenderer.createText(label || '', attrs);
3824
3825 classes$1(text).add('djs-label');
3826
3827 append(parentGfx, text);
3828
3829 return text;
3830 }
3831
3832 function renderEmbeddedLabel(parentGfx, element, align, attrs = {}) {
3833 var semantic = getBusinessObject(element);
3834
3835 var box = getBounds({
3836 x: element.x,
3837 y: element.y,
3838 width: element.width,
3839 height: element.height
3840 }, attrs);
3841
3842 return renderLabel(parentGfx, semantic.name, {
3843 align,
3844 box,
3845 padding: 7,
3846 style: {
3847 fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor, attrs.stroke)
3848 }
3849 });
3850 }
3851
3852 function renderExternalLabel(parentGfx, element, attrs = {}) {
3853 var box = {
3854 width: 90,
3855 height: 30,
3856 x: element.width / 2 + element.x,
3857 y: element.height / 2 + element.y
3858 };
3859
3860 return renderLabel(parentGfx, getLabel(element), {
3861 box: box,
3862 fitBox: true,
3863 style: assign$1(
3864 {},
3865 textRenderer.getExternalStyle(),
3866 {
3867 fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor, attrs.stroke)
3868 }
3869 )
3870 });
3871 }
3872
3873 function renderLaneLabel(parentGfx, text, element, attrs = {}) {
3874 var isHorizontalLane = isHorizontal(element);
3875
3876 var textBox = renderLabel(parentGfx, text, {
3877 box: {
3878 height: 30,
3879 width: isHorizontalLane ? getHeight(element, attrs) : getWidth(element, attrs),
3880 },
3881 align: 'center-middle',
3882 style: {
3883 fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor, attrs.stroke)
3884 }
3885 });
3886
3887 if (isHorizontalLane) {
3888 var top = -1 * getHeight(element, attrs);
3889 transform(textBox, 0, -top, 270);
3890 }
3891 }
3892
3893 function renderActivity(parentGfx, element, attrs = {}) {
3894 var {
3895 width,
3896 height
3897 } = getBounds(element, attrs);
3898
3899 return drawRect(parentGfx, width, height, TASK_BORDER_RADIUS, {
3900 ...attrs,
3901 fill: getFillColor(element, defaultFillColor, attrs.fill),
3902 fillOpacity: DEFAULT_OPACITY,
3903 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3904 });
3905 }
3906
3907 function renderAssociation(parentGfx, element, attrs = {}) {
3908 var semantic = getBusinessObject(element);
3909
3910 var fill = getFillColor(element, defaultFillColor, attrs.fill),
3911 stroke = getStrokeColor(element, defaultStrokeColor, attrs.stroke);
3912
3913 if (semantic.get('associationDirection') === 'One' ||
3914 semantic.get('associationDirection') === 'Both') {
3915 attrs.markerEnd = marker('association-end', fill, stroke);
3916 }
3917
3918 if (semantic.get('associationDirection') === 'Both') {
3919 attrs.markerStart = marker('association-start', fill, stroke);
3920 }
3921
3922 attrs = pickAttrs(attrs, [
3923 'markerStart',
3924 'markerEnd'
3925 ]);
3926
3927 return drawConnectionSegments(parentGfx, element.waypoints, {
3928 ...attrs,
3929 stroke,
3930 strokeDasharray: '0, 5'
3931 });
3932 }
3933
3934 function renderDataObject(parentGfx, element, attrs = {}) {
3935 var fill = getFillColor(element, defaultFillColor, attrs.fill),
3936 stroke = getStrokeColor(element, defaultStrokeColor, attrs.stroke);
3937
3938 var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
3939 xScaleFactor: 1,
3940 yScaleFactor: 1,
3941 containerWidth: element.width,
3942 containerHeight: element.height,
3943 position: {
3944 mx: 0.474,
3945 my: 0.296
3946 }
3947 });
3948
3949 var dataObject = drawPath(parentGfx, pathData, {
3950 fill,
3951 fillOpacity: DEFAULT_OPACITY,
3952 stroke
3953 });
3954
3955 var semantic = getBusinessObject(element);
3956
3957 if (isCollection(semantic)) {
3958 var collectionPathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
3959 xScaleFactor: 1,
3960 yScaleFactor: 1,
3961 containerWidth: element.width,
3962 containerHeight: element.height,
3963 position: {
3964 mx: 0.33,
3965 my: (element.height - 18) / element.height
3966 }
3967 });
3968
3969 drawPath(parentGfx, collectionPathData, {
3970 strokeWidth: 2,
3971 fill,
3972 stroke
3973 });
3974 }
3975
3976 return dataObject;
3977 }
3978
3979 function renderEvent(parentGfx, element, attrs = {}) {
3980 return drawCircle(parentGfx, element.width, element.height, {
3981 fillOpacity: DEFAULT_OPACITY,
3982 ...attrs,
3983 fill: getFillColor(element, defaultFillColor, attrs.fill),
3984 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3985 });
3986 }
3987
3988 function renderGateway(parentGfx, element, attrs = {}) {
3989 return drawDiamond(parentGfx, element.width, element.height, {
3990 fill: getFillColor(element, defaultFillColor, attrs.fill),
3991 fillOpacity: DEFAULT_OPACITY,
3992 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
3993 });
3994 }
3995
3996 function renderLane(parentGfx, element, attrs = {}) {
3997 var lane = drawRect(parentGfx, getWidth(element, attrs), getHeight(element, attrs), 0, {
3998 fill: getFillColor(element, defaultFillColor, attrs.fill),
3999 fillOpacity: attrs.fillOpacity || DEFAULT_OPACITY,
4000 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4001 strokeWidth: 1.5
4002 });
4003
4004 var semantic = getBusinessObject(element);
4005
4006 if (is$1(semantic, 'bpmn:Lane')) {
4007 var text = semantic.get('name');
4008
4009 renderLaneLabel(parentGfx, text, element, attrs);
4010 }
4011
4012 return lane;
4013 }
4014
4015 function renderSubProcess(parentGfx, element, attrs = {}) {
4016 var activity = renderActivity(parentGfx, element, attrs);
4017
4018 if (isEventSubProcess(element)) {
4019 attr$1(activity, {
4020 strokeDasharray: '0, 5.5',
4021 strokeWidth: 2.5
4022 });
4023 }
4024
4025 var expanded = isExpanded(element);
4026
4027 renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle', attrs);
4028
4029 if (expanded) {
4030 renderTaskMarkers(parentGfx, element, undefined, attrs);
4031 } else {
4032 renderTaskMarkers(parentGfx, element, [ 'SubProcessMarker' ], attrs);
4033 }
4034
4035 return activity;
4036 }
4037
4038 function renderTask(parentGfx, element, attrs = {}) {
4039 var activity = renderActivity(parentGfx, element, attrs);
4040
4041 renderEmbeddedLabel(parentGfx, element, 'center-middle', attrs);
4042
4043 renderTaskMarkers(parentGfx, element, undefined, attrs);
4044
4045 return activity;
4046 }
4047
4048 var handlers = this.handlers = {
4049 'bpmn:AdHocSubProcess': function(parentGfx, element, attrs = {}) {
4050 if (isExpanded(element)) {
4051 attrs = pickAttrs(attrs, [
4052 'fill',
4053 'stroke',
4054 'width',
4055 'height'
4056 ]);
4057 } else {
4058 attrs = pickAttrs(attrs, [
4059 'fill',
4060 'stroke'
4061 ]);
4062 }
4063
4064 return renderSubProcess(parentGfx, element, attrs);
4065 },
4066 'bpmn:Association': function(parentGfx, element, attrs = {}) {
4067 attrs = pickAttrs(attrs, [
4068 'fill',
4069 'stroke'
4070 ]);
4071
4072 return renderAssociation(parentGfx, element, attrs);
4073 },
4074 'bpmn:BoundaryEvent': function(parentGfx, element, attrs = {}) {
4075 var { renderIcon = true } = attrs;
4076
4077 attrs = pickAttrs(attrs, [
4078 'fill',
4079 'stroke'
4080 ]);
4081
4082 var semantic = getBusinessObject(element),
4083 cancelActivity = semantic.get('cancelActivity');
4084
4085 attrs = {
4086 strokeWidth: 1.5,
4087 fill: getFillColor(element, defaultFillColor, attrs.fill),
4088 fillOpacity: FULL_OPACITY,
4089 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
4090 };
4091
4092 if (!cancelActivity) {
4093 attrs.strokeDasharray = '6';
4094 }
4095
4096 var event = renderEvent(parentGfx, element, attrs);
4097
4098 drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
4099 ...attrs,
4100 fill: 'none'
4101 });
4102
4103 if (renderIcon) {
4104 renderEventIcon(element, parentGfx, attrs);
4105 }
4106
4107 return event;
4108 },
4109 'bpmn:BusinessRuleTask': function(parentGfx, element, attrs = {}) {
4110 attrs = pickAttrs(attrs, [
4111 'fill',
4112 'stroke'
4113 ]);
4114
4115 var task = renderTask(parentGfx, element, attrs);
4116
4117 var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
4118 abspos: {
4119 x: 8,
4120 y: 8
4121 }
4122 });
4123
4124 var businessPath = drawPath(parentGfx, headerData);
4125
4126 attr$1(businessPath, {
4127 fill: getFillColor(element, defaultFillColor, attrs.fill),
4128 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4129 strokeWidth: 1
4130 });
4131
4132 var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
4133 abspos: {
4134 x: 8,
4135 y: 8
4136 }
4137 });
4138
4139 var businessHeaderPath = drawPath(parentGfx, headerPathData);
4140
4141 attr$1(businessHeaderPath, {
4142 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4143 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4144 strokeWidth: 1
4145 });
4146
4147 return task;
4148 },
4149 'bpmn:CallActivity': function(parentGfx, element, attrs = {}) {
4150 attrs = pickAttrs(attrs, [
4151 'fill',
4152 'stroke'
4153 ]);
4154
4155 return renderSubProcess(parentGfx, element, {
4156 strokeWidth: 5,
4157 ...attrs
4158 });
4159 },
4160 'bpmn:ComplexGateway': function(parentGfx, element, attrs = {}) {
4161 attrs = pickAttrs(attrs, [
4162 'fill',
4163 'stroke'
4164 ]);
4165
4166 var gateway = renderGateway(parentGfx, element, attrs);
4167
4168 var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
4169 xScaleFactor: 0.5,
4170 yScaleFactor:0.5,
4171 containerWidth: element.width,
4172 containerHeight: element.height,
4173 position: {
4174 mx: 0.46,
4175 my: 0.26
4176 }
4177 });
4178
4179 drawPath(parentGfx, pathData, {
4180 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4181 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4182 strokeWidth: 1
4183 });
4184
4185 return gateway;
4186 },
4187 'bpmn:DataInput': function(parentGfx, element, attrs = {}) {
4188 attrs = pickAttrs(attrs, [
4189 'fill',
4190 'stroke'
4191 ]);
4192
4193 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
4194
4195 var dataObject = renderDataObject(parentGfx, element, attrs);
4196
4197 drawPath(parentGfx, arrowPathData, {
4198 fill: 'none',
4199 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4200 strokeWidth: 1
4201 });
4202
4203 return dataObject;
4204 },
4205 'bpmn:DataInputAssociation': function(parentGfx, element, attrs = {}) {
4206 attrs = pickAttrs(attrs, [
4207 'fill',
4208 'stroke'
4209 ]);
4210
4211 return renderAssociation(parentGfx, element, {
4212 ...attrs,
4213 markerEnd: marker('association-end', getFillColor(element, defaultFillColor, attrs.fill), getStrokeColor(element, defaultStrokeColor, attrs.stroke))
4214 });
4215 },
4216 'bpmn:DataObject': function(parentGfx, element, attrs = {}) {
4217 attrs = pickAttrs(attrs, [
4218 'fill',
4219 'stroke'
4220 ]);
4221
4222 return renderDataObject(parentGfx, element, attrs);
4223 },
4224 'bpmn:DataObjectReference': as('bpmn:DataObject'),
4225 'bpmn:DataOutput': function(parentGfx, element, attrs = {}) {
4226 attrs = pickAttrs(attrs, [
4227 'fill',
4228 'stroke'
4229 ]);
4230
4231 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
4232
4233 var dataObject = renderDataObject(parentGfx, element, attrs);
4234
4235 drawPath(parentGfx, arrowPathData, {
4236 strokeWidth: 1,
4237 fill: getFillColor(element, defaultFillColor, attrs.fill),
4238 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
4239 });
4240
4241 return dataObject;
4242 },
4243 'bpmn:DataOutputAssociation': function(parentGfx, element, attrs = {}) {
4244 attrs = pickAttrs(attrs, [
4245 'fill',
4246 'stroke'
4247 ]);
4248
4249 return renderAssociation(parentGfx, element, {
4250 ...attrs,
4251 markerEnd: marker('association-end', getFillColor(element, defaultFillColor, attrs.fill), getStrokeColor(element, defaultStrokeColor, attrs.stroke))
4252 });
4253 },
4254 'bpmn:DataStoreReference': function(parentGfx, element, attrs = {}) {
4255 attrs = pickAttrs(attrs, [
4256 'fill',
4257 'stroke'
4258 ]);
4259
4260 var dataStorePath = pathMap.getScaledPath('DATA_STORE', {
4261 xScaleFactor: 1,
4262 yScaleFactor: 1,
4263 containerWidth: element.width,
4264 containerHeight: element.height,
4265 position: {
4266 mx: 0,
4267 my: 0.133
4268 }
4269 });
4270
4271 return drawPath(parentGfx, dataStorePath, {
4272 fill: getFillColor(element, defaultFillColor, attrs.fill),
4273 fillOpacity: DEFAULT_OPACITY,
4274 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4275 strokeWidth: 2
4276 });
4277 },
4278 'bpmn:EndEvent': function(parentGfx, element, attrs = {}) {
4279 var { renderIcon = true } = attrs;
4280
4281 attrs = pickAttrs(attrs, [
4282 'fill',
4283 'stroke'
4284 ]);
4285
4286 var event = renderEvent(parentGfx, element, {
4287 ...attrs,
4288 strokeWidth: 4
4289 });
4290
4291 if (renderIcon) {
4292 renderEventIcon(element, parentGfx, attrs);
4293 }
4294
4295 return event;
4296 },
4297 'bpmn:EventBasedGateway': function(parentGfx, element, attrs = {}) {
4298 attrs = pickAttrs(attrs, [
4299 'fill',
4300 'stroke'
4301 ]);
4302
4303 var semantic = getBusinessObject(element);
4304
4305 var diamond = renderGateway(parentGfx, element, attrs);
4306
4307 drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
4308 fill: getFillColor(element, 'none', attrs.fill),
4309 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4310 strokeWidth: 1
4311 });
4312
4313 var type = semantic.get('eventGatewayType'),
4314 instantiate = !!semantic.get('instantiate');
4315
4316 function drawEvent() {
4317
4318 var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
4319 xScaleFactor: 0.18,
4320 yScaleFactor: 0.18,
4321 containerWidth: element.width,
4322 containerHeight: element.height,
4323 position: {
4324 mx: 0.36,
4325 my: 0.44
4326 }
4327 });
4328
4329 drawPath(parentGfx, pathData, {
4330 fill: 'none',
4331 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4332 strokeWidth: 2
4333 });
4334 }
4335
4336 if (type === 'Parallel') {
4337 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
4338 xScaleFactor: 0.4,
4339 yScaleFactor: 0.4,
4340 containerWidth: element.width,
4341 containerHeight: element.height,
4342 position: {
4343 mx: 0.474,
4344 my: 0.296
4345 }
4346 });
4347
4348 drawPath(parentGfx, pathData, {
4349 fill: 'none',
4350 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4351 strokeWidth: 1
4352 });
4353 } else if (type === 'Exclusive') {
4354 if (!instantiate) {
4355 drawCircle(parentGfx, element.width, element.height, element.height * 0.26, {
4356 fill: 'none',
4357 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4358 strokeWidth: 1
4359 });
4360 }
4361
4362 drawEvent();
4363 }
4364
4365
4366 return diamond;
4367 },
4368 'bpmn:ExclusiveGateway': function(parentGfx, element, attrs = {}) {
4369 attrs = pickAttrs(attrs, [
4370 'fill',
4371 'stroke'
4372 ]);
4373
4374 var gateway = renderGateway(parentGfx, element, attrs);
4375
4376 var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
4377 xScaleFactor: 0.4,
4378 yScaleFactor: 0.4,
4379 containerWidth: element.width,
4380 containerHeight: element.height,
4381 position: {
4382 mx: 0.32,
4383 my: 0.3
4384 }
4385 });
4386
4387 var di = getDi(element);
4388
4389 if (di.get('isMarkerVisible')) {
4390 drawPath(parentGfx, pathData, {
4391 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4392 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4393 strokeWidth: 1
4394 });
4395 }
4396
4397 return gateway;
4398 },
4399 'bpmn:Gateway': function(parentGfx, element, attrs = {}) {
4400 attrs = pickAttrs(attrs, [
4401 'fill',
4402 'stroke'
4403 ]);
4404
4405 return renderGateway(parentGfx, element, attrs);
4406 },
4407 'bpmn:Group': function(parentGfx, element, attrs = {}) {
4408 attrs = pickAttrs(attrs, [
4409 'fill',
4410 'stroke',
4411 'width',
4412 'height'
4413 ]);
4414
4415 return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
4416 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4417 strokeWidth: 1.5,
4418 strokeDasharray: '10, 6, 0, 6',
4419 fill: 'none',
4420 pointerEvents: 'none',
4421 width: getWidth(element, attrs),
4422 height: getHeight(element, attrs)
4423 });
4424 },
4425 'bpmn:InclusiveGateway': function(parentGfx, element, attrs = {}) {
4426 attrs = pickAttrs(attrs, [
4427 'fill',
4428 'stroke'
4429 ]);
4430
4431 var gateway = renderGateway(parentGfx, element, attrs);
4432
4433 drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
4434 fill: getFillColor(element, defaultFillColor, attrs.fill),
4435 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4436 strokeWidth: 2.5
4437 });
4438
4439 return gateway;
4440 },
4441 'bpmn:IntermediateEvent': function(parentGfx, element, attrs = {}) {
4442 var { renderIcon = true } = attrs;
4443
4444 attrs = pickAttrs(attrs, [
4445 'fill',
4446 'stroke'
4447 ]);
4448
4449 var outer = renderEvent(parentGfx, element, {
4450 ...attrs,
4451 strokeWidth: 1.5
4452 });
4453
4454 drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
4455 fill: 'none',
4456 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4457 strokeWidth: 1.5
4458 });
4459
4460 if (renderIcon) {
4461 renderEventIcon(element, parentGfx, attrs);
4462 }
4463
4464 return outer;
4465 },
4466 'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
4467 'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
4468 'bpmn:Lane': function(parentGfx, element, attrs = {}) {
4469 attrs = pickAttrs(attrs, [
4470 'fill',
4471 'stroke',
4472 'width',
4473 'height'
4474 ]);
4475
4476 return renderLane(parentGfx, element, {
4477 ...attrs,
4478 fillOpacity: LOW_OPACITY
4479 });
4480 },
4481 'bpmn:ManualTask': function(parentGfx, element, attrs = {}) {
4482 attrs = pickAttrs(attrs, [
4483 'fill',
4484 'stroke'
4485 ]);
4486
4487 var task = renderTask(parentGfx, element, attrs);
4488
4489 var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
4490 abspos: {
4491 x: 17,
4492 y: 15
4493 }
4494 });
4495
4496 drawPath(parentGfx, pathData, {
4497 fill: getFillColor(element, defaultFillColor, attrs.fill),
4498 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4499 strokeWidth: 0.5
4500 });
4501
4502 return task;
4503 },
4504 'bpmn:MessageFlow': function(parentGfx, element, attrs = {}) {
4505 attrs = pickAttrs(attrs, [
4506 'fill',
4507 'stroke'
4508 ]);
4509
4510 var semantic = getBusinessObject(element),
4511 di = getDi(element);
4512
4513 var fill = getFillColor(element, defaultFillColor, attrs.fill),
4514 stroke = getStrokeColor(element, defaultStrokeColor, attrs.stroke);
4515
4516 var path = drawConnectionSegments(parentGfx, element.waypoints, {
4517 markerEnd: marker('messageflow-end', fill, stroke),
4518 markerStart: marker('messageflow-start', fill, stroke),
4519 stroke,
4520 strokeDasharray: '10, 11',
4521 strokeWidth: 1.5
4522 });
4523
4524 if (semantic.get('messageRef')) {
4525 var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
4526
4527 var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
4528 abspos: {
4529 x: midPoint.x,
4530 y: midPoint.y
4531 }
4532 });
4533
4534 var messageAttrs = {
4535 strokeWidth: 1
4536 };
4537
4538 if (di.get('messageVisibleKind') === 'initiating') {
4539 messageAttrs.fill = fill;
4540 messageAttrs.stroke = stroke;
4541 } else {
4542 messageAttrs.fill = stroke;
4543 messageAttrs.stroke = fill;
4544 }
4545
4546 var message = drawPath(parentGfx, markerPathData, messageAttrs);
4547
4548 var messageRef = semantic.get('messageRef'),
4549 name = messageRef.get('name');
4550
4551 var label = renderLabel(parentGfx, name, {
4552 align: 'center-top',
4553 fitBox: true,
4554 style: {
4555 fill: stroke
4556 }
4557 });
4558
4559 var messageBounds = message.getBBox(),
4560 labelBounds = label.getBBox();
4561
4562 var translateX = midPoint.x - labelBounds.width / 2,
4563 translateY = midPoint.y + messageBounds.height / 2 + ELEMENT_LABEL_DISTANCE;
4564
4565 transform(label, translateX, translateY, 0);
4566 }
4567
4568 return path;
4569 },
4570 'bpmn:ParallelGateway': function(parentGfx, element, attrs = {}) {
4571 attrs = pickAttrs(attrs, [
4572 'fill',
4573 'stroke'
4574 ]);
4575
4576 var diamond = renderGateway(parentGfx, element, attrs);
4577
4578 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
4579 xScaleFactor: 0.6,
4580 yScaleFactor: 0.6,
4581 containerWidth: element.width,
4582 containerHeight: element.height,
4583 position: {
4584 mx: 0.46,
4585 my: 0.2
4586 }
4587 });
4588
4589 drawPath(parentGfx, pathData, {
4590 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4591 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4592 strokeWidth: 1
4593 });
4594
4595 return diamond;
4596 },
4597 'bpmn:Participant': function(parentGfx, element, attrs = {}) {
4598 attrs = pickAttrs(attrs, [
4599 'fill',
4600 'stroke',
4601 'width',
4602 'height'
4603 ]);
4604
4605 var participant = renderLane(parentGfx, element, attrs);
4606
4607 var expandedParticipant = isExpanded(element);
4608 var horizontalParticipant = isHorizontal(element);
4609
4610 var semantic = getBusinessObject(element),
4611 name = semantic.get('name');
4612
4613 if (expandedParticipant) {
4614 var waypoints = horizontalParticipant ? [
4615 {
4616 x: 30,
4617 y: 0
4618 },
4619 {
4620 x: 30,
4621 y: getHeight(element, attrs)
4622 }
4623 ] : [
4624 {
4625 x: 0,
4626 y: 30
4627 },
4628 {
4629 x: getWidth(element, attrs),
4630 y: 30
4631 }
4632 ];
4633
4634 drawLine(parentGfx, waypoints, {
4635 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4636 strokeWidth: PARTICIPANT_STROKE_WIDTH
4637 });
4638
4639 renderLaneLabel(parentGfx, name, element, attrs);
4640 } else {
4641 var bounds = getBounds(element, attrs);
4642
4643 if (!horizontalParticipant) {
4644 bounds.height = getWidth(element, attrs);
4645 bounds.width = getHeight(element, attrs);
4646 }
4647
4648 var textBox = renderLabel(parentGfx, name, {
4649 box: bounds,
4650 align: 'center-middle',
4651 style: {
4652 fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor, attrs.stroke)
4653 }
4654 });
4655
4656 if (!horizontalParticipant) {
4657 var top = -1 * getHeight(element, attrs);
4658 transform(textBox, 0, -top, 270);
4659 }
4660 }
4661
4662 if (semantic.get('participantMultiplicity')) {
4663 renderTaskMarker('ParticipantMultiplicityMarker', parentGfx, element, attrs);
4664 }
4665
4666 return participant;
4667 },
4668 'bpmn:ReceiveTask' : function(parentGfx, element, attrs = {}) {
4669 attrs = pickAttrs(attrs, [
4670 'fill',
4671 'stroke'
4672 ]);
4673
4674 var semantic = getBusinessObject(element);
4675
4676 var task = renderTask(parentGfx, element, attrs);
4677
4678 var pathData;
4679
4680 if (semantic.get('instantiate')) {
4681 drawCircle(parentGfx, 28, 28, 20 * 0.22, {
4682 fill: getFillColor(element, defaultFillColor, attrs.fill),
4683 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4684 strokeWidth: 1
4685 });
4686
4687 pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
4688 abspos: {
4689 x: 7.77,
4690 y: 9.52
4691 }
4692 });
4693 } else {
4694 pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
4695 xScaleFactor: 0.9,
4696 yScaleFactor: 0.9,
4697 containerWidth: 21,
4698 containerHeight: 14,
4699 position: {
4700 mx: 0.3,
4701 my: 0.4
4702 }
4703 });
4704 }
4705
4706 drawPath(parentGfx, pathData, {
4707 fill: getFillColor(element, defaultFillColor, attrs.fill),
4708 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4709 strokeWidth: 1
4710 });
4711
4712 return task;
4713 },
4714 'bpmn:ScriptTask': function(parentGfx, element, attrs = {}) {
4715 attrs = pickAttrs(attrs, [
4716 'fill',
4717 'stroke'
4718 ]);
4719
4720 var task = renderTask(parentGfx, element, attrs);
4721
4722 var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
4723 abspos: {
4724 x: 15,
4725 y: 20
4726 }
4727 });
4728
4729 drawPath(parentGfx, pathData, {
4730 fill: getFillColor(element, defaultFillColor, attrs.fill),
4731 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4732 strokeWidth: 1
4733 });
4734
4735 return task;
4736 },
4737 'bpmn:SendTask': function(parentGfx, element, attrs = {}) {
4738 attrs = pickAttrs(attrs, [
4739 'fill',
4740 'stroke'
4741 ]);
4742
4743 var task = renderTask(parentGfx, element, attrs);
4744
4745 var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
4746 xScaleFactor: 1,
4747 yScaleFactor: 1,
4748 containerWidth: 21,
4749 containerHeight: 14,
4750 position: {
4751 mx: 0.285,
4752 my: 0.357
4753 }
4754 });
4755
4756 drawPath(parentGfx, pathData, {
4757 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4758 stroke: getFillColor(element, defaultFillColor, attrs.fill),
4759 strokeWidth: 1
4760 });
4761
4762 return task;
4763 },
4764 'bpmn:SequenceFlow': function(parentGfx, element, attrs = {}) {
4765 attrs = pickAttrs(attrs, [
4766 'fill',
4767 'stroke'
4768 ]);
4769
4770 var fill = getFillColor(element, defaultFillColor, attrs.fill),
4771 stroke = getStrokeColor(element, defaultStrokeColor, attrs.stroke);
4772
4773 var connection = drawConnectionSegments(parentGfx, element.waypoints, {
4774 markerEnd: marker('sequenceflow-end', fill, stroke),
4775 stroke
4776 });
4777
4778 var semantic = getBusinessObject(element);
4779
4780 var { source } = element;
4781
4782 if (source) {
4783 var sourceSemantic = getBusinessObject(source);
4784
4785 // conditional flow marker
4786 if (semantic.get('conditionExpression') && is$1(sourceSemantic, 'bpmn:Activity')) {
4787 attr$1(connection, {
4788 markerStart: marker('conditional-flow-marker', fill, stroke)
4789 });
4790 }
4791
4792 // default marker
4793 if (sourceSemantic.get('default') && (is$1(sourceSemantic, 'bpmn:Gateway') || is$1(sourceSemantic, 'bpmn:Activity')) &&
4794 sourceSemantic.get('default') === semantic) {
4795 attr$1(connection, {
4796 markerStart: marker('conditional-default-flow-marker', fill, stroke)
4797 });
4798 }
4799 }
4800
4801 return connection;
4802 },
4803 'bpmn:ServiceTask': function(parentGfx, element, attrs = {}) {
4804 attrs = pickAttrs(attrs, [
4805 'fill',
4806 'stroke'
4807 ]);
4808
4809 var task = renderTask(parentGfx, element, attrs);
4810
4811 drawCircle(parentGfx, 10, 10, {
4812 fill: getFillColor(element, defaultFillColor, attrs.fill),
4813 stroke: 'none',
4814 transform: 'translate(6, 6)'
4815 });
4816
4817 var pathDataService1 = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
4818 abspos: {
4819 x: 12,
4820 y: 18
4821 }
4822 });
4823
4824 drawPath(parentGfx, pathDataService1, {
4825 fill: getFillColor(element, defaultFillColor, attrs.fill),
4826 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4827 strokeWidth: 1
4828 });
4829
4830 drawCircle(parentGfx, 10, 10, {
4831 fill: getFillColor(element, defaultFillColor, attrs.fill),
4832 stroke: 'none',
4833 transform: 'translate(11, 10)'
4834 });
4835
4836 var pathDataService2 = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
4837 abspos: {
4838 x: 17,
4839 y: 22
4840 }
4841 });
4842
4843 drawPath(parentGfx, pathDataService2, {
4844 fill: getFillColor(element, defaultFillColor, attrs.fill),
4845 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4846 strokeWidth: 1
4847 });
4848
4849 return task;
4850 },
4851 'bpmn:StartEvent': function(parentGfx, element, attrs = {}) {
4852 var { renderIcon = true } = attrs;
4853
4854 attrs = pickAttrs(attrs, [
4855 'fill',
4856 'stroke'
4857 ]);
4858
4859 var semantic = getBusinessObject(element);
4860
4861 if (!semantic.get('isInterrupting')) {
4862 attrs = {
4863 ...attrs,
4864 strokeDasharray: '6'
4865 };
4866 }
4867
4868 var event = renderEvent(parentGfx, element, attrs);
4869
4870 if (renderIcon) {
4871 renderEventIcon(element, parentGfx, attrs);
4872 }
4873
4874 return event;
4875 },
4876 'bpmn:SubProcess': function(parentGfx, element, attrs = {}) {
4877 if (isExpanded(element)) {
4878 attrs = pickAttrs(attrs, [
4879 'fill',
4880 'stroke',
4881 'width',
4882 'height'
4883 ]);
4884 } else {
4885 attrs = pickAttrs(attrs, [
4886 'fill',
4887 'stroke'
4888 ]);
4889 }
4890
4891 return renderSubProcess(parentGfx, element, attrs);
4892 },
4893 'bpmn:Task': function(parentGfx, element, attrs = {}) {
4894 attrs = pickAttrs(attrs, [
4895 'fill',
4896 'stroke'
4897 ]);
4898
4899 return renderTask(parentGfx, element, attrs);
4900 },
4901 'bpmn:TextAnnotation': function(parentGfx, element, attrs = {}) {
4902 attrs = pickAttrs(attrs, [
4903 'fill',
4904 'stroke',
4905 'width',
4906 'height'
4907 ]);
4908
4909 var {
4910 width,
4911 height
4912 } = getBounds(element, attrs);
4913
4914 var textElement = drawRect(parentGfx, width, height, 0, 0, {
4915 fill: 'none',
4916 stroke: 'none'
4917 });
4918
4919 var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
4920 xScaleFactor: 1,
4921 yScaleFactor: 1,
4922 containerWidth: width,
4923 containerHeight: height,
4924 position: {
4925 mx: 0.0,
4926 my: 0.0
4927 }
4928 });
4929
4930 drawPath(parentGfx, textPathData, {
4931 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke)
4932 });
4933
4934 var semantic = getBusinessObject(element),
4935 text = semantic.get('text') || '';
4936
4937 renderLabel(parentGfx, text, {
4938 align: 'left-top',
4939 box: getBounds(element, attrs),
4940 padding: 7,
4941 style: {
4942 fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor, attrs.stroke)
4943 }
4944 });
4945
4946 return textElement;
4947 },
4948 'bpmn:Transaction': function(parentGfx, element, attrs = {}) {
4949 if (isExpanded(element)) {
4950 attrs = pickAttrs(attrs, [
4951 'fill',
4952 'stroke',
4953 'width',
4954 'height'
4955 ]);
4956 } else {
4957 attrs = pickAttrs(attrs, [
4958 'fill',
4959 'stroke'
4960 ]);
4961 }
4962
4963 var outer = renderSubProcess(parentGfx, element, {
4964 strokeWidth: 1.5,
4965 ...attrs
4966 });
4967
4968 var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
4969 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
4970 strokeWidth: 1.5
4971 });
4972
4973 var expanded = isExpanded(element);
4974
4975 if (!expanded) {
4976 attrs = {};
4977 }
4978
4979 drawRect(
4980 parentGfx,
4981 getWidth(element, attrs),
4982 getHeight(element, attrs),
4983 TASK_BORDER_RADIUS - INNER_OUTER_DIST,
4984 INNER_OUTER_DIST,
4985 innerAttrs
4986 );
4987
4988 return outer;
4989 },
4990 'bpmn:UserTask': function(parentGfx, element, attrs = {}) {
4991 attrs = pickAttrs(attrs, [
4992 'fill',
4993 'stroke'
4994 ]);
4995
4996 var task = renderTask(parentGfx, element, attrs);
4997
4998 var x = 15;
4999 var y = 12;
5000
5001 var pathDataUser1 = pathMap.getScaledPath('TASK_TYPE_USER_1', {
5002 abspos: {
5003 x: x,
5004 y: y
5005 }
5006 });
5007
5008 drawPath(parentGfx, pathDataUser1, {
5009 fill: getFillColor(element, defaultFillColor, attrs.fill),
5010 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
5011 strokeWidth: 0.5
5012 });
5013
5014 var pathDataUser2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
5015 abspos: {
5016 x: x,
5017 y: y
5018 }
5019 });
5020
5021 drawPath(parentGfx, pathDataUser2, {
5022 fill: getFillColor(element, defaultFillColor, attrs.fill),
5023 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
5024 strokeWidth: 0.5
5025 });
5026
5027 var pathDataUser3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
5028 abspos: {
5029 x: x,
5030 y: y
5031 }
5032 });
5033
5034 drawPath(parentGfx, pathDataUser3, {
5035 fill: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
5036 stroke: getStrokeColor(element, defaultStrokeColor, attrs.stroke),
5037 strokeWidth: 0.5
5038 });
5039
5040 return task;
5041 },
5042 'label': function(parentGfx, element, attrs = {}) {
5043 return renderExternalLabel(parentGfx, element, attrs);
5044 }
5045 };
5046
5047 // extension API, use at your own risk
5048 this._drawPath = drawPath;
5049
5050 this._renderer = renderer;
5051 }
5052
5053
5054 e(BpmnRenderer, BaseRenderer);
5055
5056 BpmnRenderer.$inject = [
5057 'config.bpmnRenderer',
5058 'eventBus',
5059 'styles',
5060 'pathMap',
5061 'canvas',
5062 'textRenderer'
5063 ];
5064
5065
5066 /**
5067 * @param {Element} element
5068 *
5069 * @return {boolean}
5070 */
5071 BpmnRenderer.prototype.canRender = function(element) {
5072 return is$1(element, 'bpmn:BaseElement');
5073 };
5074
5075 /**
5076 * Draw shape into parentGfx.
5077 *
5078 * @param {SVGElement} parentGfx
5079 * @param {Element} element
5080 * @param {Attrs} [attrs]
5081 *
5082 * @return {SVGElement} mainGfx
5083 */
5084 BpmnRenderer.prototype.drawShape = function(parentGfx, element, attrs = {}) {
5085 var { type } = element;
5086
5087 var handler = this._renderer(type);
5088
5089 return handler(parentGfx, element, attrs);
5090 };
5091
5092 /**
5093 * Draw connection into parentGfx.
5094 *
5095 * @param {SVGElement} parentGfx
5096 * @param {Element} element
5097 * @param {Attrs} [attrs]
5098 *
5099 * @return {SVGElement} mainGfx
5100 */
5101 BpmnRenderer.prototype.drawConnection = function(parentGfx, element, attrs = {}) {
5102 var { type } = element;
5103
5104 var handler = this._renderer(type);
5105
5106 return handler(parentGfx, element, attrs);
5107 };
5108
5109 /**
5110 * Get shape path.
5111 *
5112 * @param {Element} element
5113 *
5114 * @return {string} path
5115 */
5116 BpmnRenderer.prototype.getShapePath = function(element) {
5117 if (is$1(element, 'bpmn:Event')) {
5118 return getCirclePath(element);
5119 }
5120
5121 if (is$1(element, 'bpmn:Activity')) {
5122 return getRoundRectPath(element, TASK_BORDER_RADIUS);
5123 }
5124
5125 if (is$1(element, 'bpmn:Gateway')) {
5126 return getDiamondPath(element);
5127 }
5128
5129 return getRectPath(element);
5130 };
5131
5132 /**
5133 * Pick attributes if they exist.
5134 *
5135 * @param {Object} attrs
5136 * @param {string[]} keys
5137 *
5138 * @returns {Object}
5139 */
5140 function pickAttrs(attrs, keys = []) {
5141 return keys.reduce((pickedAttrs, key) => {
5142 if (attrs[ key ]) {
5143 pickedAttrs[ key ] = attrs[ key ];
5144 }
5145
5146 return pickedAttrs;
5147 }, {});
5148 }
5149
5150 /**
5151 * @typedef {import('../util/Types').Dimensions} Dimensions
5152 *
5153 * @typedef { {
5154 * top: number;
5155 * left: number;
5156 * right: number;
5157 * bottom: number;
5158 * } } Padding
5159 *
5160 * @typedef { number | Partial<Padding> } PaddingConfig
5161 *
5162 * @typedef { {
5163 * horizontal: 'center' | 'left' | 'right';
5164 * vertical: 'top' | 'middle';
5165 * } } Alignment
5166 *
5167 * @typedef { 'center-middle' | 'center-top' } AlignmentConfig
5168 *
5169 * @typedef { Partial<{
5170 * align: AlignmentConfig;
5171 * style: Record<string, number | string>;
5172 * padding: PaddingConfig;
5173 * }> } BaseTextConfig
5174 *
5175 * @typedef { BaseTextConfig & Partial<{
5176 * size: Dimensions;
5177 * }> } TextConfig
5178 *
5179 * @typedef { BaseTextConfig & Partial<{
5180 * box: Dimensions;
5181 * fitBox: boolean;
5182 * }> } TextLayoutConfig
5183 *
5184 * @typedef { Dimensions & {
5185 * text: string;
5186 * } } LineDescriptor
5187 */
5188
5189 var DEFAULT_BOX_PADDING = 0;
5190
5191 var DEFAULT_LABEL_SIZE = {
5192 width: 150,
5193 height: 50
5194 };
5195
5196
5197 /**
5198 * @param {AlignmentConfig} align
5199 * @return {Alignment}
5200 */
5201 function parseAlign(align) {
5202
5203 var parts = align.split('-');
5204
5205 return {
5206 horizontal: parts[0] || 'center',
5207 vertical: parts[1] || 'top'
5208 };
5209 }
5210
5211 /**
5212 * @param {PaddingConfig} padding
5213 *
5214 * @return {Padding}
5215 */
5216 function parsePadding(padding) {
5217
5218 if (isObject(padding)) {
5219 return assign$1({ top: 0, left: 0, right: 0, bottom: 0 }, padding);
5220 } else {
5221 return {
5222 top: padding,
5223 left: padding,
5224 right: padding,
5225 bottom: padding
5226 };
5227 }
5228 }
5229
5230 /**
5231 * @param {string} text
5232 * @param {SVGTextElement} fakeText
5233 *
5234 * @return {import('../util/Types').Dimensions}
5235 */
5236 function getTextBBox(text, fakeText) {
5237
5238 fakeText.textContent = text;
5239
5240 var textBBox;
5241
5242 try {
5243 var bbox,
5244 emptyLine = text === '';
5245
5246 // add dummy text, when line is empty to
5247 // determine correct height
5248 fakeText.textContent = emptyLine ? 'dummy' : text;
5249
5250 textBBox = fakeText.getBBox();
5251
5252 // take text rendering related horizontal
5253 // padding into account
5254 bbox = {
5255 width: textBBox.width + textBBox.x * 2,
5256 height: textBBox.height
5257 };
5258
5259 if (emptyLine) {
5260
5261 // correct width
5262 bbox.width = 0;
5263 }
5264
5265 return bbox;
5266 } catch (e) {
5267 return { width: 0, height: 0 };
5268 }
5269 }
5270
5271
5272 /**
5273 * Layout the next line and return the layouted element.
5274 *
5275 * Alters the lines passed.
5276 *
5277 * @param {string[]} lines
5278 * @param {number} maxWidth
5279 * @param {SVGTextElement} fakeText
5280 *
5281 * @return {LineDescriptor} the line descriptor
5282 */
5283 function layoutNext(lines, maxWidth, fakeText) {
5284
5285 var originalLine = lines.shift(),
5286 fitLine = originalLine;
5287
5288 var textBBox;
5289
5290 for (;;) {
5291 textBBox = getTextBBox(fitLine, fakeText);
5292
5293 textBBox.width = fitLine ? textBBox.width : 0;
5294
5295 // try to fit
5296 if (fitLine === ' ' || fitLine === '' || textBBox.width < Math.round(maxWidth) || fitLine.length < 2) {
5297 return fit(lines, fitLine, originalLine, textBBox);
5298 }
5299
5300 fitLine = shortenLine(fitLine, textBBox.width, maxWidth);
5301 }
5302 }
5303
5304 /**
5305 * @param {string[]} lines
5306 * @param {string} fitLine
5307 * @param {string} originalLine
5308 * @param {Dimensions} textBBox
5309 *
5310 * @return {LineDescriptor}
5311 */
5312 function fit(lines, fitLine, originalLine, textBBox) {
5313 if (fitLine.length < originalLine.length) {
5314 var remainder = originalLine.slice(fitLine.length).trim();
5315
5316 lines.unshift(remainder);
5317 }
5318
5319 return {
5320 width: textBBox.width,
5321 height: textBBox.height,
5322 text: fitLine
5323 };
5324 }
5325
5326 var SOFT_BREAK = '\u00AD';
5327
5328
5329 /**
5330 * Shortens a line based on spacing and hyphens.
5331 * Returns the shortened result on success.
5332 *
5333 * @param {string} line
5334 * @param {number} maxLength the maximum characters of the string
5335 *
5336 * @return {string} the shortened string
5337 */
5338 function semanticShorten(line, maxLength) {
5339
5340 var parts = line.split(/(\s|-|\u00AD)/g),
5341 part,
5342 shortenedParts = [],
5343 length = 0;
5344
5345 // try to shorten via break chars
5346 if (parts.length > 1) {
5347
5348 while ((part = parts.shift())) {
5349 if (part.length + length < maxLength) {
5350 shortenedParts.push(part);
5351 length += part.length;
5352 } else {
5353
5354 // remove previous part, too if hyphen does not fit anymore
5355 if (part === '-' || part === SOFT_BREAK) {
5356 shortenedParts.pop();
5357 }
5358
5359 break;
5360 }
5361 }
5362 }
5363
5364 var last = shortenedParts[shortenedParts.length - 1];
5365
5366 // translate trailing soft break to actual hyphen
5367 if (last && last === SOFT_BREAK) {
5368 shortenedParts[shortenedParts.length - 1] = '-';
5369 }
5370
5371 return shortenedParts.join('');
5372 }
5373
5374
5375 /**
5376 * @param {string} line
5377 * @param {number} width
5378 * @param {number} maxWidth
5379 *
5380 * @return {string}
5381 */
5382 function shortenLine(line, width, maxWidth) {
5383 var length = Math.max(line.length * (maxWidth / width), 1);
5384
5385 // try to shorten semantically (i.e. based on spaces and hyphens)
5386 var shortenedLine = semanticShorten(line, length);
5387
5388 if (!shortenedLine) {
5389
5390 // force shorten by cutting the long word
5391 shortenedLine = line.slice(0, Math.max(Math.round(length - 1), 1));
5392 }
5393
5394 return shortenedLine;
5395 }
5396
5397
5398 /**
5399 * @return {SVGSVGElement}
5400 */
5401 function getHelperSvg() {
5402 var helperSvg = document.getElementById('helper-svg');
5403
5404 if (!helperSvg) {
5405 helperSvg = create$1('svg');
5406
5407 attr$1(helperSvg, {
5408 id: 'helper-svg'
5409 });
5410
5411 assign(helperSvg, {
5412 visibility: 'hidden',
5413 position: 'fixed',
5414 width: 0,
5415 height: 0
5416 });
5417
5418 document.body.appendChild(helperSvg);
5419 }
5420
5421 return helperSvg;
5422 }
5423
5424
5425 /**
5426 * Creates a new label utility
5427 *
5428 * @param {TextConfig} [config]
5429 */
5430 function Text(config) {
5431
5432 this._config = assign$1({}, {
5433 size: DEFAULT_LABEL_SIZE,
5434 padding: DEFAULT_BOX_PADDING,
5435 style: {},
5436 align: 'center-top'
5437 }, config || {});
5438 }
5439
5440 /**
5441 * Returns the layouted text as an SVG element.
5442 *
5443 * @param {string} text
5444 * @param {TextLayoutConfig} options
5445 *
5446 * @return {SVGElement}
5447 */
5448 Text.prototype.createText = function(text, options) {
5449 return this.layoutText(text, options).element;
5450 };
5451
5452 /**
5453 * Returns a labels layouted dimensions.
5454 *
5455 * @param {string} text to layout
5456 * @param {TextLayoutConfig} options
5457 *
5458 * @return {Dimensions}
5459 */
5460 Text.prototype.getDimensions = function(text, options) {
5461 return this.layoutText(text, options).dimensions;
5462 };
5463
5464 /**
5465 * Creates and returns a label and its bounding box.
5466 *
5467 * @param {string} text the text to render on the label
5468 * @param {TextLayoutConfig} options
5469 *
5470 * @return { {
5471 * element: SVGElement,
5472 * dimensions: Dimensions
5473 * } }
5474 */
5475 Text.prototype.layoutText = function(text, options) {
5476 var box = assign$1({}, this._config.size, options.box),
5477 style = assign$1({}, this._config.style, options.style),
5478 align = parseAlign(options.align || this._config.align),
5479 padding = parsePadding(options.padding !== undefined ? options.padding : this._config.padding),
5480 fitBox = options.fitBox || false;
5481
5482 var lineHeight = getLineHeight(style);
5483
5484 // we split text by lines and normalize
5485 // {soft break} + {line break} => { line break }
5486 var lines = text.split(/\u00AD?\r?\n/),
5487 layouted = [];
5488
5489 var maxWidth = box.width - padding.left - padding.right;
5490
5491 // ensure correct rendering by attaching helper text node to invisible SVG
5492 var helperText = create$1('text');
5493 attr$1(helperText, { x: 0, y: 0 });
5494 attr$1(helperText, style);
5495
5496 var helperSvg = getHelperSvg();
5497
5498 append(helperSvg, helperText);
5499
5500 while (lines.length) {
5501 layouted.push(layoutNext(lines, maxWidth, helperText));
5502 }
5503
5504 if (align.vertical === 'middle') {
5505 padding.top = padding.bottom = 0;
5506 }
5507
5508 var totalHeight = reduce(layouted, function(sum, line, idx) {
5509 return sum + (lineHeight || line.height);
5510 }, 0) + padding.top + padding.bottom;
5511
5512 var maxLineWidth = reduce(layouted, function(sum, line, idx) {
5513 return line.width > sum ? line.width : sum;
5514 }, 0);
5515
5516 // the y position of the next line
5517 var y = padding.top;
5518
5519 if (align.vertical === 'middle') {
5520 y += (box.height - totalHeight) / 2;
5521 }
5522
5523 // magic number initial offset
5524 y -= (lineHeight || layouted[0].height) / 4;
5525
5526
5527 var textElement = create$1('text');
5528
5529 attr$1(textElement, style);
5530
5531 // layout each line taking into account that parent
5532 // shape might resize to fit text size
5533 forEach$1(layouted, function(line) {
5534
5535 var x;
5536
5537 y += (lineHeight || line.height);
5538
5539 switch (align.horizontal) {
5540 case 'left':
5541 x = padding.left;
5542 break;
5543
5544 case 'right':
5545 x = ((fitBox ? maxLineWidth : maxWidth)
5546 - padding.right - line.width);
5547 break;
5548
5549 default:
5550
5551 // aka center
5552 x = Math.max((((fitBox ? maxLineWidth : maxWidth)
5553 - line.width) / 2 + padding.left), 0);
5554 }
5555
5556 var tspan = create$1('tspan');
5557 attr$1(tspan, { x: x, y: y });
5558
5559 tspan.textContent = line.text;
5560
5561 append(textElement, tspan);
5562 });
5563
5564 remove$2(helperText);
5565
5566 var dimensions = {
5567 width: maxLineWidth,
5568 height: totalHeight
5569 };
5570
5571 return {
5572 dimensions: dimensions,
5573 element: textElement
5574 };
5575 };
5576
5577
5578 function getLineHeight(style) {
5579 if ('fontSize' in style && 'lineHeight' in style) {
5580 return style.lineHeight * parseInt(style.fontSize, 10);
5581 }
5582 }
5583
5584 var DEFAULT_FONT_SIZE = 12;
5585 var LINE_HEIGHT_RATIO = 1.2;
5586
5587 var MIN_TEXT_ANNOTATION_HEIGHT = 30;
5588
5589 /**
5590 * @typedef { {
5591 * fontFamily: string;
5592 * fontSize: number;
5593 * fontWeight: string;
5594 * lineHeight: number;
5595 * } } TextRendererStyle
5596 *
5597 * @typedef { {
5598 * defaultStyle?: Partial<TextRendererStyle>;
5599 * externalStyle?: Partial<TextRendererStyle>;
5600 * } } TextRendererConfig
5601 *
5602 * @typedef { import('diagram-js/lib/util/Text').TextLayoutConfig } TextLayoutConfig
5603 *
5604 * @typedef { import('diagram-js/lib/util/Types').Rect } Rect
5605 */
5606
5607
5608 /**
5609 * Renders text and computes text bounding boxes.
5610 *
5611 * @param {TextRendererConfig} [config]
5612 */
5613 function TextRenderer(config) {
5614
5615 var defaultStyle = assign$1({
5616 fontFamily: 'Arial, sans-serif',
5617 fontSize: DEFAULT_FONT_SIZE,
5618 fontWeight: 'normal',
5619 lineHeight: LINE_HEIGHT_RATIO
5620 }, config && config.defaultStyle || {});
5621
5622 var fontSize = parseInt(defaultStyle.fontSize, 10) - 1;
5623
5624 var externalStyle = assign$1({}, defaultStyle, {
5625 fontSize: fontSize
5626 }, config && config.externalStyle || {});
5627
5628 var textUtil = new Text({
5629 style: defaultStyle
5630 });
5631
5632 /**
5633 * Get the new bounds of an externally rendered,
5634 * layouted label.
5635 *
5636 * @param {Rect} bounds
5637 * @param {string} text
5638 *
5639 * @return {Rect}
5640 */
5641 this.getExternalLabelBounds = function(bounds, text) {
5642
5643 var layoutedDimensions = textUtil.getDimensions(text, {
5644 box: {
5645 width: 90,
5646 height: 30
5647 },
5648 style: externalStyle
5649 });
5650
5651 // resize label shape to fit label text
5652 return {
5653 x: Math.round(bounds.x + bounds.width / 2 - layoutedDimensions.width / 2),
5654 y: Math.round(bounds.y),
5655 width: Math.ceil(layoutedDimensions.width),
5656 height: Math.ceil(layoutedDimensions.height)
5657 };
5658
5659 };
5660
5661 /**
5662 * Get the new bounds of text annotation.
5663 *
5664 * @param {Rect} bounds
5665 * @param {string} text
5666 *
5667 * @return {Rect}
5668 */
5669 this.getTextAnnotationBounds = function(bounds, text) {
5670
5671 var layoutedDimensions = textUtil.getDimensions(text, {
5672 box: bounds,
5673 style: defaultStyle,
5674 align: 'left-top',
5675 padding: 5
5676 });
5677
5678 return {
5679 x: bounds.x,
5680 y: bounds.y,
5681 width: bounds.width,
5682 height: Math.max(MIN_TEXT_ANNOTATION_HEIGHT, Math.round(layoutedDimensions.height))
5683 };
5684 };
5685
5686 /**
5687 * Create a layouted text element.
5688 *
5689 * @param {string} text
5690 * @param {TextLayoutConfig} [options]
5691 *
5692 * @return {SVGElement} rendered text
5693 */
5694 this.createText = function(text, options) {
5695 return textUtil.createText(text, options || {});
5696 };
5697
5698 /**
5699 * Get default text style.
5700 */
5701 this.getDefaultStyle = function() {
5702 return defaultStyle;
5703 };
5704
5705 /**
5706 * Get the external text style.
5707 */
5708 this.getExternalStyle = function() {
5709 return externalStyle;
5710 };
5711
5712 }
5713
5714 TextRenderer.$inject = [
5715 'config.textRenderer'
5716 ];
5717
5718 /**
5719 * Map containing SVG paths needed by BpmnRenderer
5720 */
5721 function PathMap() {
5722
5723 /**
5724 * Contains a map of path elements
5725 *
5726 * <h1>Path definition</h1>
5727 * A parameterized path is defined like this:
5728 * <pre>
5729 * 'GATEWAY_PARALLEL': {
5730 * d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
5731 '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
5732 * height: 17.5,
5733 * width: 17.5,
5734 * heightElements: [2.5, 7.5],
5735 * widthElements: [2.5, 7.5]
5736 * }
5737 * </pre>
5738 * <p>It's important to specify a correct <b>height and width</b> for the path as the scaling
5739 * is based on the ratio between the specified height and width in this object and the
5740 * height and width that is set as scale target (Note x,y coordinates will be scaled with
5741 * individual ratios).</p>
5742 * <p>The '<b>heightElements</b>' and '<b>widthElements</b>' array must contain the values that will be scaled.
5743 * The scaling is based on the computed ratios.
5744 * Coordinates on the y axis should be in the <b>heightElement</b>'s array, they will be scaled using
5745 * the computed ratio coefficient.
5746 * In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets.
5747 * <ul>
5748 * <li>The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....</li>
5749 * <li>The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....</li>
5750 * </ul>
5751 * The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index.
5752 * </p>
5753 */
5754 this.pathMap = {
5755 'EVENT_MESSAGE': {
5756 d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}',
5757 height: 36,
5758 width: 36,
5759 heightElements: [ 6, 14 ],
5760 widthElements: [ 10.5, 21 ]
5761 },
5762 'EVENT_SIGNAL': {
5763 d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x1},0 Z',
5764 height: 36,
5765 width: 36,
5766 heightElements: [ 18 ],
5767 widthElements: [ 10, 20 ]
5768 },
5769 'EVENT_ESCALATION': {
5770 d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x0},-{e.y1} l -{e.x0},{e.y1} Z',
5771 height: 36,
5772 width: 36,
5773 heightElements: [ 20, 7 ],
5774 widthElements: [ 8 ]
5775 },
5776 'EVENT_CONDITIONAL': {
5777 d: 'M {e.x0},{e.y0} l {e.x1},0 l 0,{e.y2} l -{e.x1},0 Z ' +
5778 'M {e.x2},{e.y3} l {e.x0},0 ' +
5779 'M {e.x2},{e.y4} l {e.x0},0 ' +
5780 'M {e.x2},{e.y5} l {e.x0},0 ' +
5781 'M {e.x2},{e.y6} l {e.x0},0 ' +
5782 'M {e.x2},{e.y7} l {e.x0},0 ' +
5783 'M {e.x2},{e.y8} l {e.x0},0 ',
5784 height: 36,
5785 width: 36,
5786 heightElements: [ 8.5, 14.5, 18, 11.5, 14.5, 17.5, 20.5, 23.5, 26.5 ],
5787 widthElements: [ 10.5, 14.5, 12.5 ]
5788 },
5789 'EVENT_LINK': {
5790 d: 'm {mx},{my} 0,{e.y0} -{e.x1},0 0,{e.y1} {e.x1},0 0,{e.y0} {e.x0},-{e.y2} -{e.x0},-{e.y2} z',
5791 height: 36,
5792 width: 36,
5793 heightElements: [ 4.4375, 6.75, 7.8125 ],
5794 widthElements: [ 9.84375, 13.5 ]
5795 },
5796 'EVENT_ERROR': {
5797 d: 'm {mx},{my} {e.x0},-{e.y0} {e.x1},-{e.y1} {e.x2},{e.y2} {e.x3},-{e.y3} -{e.x4},{e.y4} -{e.x5},-{e.y5} z',
5798 height: 36,
5799 width: 36,
5800 heightElements: [ 0.023, 8.737, 8.151, 16.564, 10.591, 8.714 ],
5801 widthElements: [ 0.085, 6.672, 6.97, 4.273, 5.337, 6.636 ]
5802 },
5803 'EVENT_CANCEL_45': {
5804 d: 'm {mx},{my} -{e.x1},0 0,{e.x0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
5805 '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
5806 height: 36,
5807 width: 36,
5808 heightElements: [ 4.75, 8.5 ],
5809 widthElements: [ 4.75, 8.5 ]
5810 },
5811 'EVENT_COMPENSATION': {
5812 d: 'm {mx},{my} {e.x0},-{e.y0} 0,{e.y1} z m {e.x1},-{e.y2} {e.x2},-{e.y3} 0,{e.y1} -{e.x2},-{e.y3} z',
5813 height: 36,
5814 width: 36,
5815 heightElements: [ 6.5, 13, 0.4, 6.1 ],
5816 widthElements: [ 9, 9.3, 8.7 ]
5817 },
5818 'EVENT_TIMER_WH': {
5819 d: 'M {mx},{my} l {e.x0},-{e.y0} m -{e.x0},{e.y0} l {e.x1},{e.y1} ',
5820 height: 36,
5821 width: 36,
5822 heightElements: [ 10, 2 ],
5823 widthElements: [ 3, 7 ]
5824 },
5825 'EVENT_TIMER_LINE': {
5826 d: 'M {mx},{my} ' +
5827 'm {e.x0},{e.y0} l -{e.x1},{e.y1} ',
5828 height: 36,
5829 width: 36,
5830 heightElements: [ 10, 3 ],
5831 widthElements: [ 0, 0 ]
5832 },
5833 'EVENT_MULTIPLE': {
5834 d:'m {mx},{my} {e.x1},-{e.y0} {e.x1},{e.y0} -{e.x0},{e.y1} -{e.x2},0 z',
5835 height: 36,
5836 width: 36,
5837 heightElements: [ 6.28099, 12.56199 ],
5838 widthElements: [ 3.1405, 9.42149, 12.56198 ]
5839 },
5840 'EVENT_PARALLEL_MULTIPLE': {
5841 d:'m {mx},{my} {e.x0},0 0,{e.y1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
5842 '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
5843 height: 36,
5844 width: 36,
5845 heightElements: [ 2.56228, 7.68683 ],
5846 widthElements: [ 2.56228, 7.68683 ]
5847 },
5848 'GATEWAY_EXCLUSIVE': {
5849 d:'m {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' +
5850 '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' +
5851 '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z',
5852 height: 17.5,
5853 width: 17.5,
5854 heightElements: [ 8.5, 6.5312, -6.5312, -8.5 ],
5855 widthElements: [ 6.5, -6.5, 3, -3, 5, -5 ]
5856 },
5857 'GATEWAY_PARALLEL': {
5858 d:'m {mx},{my} 0,{e.y1} -{e.x1},0 0,{e.y0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
5859 '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
5860 height: 30,
5861 width: 30,
5862 heightElements: [ 5, 12.5 ],
5863 widthElements: [ 5, 12.5 ]
5864 },
5865 'GATEWAY_EVENT_BASED': {
5866 d:'m {mx},{my} {e.x0},{e.y0} {e.x0},{e.y1} {e.x1},{e.y2} {e.x2},0 z',
5867 height: 11,
5868 width: 11,
5869 heightElements: [ -6, 6, 12, -12 ],
5870 widthElements: [ 9, -3, -12 ]
5871 },
5872 'GATEWAY_COMPLEX': {
5873 d:'m {mx},{my} 0,{e.y0} -{e.x0},-{e.y1} -{e.x1},{e.y2} {e.x0},{e.y1} -{e.x2},0 0,{e.y3} ' +
5874 '{e.x2},0 -{e.x0},{e.y1} l {e.x1},{e.y2} {e.x0},-{e.y1} 0,{e.y0} {e.x3},0 0,-{e.y0} {e.x0},{e.y1} ' +
5875 '{e.x1},-{e.y2} -{e.x0},-{e.y1} {e.x2},0 0,-{e.y3} -{e.x2},0 {e.x0},-{e.y1} -{e.x1},-{e.y2} ' +
5876 '-{e.x0},{e.y1} 0,-{e.y0} -{e.x3},0 z',
5877 height: 17.125,
5878 width: 17.125,
5879 heightElements: [ 4.875, 3.4375, 2.125, 3 ],
5880 widthElements: [ 3.4375, 2.125, 4.875, 3 ]
5881 },
5882 'DATA_OBJECT_PATH': {
5883 d:'m 0,0 {e.x1},0 {e.x0},{e.y0} 0,{e.y1} -{e.x2},0 0,-{e.y2} {e.x1},0 0,{e.y0} {e.x0},0',
5884 height: 61,
5885 width: 51,
5886 heightElements: [ 10, 50, 60 ],
5887 widthElements: [ 10, 40, 50, 60 ]
5888 },
5889 'DATA_OBJECT_COLLECTION_PATH': {
5890 d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
5891 height: 10,
5892 width: 10,
5893 heightElements: [],
5894 widthElements: []
5895 },
5896 'DATA_ARROW': {
5897 d:'m 5,9 9,0 0,-3 5,5 -5,5 0,-3 -9,0 z',
5898 height: 61,
5899 width: 51,
5900 heightElements: [],
5901 widthElements: []
5902 },
5903 'DATA_STORE': {
5904 d:'m {mx},{my} ' +
5905 'l 0,{e.y2} ' +
5906 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
5907 'l 0,-{e.y2} ' +
5908 'c -{e.x0},-{e.y1} -{e.x1},-{e.y1} -{e.x2},0' +
5909 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
5910 'm -{e.x2},{e.y0}' +
5911 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0' +
5912 'm -{e.x2},{e.y0}' +
5913 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0',
5914 height: 61,
5915 width: 61,
5916 heightElements: [ 7, 10, 45 ],
5917 widthElements: [ 2, 58, 60 ]
5918 },
5919 'TEXT_ANNOTATION': {
5920 d: 'm {mx}, {my} m 10,0 l -10,0 l 0,{e.y0} l 10,0',
5921 height: 30,
5922 width: 10,
5923 heightElements: [ 30 ],
5924 widthElements: [ 10 ]
5925 },
5926 'MARKER_SUB_PROCESS': {
5927 d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0',
5928 height: 10,
5929 width: 10,
5930 heightElements: [],
5931 widthElements: []
5932 },
5933 'MARKER_PARALLEL': {
5934 d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
5935 height: 10,
5936 width: 10,
5937 heightElements: [],
5938 widthElements: []
5939 },
5940 'MARKER_SEQUENTIAL': {
5941 d: 'm{mx},{my} m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0',
5942 height: 10,
5943 width: 10,
5944 heightElements: [],
5945 widthElements: []
5946 },
5947 'MARKER_COMPENSATION': {
5948 d: 'm {mx},{my} 7,-5 0,10 z m 7.1,-0.3 6.9,-4.7 0,10 -6.9,-4.7 z',
5949 height: 10,
5950 width: 21,
5951 heightElements: [],
5952 widthElements: []
5953 },
5954 'MARKER_LOOP': {
5955 d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' +
5956 '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' +
5957 '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' +
5958 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902',
5959 height: 13.9,
5960 width: 13.7,
5961 heightElements: [],
5962 widthElements: []
5963 },
5964 'MARKER_ADHOC': {
5965 d: 'm {mx},{my} m 0.84461,2.64411 c 1.05533,-1.23780996 2.64337,-2.07882 4.29653,-1.97997996 2.05163,0.0805 ' +
5966 '3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' +
5967 '1.2775,-0.64078 1.7542,-1.17511 0,0.56023 0,1.12046 0,1.6807 -0.98706,0.96237996 -2.29792,1.62393996 ' +
5968 '-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' +
5969 '-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z',
5970 height: 4,
5971 width: 15,
5972 heightElements: [],
5973 widthElements: []
5974 },
5975 'TASK_TYPE_SEND': {
5976 d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}',
5977 height: 14,
5978 width: 21,
5979 heightElements: [ 6, 14 ],
5980 widthElements: [ 10.5, 21 ]
5981 },
5982 'TASK_TYPE_SCRIPT': {
5983 d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' +
5984 'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' +
5985 'm -7,-12 l 5,0 ' +
5986 'm -4.5,3 l 4.5,0 ' +
5987 'm -3,3 l 5,0' +
5988 'm -4,3 l 5,0',
5989 height: 15,
5990 width: 12.6,
5991 heightElements: [ 6, 14 ],
5992 widthElements: [ 10.5, 21 ]
5993 },
5994 'TASK_TYPE_USER_1': {
5995 d: 'm {mx},{my} c 0.909,-0.845 1.594,-2.049 1.594,-3.385 0,-2.554 -1.805,-4.62199999 ' +
5996 '-4.357,-4.62199999 -2.55199998,0 -4.28799998,2.06799999 -4.28799998,4.62199999 0,1.348 ' +
5997 '0.974,2.562 1.89599998,3.405 -0.52899998,0.187 -5.669,2.097 -5.794,4.7560005 v 6.718 ' +
5998 'h 17 v -6.718 c 0,-2.2980005 -5.5279996,-4.5950005 -6.0509996,-4.7760005 z' +
5999 'm -8,6 l 0,5.5 m 11,0 l 0,-5'
6000 },
6001 'TASK_TYPE_USER_2': {
6002 d: 'm {mx},{my} m 2.162,1.009 c 0,2.4470005 -2.158,4.4310005 -4.821,4.4310005 ' +
6003 '-2.66499998,0 -4.822,-1.981 -4.822,-4.4310005 '
6004 },
6005 'TASK_TYPE_USER_3': {
6006 d: 'm {mx},{my} m -6.9,-3.80 c 0,0 2.25099998,-2.358 4.27399998,-1.177 2.024,1.181 4.221,1.537 ' +
6007 '4.124,0.965 -0.098,-0.57 -0.117,-3.79099999 -4.191,-4.13599999 -3.57499998,0.001 ' +
6008 '-4.20799998,3.36699999 -4.20699998,4.34799999 z'
6009 },
6010 'TASK_TYPE_MANUAL': {
6011 d: 'm {mx},{my} c 0.234,-0.01 5.604,0.008 8.029,0.004 0.808,0 1.271,-0.172 1.417,-0.752 0.227,-0.898 ' +
6012 '-0.334,-1.314 -1.338,-1.316 -2.467,-0.01 -7.886,-0.004 -8.108,-0.004 -0.014,-0.079 0.016,-0.533 0,-0.61 ' +
6013 '0.195,-0.042 8.507,0.006 9.616,0.002 0.877,-0.007 1.35,-0.438 1.353,-1.208 0.003,-0.768 -0.479,-1.09 ' +
6014 '-1.35,-1.091 -2.968,-0.002 -9.619,-0.013 -9.619,-0.013 v -0.591 c 0,0 5.052,-0.016 7.225,-0.016 ' +
6015 '0.888,-0.002 1.354,-0.416 1.351,-1.193 -0.006,-0.761 -0.492,-1.196 -1.361,-1.196 -3.473,-0.005 ' +
6016 '-10.86,-0.003 -11.0829995,-0.003 -0.022,-0.047 -0.045,-0.094 -0.069,-0.139 0.3939995,-0.319 ' +
6017 '2.0409995,-1.626 2.4149995,-2.017 0.469,-0.4870005 0.519,-1.1650005 0.162,-1.6040005 -0.414,-0.511 ' +
6018 '-0.973,-0.5 -1.48,-0.236 -1.4609995,0.764 -6.5999995,3.6430005 -7.7329995,4.2710005 -0.9,0.499 ' +
6019 '-1.516,1.253 -1.882,2.19 -0.37000002,0.95 -0.17,2.01 -0.166,2.979 0.004,0.718 -0.27300002,1.345 ' +
6020 '-0.055,2.063 0.629,2.087 2.425,3.312 4.859,3.318 4.6179995,0.014 9.2379995,-0.139 13.8569995,-0.158 ' +
6021 '0.755,-0.004 1.171,-0.301 1.182,-1.033 0.012,-0.754 -0.423,-0.969 -1.183,-0.973 -1.778,-0.01 ' +
6022 '-5.824,-0.004 -6.04,-0.004 10e-4,-0.084 0.003,-0.586 10e-4,-0.67 z'
6023 },
6024 'TASK_TYPE_INSTANTIATING_SEND': {
6025 d: 'm {mx},{my} l 0,8.4 l 12.6,0 l 0,-8.4 z l 6.3,3.6 l 6.3,-3.6'
6026 },
6027 'TASK_TYPE_SERVICE': {
6028 d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' +
6029 '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' +
6030 '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' +
6031 'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' +
6032 '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' +
6033 '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' +
6034 'h -2.241173 l 0.0042,1.63124 c -0.353763,0.0736 -0.705369,0.17977 -1.049785,0.32371 -0.344415,0.14437 ' +
6035 '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' +
6036 'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' +
6037 'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' +
6038 '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' +
6039 'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' +
6040 'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
6041 '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
6042 '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
6043 },
6044 'TASK_TYPE_SERVICE_FILL': {
6045 d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
6046 '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
6047 '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
6048 },
6049 'TASK_TYPE_BUSINESS_RULE_HEADER': {
6050 d: 'm {mx},{my} 0,4 20,0 0,-4 z'
6051 },
6052 'TASK_TYPE_BUSINESS_RULE_MAIN': {
6053 d: 'm {mx},{my} 0,12 20,0 0,-12 z' +
6054 'm 0,8 l 20,0 ' +
6055 'm -13,-4 l 0,8'
6056 },
6057 'MESSAGE_FLOW_MARKER': {
6058 d: 'm {mx},{my} m -10.5 ,-7 l 0,14 l 21,0 l 0,-14 z l 10.5,6 l 10.5,-6'
6059 }
6060 };
6061
6062 /**
6063 * Return raw path for the given ID.
6064 *
6065 * @param {string} pathId
6066 *
6067 * @return {string} raw path
6068 */
6069 this.getRawPath = function getRawPath(pathId) {
6070 return this.pathMap[pathId].d;
6071 };
6072
6073 /**
6074 * Scales the path to the given height and width.
6075 * <h1>Use case</h1>
6076 * <p>Use case is to scale the content of elements (event, gateways) based
6077 * on the element bounding box's size.
6078 * </p>
6079 * <h1>Why not transform</h1>
6080 * <p>Scaling a path with transform() will also scale the stroke and IE does not support
6081 * the option 'non-scaling-stroke' to prevent this.
6082 * Also there are use cases where only some parts of a path should be
6083 * scaled.</p>
6084 *
6085 * @param {string} pathId The ID of the path.
6086 * @param {Object} param <p>
6087 * Example param object scales the path to 60% size of the container (data.width, data.height).
6088 * <pre>
6089 * {
6090 * xScaleFactor: 0.6,
6091 * yScaleFactor:0.6,
6092 * containerWidth: data.width,
6093 * containerHeight: data.height,
6094 * position: {
6095 * mx: 0.46,
6096 * my: 0.2,
6097 * }
6098 * }
6099 * </pre>
6100 * <ul>
6101 * <li>targetpathwidth = xScaleFactor * containerWidth</li>
6102 * <li>targetpathheight = yScaleFactor * containerHeight</li>
6103 * <li>Position is used to set the starting coordinate of the path. M is computed:
6104 * <ul>
6105 * <li>position.x * containerWidth</li>
6106 * <li>position.y * containerHeight</li>
6107 * </ul>
6108 * Center of the container <pre> position: {
6109 * mx: 0.5,
6110 * my: 0.5,
6111 * }</pre>
6112 * Upper left corner of the container
6113 * <pre> position: {
6114 * mx: 0.0,
6115 * my: 0.0,
6116 * }</pre>
6117 * </li>
6118 * </ul>
6119 * </p>
6120 *
6121 * @return {string} scaled path
6122 */
6123 this.getScaledPath = function getScaledPath(pathId, param) {
6124 var rawPath = this.pathMap[pathId];
6125
6126 // positioning
6127 // compute the start point of the path
6128 var mx, my;
6129
6130 if (param.abspos) {
6131 mx = param.abspos.x;
6132 my = param.abspos.y;
6133 } else {
6134 mx = param.containerWidth * param.position.mx;
6135 my = param.containerHeight * param.position.my;
6136 }
6137
6138 var coordinates = {}; // map for the scaled coordinates
6139 if (param.position) {
6140
6141 // path
6142 var heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor;
6143 var widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor;
6144
6145
6146 // Apply height ratio
6147 for (var heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) {
6148 coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio;
6149 }
6150
6151 // Apply width ratio
6152 for (var widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) {
6153 coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio;
6154 }
6155 }
6156
6157 // Apply value to raw path
6158 var path = format(
6159 rawPath.d, {
6160 mx: mx,
6161 my: my,
6162 e: coordinates
6163 }
6164 );
6165 return path;
6166 };
6167 }
6168
6169 // helpers //////////////////////
6170
6171 // copied and adjusted from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js
6172 var tokenRegex = /\{([^{}]+)\}/g,
6173 objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties
6174
6175 function replacer(all, key, obj) {
6176 var res = obj;
6177 key.replace(objNotationRegex, function(all, name, quote, quotedName, isFunc) {
6178 name = name || quotedName;
6179 if (res) {
6180 if (name in res) {
6181 res = res[name];
6182 }
6183 typeof res == 'function' && isFunc && (res = res());
6184 }
6185 });
6186 res = (res == null || res == obj ? all : res) + '';
6187
6188 return res;
6189 }
6190
6191 function format(str, obj) {
6192 return String(str).replace(tokenRegex, function(all, key) {
6193 return replacer(all, key, obj);
6194 });
6195 }
6196
6197 var DrawModule$1 = {
6198 __init__: [ 'bpmnRenderer' ],
6199 bpmnRenderer: [ 'type', BpmnRenderer ],
6200 textRenderer: [ 'type', TextRenderer ],
6201 pathMap: [ 'type', PathMap ]
6202 };
6203
6204 /**
6205 * @typedef { {
6206 * [key: string]: string;
6207 * } } TranslateReplacements
6208 */
6209
6210 /**
6211 * A simple translation stub to be used for multi-language support
6212 * in diagrams. Can be easily replaced with a more sophisticated
6213 * solution.
6214 *
6215 * @example
6216 *
6217 * ```javascript
6218 * // use it inside any diagram component by injecting `translate`.
6219 *
6220 * function MyService(translate) {
6221 * alert(translate('HELLO {you}', { you: 'You!' }));
6222 * }
6223 * ```
6224 *
6225 * @param {string} template to interpolate
6226 * @param {TranslateReplacements} [replacements] a map with substitutes
6227 *
6228 * @return {string} the translated string
6229 */
6230 function translate(template, replacements) {
6231
6232 replacements = replacements || {};
6233
6234 return template.replace(/{([^}]+)}/g, function(_, key) {
6235 return replacements[key] || '{' + key + '}';
6236 });
6237 }
6238
6239 /**
6240 * @type { import('didi').ModuleDeclaration }
6241 */
6242 var TranslateModule = {
6243 translate: [ 'value', translate ]
6244 };
6245
6246 /**
6247 * @param {Point} point
6248 *
6249 * @returns {Point}
6250 */
6251 function roundPoint(point) {
6252
6253 return {
6254 x: Math.round(point.x),
6255 y: Math.round(point.y)
6256 };
6257 }
6258
6259
6260 /**
6261 * Convert the given bounds to a { top, left, bottom, right } descriptor.
6262 *
6263 * @param {Point|Rect} bounds
6264 *
6265 * @return {RectTRBL}
6266 */
6267 function asTRBL(bounds) {
6268 return {
6269 top: bounds.y,
6270 right: bounds.x + (bounds.width || 0),
6271 bottom: bounds.y + (bounds.height || 0),
6272 left: bounds.x
6273 };
6274 }
6275
6276
6277 /**
6278 * Convert a { top, left, bottom, right } to an objects bounds.
6279 *
6280 * @param {RectTRBL} trbl
6281 *
6282 * @return {Rect}
6283 */
6284 function asBounds(trbl) {
6285 return {
6286 x: trbl.left,
6287 y: trbl.top,
6288 width: trbl.right - trbl.left,
6289 height: trbl.bottom - trbl.top
6290 };
6291 }
6292
6293
6294 /**
6295 * Get the mid of the given bounds or point.
6296 *
6297 * @param {Point|Rect} bounds
6298 *
6299 * @return {Point}
6300 */
6301 function getBoundsMid(bounds) {
6302 return roundPoint({
6303 x: bounds.x + (bounds.width || 0) / 2,
6304 y: bounds.y + (bounds.height || 0) / 2
6305 });
6306 }
6307
6308
6309 /**
6310 * Get the mid of the given Connection.
6311 *
6312 * @param {Connection} connection
6313 *
6314 * @return {Point}
6315 */
6316 function getConnectionMid(connection) {
6317 var waypoints = connection.waypoints;
6318
6319 // calculate total length and length of each segment
6320 var parts = waypoints.reduce(function(parts, point, index) {
6321
6322 var lastPoint = waypoints[index - 1];
6323
6324 if (lastPoint) {
6325 var lastPart = parts[parts.length - 1];
6326
6327 var startLength = lastPart && lastPart.endLength || 0;
6328 var length = distance(lastPoint, point);
6329
6330 parts.push({
6331 start: lastPoint,
6332 end: point,
6333 startLength: startLength,
6334 endLength: startLength + length,
6335 length: length
6336 });
6337 }
6338
6339 return parts;
6340 }, []);
6341
6342 var totalLength = parts.reduce(function(length, part) {
6343 return length + part.length;
6344 }, 0);
6345
6346 // find which segement contains middle point
6347 var midLength = totalLength / 2;
6348
6349 var i = 0;
6350 var midSegment = parts[i];
6351
6352 while (midSegment.endLength < midLength) {
6353 midSegment = parts[++i];
6354 }
6355
6356 // calculate relative position on mid segment
6357 var segmentProgress = (midLength - midSegment.startLength) / midSegment.length;
6358
6359 var midPoint = {
6360 x: midSegment.start.x + (midSegment.end.x - midSegment.start.x) * segmentProgress,
6361 y: midSegment.start.y + (midSegment.end.y - midSegment.start.y) * segmentProgress
6362 };
6363
6364 return midPoint;
6365 }
6366
6367
6368 /**
6369 * Get the mid of the given Element.
6370 *
6371 * @param {Element} element
6372 *
6373 * @return {Point}
6374 */
6375 function getMid(element) {
6376 if (isConnection(element)) {
6377 return getConnectionMid(element);
6378 }
6379
6380 return getBoundsMid(element);
6381 }
6382
6383 // helpers //////////////////////
6384
6385 function distance(a, b) {
6386 return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
6387 }
6388
6389 function elementToString(e) {
6390 if (!e) {
6391 return '<null>';
6392 }
6393
6394 return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
6395 }
6396
6397 /**
6398 * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
6399 * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
6400 * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
6401 * @typedef {import('diagram-js/lib/i18n/translate/translate').default} Translate
6402 *
6403 * @typedef {import('../features/modeling/ElementFactory').default} ElementFactory
6404 * @typedef {import('../draw/TextRenderer').default} TextRenderer
6405 *
6406 * @typedef {import('../model/Types').Element} Element
6407 * @typedef {import('../model/Types').Label} Label
6408 * @typedef {import('../model/Types').Shape} Shape
6409 * @typedef {import('../model/Types').Connection} Connection
6410 * @typedef {import('../model/Types').Root} Root
6411 * @typedef {import('../model/Types').ModdleElement} ModdleElement
6412 */
6413
6414 /**
6415 * @param {ModdleElement} semantic
6416 * @param {ModdleElement} di
6417 * @param {Object} [attrs=null]
6418 *
6419 * @return {Object}
6420 */
6421 function elementData(semantic, di, attrs) {
6422 return assign$1({
6423 id: semantic.id,
6424 type: semantic.$type,
6425 businessObject: semantic,
6426 di: di
6427 }, attrs);
6428 }
6429
6430 function getWaypoints(di, source, target) {
6431
6432 var waypoints = di.waypoint;
6433
6434 if (!waypoints || waypoints.length < 2) {
6435 return [ getMid(source), getMid(target) ];
6436 }
6437
6438 return waypoints.map(function(p) {
6439 return { x: p.x, y: p.y };
6440 });
6441 }
6442
6443 function notYetDrawn(translate, semantic, refSemantic, property) {
6444 return new Error(translate('element {element} referenced by {referenced}#{property} not yet drawn', {
6445 element: elementToString(refSemantic),
6446 referenced: elementToString(semantic),
6447 property: property
6448 }));
6449 }
6450
6451
6452 /**
6453 * An importer that adds bpmn elements to the canvas
6454 *
6455 * @param {EventBus} eventBus
6456 * @param {Canvas} canvas
6457 * @param {ElementFactory} elementFactory
6458 * @param {ElementRegistry} elementRegistry
6459 * @param {Function} translate
6460 * @param {TextRenderer} textRenderer
6461 */
6462 function BpmnImporter(
6463 eventBus, canvas, elementFactory,
6464 elementRegistry, translate, textRenderer) {
6465
6466 this._eventBus = eventBus;
6467 this._canvas = canvas;
6468 this._elementFactory = elementFactory;
6469 this._elementRegistry = elementRegistry;
6470 this._translate = translate;
6471 this._textRenderer = textRenderer;
6472 }
6473
6474 BpmnImporter.$inject = [
6475 'eventBus',
6476 'canvas',
6477 'elementFactory',
6478 'elementRegistry',
6479 'translate',
6480 'textRenderer'
6481 ];
6482
6483
6484 /**
6485 * Add a BPMN element (semantic) to the canvas making it a child of the
6486 * given parent.
6487 *
6488 * @param {ModdleElement} semantic
6489 * @param {ModdleElement} di
6490 * @param {Shape} parentElement
6491 *
6492 * @return {Shape | Root | Connection}
6493 */
6494 BpmnImporter.prototype.add = function(semantic, di, parentElement) {
6495 var element,
6496 translate = this._translate,
6497 hidden;
6498
6499 var parentIndex;
6500
6501 // ROOT ELEMENT
6502 // handle the special case that we deal with a
6503 // invisible root element (process, subprocess or collaboration)
6504 if (is$1(di, 'bpmndi:BPMNPlane')) {
6505
6506 var attrs = is$1(semantic, 'bpmn:SubProcess')
6507 ? { id: semantic.id + '_plane' }
6508 : {};
6509
6510 // add a virtual element (not being drawn)
6511 element = this._elementFactory.createRoot(elementData(semantic, di, attrs));
6512
6513 this._canvas.addRootElement(element);
6514 }
6515
6516 // SHAPE
6517 else if (is$1(di, 'bpmndi:BPMNShape')) {
6518
6519 var collapsed = !isExpanded(semantic, di),
6520 isFrame = isFrameElement$1(semantic);
6521
6522 hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
6523
6524 var bounds = di.bounds;
6525
6526 element = this._elementFactory.createShape(elementData(semantic, di, {
6527 collapsed: collapsed,
6528 hidden: hidden,
6529 x: Math.round(bounds.x),
6530 y: Math.round(bounds.y),
6531 width: Math.round(bounds.width),
6532 height: Math.round(bounds.height),
6533 isFrame: isFrame
6534 }));
6535
6536 if (is$1(semantic, 'bpmn:BoundaryEvent')) {
6537 this._attachBoundary(semantic, element);
6538 }
6539
6540 // insert lanes behind other flow nodes (cf. #727)
6541 if (is$1(semantic, 'bpmn:Lane')) {
6542 parentIndex = 0;
6543 }
6544
6545 if (is$1(semantic, 'bpmn:DataStoreReference')) {
6546
6547 // check whether data store is inside our outside of its semantic parent
6548 if (!isPointInsideBBox(parentElement, getMid(bounds))) {
6549 parentElement = this._canvas.findRoot(parentElement);
6550 }
6551 }
6552
6553 this._canvas.addShape(element, parentElement, parentIndex);
6554 }
6555
6556 // CONNECTION
6557 else if (is$1(di, 'bpmndi:BPMNEdge')) {
6558
6559 var source = this._getSource(semantic),
6560 target = this._getTarget(semantic);
6561
6562 hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
6563
6564 element = this._elementFactory.createConnection(elementData(semantic, di, {
6565 hidden: hidden,
6566 source: source,
6567 target: target,
6568 waypoints: getWaypoints(di, source, target)
6569 }));
6570
6571 if (is$1(semantic, 'bpmn:DataAssociation')) {
6572
6573 // render always on top; this ensures DataAssociations
6574 // are rendered correctly across different "hacks" people
6575 // love to model such as cross participant / sub process
6576 // associations
6577 parentElement = this._canvas.findRoot(parentElement);
6578 }
6579
6580 this._canvas.addConnection(element, parentElement, parentIndex);
6581 } else {
6582 throw new Error(translate('unknown di {di} for element {semantic}', {
6583 di: elementToString(di),
6584 semantic: elementToString(semantic)
6585 }));
6586 }
6587
6588 // (optional) LABEL
6589 if (isLabelExternal(semantic) && getLabel(element)) {
6590 this.addLabel(semantic, di, element);
6591 }
6592
6593
6594 this._eventBus.fire('bpmnElement.added', { element: element });
6595
6596 return element;
6597 };
6598
6599
6600 /**
6601 * Attach a boundary element to the given host.
6602 *
6603 * @param {ModdleElement} boundarySemantic
6604 * @param {Shape} boundaryElement
6605 */
6606 BpmnImporter.prototype._attachBoundary = function(boundarySemantic, boundaryElement) {
6607 var translate = this._translate;
6608 var hostSemantic = boundarySemantic.attachedToRef;
6609
6610 if (!hostSemantic) {
6611 throw new Error(translate('missing {semantic}#attachedToRef', {
6612 semantic: elementToString(boundarySemantic)
6613 }));
6614 }
6615
6616 var host = this._elementRegistry.get(hostSemantic.id),
6617 attachers = host && host.attachers;
6618
6619 if (!host) {
6620 throw notYetDrawn(translate, boundarySemantic, hostSemantic, 'attachedToRef');
6621 }
6622
6623 // wire element.host <> host.attachers
6624 boundaryElement.host = host;
6625
6626 if (!attachers) {
6627 host.attachers = attachers = [];
6628 }
6629
6630 if (attachers.indexOf(boundaryElement) === -1) {
6631 attachers.push(boundaryElement);
6632 }
6633 };
6634
6635
6636 /**
6637 * Add a label to a given element.
6638 *
6639 * @param {ModdleElement} semantic
6640 * @param {ModdleElement} di
6641 * @param {Element} element
6642 *
6643 * @return {Label}
6644 */
6645 BpmnImporter.prototype.addLabel = function(semantic, di, element) {
6646 var bounds,
6647 text,
6648 label;
6649
6650 bounds = getExternalLabelBounds(di, element);
6651
6652 text = getLabel(element);
6653
6654 if (text) {
6655
6656 // get corrected bounds from actual layouted text
6657 bounds = this._textRenderer.getExternalLabelBounds(bounds, text);
6658 }
6659
6660 label = this._elementFactory.createLabel(elementData(semantic, di, {
6661 id: semantic.id + '_label',
6662 labelTarget: element,
6663 type: 'label',
6664 hidden: element.hidden || !getLabel(element),
6665 x: Math.round(bounds.x),
6666 y: Math.round(bounds.y),
6667 width: Math.round(bounds.width),
6668 height: Math.round(bounds.height)
6669 }));
6670
6671 return this._canvas.addShape(label, element.parent);
6672 };
6673
6674 /**
6675 * Get the source or target of the given connection.
6676 *
6677 * @param {ModdleElement} semantic
6678 * @param {'source' | 'target'} side
6679 *
6680 * @return {Element}
6681 */
6682 BpmnImporter.prototype._getConnectedElement = function(semantic, side) {
6683
6684 var element,
6685 refSemantic,
6686 type = semantic.$type,
6687 translate = this._translate;
6688
6689 refSemantic = semantic[side + 'Ref'];
6690
6691 // handle mysterious isMany DataAssociation#sourceRef
6692 if (side === 'source' && type === 'bpmn:DataInputAssociation') {
6693 refSemantic = refSemantic && refSemantic[0];
6694 }
6695
6696 // fix source / target for DataInputAssociation / DataOutputAssociation
6697 if (side === 'source' && type === 'bpmn:DataOutputAssociation' ||
6698 side === 'target' && type === 'bpmn:DataInputAssociation') {
6699
6700 refSemantic = semantic.$parent;
6701 }
6702
6703 element = refSemantic && this._getElement(refSemantic);
6704
6705 if (element) {
6706 return element;
6707 }
6708
6709 if (refSemantic) {
6710 throw notYetDrawn(translate, semantic, refSemantic, side + 'Ref');
6711 } else {
6712 throw new Error(translate('{semantic}#{side} Ref not specified', {
6713 semantic: elementToString(semantic),
6714 side: side
6715 }));
6716 }
6717 };
6718
6719 BpmnImporter.prototype._getSource = function(semantic) {
6720 return this._getConnectedElement(semantic, 'source');
6721 };
6722
6723 BpmnImporter.prototype._getTarget = function(semantic) {
6724 return this._getConnectedElement(semantic, 'target');
6725 };
6726
6727
6728 BpmnImporter.prototype._getElement = function(semantic) {
6729 return this._elementRegistry.get(semantic.id);
6730 };
6731
6732
6733 // helpers ////////////////////
6734
6735 function isPointInsideBBox(bbox, point) {
6736 var x = point.x,
6737 y = point.y;
6738
6739 return x >= bbox.x &&
6740 x <= bbox.x + bbox.width &&
6741 y >= bbox.y &&
6742 y <= bbox.y + bbox.height;
6743 }
6744
6745 function isFrameElement$1(semantic) {
6746 return is$1(semantic, 'bpmn:Group');
6747 }
6748
6749 var ImportModule = {
6750 __depends__: [
6751 TranslateModule
6752 ],
6753 bpmnImporter: [ 'type', BpmnImporter ]
6754 };
6755
6756 var CoreModule$1 = {
6757 __depends__: [
6758 DrawModule$1,
6759 ImportModule
6760 ]
6761 };
6762
6763 /**
6764 * Returns the surrounding bbox for all elements in
6765 * the array or the element primitive.
6766 *
6767 * @param {Element|Element[]} elements
6768 * @param {boolean} [stopRecursion=false]
6769 *
6770 * @return {Rect}
6771 */
6772 function getBBox(elements, stopRecursion) {
6773
6774 stopRecursion = !!stopRecursion;
6775 if (!isArray$2(elements)) {
6776 elements = [ elements ];
6777 }
6778
6779 var minX,
6780 minY,
6781 maxX,
6782 maxY;
6783
6784 forEach$1(elements, function(element) {
6785
6786 // If element is a connection the bbox must be computed first
6787 var bbox = element;
6788 if (element.waypoints && !stopRecursion) {
6789 bbox = getBBox(element.waypoints, true);
6790 }
6791
6792 var x = bbox.x,
6793 y = bbox.y,
6794 height = bbox.height || 0,
6795 width = bbox.width || 0;
6796
6797 if (x < minX || minX === undefined) {
6798 minX = x;
6799 }
6800 if (y < minY || minY === undefined) {
6801 minY = y;
6802 }
6803
6804 if ((x + width) > maxX || maxX === undefined) {
6805 maxX = x + width;
6806 }
6807 if ((y + height) > maxY || maxY === undefined) {
6808 maxY = y + height;
6809 }
6810 });
6811
6812 return {
6813 x: minX,
6814 y: minY,
6815 height: maxY - minY,
6816 width: maxX - minX
6817 };
6818 }
6819
6820 /**
6821 * Get the element's type
6822 *
6823 * @param {Element} element
6824 *
6825 * @return {'connection' | 'shape' | 'root'}
6826 */
6827 function getType(element) {
6828
6829 if ('waypoints' in element) {
6830 return 'connection';
6831 }
6832
6833 if ('x' in element) {
6834 return 'shape';
6835 }
6836
6837 return 'root';
6838 }
6839
6840 /**
6841 * @param {Element} element
6842 *
6843 * @return {boolean}
6844 */
6845 function isFrameElement(element) {
6846 return !!(element && element.isFrame);
6847 }
6848
6849 /**
6850 * Util that provides unique IDs.
6851 *
6852 * @class
6853 * @constructor
6854 *
6855 * The ids can be customized via a given prefix and contain a random value to avoid collisions.
6856 *
6857 * @param {string} [prefix] a prefix to prepend to generated ids (for better readability)
6858 */
6859 function IdGenerator(prefix) {
6860
6861 this._counter = 0;
6862 this._prefix = (prefix ? prefix + '-' : '') + Math.floor(Math.random() * 1000000000) + '-';
6863 }
6864
6865 /**
6866 * Returns a next unique ID.
6867 *
6868 * @return {string} the id
6869 */
6870 IdGenerator.prototype.next = function() {
6871 return this._prefix + (++this._counter);
6872 };
6873
6874 // document wide unique overlay ids
6875 var ids = new IdGenerator('ov');
6876
6877 var LOW_PRIORITY$3 = 500;
6878
6879 /**
6880 * @typedef {import('../../core/Canvas').default} Canvas
6881 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
6882 * @typedef {import('../../core/EventBus').default} EventBus
6883 *
6884 * @typedef {import('../../model/Types').Element} Element
6885 *
6886 * @typedef { {
6887 * minZoom?: number,
6888 * maxZoom?: number
6889 * } } OverlaysConfigShow
6890 *
6891 * @typedef { {
6892 * min?: number,
6893 * max?: number
6894 * } } OverlaysConfigScale
6895 *
6896 * @typedef { {
6897 * id: string,
6898 * type: string | null,
6899 * element: Element | string
6900 * } & OverlayAttrs } Overlay
6901 *
6902 * @typedef { {
6903 * html: HTMLElement | string,
6904 * position: {
6905 * top?: number,
6906 * right?: number,
6907 * bottom?: number,
6908 * left?: number
6909 * }
6910 * } & OverlaysConfigDefault } OverlayAttrs
6911 *
6912 * @typedef { {
6913 * html: HTMLElement,
6914 * element: Element,
6915 * overlays: Overlay[]
6916 * } } OverlayContainer
6917 *
6918 * @typedef {{
6919 * defaults?: OverlaysConfigDefault
6920 * }} OverlaysConfig
6921 *
6922 * @typedef { {
6923 * show?: OverlaysConfigShow,
6924 * scale?: OverlaysConfigScale | boolean
6925 * } } OverlaysConfigDefault
6926 *
6927 * @typedef { {
6928 * id?: string;
6929 * element?: Element | string;
6930 * type?: string;
6931 * } | string } OverlaysFilter
6932 */
6933
6934 /**
6935 * A service that allows users to attach overlays to diagram elements.
6936 *
6937 * The overlay service will take care of overlay positioning during updates.
6938 *
6939 * @example
6940 *
6941 * ```javascript
6942 * // add a pink badge on the top left of the shape
6943 *
6944 * overlays.add(someShape, {
6945 * position: {
6946 * top: -5,
6947 * left: -5
6948 * },
6949 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
6950 * });
6951 *
6952 * // or add via shape id
6953 *
6954 * overlays.add('some-element-id', {
6955 * position: {
6956 * top: -5,
6957 * left: -5
6958 * }
6959 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
6960 * });
6961 *
6962 * // or add with optional type
6963 *
6964 * overlays.add(someShape, 'badge', {
6965 * position: {
6966 * top: -5,
6967 * left: -5
6968 * }
6969 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
6970 * });
6971 * ```
6972 *
6973 * ```javascript
6974 * // remove an overlay
6975 *
6976 * var id = overlays.add(...);
6977 * overlays.remove(id);
6978 *
6979 *
6980 * You may configure overlay defaults during tool by providing a `config` module
6981 * with `overlays.defaults` as an entry:
6982 *
6983 * {
6984 * overlays: {
6985 * defaults: {
6986 * show: {
6987 * minZoom: 0.7,
6988 * maxZoom: 5.0
6989 * },
6990 * scale: {
6991 * min: 1
6992 * }
6993 * }
6994 * }
6995 * ```
6996 *
6997 * @param {OverlaysConfig} config
6998 * @param {EventBus} eventBus
6999 * @param {Canvas} canvas
7000 * @param {ElementRegistry} elementRegistry
7001 */
7002 function Overlays(config, eventBus, canvas, elementRegistry) {
7003 this._eventBus = eventBus;
7004 this._canvas = canvas;
7005 this._elementRegistry = elementRegistry;
7006
7007 this._ids = ids;
7008
7009 /**
7010 * @type {OverlaysConfigDefault}
7011 */
7012 this._overlayDefaults = assign$1({
7013
7014 // no show constraints
7015 show: null,
7016
7017 // always scale
7018 scale: true
7019 }, config && config.defaults);
7020
7021 /**
7022 * @type {Record<string, Overlay>}
7023 */
7024 this._overlays = {};
7025
7026 /**
7027 * @type {OverlayContainer[]}
7028 */
7029 this._overlayContainers = [];
7030
7031 /**
7032 * @type {HTMLElement}
7033 */
7034 this._overlayRoot = createRoot(canvas.getContainer());
7035
7036 this._init();
7037 }
7038
7039
7040 Overlays.$inject = [
7041 'config.overlays',
7042 'eventBus',
7043 'canvas',
7044 'elementRegistry'
7045 ];
7046
7047
7048 /**
7049 * Returns the overlay with the specified ID or a list of overlays
7050 * for an element with a given type.
7051 *
7052 * @example
7053 *
7054 * ```javascript
7055 * // return the single overlay with the given ID
7056 * overlays.get('some-id');
7057 *
7058 * // return all overlays for the shape
7059 * overlays.get({ element: someShape });
7060 *
7061 * // return all overlays on shape with type 'badge'
7062 * overlays.get({ element: someShape, type: 'badge' });
7063 *
7064 * // shape can also be specified as ID
7065 * overlays.get({ element: 'element-id', type: 'badge' });
7066 * ```
7067 *
7068 * @param {OverlaysFilter} search The filter to be used to find the overlay(s).
7069 *
7070 * @return {Overlay|Overlay[]} The overlay(s).
7071 */
7072 Overlays.prototype.get = function(search) {
7073
7074 if (isString(search)) {
7075 search = { id: search };
7076 }
7077
7078 if (isString(search.element)) {
7079 search.element = this._elementRegistry.get(search.element);
7080 }
7081
7082 if (search.element) {
7083 var container = this._getOverlayContainer(search.element, true);
7084
7085 // return a list of overlays when searching by element (+type)
7086 if (container) {
7087 return search.type ? filter(container.overlays, matchPattern({ type: search.type })) : container.overlays.slice();
7088 } else {
7089 return [];
7090 }
7091 } else if (search.type) {
7092 return filter(this._overlays, matchPattern({ type: search.type }));
7093 } else {
7094
7095 // return single element when searching by id
7096 return search.id ? this._overlays[search.id] : null;
7097 }
7098 };
7099
7100 /**
7101 * Adds an HTML overlay to an element.
7102 *
7103 * @param {Element|string} element The element to add the overlay to.
7104 * @param {string} [type] An optional type that can be used to filter.
7105 * @param {OverlayAttrs} overlay The overlay.
7106 *
7107 * @return {string} The overlay's ID that can be used to get or remove it.
7108 */
7109 Overlays.prototype.add = function(element, type, overlay) {
7110
7111 if (isObject(type)) {
7112 overlay = type;
7113 type = null;
7114 }
7115
7116 if (!element.id) {
7117 element = this._elementRegistry.get(element);
7118 }
7119
7120 if (!overlay.position) {
7121 throw new Error('must specifiy overlay position');
7122 }
7123
7124 if (!overlay.html) {
7125 throw new Error('must specifiy overlay html');
7126 }
7127
7128 if (!element) {
7129 throw new Error('invalid element specified');
7130 }
7131
7132 var id = this._ids.next();
7133
7134 overlay = assign$1({}, this._overlayDefaults, overlay, {
7135 id: id,
7136 type: type,
7137 element: element,
7138 html: overlay.html
7139 });
7140
7141 this._addOverlay(overlay);
7142
7143 return id;
7144 };
7145
7146
7147 /**
7148 * Remove an overlay with the given ID or all overlays matching the given filter.
7149 *
7150 * @see Overlays#get for filter options.
7151 *
7152 * @param {OverlaysFilter} filter The filter to be used to find the overlay.
7153 */
7154 Overlays.prototype.remove = function(filter) {
7155
7156 var overlays = this.get(filter) || [];
7157
7158 if (!isArray$2(overlays)) {
7159 overlays = [ overlays ];
7160 }
7161
7162 var self = this;
7163
7164 forEach$1(overlays, function(overlay) {
7165
7166 var container = self._getOverlayContainer(overlay.element, true);
7167
7168 if (overlay) {
7169 remove$1(overlay.html);
7170 remove$1(overlay.htmlContainer);
7171
7172 delete overlay.htmlContainer;
7173 delete overlay.element;
7174
7175 delete self._overlays[overlay.id];
7176 }
7177
7178 if (container) {
7179 var idx = container.overlays.indexOf(overlay);
7180 if (idx !== -1) {
7181 container.overlays.splice(idx, 1);
7182 }
7183 }
7184 });
7185
7186 };
7187
7188 /**
7189 * Checks whether overlays are shown.
7190 *
7191 * @return {boolean} Whether overlays are shown.
7192 */
7193 Overlays.prototype.isShown = function() {
7194 return this._overlayRoot.style.display !== 'none';
7195 };
7196
7197 /**
7198 * Show all overlays.
7199 */
7200 Overlays.prototype.show = function() {
7201 setVisible(this._overlayRoot);
7202 };
7203
7204 /**
7205 * Hide all overlays.
7206 */
7207 Overlays.prototype.hide = function() {
7208 setVisible(this._overlayRoot, false);
7209 };
7210
7211 /**
7212 * Remove all overlays and their container.
7213 */
7214 Overlays.prototype.clear = function() {
7215 this._overlays = {};
7216
7217 this._overlayContainers = [];
7218
7219 clear(this._overlayRoot);
7220 };
7221
7222 Overlays.prototype._updateOverlayContainer = function(container) {
7223 var element = container.element,
7224 html = container.html;
7225
7226 // update container left,top according to the elements x,y coordinates
7227 // this ensures we can attach child elements relative to this container
7228
7229 var x = element.x,
7230 y = element.y;
7231
7232 if (element.waypoints) {
7233 var bbox = getBBox(element);
7234 x = bbox.x;
7235 y = bbox.y;
7236 }
7237
7238 setPosition(html, x, y);
7239
7240 attr(container.html, 'data-container-id', element.id);
7241 };
7242
7243
7244 Overlays.prototype._updateOverlay = function(overlay) {
7245
7246 var position = overlay.position,
7247 htmlContainer = overlay.htmlContainer,
7248 element = overlay.element;
7249
7250 // update overlay html relative to shape because
7251 // it is already positioned on the element
7252
7253 // update relative
7254 var left = position.left,
7255 top = position.top;
7256
7257 if (position.right !== undefined) {
7258
7259 var width;
7260
7261 if (element.waypoints) {
7262 width = getBBox(element).width;
7263 } else {
7264 width = element.width;
7265 }
7266
7267 left = position.right * -1 + width;
7268 }
7269
7270 if (position.bottom !== undefined) {
7271
7272 var height;
7273
7274 if (element.waypoints) {
7275 height = getBBox(element).height;
7276 } else {
7277 height = element.height;
7278 }
7279
7280 top = position.bottom * -1 + height;
7281 }
7282
7283 setPosition(htmlContainer, left || 0, top || 0);
7284 this._updateOverlayVisibilty(overlay, this._canvas.viewbox());
7285 };
7286
7287
7288 Overlays.prototype._createOverlayContainer = function(element) {
7289 var html = domify$1('<div class="djs-overlays" />');
7290 assign(html, { position: 'absolute' });
7291
7292 this._overlayRoot.appendChild(html);
7293
7294 var container = {
7295 html: html,
7296 element: element,
7297 overlays: []
7298 };
7299
7300 this._updateOverlayContainer(container);
7301
7302 this._overlayContainers.push(container);
7303
7304 return container;
7305 };
7306
7307
7308 Overlays.prototype._updateRoot = function(viewbox) {
7309 var scale = viewbox.scale || 1;
7310
7311 var matrix = 'matrix(' +
7312 [
7313 scale,
7314 0,
7315 0,
7316 scale,
7317 -1 * viewbox.x * scale,
7318 -1 * viewbox.y * scale
7319 ].join(',') +
7320 ')';
7321
7322 setTransform(this._overlayRoot, matrix);
7323 };
7324
7325
7326 Overlays.prototype._getOverlayContainer = function(element, raw) {
7327 var container = find(this._overlayContainers, function(c) {
7328 return c.element === element;
7329 });
7330
7331
7332 if (!container && !raw) {
7333 return this._createOverlayContainer(element);
7334 }
7335
7336 return container;
7337 };
7338
7339
7340 Overlays.prototype._addOverlay = function(overlay) {
7341
7342 var id = overlay.id,
7343 element = overlay.element,
7344 html = overlay.html,
7345 htmlContainer,
7346 overlayContainer;
7347
7348 // unwrap jquery (for those who need it)
7349 if (html.get && html.constructor.prototype.jquery) {
7350 html = html.get(0);
7351 }
7352
7353 // create proper html elements from
7354 // overlay HTML strings
7355 if (isString(html)) {
7356 html = domify$1(html);
7357 }
7358
7359 overlayContainer = this._getOverlayContainer(element);
7360
7361 htmlContainer = domify$1('<div class="djs-overlay" data-overlay-id="' + id + '">');
7362 assign(htmlContainer, { position: 'absolute' });
7363
7364 htmlContainer.appendChild(html);
7365
7366 if (overlay.type) {
7367 classes(htmlContainer).add('djs-overlay-' + overlay.type);
7368 }
7369
7370 var elementRoot = this._canvas.findRoot(element);
7371 var activeRoot = this._canvas.getRootElement();
7372
7373 setVisible(htmlContainer, elementRoot === activeRoot);
7374
7375 overlay.htmlContainer = htmlContainer;
7376
7377 overlayContainer.overlays.push(overlay);
7378 overlayContainer.html.appendChild(htmlContainer);
7379
7380 this._overlays[id] = overlay;
7381
7382 this._updateOverlay(overlay);
7383 this._updateOverlayVisibilty(overlay, this._canvas.viewbox());
7384 };
7385
7386
7387 Overlays.prototype._updateOverlayVisibilty = function(overlay, viewbox) {
7388 var show = overlay.show,
7389 rootElement = this._canvas.findRoot(overlay.element),
7390 minZoom = show && show.minZoom,
7391 maxZoom = show && show.maxZoom,
7392 htmlContainer = overlay.htmlContainer,
7393 activeRootElement = this._canvas.getRootElement(),
7394 visible = true;
7395
7396 if (rootElement !== activeRootElement) {
7397 visible = false;
7398 } else if (show) {
7399 if (
7400 (isDefined(minZoom) && minZoom > viewbox.scale) ||
7401 (isDefined(maxZoom) && maxZoom < viewbox.scale)
7402 ) {
7403 visible = false;
7404 }
7405 }
7406
7407 setVisible(htmlContainer, visible);
7408
7409 this._updateOverlayScale(overlay, viewbox);
7410 };
7411
7412
7413 Overlays.prototype._updateOverlayScale = function(overlay, viewbox) {
7414 var shouldScale = overlay.scale,
7415 minScale,
7416 maxScale,
7417 htmlContainer = overlay.htmlContainer;
7418
7419 var scale, transform = '';
7420
7421 if (shouldScale !== true) {
7422
7423 if (shouldScale === false) {
7424 minScale = 1;
7425 maxScale = 1;
7426 } else {
7427 minScale = shouldScale.min;
7428 maxScale = shouldScale.max;
7429 }
7430
7431 if (isDefined(minScale) && viewbox.scale < minScale) {
7432 scale = (1 / viewbox.scale || 1) * minScale;
7433 }
7434
7435 if (isDefined(maxScale) && viewbox.scale > maxScale) {
7436 scale = (1 / viewbox.scale || 1) * maxScale;
7437 }
7438 }
7439
7440 if (isDefined(scale)) {
7441 transform = 'scale(' + scale + ',' + scale + ')';
7442 }
7443
7444 setTransform(htmlContainer, transform);
7445 };
7446
7447
7448 Overlays.prototype._updateOverlaysVisibilty = function(viewbox) {
7449
7450 var self = this;
7451
7452 forEach$1(this._overlays, function(overlay) {
7453 self._updateOverlayVisibilty(overlay, viewbox);
7454 });
7455 };
7456
7457
7458 Overlays.prototype._init = function() {
7459
7460 var eventBus = this._eventBus;
7461
7462 var self = this;
7463
7464
7465 // scroll/zoom integration
7466
7467 function updateViewbox(viewbox) {
7468 self._updateRoot(viewbox);
7469 self._updateOverlaysVisibilty(viewbox);
7470
7471 self.show();
7472 }
7473
7474 eventBus.on('canvas.viewbox.changing', function(event) {
7475 self.hide();
7476 });
7477
7478 eventBus.on('canvas.viewbox.changed', function(event) {
7479 updateViewbox(event.viewbox);
7480 });
7481
7482
7483 // remove integration
7484
7485 eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
7486 var element = e.element;
7487 var overlays = self.get({ element: element });
7488
7489 forEach$1(overlays, function(o) {
7490 self.remove(o.id);
7491 });
7492
7493 var container = self._getOverlayContainer(element);
7494
7495 if (container) {
7496 remove$1(container.html);
7497 var i = self._overlayContainers.indexOf(container);
7498 if (i !== -1) {
7499 self._overlayContainers.splice(i, 1);
7500 }
7501 }
7502 });
7503
7504
7505 // move integration
7506
7507 eventBus.on('element.changed', LOW_PRIORITY$3, function(e) {
7508 var element = e.element;
7509
7510 var container = self._getOverlayContainer(element, true);
7511
7512 if (container) {
7513 forEach$1(container.overlays, function(overlay) {
7514 self._updateOverlay(overlay);
7515 });
7516
7517 self._updateOverlayContainer(container);
7518 }
7519 });
7520
7521
7522 // marker integration, simply add them on the overlays as classes, too.
7523
7524 eventBus.on('element.marker.update', function(e) {
7525 var container = self._getOverlayContainer(e.element, true);
7526 if (container) {
7527 classes(container.html)[e.add ? 'add' : 'remove'](e.marker);
7528 }
7529 });
7530
7531
7532 eventBus.on('root.set', function() {
7533 self._updateOverlaysVisibilty(self._canvas.viewbox());
7534 });
7535
7536 // clear overlays with diagram
7537
7538 eventBus.on('diagram.clear', this.clear, this);
7539 };
7540
7541
7542
7543 // helpers /////////////////////////////
7544
7545 function createRoot(parentNode) {
7546 var root = domify$1(
7547 '<div class="djs-overlay-container" />'
7548 );
7549
7550 assign(root, {
7551 position: 'absolute',
7552 width: 0,
7553 height: 0
7554 });
7555
7556 parentNode.insertBefore(root, parentNode.firstChild);
7557
7558 return root;
7559 }
7560
7561 function setPosition(el, x, y) {
7562 assign(el, { left: x + 'px', top: y + 'px' });
7563 }
7564
7565 /**
7566 * Set element visible
7567 *
7568 * @param {DOMElement} el
7569 * @param {boolean} [visible=true]
7570 */
7571 function setVisible(el, visible) {
7572 el.style.display = visible === false ? 'none' : '';
7573 }
7574
7575 function setTransform(el, transform) {
7576
7577 el.style['transform-origin'] = 'top left';
7578
7579 [ '', '-ms-', '-webkit-' ].forEach(function(prefix) {
7580 el.style[prefix + 'transform'] = transform;
7581 });
7582 }
7583
7584 /**
7585 * @type { import('didi').ModuleDeclaration }
7586 */
7587 var OverlaysModule = {
7588 __init__: [ 'overlays' ],
7589 overlays: [ 'type', Overlays ]
7590 };
7591
7592 /**
7593 * @typedef {import('../../core/Canvas').default} Canvas
7594 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
7595 * @typedef {import('../../core/EventBus').default} EventBus
7596 * @typedef {import('../../core/GraphicsFactory').default} GraphicsFactory
7597 */
7598
7599 /**
7600 * Adds change support to the diagram, including
7601 *
7602 * <ul>
7603 * <li>redrawing shapes and connections on change</li>
7604 * </ul>
7605 *
7606 * @param {EventBus} eventBus
7607 * @param {Canvas} canvas
7608 * @param {ElementRegistry} elementRegistry
7609 * @param {GraphicsFactory} graphicsFactory
7610 */
7611 function ChangeSupport(
7612 eventBus, canvas, elementRegistry,
7613 graphicsFactory) {
7614
7615
7616 // redraw shapes / connections on change
7617
7618 eventBus.on('element.changed', function(event) {
7619
7620 var element = event.element;
7621
7622 // element might have been deleted and replaced by new element with same ID
7623 // thus check for parent of element except for root element
7624 if (element.parent || element === canvas.getRootElement()) {
7625 event.gfx = elementRegistry.getGraphics(element);
7626 }
7627
7628 // shape + gfx may have been deleted
7629 if (!event.gfx) {
7630 return;
7631 }
7632
7633 eventBus.fire(getType(element) + '.changed', event);
7634 });
7635
7636 eventBus.on('elements.changed', function(event) {
7637
7638 var elements = event.elements;
7639
7640 elements.forEach(function(e) {
7641 eventBus.fire('element.changed', { element: e });
7642 });
7643
7644 graphicsFactory.updateContainments(elements);
7645 });
7646
7647 eventBus.on('shape.changed', function(event) {
7648 graphicsFactory.update('shape', event.element, event.gfx);
7649 });
7650
7651 eventBus.on('connection.changed', function(event) {
7652 graphicsFactory.update('connection', event.element, event.gfx);
7653 });
7654 }
7655
7656 ChangeSupport.$inject = [
7657 'eventBus',
7658 'canvas',
7659 'elementRegistry',
7660 'graphicsFactory'
7661 ];
7662
7663 /**
7664 * @type { import('didi').ModuleDeclaration }
7665 */
7666 var ChangeSupportModule = {
7667 __init__: [ 'changeSupport' ],
7668 changeSupport: [ 'type', ChangeSupport ]
7669 };
7670
7671 /**
7672 * @typedef {import('../core/Types').ElementLike} ElementLike
7673 * @typedef {import('../core/EventBus').default} EventBus
7674 * @typedef {import('./CommandStack').CommandContext} CommandContext
7675 *
7676 * @typedef {string|string[]} Events
7677 * @typedef { (context: CommandContext) => ElementLike[] | void } HandlerFunction
7678 * @typedef { (context: CommandContext) => void } ComposeHandlerFunction
7679 */
7680
7681 var DEFAULT_PRIORITY$2 = 1000;
7682
7683 /**
7684 * A utility that can be used to plug into the command execution for
7685 * extension and/or validation.
7686 *
7687 * @class
7688 * @constructor
7689 *
7690 * @example
7691 *
7692 * ```javascript
7693 * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
7694 *
7695 * class CommandLogger extends CommandInterceptor {
7696 * constructor(eventBus) {
7697 * super(eventBus);
7698 *
7699 * this.preExecute('shape.create', (event) => {
7700 * console.log('commandStack.shape-create.preExecute', event);
7701 * });
7702 * }
7703 * ```
7704 *
7705 * @param {EventBus} eventBus
7706 */
7707 function CommandInterceptor(eventBus) {
7708
7709 /**
7710 * @type {EventBus}
7711 */
7712 this._eventBus = eventBus;
7713 }
7714
7715 CommandInterceptor.$inject = [ 'eventBus' ];
7716
7717 function unwrapEvent(fn, that) {
7718 return function(event) {
7719 return fn.call(that || null, event.context, event.command, event);
7720 };
7721 }
7722
7723
7724 /**
7725 * Intercept a command during one of the phases.
7726 *
7727 * @param {Events} [events] command(s) to intercept
7728 * @param {string} [hook] phase to intercept
7729 * @param {number} [priority]
7730 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7731 * @param {boolean} [unwrap] whether the event should be unwrapped
7732 * @param {any} [that]
7733 */
7734 CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) {
7735
7736 if (isFunction(hook) || isNumber(hook)) {
7737 that = unwrap;
7738 unwrap = handlerFn;
7739 handlerFn = priority;
7740 priority = hook;
7741 hook = null;
7742 }
7743
7744 if (isFunction(priority)) {
7745 that = unwrap;
7746 unwrap = handlerFn;
7747 handlerFn = priority;
7748 priority = DEFAULT_PRIORITY$2;
7749 }
7750
7751 if (isObject(unwrap)) {
7752 that = unwrap;
7753 unwrap = false;
7754 }
7755
7756 if (!isFunction(handlerFn)) {
7757 throw new Error('handlerFn must be a function');
7758 }
7759
7760 if (!isArray$2(events)) {
7761 events = [ events ];
7762 }
7763
7764 var eventBus = this._eventBus;
7765
7766 forEach$1(events, function(event) {
7767
7768 // concat commandStack(.event)?(.hook)?
7769 var fullEvent = [ 'commandStack', event, hook ].filter(function(e) { return e; }).join('.');
7770
7771 eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
7772 });
7773 };
7774
7775 /**
7776 * Add a <canExecute> phase of command interceptor.
7777 *
7778 * @param {Events} [events] command(s) to intercept
7779 * @param {number} [priority]
7780 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7781 * @param {boolean} [unwrap] whether the event should be unwrapped
7782 * @param {any} [that]
7783 */
7784 CommandInterceptor.prototype.canExecute = createHook('canExecute');
7785
7786 /**
7787 * Add a <preExecute> phase of command interceptor.
7788 *
7789 * @param {Events} [events] command(s) to intercept
7790 * @param {number} [priority]
7791 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7792 * @param {boolean} [unwrap] whether the event should be unwrapped
7793 * @param {any} [that]
7794 */
7795 CommandInterceptor.prototype.preExecute = createHook('preExecute');
7796
7797 /**
7798 * Add a <preExecuted> phase of command interceptor.
7799 *
7800 * @param {Events} [events] command(s) to intercept
7801 * @param {number} [priority]
7802 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7803 * @param {boolean} [unwrap] whether the event should be unwrapped
7804 * @param {any} [that]
7805 */
7806 CommandInterceptor.prototype.preExecuted = createHook('preExecuted');
7807
7808 /**
7809 * Add a <execute> phase of command interceptor.
7810 *
7811 * @param {Events} [events] command(s) to intercept
7812 * @param {number} [priority]
7813 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7814 * @param {boolean} [unwrap] whether the event should be unwrapped
7815 * @param {any} [that]
7816 */
7817 CommandInterceptor.prototype.execute = createHook('execute');
7818
7819 /**
7820 * Add a <executed> phase of command interceptor.
7821 *
7822 * @param {Events} [events] command(s) to intercept
7823 * @param {number} [priority]
7824 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7825 * @param {boolean} [unwrap] whether the event should be unwrapped
7826 * @param {any} [that]
7827 */
7828 CommandInterceptor.prototype.executed = createHook('executed');
7829
7830 /**
7831 * Add a <postExecute> phase of command interceptor.
7832 *
7833 * @param {Events} [events] command(s) to intercept
7834 * @param {number} [priority]
7835 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7836 * @param {boolean} [unwrap] whether the event should be unwrapped
7837 * @param {any} [that]
7838 */
7839 CommandInterceptor.prototype.postExecute = createHook('postExecute');
7840
7841 /**
7842 * Add a <postExecuted> phase of command interceptor.
7843 *
7844 * @param {Events} [events] command(s) to intercept
7845 * @param {number} [priority]
7846 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7847 * @param {boolean} [unwrap] whether the event should be unwrapped
7848 * @param {any} [that]
7849 */
7850 CommandInterceptor.prototype.postExecuted = createHook('postExecuted');
7851
7852 /**
7853 * Add a <revert> phase of command interceptor.
7854 *
7855 * @param {Events} [events] command(s) to intercept
7856 * @param {number} [priority]
7857 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7858 * @param {boolean} [unwrap] whether the event should be unwrapped
7859 * @param {any} [that]
7860 */
7861 CommandInterceptor.prototype.revert = createHook('revert');
7862
7863 /**
7864 * Add a <reverted> phase of command interceptor.
7865 *
7866 * @param {Events} [events] command(s) to intercept
7867 * @param {number} [priority]
7868 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7869 * @param {boolean} [unwrap] whether the event should be unwrapped
7870 * @param {any} [that]
7871 */
7872 CommandInterceptor.prototype.reverted = createHook('reverted');
7873
7874 /*
7875 * Add prototype methods for each phase of command execution (e.g. execute,
7876 * revert).
7877 *
7878 * @param {string} hook
7879 *
7880 * @return { (
7881 * events?: Events,
7882 * priority?: number,
7883 * handlerFn: ComposeHandlerFunction|HandlerFunction,
7884 * unwrap?: boolean
7885 * ) => any }
7886 */
7887 function createHook(hook) {
7888
7889 /**
7890 * @this {CommandInterceptor}
7891 *
7892 * @param {Events} [events]
7893 * @param {number} [priority]
7894 * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
7895 * @param {boolean} [unwrap]
7896 * @param {any} [that]
7897 */
7898 const hookFn = function(events, priority, handlerFn, unwrap, that) {
7899
7900 if (isFunction(events) || isNumber(events)) {
7901 that = unwrap;
7902 unwrap = handlerFn;
7903 handlerFn = priority;
7904 priority = events;
7905 events = null;
7906 }
7907
7908 this.on(events, hook, priority, handlerFn, unwrap, that);
7909 };
7910
7911 return hookFn;
7912 }
7913
7914 /**
7915 * @typedef {import('didi').Injector} Injector
7916 *
7917 * @typedef {import('../../core/Canvas').default} Canvas
7918 */
7919
7920 /**
7921 * A modeling behavior that ensures we set the correct root element
7922 * as we undo and redo commands.
7923 *
7924 * @param {Canvas} canvas
7925 * @param {Injector} injector
7926 */
7927 function RootElementsBehavior(canvas, injector) {
7928
7929 injector.invoke(CommandInterceptor, this);
7930
7931 this.executed(function(event) {
7932 var context = event.context;
7933
7934 if (context.rootElement) {
7935 canvas.setRootElement(context.rootElement);
7936 } else {
7937 context.rootElement = canvas.getRootElement();
7938 }
7939 });
7940
7941 this.revert(function(event) {
7942 var context = event.context;
7943
7944 if (context.rootElement) {
7945 canvas.setRootElement(context.rootElement);
7946 }
7947 });
7948 }
7949
7950 e(RootElementsBehavior, CommandInterceptor);
7951
7952 RootElementsBehavior.$inject = [ 'canvas', 'injector' ];
7953
7954 /**
7955 * @type { import('didi').ModuleDeclaration }
7956 */
7957 var RootElementsModule = {
7958 __init__: [ 'rootElementsBehavior' ],
7959 rootElementsBehavior: [ 'type', RootElementsBehavior ]
7960 };
7961
7962 /**
7963 * @param {string} str
7964 *
7965 * @return {string}
7966 */
7967
7968 var HTML_ESCAPE_MAP = {
7969 '&': '&amp;',
7970 '<': '&lt;',
7971 '>': '&gt;',
7972 '"': '&quot;',
7973 '\'': '&#39;'
7974 };
7975
7976 /**
7977 * @param {string} str
7978 *
7979 * @return {string}
7980 */
7981 function escapeHTML(str) {
7982 str = '' + str;
7983
7984 return str && str.replace(/[&<>"']/g, function(match) {
7985 return HTML_ESCAPE_MAP[match];
7986 });
7987 }
7988
7989 /**
7990 * @typedef {import('../model/Types').Element} Element
7991 * @typedef {import('../model/Types').ModdleElement} ModdleElement
7992 */
7993
7994 var planeSuffix = '_plane';
7995
7996 /**
7997 * Get plane ID for a primary shape.
7998 *
7999 * @param {Element|ModdleElement} element
8000 *
8001 * @return {string}
8002 */
8003 function getPlaneIdFromShape(element) {
8004 var id = element.id;
8005
8006 if (is$1(element, 'bpmn:SubProcess')) {
8007 return addPlaneSuffix(id);
8008 }
8009
8010 return id;
8011 }
8012
8013 function addPlaneSuffix(id) {
8014 return id + planeSuffix;
8015 }
8016
8017 /**
8018 * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
8019 * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
8020 * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
8021 *
8022 * @typedef {import('../../model/Types').Element} Element
8023 * @typedef {import('../../model/Types').Shape} Shape
8024 */
8025
8026 var OPEN_CLASS = 'bjs-breadcrumbs-shown';
8027
8028
8029 /**
8030 * Adds overlays that allow switching planes on collapsed subprocesses.
8031 *
8032 * @param {EventBus} eventBus
8033 * @param {ElementRegistry} elementRegistry
8034 * @param {Canvas} canvas
8035 */
8036 function DrilldownBreadcrumbs(eventBus, elementRegistry, canvas) {
8037 var breadcrumbs = domify$1('<ul class="bjs-breadcrumbs"></ul>');
8038 var container = canvas.getContainer();
8039 var containerClasses = classes(container);
8040 container.appendChild(breadcrumbs);
8041
8042 var businessObjectParents = [];
8043
8044 // update breadcrumbs if name or ID of the primary shape changes
8045 eventBus.on('element.changed', function(event) {
8046 var shape = event.element,
8047 businessObject = getBusinessObject(shape);
8048
8049 var isPresent = find(businessObjectParents, function(element) {
8050 return element === businessObject;
8051 });
8052
8053 if (!isPresent) {
8054 return;
8055 }
8056
8057 updateBreadcrumbs();
8058 });
8059
8060 /**
8061 * Updates the displayed breadcrumbs. If no element is provided, only the
8062 * labels are updated.
8063 *
8064 * @param {Element} [element]
8065 */
8066 function updateBreadcrumbs(element) {
8067 if (element) {
8068 businessObjectParents = getBusinessObjectParentChain(element);
8069 }
8070
8071 var path = businessObjectParents.map(function(parent) {
8072 var title = escapeHTML(parent.name || parent.id);
8073 var link = domify$1('<li><span class="bjs-crumb"><a title="' + title + '">' + title + '</a></span></li>');
8074
8075 var parentPlane = canvas.findRoot(getPlaneIdFromShape(parent)) || canvas.findRoot(parent.id);
8076
8077 // when the root is a collaboration, the process does not have a corresponding
8078 // element in the elementRegisty. Instead, we search for the corresponding participant
8079 if (!parentPlane && is$1(parent, 'bpmn:Process')) {
8080 var participant = elementRegistry.find(function(element) {
8081 var businessObject = getBusinessObject(element);
8082
8083 return businessObject && businessObject.get('processRef') && businessObject.get('processRef') === parent;
8084 });
8085
8086 parentPlane = canvas.findRoot(participant.id);
8087 }
8088
8089 link.addEventListener('click', function() {
8090 canvas.setRootElement(parentPlane);
8091 });
8092
8093 return link;
8094 });
8095
8096 breadcrumbs.innerHTML = '';
8097
8098 // show breadcrumbs and expose state to .djs-container
8099 var visible = path.length > 1;
8100
8101 containerClasses.toggle(OPEN_CLASS, visible);
8102
8103 path.forEach(function(element) {
8104 breadcrumbs.appendChild(element);
8105 });
8106 }
8107
8108 eventBus.on('root.set', function(event) {
8109 updateBreadcrumbs(event.element);
8110 });
8111
8112 }
8113
8114 DrilldownBreadcrumbs.$inject = [ 'eventBus', 'elementRegistry', 'canvas' ];
8115
8116
8117 // helpers //////////
8118
8119 /**
8120 * Returns the parents for the element using the business object chain,
8121 * starting with the root element.
8122 *
8123 * @param {Shape} child
8124 *
8125 * @return {Shape}
8126 */
8127 function getBusinessObjectParentChain(child) {
8128 var businessObject = getBusinessObject(child);
8129
8130 var parents = [];
8131
8132 for (var element = businessObject; element; element = element.$parent) {
8133 if (is$1(element, 'bpmn:SubProcess') || is$1(element, 'bpmn:Process')) {
8134 parents.push(element);
8135 }
8136 }
8137
8138 return parents.reverse();
8139 }
8140
8141 /**
8142 * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
8143 * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
8144 */
8145
8146 /**
8147 * Move collapsed subprocesses into view when drilling down.
8148 *
8149 * Zoom and scroll are saved in a session.
8150 *
8151 * @param {EventBus} eventBus
8152 * @param {Canvas} canvas
8153 */
8154 function DrilldownCentering(eventBus, canvas) {
8155
8156 var currentRoot = null;
8157 var positionMap = new Map();
8158
8159 eventBus.on('root.set', function(event) {
8160 var newRoot = event.element;
8161 var currentViewbox = canvas.viewbox();
8162 var storedViewbox = positionMap.get(newRoot);
8163
8164 positionMap.set(currentRoot, {
8165 x: currentViewbox.x,
8166 y: currentViewbox.y,
8167 zoom: currentViewbox.scale
8168 });
8169
8170 currentRoot = newRoot;
8171
8172 // current root was replaced with a collaboration, we don't update the viewbox
8173 if (is$1(newRoot, 'bpmn:Collaboration') && !storedViewbox) {
8174 return;
8175 }
8176
8177 storedViewbox = storedViewbox || { x: 0, y: 0, zoom: 1 };
8178
8179 var dx = (currentViewbox.x - storedViewbox.x) * currentViewbox.scale,
8180 dy = (currentViewbox.y - storedViewbox.y) * currentViewbox.scale;
8181
8182 if (dx !== 0 || dy !== 0) {
8183 canvas.scroll({
8184 dx: dx,
8185 dy: dy
8186 });
8187 }
8188
8189 if (storedViewbox.zoom !== currentViewbox.scale) {
8190 canvas.zoom(storedViewbox.zoom, { x: 0, y: 0 });
8191 }
8192 });
8193
8194 eventBus.on('diagram.clear', function() {
8195 positionMap.clear();
8196 currentRoot = null;
8197 });
8198
8199 }
8200
8201 DrilldownCentering.$inject = [ 'eventBus', 'canvas' ];
8202
8203
8204 /**
8205 * ES5 Map implementation. Works.
8206 */
8207 function Map() {
8208
8209 this._entries = [];
8210
8211 this.set = function(key, value) {
8212
8213 var found = false;
8214
8215 for (var k in this._entries) {
8216 if (this._entries[k][0] === key) {
8217 this._entries[k][1] = value;
8218
8219 found = true;
8220
8221 break;
8222 }
8223 }
8224
8225 if (!found) {
8226 this._entries.push([ key, value ]);
8227 }
8228 };
8229
8230 this.get = function(key) {
8231
8232 for (var k in this._entries) {
8233 if (this._entries[k][0] === key) {
8234 return this._entries[k][1];
8235 }
8236 }
8237
8238 return null;
8239 };
8240
8241 this.clear = function() {
8242 this._entries.length = 0;
8243 };
8244
8245 this.remove = function(key) {
8246
8247 var idx = -1;
8248
8249 for (var k in this._entries) {
8250 if (this._entries[k][0] === key) {
8251 idx = k;
8252
8253 break;
8254 }
8255 }
8256
8257 if (idx !== -1) {
8258 this._entries.splice(idx, 1);
8259 }
8260 };
8261 }
8262
8263 /**
8264 * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
8265 * @typedef {import('../../model/Types').Moddle} Moddle
8266 *
8267 * @typedef {import('../../model/Types').Element} Element
8268 * @typedef {import('../../model/Types').Shape} Shape
8269 *
8270 * @typedef {import('diagram-js/lib/core/Canvas').CanvasPlane} CanvasPlane
8271 *
8272 * @typedef {import('diagram-js/lib/util/Types').Rect} Rect
8273 */
8274
8275 var DEFAULT_POSITION = {
8276 x: 180,
8277 y: 160
8278 };
8279
8280 /**
8281 * Hook into `import.render.start` and create new planes for diagrams with
8282 * collapsed subprocesses and all DI elements on the same plane.
8283 *
8284 * @param {EventBus} eventBus
8285 * @param {Moddle} moddle
8286 */
8287 function SubprocessCompatibility(eventBus, moddle) {
8288 this._eventBus = eventBus;
8289 this._moddle = moddle;
8290
8291 var self = this;
8292
8293 eventBus.on('import.render.start', 1500, function(e, context) {
8294 self._handleImport(context.definitions);
8295 });
8296 }
8297
8298 /**
8299 * @param {ModdleElement} definitions
8300 */
8301 SubprocessCompatibility.prototype._handleImport = function(definitions) {
8302 if (!definitions.diagrams) {
8303 return;
8304 }
8305
8306 var self = this;
8307 this._definitions = definitions;
8308 this._processToDiagramMap = {};
8309
8310 definitions.diagrams.forEach(function(diagram) {
8311 if (!diagram.plane || !diagram.plane.bpmnElement) {
8312 return;
8313 }
8314
8315 self._processToDiagramMap[diagram.plane.bpmnElement.id] = diagram;
8316 });
8317
8318 var newDiagrams = [];
8319 definitions.diagrams.forEach(function(diagram) {
8320 var createdDiagrams = self._createNewDiagrams(diagram.plane);
8321 Array.prototype.push.apply(newDiagrams, createdDiagrams);
8322 });
8323
8324 newDiagrams.forEach(function(diagram) {
8325 self._movePlaneElementsToOrigin(diagram.plane);
8326 });
8327 };
8328
8329
8330 /**
8331 * Moves all DI elements from collapsed subprocesses to a new plane.
8332 *
8333 * @param {CanvasPlane} plane
8334 *
8335 * @return {ModdleElement[]} new diagrams created for the collapsed subprocesses
8336 */
8337 SubprocessCompatibility.prototype._createNewDiagrams = function(plane) {
8338 var self = this;
8339
8340 var collapsedElements = [];
8341 var elementsToMove = [];
8342
8343 plane.get('planeElement').forEach(function(diElement) {
8344 var businessObject = diElement.bpmnElement;
8345
8346 if (!businessObject) {
8347 return;
8348 }
8349
8350 var parent = businessObject.$parent;
8351
8352 if (is$1(businessObject, 'bpmn:SubProcess') && !diElement.isExpanded) {
8353 collapsedElements.push(businessObject);
8354 }
8355
8356 if (shouldMoveToPlane(businessObject, plane)) {
8357
8358 // don't change the array while we iterate over it
8359 elementsToMove.push({ diElement: diElement, parent: parent });
8360 }
8361 });
8362
8363 var newDiagrams = [];
8364
8365 // create new planes for all collapsed subprocesses, even when they are empty
8366 collapsedElements.forEach(function(element) {
8367 if (!self._processToDiagramMap[ element.id ]) {
8368 var diagram = self._createDiagram(element);
8369
8370 self._processToDiagramMap[element.id] = diagram;
8371
8372 newDiagrams.push(diagram);
8373 }
8374 });
8375
8376 elementsToMove.forEach(function(element) {
8377 var diElement = element.diElement;
8378 var parent = element.parent;
8379
8380 // parent is expanded, get nearest collapsed parent
8381 while (parent && collapsedElements.indexOf(parent) === -1) {
8382 parent = parent.$parent;
8383 }
8384
8385 // false positive, all parents are expanded
8386 if (!parent) {
8387 return;
8388 }
8389
8390 var diagram = self._processToDiagramMap[ parent.id ];
8391
8392 self._moveToDiPlane(diElement, diagram.plane);
8393 });
8394
8395 return newDiagrams;
8396 };
8397
8398 /**
8399 * @param {CanvasPlane} plane
8400 */
8401 SubprocessCompatibility.prototype._movePlaneElementsToOrigin = function(plane) {
8402 var elements = plane.get('planeElement');
8403
8404 // get bounding box of all elements
8405 var planeBounds = getPlaneBounds(plane);
8406
8407 var offset = {
8408 x: planeBounds.x - DEFAULT_POSITION.x,
8409 y: planeBounds.y - DEFAULT_POSITION.y
8410 };
8411
8412 elements.forEach(function(diElement) {
8413 if (diElement.waypoint) {
8414 diElement.waypoint.forEach(function(waypoint) {
8415 waypoint.x = waypoint.x - offset.x;
8416 waypoint.y = waypoint.y - offset.y;
8417 });
8418 } else if (diElement.bounds) {
8419 diElement.bounds.x = diElement.bounds.x - offset.x;
8420 diElement.bounds.y = diElement.bounds.y - offset.y;
8421 }
8422 });
8423 };
8424
8425 /**
8426 * @param {ModdleElement} diElement
8427 * @param {CanvasPlane} newPlane
8428 */
8429 SubprocessCompatibility.prototype._moveToDiPlane = function(diElement, newPlane) {
8430 var containingDiagram = findRootDiagram(diElement);
8431
8432 // remove DI from old Plane and add it to the new one
8433 var parentPlaneElement = containingDiagram.plane.get('planeElement');
8434
8435 parentPlaneElement.splice(parentPlaneElement.indexOf(diElement), 1);
8436
8437 newPlane.get('planeElement').push(diElement);
8438 };
8439
8440 /**
8441 * @param {ModdleElement} businessObject
8442 *
8443 * @return {ModdleElement}
8444 */
8445 SubprocessCompatibility.prototype._createDiagram = function(businessObject) {
8446 var plane = this._moddle.create('bpmndi:BPMNPlane', {
8447 bpmnElement: businessObject
8448 });
8449
8450 var diagram = this._moddle.create('bpmndi:BPMNDiagram', {
8451 plane: plane
8452 });
8453
8454 plane.$parent = diagram;
8455
8456 plane.bpmnElement = businessObject;
8457
8458 diagram.$parent = this._definitions;
8459
8460 this._definitions.diagrams.push(diagram);
8461
8462 return diagram;
8463 };
8464
8465 SubprocessCompatibility.$inject = [ 'eventBus', 'moddle' ];
8466
8467
8468 // helpers //////////
8469
8470 function findRootDiagram(element) {
8471 if (is$1(element, 'bpmndi:BPMNDiagram')) {
8472 return element;
8473 } else {
8474 return findRootDiagram(element.$parent);
8475 }
8476 }
8477
8478 /**
8479 * @param {CanvasPlane} plane
8480 *
8481 * @return {Rect}
8482 */
8483 function getPlaneBounds(plane) {
8484 var planeTrbl = {
8485 top: Infinity,
8486 right: -Infinity,
8487 bottom: -Infinity,
8488 left: Infinity
8489 };
8490
8491 plane.planeElement.forEach(function(element) {
8492 if (!element.bounds) {
8493 return;
8494 }
8495
8496 var trbl = asTRBL(element.bounds);
8497
8498 planeTrbl.top = Math.min(trbl.top, planeTrbl.top);
8499 planeTrbl.left = Math.min(trbl.left, planeTrbl.left);
8500 });
8501
8502 return asBounds(planeTrbl);
8503 }
8504
8505 /**
8506 * @param {ModdleElement} businessObject
8507 * @param {CanvasPlane} plane
8508 *
8509 * @return {boolean}
8510 */
8511 function shouldMoveToPlane(businessObject, plane) {
8512 var parent = businessObject.$parent;
8513
8514 // don't move elements that are already on the plane
8515 if (!is$1(parent, 'bpmn:SubProcess') || parent === plane.bpmnElement) {
8516 return false;
8517 }
8518
8519 // dataAssociations are children of the subprocess but rendered on process level
8520 // cf. https://github.com/bpmn-io/bpmn-js/issues/1619
8521 if (isAny(businessObject, [ 'bpmn:DataInputAssociation', 'bpmn:DataOutputAssociation' ])) {
8522 return false;
8523 }
8524
8525 return true;
8526 }
8527
8528 /**
8529 * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
8530 * @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
8531 * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
8532 * @typedef {import('diagram-js/lib/features/overlays/Overlays').default} Overlays
8533 *
8534 * @typedef {import('../../model/Types').Element} Element
8535 * @typedef {import('../../model/Types').Parent} Parent
8536 * @typedef {import('../../model/Types').Shape} Shape
8537 */
8538
8539 var LOW_PRIORITY$2 = 250;
8540 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>';
8541
8542 var EMPTY_MARKER = 'bjs-drilldown-empty';
8543
8544 /**
8545 * @param {Canvas} canvas
8546 * @param {EventBus} eventBus
8547 * @param {ElementRegistry} elementRegistry
8548 * @param {Overlays} overlays
8549 */
8550 function DrilldownOverlayBehavior(
8551 canvas, eventBus, elementRegistry, overlays
8552 ) {
8553 CommandInterceptor.call(this, eventBus);
8554
8555 this._canvas = canvas;
8556 this._eventBus = eventBus;
8557 this._elementRegistry = elementRegistry;
8558 this._overlays = overlays;
8559
8560 var self = this;
8561
8562 this.executed('shape.toggleCollapse', LOW_PRIORITY$2, function(context) {
8563 var shape = context.shape;
8564
8565 // Add overlay to the collapsed shape
8566 if (self._canDrillDown(shape)) {
8567 self._addOverlay(shape);
8568 } else {
8569 self._removeOverlay(shape);
8570 }
8571 }, true);
8572
8573
8574 this.reverted('shape.toggleCollapse', LOW_PRIORITY$2, function(context) {
8575 var shape = context.shape;
8576
8577 // Add overlay to the collapsed shape
8578 if (self._canDrillDown(shape)) {
8579 self._addOverlay(shape);
8580 } else {
8581 self._removeOverlay(shape);
8582 }
8583 }, true);
8584
8585
8586 this.executed([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$2,
8587 function(context) {
8588 var oldParent = context.oldParent,
8589 newParent = context.newParent || context.parent,
8590 shape = context.shape;
8591
8592 // Add overlay to the collapsed shape
8593 if (self._canDrillDown(shape)) {
8594 self._addOverlay(shape);
8595 }
8596
8597 self._updateDrilldownOverlay(oldParent);
8598 self._updateDrilldownOverlay(newParent);
8599 self._updateDrilldownOverlay(shape);
8600 }, true);
8601
8602
8603 this.reverted([ 'shape.create', 'shape.move', 'shape.delete' ], LOW_PRIORITY$2,
8604 function(context) {
8605 var oldParent = context.oldParent,
8606 newParent = context.newParent || context.parent,
8607 shape = context.shape;
8608
8609 // Add overlay to the collapsed shape
8610 if (self._canDrillDown(shape)) {
8611 self._addOverlay(shape);
8612 }
8613
8614 self._updateDrilldownOverlay(oldParent);
8615 self._updateDrilldownOverlay(newParent);
8616 self._updateDrilldownOverlay(shape);
8617 }, true);
8618
8619
8620 eventBus.on('import.render.complete', function() {
8621 elementRegistry.filter(function(e) {
8622 return self._canDrillDown(e);
8623 }).map(function(el) {
8624 self._addOverlay(el);
8625 });
8626 });
8627
8628 }
8629
8630 e(DrilldownOverlayBehavior, CommandInterceptor);
8631
8632 /**
8633 * @param {Shape} shape
8634 */
8635 DrilldownOverlayBehavior.prototype._updateDrilldownOverlay = function(shape) {
8636 var canvas = this._canvas;
8637
8638 if (!shape) {
8639 return;
8640 }
8641
8642 var root = canvas.findRoot(shape);
8643
8644 if (root) {
8645 this._updateOverlayVisibility(root);
8646 }
8647 };
8648
8649 /**
8650 * @param {Element} element
8651 *
8652 * @return {boolean}
8653 */
8654 DrilldownOverlayBehavior.prototype._canDrillDown = function(element) {
8655 var canvas = this._canvas;
8656
8657 return is$1(element, 'bpmn:SubProcess') && canvas.findRoot(getPlaneIdFromShape(element));
8658 };
8659
8660 /**
8661 * Update the visibility of the drilldown overlay. If the plane has no elements,
8662 * the drilldown will only be shown when the element is selected.
8663 *
8664 * @param {Parent} element The collapsed root or shape.
8665 */
8666 DrilldownOverlayBehavior.prototype._updateOverlayVisibility = function(element) {
8667 var overlays = this._overlays;
8668
8669 var businessObject = getBusinessObject(element);
8670
8671 var overlay = overlays.get({ element: businessObject.id, type: 'drilldown' })[0];
8672
8673 if (!overlay) {
8674 return;
8675 }
8676
8677 var hasFlowElements = businessObject
8678 && businessObject.get('flowElements')
8679 && businessObject.get('flowElements').length;
8680
8681 classes(overlay.html).toggle(EMPTY_MARKER, !hasFlowElements);
8682 };
8683
8684 /**
8685 * Add a drilldown button to the given element assuming the plane has the same
8686 * ID as the element.
8687 *
8688 * @param {Shape} element The collapsed shape.
8689 */
8690 DrilldownOverlayBehavior.prototype._addOverlay = function(element) {
8691 var canvas = this._canvas,
8692 overlays = this._overlays;
8693
8694 var existingOverlays = overlays.get({ element: element, type: 'drilldown' });
8695
8696 if (existingOverlays.length) {
8697 this._removeOverlay(element);
8698 }
8699
8700 var button = domify$1('<button class="bjs-drilldown">' + ARROW_DOWN_SVG + '</button>');
8701
8702 button.addEventListener('click', function() {
8703 canvas.setRootElement(canvas.findRoot(getPlaneIdFromShape(element)));
8704 });
8705
8706 overlays.add(element, 'drilldown', {
8707 position: {
8708 bottom: -7,
8709 right: -8
8710 },
8711 html: button
8712 });
8713
8714 this._updateOverlayVisibility(element);
8715 };
8716
8717 DrilldownOverlayBehavior.prototype._removeOverlay = function(element) {
8718 var overlays = this._overlays;
8719
8720 overlays.remove({
8721 element: element,
8722 type: 'drilldown'
8723 });
8724 };
8725
8726 DrilldownOverlayBehavior.$inject = [
8727 'canvas',
8728 'eventBus',
8729 'elementRegistry',
8730 'overlays'
8731 ];
8732
8733 var DrilldownModdule = {
8734 __depends__: [ OverlaysModule, ChangeSupportModule, RootElementsModule ],
8735 __init__: [ 'drilldownBreadcrumbs', 'drilldownOverlayBehavior', 'drilldownCentering', 'subprocessCompatibility' ],
8736 drilldownBreadcrumbs: [ 'type', DrilldownBreadcrumbs ],
8737 drilldownCentering: [ 'type', DrilldownCentering ],
8738 drilldownOverlayBehavior: [ 'type', DrilldownOverlayBehavior ],
8739 subprocessCompatibility: [ 'type', SubprocessCompatibility ]
8740 };
8741
8742 var LOW_PRIORITY$1 = 500;
8743
8744 var DEFAULT_PRIORITY$1 = 1000;
8745
8746 /**
8747 * @typedef {import('../../model/Types').Element} Element
8748 *
8749 * @typedef {import('./OutlineProvider').default} OutlineProvider
8750 * @typedef {import('../../core/EventBus').default} EventBus
8751 * @typedef {import('../../draw/Styles').default} Styles
8752 */
8753
8754 /**
8755 * @class
8756 *
8757 * A plugin that adds an outline to shapes and connections that may be activated and styled
8758 * via CSS classes.
8759 *
8760 * @param {EventBus} eventBus
8761 * @param {Styles} styles
8762 */
8763 function Outline(eventBus, styles) {
8764
8765 this._eventBus = eventBus;
8766
8767 this.offset = 5;
8768
8769 var OUTLINE_STYLE = styles.cls('djs-outline', [ 'no-fill' ]);
8770
8771 var self = this;
8772
8773 /**
8774 * @param {SVGElement} gfx
8775 *
8776 * @return {SVGElement} outline
8777 */
8778 function createOutline(gfx) {
8779 var outline = create$1('rect');
8780
8781 attr$1(outline, assign$1({
8782 x: 0,
8783 y: 0,
8784 rx: 4,
8785 width: 100,
8786 height: 100
8787 }, OUTLINE_STYLE));
8788
8789 return outline;
8790 }
8791
8792 // A low priortity is necessary, because outlines of labels have to be updated
8793 // after the label bounds have been updated in the renderer.
8794 eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$1, function(event) {
8795 var element = event.element,
8796 gfx = event.gfx;
8797
8798 var outline = query('.djs-outline', gfx);
8799
8800 if (!outline) {
8801 outline = self.getOutline(element) || createOutline();
8802 append(gfx, outline);
8803 }
8804
8805 self.updateShapeOutline(outline, element);
8806 });
8807
8808 eventBus.on([ 'connection.added', 'connection.changed' ], function(event) {
8809 var element = event.element,
8810 gfx = event.gfx;
8811
8812 var outline = query('.djs-outline', gfx);
8813
8814 if (!outline) {
8815 outline = createOutline();
8816 append(gfx, outline);
8817 }
8818
8819 self.updateConnectionOutline(outline, element);
8820 });
8821 }
8822
8823
8824 /**
8825 * Updates the outline of a shape respecting the dimension of the
8826 * element and an outline offset.
8827 *
8828 * @param {SVGElement} outline
8829 * @param {Element} element
8830 */
8831 Outline.prototype.updateShapeOutline = function(outline, element) {
8832
8833 var updated = false;
8834 var providers = this._getProviders();
8835
8836 if (providers.length) {
8837 forEach$1(providers, function(provider) {
8838 updated = updated || provider.updateOutline(element, outline);
8839 });
8840 }
8841
8842 if (!updated) {
8843 attr$1(outline, {
8844 x: -this.offset,
8845 y: -this.offset,
8846 width: element.width + this.offset * 2,
8847 height: element.height + this.offset * 2
8848 });
8849 }
8850 };
8851
8852 /**
8853 * Updates the outline of a connection respecting the bounding box of
8854 * the connection and an outline offset.
8855 * Register an outline provider with the given priority.
8856 *
8857 * @param {SVGElement} outline
8858 * @param {Element} connection
8859 */
8860 Outline.prototype.updateConnectionOutline = function(outline, connection) {
8861 var bbox = getBBox(connection);
8862
8863 attr$1(outline, {
8864 x: bbox.x - this.offset,
8865 y: bbox.y - this.offset,
8866 width: bbox.width + this.offset * 2,
8867 height: bbox.height + this.offset * 2
8868 });
8869 };
8870
8871 /**
8872 * Register an outline provider with the given priority.
8873 *
8874 * @param {number} priority
8875 * @param {OutlineProvider} provider
8876 */
8877 Outline.prototype.registerProvider = function(priority, provider) {
8878 if (!provider) {
8879 provider = priority;
8880 priority = DEFAULT_PRIORITY$1;
8881 }
8882
8883 this._eventBus.on('outline.getProviders', priority, function(event) {
8884 event.providers.push(provider);
8885 });
8886 };
8887
8888 /**
8889 * Returns the registered outline providers.
8890 *
8891 * @returns {OutlineProvider[]}
8892 */
8893 Outline.prototype._getProviders = function() {
8894 var event = this._eventBus.createEvent({
8895 type: 'outline.getProviders',
8896 providers: []
8897 });
8898
8899 this._eventBus.fire(event);
8900
8901 return event.providers;
8902 };
8903
8904 /**
8905 * Returns the outline for an element.
8906 *
8907 * @param {Element} element
8908 */
8909 Outline.prototype.getOutline = function(element) {
8910 var outline;
8911 var providers = this._getProviders();
8912
8913 forEach$1(providers, function(provider) {
8914
8915 if (!isFunction(provider.getOutline)) {
8916 return;
8917 }
8918
8919 outline = outline || provider.getOutline(element);
8920 });
8921
8922 return outline;
8923 };
8924
8925 Outline.$inject = [ 'eventBus', 'styles', 'elementRegistry' ];
8926
8927 /**
8928 * @type { import('didi').ModuleDeclaration }
8929 */
8930 var OutlineModule$1 = {
8931 __init__: [ 'outline' ],
8932 outline: [ 'type', Outline ]
8933 };
8934
8935 const DATA_OBJECT_REFERENCE_OUTLINE_PATH = 'M44.7648 11.3263L36.9892 2.64074C36.0451 1.58628 34.5651 0.988708 33.1904 0.988708H5.98667C3.22688 0.988708 0.989624 3.34892 0.989624 6.26039V55.0235C0.989624 57.9349 3.22688 60.2952 5.98667 60.2952H40.966C43.7257 60.2952 45.963 57.9349 45.963 55.0235V14.9459C45.963 13.5998 45.6407 12.3048 44.7648 11.3263Z';
8936 const DATA_STORE_REFERENCE_OUTLINE_PATH = 'M1.03845 48.1347C1.03845 49.3511 1.07295 50.758 1.38342 52.064C1.69949 53.3938 2.32428 54.7154 3.56383 55.6428C6.02533 57.4841 10.1161 58.7685 14.8212 59.6067C19.5772 60.4538 25.1388 60.8738 30.6831 60.8738C36.2276 60.8738 41.7891 60.4538 46.545 59.6067C51.2504 58.7687 55.3412 57.4842 57.8028 55.6429C59.0424 54.7156 59.6673 53.3938 59.9834 52.064C60.2938 50.7579 60.3285 49.351 60.3285 48.1344V13.8415C60.3285 12.6249 60.2938 11.218 59.9834 9.91171C59.6673 8.58194 59.0423 7.2602 57.8027 6.33294C55.341 4.49168 51.2503 3.20723 46.545 2.36914C41.7891 1.522 36.2276 1.10204 30.6831 1.10205C25.1388 1.10206 19.5772 1.52206 14.8213 2.36923C10.1162 3.20734 6.02543 4.49183 3.5639 6.33314C2.32433 7.26038 1.69951 8.58206 1.38343 9.91181C1.07295 11.2179 1.03845 12.6247 1.03845 13.8411V48.1347Z';
8937
8938 /**
8939 * @type {Dimensions}
8940 */
8941 const DATA_OBJECT_REFERENCE_STANDARD_SIZE = { width: 36, height: 50 };
8942
8943 /**
8944 * @type {Dimensions}
8945 */
8946 const DATA_STORE_REFERENCE_STANDARD_SIZE = { width: 50, height: 50 };
8947
8948 /**
8949 * Create a path element with given attributes.
8950 * @param {string} path
8951 * @param {Object} attrs
8952 * @param {Object} OUTLINE_STYLE
8953 * @return {SVGElement}
8954 */
8955 function createPath(path, attrs, OUTLINE_STYLE) {
8956 return create$1('path', {
8957 d: path,
8958 strokeWidth: 2,
8959 transform: `translate(${attrs.x}, ${attrs.y})`,
8960 ...OUTLINE_STYLE
8961 });
8962 }
8963
8964 const DEFAULT_OFFSET = 5;
8965
8966 /**
8967 * BPMN-specific outline provider.
8968 *
8969 * @implements {BaseOutlineProvider}
8970 *
8971 * @param {Outline} outline
8972 * @param {Styles} styles
8973 */
8974 function OutlineProvider(outline, styles) {
8975
8976 this._styles = styles;
8977 outline.registerProvider(this);
8978 }
8979
8980 OutlineProvider.$inject = [
8981 'outline',
8982 'styles'
8983 ];
8984
8985 /**
8986 * Returns outline for a given element.
8987 *
8988 * @param {Element} element
8989 *
8990 * @return {Outline}
8991 */
8992 OutlineProvider.prototype.getOutline = function(element) {
8993
8994 const OUTLINE_STYLE = this._styles.cls('djs-outline', [ 'no-fill' ]);
8995
8996 var outline;
8997
8998 if (isLabel(element)) {
8999 return;
9000 }
9001
9002 if (is$1(element, 'bpmn:Gateway')) {
9003 outline = create$1('rect');
9004
9005 assign$1(outline.style, {
9006 'transform-box': 'fill-box',
9007 'transform': 'rotate(45deg)',
9008 'transform-origin': 'center'
9009 });
9010
9011 attr$1(outline, assign$1({
9012 x: 2,
9013 y: 2,
9014 rx: 4,
9015 width: element.width - 4,
9016 height: element.height - 4,
9017 }, OUTLINE_STYLE));
9018
9019 } else if (isAny(element, [ 'bpmn:Task', 'bpmn:SubProcess', 'bpmn:Group' ])) {
9020 outline = create$1('rect');
9021
9022 attr$1(outline, assign$1({
9023 x: -DEFAULT_OFFSET,
9024 y: -DEFAULT_OFFSET,
9025 rx: 14,
9026 width: element.width + DEFAULT_OFFSET * 2,
9027 height: element.height + DEFAULT_OFFSET * 2
9028 }, OUTLINE_STYLE));
9029
9030 } else if (is$1(element, 'bpmn:EndEvent')) {
9031
9032 outline = create$1('circle');
9033
9034 // Extra 1px offset needed due to increased stroke-width of end event
9035 // which makes it bigger than other events.
9036
9037 attr$1(outline, assign$1({
9038 cx: element.width / 2,
9039 cy: element.height / 2,
9040 r: element.width / 2 + DEFAULT_OFFSET + 1
9041 }, OUTLINE_STYLE));
9042
9043 } else if (is$1(element, 'bpmn:Event')) {
9044 outline = create$1('circle');
9045
9046 attr$1(outline, assign$1({
9047 cx: element.width / 2,
9048 cy: element.height / 2,
9049 r: element.width / 2 + DEFAULT_OFFSET
9050 }, OUTLINE_STYLE));
9051
9052 } else if (is$1(element, 'bpmn:DataObjectReference') && isStandardSize(element, 'bpmn:DataObjectReference')) {
9053
9054 outline = createPath(
9055 DATA_OBJECT_REFERENCE_OUTLINE_PATH,
9056 { x: -6, y: -6 },
9057 OUTLINE_STYLE
9058 );
9059
9060 } else if (is$1(element, 'bpmn:DataStoreReference') && isStandardSize(element, 'bpmn:DataStoreReference')) {
9061
9062 outline = createPath(
9063 DATA_STORE_REFERENCE_OUTLINE_PATH,
9064 { x: -6, y: -6 },
9065 OUTLINE_STYLE
9066 );
9067 }
9068
9069 return outline;
9070 };
9071
9072 /**
9073 * Updates the outline for a given element.
9074 * Returns true if the update for the given element was handled by this provider.
9075 *
9076 * @param {Element} element
9077 * @param {Outline} outline
9078 * @returns {boolean}
9079 */
9080 OutlineProvider.prototype.updateOutline = function(element, outline) {
9081
9082 if (isLabel(element)) {
9083 return;
9084 }
9085
9086 if (isAny(element, [ 'bpmn:SubProcess', 'bpmn:Group' ])) {
9087
9088 attr$1(outline, {
9089 width: element.width + DEFAULT_OFFSET * 2,
9090 height: element.height + DEFAULT_OFFSET * 2
9091 });
9092
9093 return true;
9094
9095 } else if (isAny(element, [
9096 'bpmn:Event',
9097 'bpmn:Gateway',
9098 'bpmn:DataStoreReference',
9099 'bpmn:DataObjectReference'
9100 ])) {
9101 return true;
9102 }
9103
9104 return false;
9105 };
9106
9107
9108 // helpers //////////
9109
9110 function isStandardSize(element, type) {
9111 var standardSize;
9112
9113 if (type === 'bpmn:DataObjectReference') {
9114 standardSize = DATA_OBJECT_REFERENCE_STANDARD_SIZE;
9115 } else if (type === 'bpmn:DataStoreReference') {
9116 standardSize = DATA_STORE_REFERENCE_STANDARD_SIZE;
9117 }
9118
9119 return element.width === standardSize.width
9120 && element.height === standardSize.height;
9121 }
9122
9123 var OutlineModule = {
9124 __depends__: [
9125 OutlineModule$1
9126 ],
9127 __init__: [ 'outlineProvider' ],
9128 outlineProvider: [ 'type', OutlineProvider ]
9129 };
9130
9131 /**
9132 * @typedef {import('../util/Types').Point} Point
9133 */
9134
9135 /**
9136 * @param {import('../core/EventBus').Event} event
9137 *
9138 * @return {Event}
9139 */
9140 function getOriginal(event) {
9141 return event.originalEvent || event.srcEvent;
9142 }
9143
9144 /**
9145 * @param {MouseEvent} event
9146 * @param {string} button
9147 *
9148 * @return {boolean}
9149 */
9150 function isButton(event, button) {
9151 return (getOriginal(event) || event).button === button;
9152 }
9153
9154 /**
9155 * @param {MouseEvent} event
9156 *
9157 * @return {boolean}
9158 */
9159 function isPrimaryButton(event) {
9160
9161 // button === 0 -> left áka primary mouse button
9162 return isButton(event, 0);
9163 }
9164
9165 /**
9166 * @param {MouseEvent} event
9167 *
9168 * @return {boolean}
9169 */
9170 function isAuxiliaryButton(event) {
9171
9172 // button === 1 -> auxiliary áka wheel button
9173 return isButton(event, 1);
9174 }
9175
9176 /**
9177 * @param {MouseEvent} event
9178 *
9179 * @return {boolean}
9180 */
9181 function hasSecondaryModifier(event) {
9182 var originalEvent = getOriginal(event) || event;
9183
9184 return isPrimaryButton(event) && originalEvent.shiftKey;
9185 }
9186
9187 /**
9188 * @typedef {import('../../model/Types').Element} Element
9189 *
9190 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
9191 * @typedef {import('../../core/EventBus').default} EventBus
9192 * @typedef {import('../../draw/Styles').default} Styles
9193 *
9194 * @typedef {import('../../util/Types').Point} Point
9195 */
9196
9197 function allowAll(event) { return true; }
9198
9199 function allowPrimaryAndAuxiliary(event) {
9200 return isPrimaryButton(event) || isAuxiliaryButton(event);
9201 }
9202
9203 var LOW_PRIORITY = 500;
9204
9205
9206 /**
9207 * A plugin that provides interaction events for diagram elements.
9208 *
9209 * It emits the following events:
9210 *
9211 * * element.click
9212 * * element.contextmenu
9213 * * element.dblclick
9214 * * element.hover
9215 * * element.mousedown
9216 * * element.mousemove
9217 * * element.mouseup
9218 * * element.out
9219 *
9220 * Each event is a tuple { element, gfx, originalEvent }.
9221 *
9222 * Canceling the event via Event#preventDefault()
9223 * prevents the original DOM operation.
9224 *
9225 * @param {EventBus} eventBus
9226 * @param {ElementRegistry} elementRegistry
9227 * @param {Styles} styles
9228 */
9229 function InteractionEvents(eventBus, elementRegistry, styles) {
9230
9231 var self = this;
9232
9233 /**
9234 * Fire an interaction event.
9235 *
9236 * @param {string} type local event name, e.g. element.click.
9237 * @param {MouseEvent|TouchEvent} event native event
9238 * @param {Element} [element] the diagram element to emit the event on;
9239 * defaults to the event target
9240 */
9241 function fire(type, event, element) {
9242
9243 if (isIgnored(type, event)) {
9244 return;
9245 }
9246
9247 var target, gfx, returnValue;
9248
9249 if (!element) {
9250 target = event.delegateTarget || event.target;
9251
9252 if (target) {
9253 gfx = target;
9254 element = elementRegistry.get(gfx);
9255 }
9256 } else {
9257 gfx = elementRegistry.getGraphics(element);
9258 }
9259
9260 if (!gfx || !element) {
9261 return;
9262 }
9263
9264 returnValue = eventBus.fire(type, {
9265 element: element,
9266 gfx: gfx,
9267 originalEvent: event
9268 });
9269
9270 if (returnValue === false) {
9271 event.stopPropagation();
9272 event.preventDefault();
9273 }
9274 }
9275
9276 // TODO(nikku): document this
9277 var handlers = {};
9278
9279 function mouseHandler(localEventName) {
9280 return handlers[localEventName];
9281 }
9282
9283 function isIgnored(localEventName, event) {
9284
9285 var filter = ignoredFilters[localEventName] || isPrimaryButton;
9286
9287 // only react on left mouse button interactions
9288 // except for interaction events that are enabled
9289 // for secundary mouse button
9290 return !filter(event);
9291 }
9292
9293 var bindings = {
9294 click: 'element.click',
9295 contextmenu: 'element.contextmenu',
9296 dblclick: 'element.dblclick',
9297 mousedown: 'element.mousedown',
9298 mousemove: 'element.mousemove',
9299 mouseover: 'element.hover',
9300 mouseout: 'element.out',
9301 mouseup: 'element.mouseup',
9302 };
9303
9304 var ignoredFilters = {
9305 'element.contextmenu': allowAll,
9306 'element.mousedown': allowPrimaryAndAuxiliary,
9307 'element.mouseup': allowPrimaryAndAuxiliary,
9308 'element.click': allowPrimaryAndAuxiliary,
9309 'element.dblclick': allowPrimaryAndAuxiliary
9310 };
9311
9312
9313 // manual event trigger //////////
9314
9315 /**
9316 * Trigger an interaction event (based on a native dom event)
9317 * on the target shape or connection.
9318 *
9319 * @param {string} eventName the name of the triggered DOM event
9320 * @param {MouseEvent|TouchEvent} event
9321 * @param {Element} targetElement
9322 */
9323 function triggerMouseEvent(eventName, event, targetElement) {
9324
9325 // i.e. element.mousedown...
9326 var localEventName = bindings[eventName];
9327
9328 if (!localEventName) {
9329 throw new Error('unmapped DOM event name <' + eventName + '>');
9330 }
9331
9332 return fire(localEventName, event, targetElement);
9333 }
9334
9335
9336 var ELEMENT_SELECTOR = 'svg, .djs-element';
9337
9338 // event handling ///////
9339
9340 function registerEvent(node, event, localEvent, ignoredFilter) {
9341
9342 var handler = handlers[localEvent] = function(event) {
9343 fire(localEvent, event);
9344 };
9345
9346 if (ignoredFilter) {
9347 ignoredFilters[localEvent] = ignoredFilter;
9348 }
9349
9350 handler.$delegate = delegate.bind(node, ELEMENT_SELECTOR, event, handler);
9351 }
9352
9353 function unregisterEvent(node, event, localEvent) {
9354
9355 var handler = mouseHandler(localEvent);
9356
9357 if (!handler) {
9358 return;
9359 }
9360
9361 delegate.unbind(node, event, handler.$delegate);
9362 }
9363
9364 function registerEvents(svg) {
9365 forEach$1(bindings, function(val, key) {
9366 registerEvent(svg, key, val);
9367 });
9368 }
9369
9370 function unregisterEvents(svg) {
9371 forEach$1(bindings, function(val, key) {
9372 unregisterEvent(svg, key, val);
9373 });
9374 }
9375
9376 eventBus.on('canvas.destroy', function(event) {
9377 unregisterEvents(event.svg);
9378 });
9379
9380 eventBus.on('canvas.init', function(event) {
9381 registerEvents(event.svg);
9382 });
9383
9384
9385 // hit box updating ////////////////
9386
9387 eventBus.on([ 'shape.added', 'connection.added' ], function(event) {
9388 var element = event.element,
9389 gfx = event.gfx;
9390
9391 eventBus.fire('interactionEvents.createHit', { element: element, gfx: gfx });
9392 });
9393
9394 // Update djs-hit on change.
9395 // A low priortity is necessary, because djs-hit of labels has to be updated
9396 // after the label bounds have been updated in the renderer.
9397 eventBus.on([
9398 'shape.changed',
9399 'connection.changed'
9400 ], LOW_PRIORITY, function(event) {
9401
9402 var element = event.element,
9403 gfx = event.gfx;
9404
9405 eventBus.fire('interactionEvents.updateHit', { element: element, gfx: gfx });
9406 });
9407
9408 eventBus.on('interactionEvents.createHit', LOW_PRIORITY, function(event) {
9409 var element = event.element,
9410 gfx = event.gfx;
9411
9412 self.createDefaultHit(element, gfx);
9413 });
9414
9415 eventBus.on('interactionEvents.updateHit', function(event) {
9416 var element = event.element,
9417 gfx = event.gfx;
9418
9419 self.updateDefaultHit(element, gfx);
9420 });
9421
9422
9423 // hit styles ////////////
9424
9425 var STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-stroke');
9426
9427 var CLICK_STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-click-stroke');
9428
9429 var ALL_HIT_STYLE = createHitStyle('djs-hit djs-hit-all');
9430
9431 var NO_MOVE_HIT_STYLE = createHitStyle('djs-hit djs-hit-no-move');
9432
9433 var HIT_TYPES = {
9434 'all': ALL_HIT_STYLE,
9435 'click-stroke': CLICK_STROKE_HIT_STYLE,
9436 'stroke': STROKE_HIT_STYLE,
9437 'no-move': NO_MOVE_HIT_STYLE
9438 };
9439
9440 function createHitStyle(classNames, attrs) {
9441
9442 attrs = assign$1({
9443 stroke: 'white',
9444 strokeWidth: 15
9445 }, attrs || {});
9446
9447 return styles.cls(classNames, [ 'no-fill', 'no-border' ], attrs);
9448 }
9449
9450
9451 // style helpers ///////////////
9452
9453 function applyStyle(hit, type) {
9454
9455 var attrs = HIT_TYPES[type];
9456
9457 if (!attrs) {
9458 throw new Error('invalid hit type <' + type + '>');
9459 }
9460
9461 attr$1(hit, attrs);
9462
9463 return hit;
9464 }
9465
9466 function appendHit(gfx, hit) {
9467 append(gfx, hit);
9468 }
9469
9470
9471 // API
9472
9473 /**
9474 * Remove hints on the given graphics.
9475 *
9476 * @param {SVGElement} gfx
9477 */
9478 this.removeHits = function(gfx) {
9479 var hits = all('.djs-hit', gfx);
9480
9481 forEach$1(hits, remove$2);
9482 };
9483
9484 /**
9485 * Create default hit for the given element.
9486 *
9487 * @param {Element} element
9488 * @param {SVGElement} gfx
9489 *
9490 * @return {SVGElement} created hit
9491 */
9492 this.createDefaultHit = function(element, gfx) {
9493 var waypoints = element.waypoints,
9494 isFrame = element.isFrame,
9495 boxType;
9496
9497 if (waypoints) {
9498 return this.createWaypointsHit(gfx, waypoints);
9499 } else {
9500
9501 boxType = isFrame ? 'stroke' : 'all';
9502
9503 return this.createBoxHit(gfx, boxType, {
9504 width: element.width,
9505 height: element.height
9506 });
9507 }
9508 };
9509
9510 /**
9511 * Create hits for the given waypoints.
9512 *
9513 * @param {SVGElement} gfx
9514 * @param {Point[]} waypoints
9515 *
9516 * @return {SVGElement}
9517 */
9518 this.createWaypointsHit = function(gfx, waypoints) {
9519
9520 var hit = createLine(waypoints);
9521
9522 applyStyle(hit, 'stroke');
9523
9524 appendHit(gfx, hit);
9525
9526 return hit;
9527 };
9528
9529 /**
9530 * Create hits for a box.
9531 *
9532 * @param {SVGElement} gfx
9533 * @param {string} type
9534 * @param {Object} attrs
9535 *
9536 * @return {SVGElement}
9537 */
9538 this.createBoxHit = function(gfx, type, attrs) {
9539
9540 attrs = assign$1({
9541 x: 0,
9542 y: 0
9543 }, attrs);
9544
9545 var hit = create$1('rect');
9546
9547 applyStyle(hit, type);
9548
9549 attr$1(hit, attrs);
9550
9551 appendHit(gfx, hit);
9552
9553 return hit;
9554 };
9555
9556 /**
9557 * Update default hit of the element.
9558 *
9559 * @param {Element} element
9560 * @param {SVGElement} gfx
9561 *
9562 * @return {SVGElement} updated hit
9563 */
9564 this.updateDefaultHit = function(element, gfx) {
9565
9566 var hit = query('.djs-hit', gfx);
9567
9568 if (!hit) {
9569 return;
9570 }
9571
9572 if (element.waypoints) {
9573 updateLine(hit, element.waypoints);
9574 } else {
9575 attr$1(hit, {
9576 width: element.width,
9577 height: element.height
9578 });
9579 }
9580
9581 return hit;
9582 };
9583
9584 this.fire = fire;
9585
9586 this.triggerMouseEvent = triggerMouseEvent;
9587
9588 this.mouseHandler = mouseHandler;
9589
9590 this.registerEvent = registerEvent;
9591 this.unregisterEvent = unregisterEvent;
9592 }
9593
9594
9595 InteractionEvents.$inject = [
9596 'eventBus',
9597 'elementRegistry',
9598 'styles'
9599 ];
9600
9601
9602 /**
9603 * An event indicating that the mouse hovered over an element
9604 *
9605 * @event element.hover
9606 *
9607 * @type {Object}
9608 * @property {Element} element
9609 * @property {SVGElement} gfx
9610 * @property {Event} originalEvent
9611 */
9612
9613 /**
9614 * An event indicating that the mouse has left an element
9615 *
9616 * @event element.out
9617 *
9618 * @type {Object}
9619 * @property {Element} element
9620 * @property {SVGElement} gfx
9621 * @property {Event} originalEvent
9622 */
9623
9624 /**
9625 * An event indicating that the mouse has clicked an element
9626 *
9627 * @event element.click
9628 *
9629 * @type {Object}
9630 * @property {Element} element
9631 * @property {SVGElement} gfx
9632 * @property {Event} originalEvent
9633 */
9634
9635 /**
9636 * An event indicating that the mouse has double clicked an element
9637 *
9638 * @event element.dblclick
9639 *
9640 * @type {Object}
9641 * @property {Element} element
9642 * @property {SVGElement} gfx
9643 * @property {Event} originalEvent
9644 */
9645
9646 /**
9647 * An event indicating that the mouse has gone down on an element.
9648 *
9649 * @event element.mousedown
9650 *
9651 * @type {Object}
9652 * @property {Element} element
9653 * @property {SVGElement} gfx
9654 * @property {Event} originalEvent
9655 */
9656
9657 /**
9658 * An event indicating that the mouse has gone up on an element.
9659 *
9660 * @event element.mouseup
9661 *
9662 * @type {Object}
9663 * @property {Element} element
9664 * @property {SVGElement} gfx
9665 * @property {Event} originalEvent
9666 */
9667
9668 /**
9669 * An event indicating that the context menu action is triggered
9670 * via mouse or touch controls.
9671 *
9672 * @event element.contextmenu
9673 *
9674 * @type {Object}
9675 * @property {Element} element
9676 * @property {SVGElement} gfx
9677 * @property {Event} originalEvent
9678 */
9679
9680 /**
9681 * @type { import('didi').ModuleDeclaration }
9682 */
9683 var InteractionEventsModule = {
9684 __init__: [ 'interactionEvents' ],
9685 interactionEvents: [ 'type', InteractionEvents ]
9686 };
9687
9688 /**
9689 * @typedef {import('../../core/Canvas').default} Canvas
9690 * @typedef {import('../../core/EventBus').default} EventBus
9691 */
9692
9693 /**
9694 * A service that offers the current selection in a diagram.
9695 * Offers the api to control the selection, too.
9696 *
9697 * @param {EventBus} eventBus
9698 * @param {Canvas} canvas
9699 */
9700 function Selection(eventBus, canvas) {
9701
9702 this._eventBus = eventBus;
9703 this._canvas = canvas;
9704
9705 /**
9706 * @type {Object[]}
9707 */
9708 this._selectedElements = [];
9709
9710 var self = this;
9711
9712 eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
9713 var element = e.element;
9714 self.deselect(element);
9715 });
9716
9717 eventBus.on([ 'diagram.clear', 'root.set' ], function(e) {
9718 self.select(null);
9719 });
9720 }
9721
9722 Selection.$inject = [ 'eventBus', 'canvas' ];
9723
9724 /**
9725 * Deselect an element.
9726 *
9727 * @param {Object} element The element to deselect.
9728 */
9729 Selection.prototype.deselect = function(element) {
9730 var selectedElements = this._selectedElements;
9731
9732 var idx = selectedElements.indexOf(element);
9733
9734 if (idx !== -1) {
9735 var oldSelection = selectedElements.slice();
9736
9737 selectedElements.splice(idx, 1);
9738
9739 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
9740 }
9741 };
9742
9743 /**
9744 * Get the selected elements.
9745 *
9746 * @return {Object[]} The selected elements.
9747 */
9748 Selection.prototype.get = function() {
9749 return this._selectedElements;
9750 };
9751
9752 /**
9753 * Check whether an element is selected.
9754 *
9755 * @param {Object} element The element.
9756 *
9757 * @return {boolean} Whether the element is selected.
9758 */
9759 Selection.prototype.isSelected = function(element) {
9760 return this._selectedElements.indexOf(element) !== -1;
9761 };
9762
9763
9764 /**
9765 * Select one or many elements.
9766 *
9767 * @param {Object|Object[]} elements The element(s) to select.
9768 * @param {boolean} [add] Whether to add the element(s) to the selected elements.
9769 * Defaults to `false`.
9770 */
9771 Selection.prototype.select = function(elements, add) {
9772 var selectedElements = this._selectedElements,
9773 oldSelection = selectedElements.slice();
9774
9775 if (!isArray$2(elements)) {
9776 elements = elements ? [ elements ] : [];
9777 }
9778
9779 var canvas = this._canvas;
9780
9781 var rootElement = canvas.getRootElement();
9782
9783 elements = elements.filter(function(element) {
9784 var elementRoot = canvas.findRoot(element);
9785
9786 return rootElement === elementRoot;
9787 });
9788
9789 // selection may be cleared by passing an empty array or null
9790 // to the method
9791 if (add) {
9792 forEach$1(elements, function(element) {
9793 if (selectedElements.indexOf(element) !== -1) {
9794
9795 // already selected
9796 return;
9797 } else {
9798 selectedElements.push(element);
9799 }
9800 });
9801 } else {
9802 this._selectedElements = selectedElements = elements.slice();
9803 }
9804
9805 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
9806 };
9807
9808 /**
9809 * @typedef {import('../../core/Canvas').default} Canvas
9810 * @typedef {import('../../core/EventBus').default} EventBus
9811 * @typedef {import('./Selection').default} Selection
9812 */
9813
9814 var MARKER_HOVER = 'hover',
9815 MARKER_SELECTED = 'selected';
9816
9817 var SELECTION_OUTLINE_PADDING = 6;
9818
9819
9820 /**
9821 * A plugin that adds a visible selection UI to shapes and connections
9822 * by appending the <code>hover</code> and <code>selected</code> classes to them.
9823 *
9824 * @class
9825 *
9826 * Makes elements selectable, too.
9827 *
9828 * @param {Canvas} canvas
9829 * @param {EventBus} eventBus
9830 * @param {Selection} selection
9831 */
9832 function SelectionVisuals(canvas, eventBus, selection) {
9833 this._canvas = canvas;
9834
9835 var self = this;
9836
9837 this._multiSelectionBox = null;
9838
9839 function addMarker(e, cls) {
9840 canvas.addMarker(e, cls);
9841 }
9842
9843 function removeMarker(e, cls) {
9844 canvas.removeMarker(e, cls);
9845 }
9846
9847 eventBus.on('element.hover', function(event) {
9848 addMarker(event.element, MARKER_HOVER);
9849 });
9850
9851 eventBus.on('element.out', function(event) {
9852 removeMarker(event.element, MARKER_HOVER);
9853 });
9854
9855 eventBus.on('selection.changed', function(event) {
9856
9857 function deselect(s) {
9858 removeMarker(s, MARKER_SELECTED);
9859 }
9860
9861 function select(s) {
9862 addMarker(s, MARKER_SELECTED);
9863 }
9864
9865 var oldSelection = event.oldSelection,
9866 newSelection = event.newSelection;
9867
9868 forEach$1(oldSelection, function(e) {
9869 if (newSelection.indexOf(e) === -1) {
9870 deselect(e);
9871 }
9872 });
9873
9874 forEach$1(newSelection, function(e) {
9875 if (oldSelection.indexOf(e) === -1) {
9876 select(e);
9877 }
9878 });
9879
9880 self._updateSelectionOutline(newSelection);
9881 });
9882
9883
9884 eventBus.on('element.changed', function(event) {
9885 if (selection.isSelected(event.element)) {
9886 self._updateSelectionOutline(selection.get());
9887 }
9888 });
9889 }
9890
9891 SelectionVisuals.$inject = [
9892 'canvas',
9893 'eventBus',
9894 'selection'
9895 ];
9896
9897 SelectionVisuals.prototype._updateSelectionOutline = function(selection) {
9898 var layer = this._canvas.getLayer('selectionOutline');
9899
9900 clear$1(layer);
9901
9902 var enabled = selection.length > 1;
9903
9904 var container = this._canvas.getContainer();
9905
9906 classes$1(container)[enabled ? 'add' : 'remove']('djs-multi-select');
9907
9908 if (!enabled) {
9909 return;
9910 }
9911
9912 var bBox = addSelectionOutlinePadding(getBBox(selection));
9913
9914 var rect = create$1('rect');
9915
9916 attr$1(rect, assign$1({
9917 rx: 3
9918 }, bBox));
9919
9920 classes$1(rect).add('djs-selection-outline');
9921
9922 append(layer, rect);
9923 };
9924
9925 // helpers //////////
9926
9927 function addSelectionOutlinePadding(bBox) {
9928 return {
9929 x: bBox.x - SELECTION_OUTLINE_PADDING,
9930 y: bBox.y - SELECTION_OUTLINE_PADDING,
9931 width: bBox.width + SELECTION_OUTLINE_PADDING * 2,
9932 height: bBox.height + SELECTION_OUTLINE_PADDING * 2
9933 };
9934 }
9935
9936 /**
9937 * @typedef {import('../../core/Canvas').default} Canvas
9938 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
9939 * @typedef {import('../../core/EventBus').default} EventBus
9940 * @typedef {import('./Selection').default} Selection
9941 */
9942
9943 /**
9944 * @param {EventBus} eventBus
9945 * @param {Selection} selection
9946 * @param {Canvas} canvas
9947 * @param {ElementRegistry} elementRegistry
9948 */
9949 function SelectionBehavior(eventBus, selection, canvas, elementRegistry) {
9950
9951 // Select elements on create
9952 eventBus.on('create.end', 500, function(event) {
9953 var context = event.context,
9954 canExecute = context.canExecute,
9955 elements = context.elements,
9956 hints = context.hints || {},
9957 autoSelect = hints.autoSelect;
9958
9959 if (canExecute) {
9960 if (autoSelect === false) {
9961
9962 // Select no elements
9963 return;
9964 }
9965
9966 if (isArray$2(autoSelect)) {
9967 selection.select(autoSelect);
9968 } else {
9969
9970 // Select all elements by default
9971 selection.select(elements.filter(isShown));
9972 }
9973 }
9974 });
9975
9976 // Select connection targets on connect
9977 eventBus.on('connect.end', 500, function(event) {
9978 var context = event.context,
9979 connection = context.connection;
9980
9981 if (connection) {
9982 selection.select(connection);
9983 }
9984 });
9985
9986 // Select shapes on move
9987 eventBus.on('shape.move.end', 500, function(event) {
9988 var previousSelection = event.previousSelection || [];
9989
9990 var shape = elementRegistry.get(event.context.shape.id);
9991
9992 // Always select main shape on move
9993 var isSelected = find(previousSelection, function(selectedShape) {
9994 return shape.id === selectedShape.id;
9995 });
9996
9997 if (!isSelected) {
9998 selection.select(shape);
9999 }
10000 });
10001
10002 // Select elements on click
10003 eventBus.on('element.click', function(event) {
10004
10005 if (!isPrimaryButton(event)) {
10006 return;
10007 }
10008
10009 var element = event.element;
10010
10011 if (element === canvas.getRootElement()) {
10012 element = null;
10013 }
10014
10015 var isSelected = selection.isSelected(element),
10016 isMultiSelect = selection.get().length > 1;
10017
10018 // Add to selection if SHIFT pressed
10019 var add = hasSecondaryModifier(event);
10020
10021 if (isSelected && isMultiSelect) {
10022 if (add) {
10023
10024 // Deselect element
10025 return selection.deselect(element);
10026 } else {
10027
10028 // Select element only
10029 return selection.select(element);
10030 }
10031 } else if (!isSelected) {
10032
10033 // Select element
10034 selection.select(element, add);
10035 } else {
10036
10037 // Deselect element
10038 selection.deselect(element);
10039 }
10040 });
10041 }
10042
10043 SelectionBehavior.$inject = [
10044 'eventBus',
10045 'selection',
10046 'canvas',
10047 'elementRegistry'
10048 ];
10049
10050
10051 function isShown(element) {
10052 return !element.hidden;
10053 }
10054
10055 /**
10056 * @type { import('didi').ModuleDeclaration }
10057 */
10058 var SelectionModule = {
10059 __init__: [ 'selectionVisuals', 'selectionBehavior' ],
10060 __depends__: [
10061 InteractionEventsModule,
10062 OutlineModule$1
10063 ],
10064 selection: [ 'type', Selection ],
10065 selectionVisuals: [ 'type', SelectionVisuals ],
10066 selectionBehavior: [ 'type', SelectionBehavior ]
10067 };
10068
10069 const CLASS_PATTERN = /^class[ {]/;
10070
10071
10072 /**
10073 * @param {function} fn
10074 *
10075 * @return {boolean}
10076 */
10077 function isClass(fn) {
10078 return CLASS_PATTERN.test(fn.toString());
10079 }
10080
10081 /**
10082 * @param {any} obj
10083 *
10084 * @return {boolean}
10085 */
10086 function isArray(obj) {
10087 return Array.isArray(obj);
10088 }
10089
10090 /**
10091 * @param {any} obj
10092 * @param {string} prop
10093 *
10094 * @return {boolean}
10095 */
10096 function hasOwnProp(obj, prop) {
10097 return Object.prototype.hasOwnProperty.call(obj, prop);
10098 }
10099
10100 /**
10101 * @typedef {import('./index.js').InjectAnnotated } InjectAnnotated
10102 */
10103
10104 /**
10105 * @template T
10106 *
10107 * @params {[...string[], T] | ...string[], T} args
10108 *
10109 * @return {T & InjectAnnotated}
10110 */
10111 function annotate(...args) {
10112
10113 if (args.length === 1 && isArray(args[0])) {
10114 args = args[0];
10115 }
10116
10117 args = [ ...args ];
10118
10119 const fn = args.pop();
10120
10121 fn.$inject = args;
10122
10123 return fn;
10124 }
10125
10126
10127 // Current limitations:
10128 // - can't put into "function arg" comments
10129 // function /* (no parenthesis like this) */ (){}
10130 // function abc( /* xx (no parenthesis like this) */ a, b) {}
10131 //
10132 // Just put the comment before function or inside:
10133 // /* (((this is fine))) */ function(a, b) {}
10134 // function abc(a) { /* (((this is fine))) */}
10135 //
10136 // - can't reliably auto-annotate constructor; we'll match the
10137 // first constructor(...) pattern found which may be the one
10138 // of a nested class, too.
10139
10140 const CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
10141 const FN_ARGS = /^(?:async\s+)?(?:function\s*[^(]*)?(?:\(\s*([^)]*)\)|(\w+))/m;
10142 const FN_ARG = /\/\*([^*]*)\*\//m;
10143
10144 /**
10145 * @param {unknown} fn
10146 *
10147 * @return {string[]}
10148 */
10149 function parseAnnotations(fn) {
10150
10151 if (typeof fn !== 'function') {
10152 throw new Error(`Cannot annotate "${fn}". Expected a function!`);
10153 }
10154
10155 const match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
10156
10157 // may parse class without constructor
10158 if (!match) {
10159 return [];
10160 }
10161
10162 const args = match[1] || match[2];
10163
10164 return args && args.split(',').map(arg => {
10165 const argMatch = arg.match(FN_ARG);
10166 return (argMatch && argMatch[1] || arg).trim();
10167 }) || [];
10168 }
10169
10170 /**
10171 * @typedef { import('./index.js').ModuleDeclaration } ModuleDeclaration
10172 * @typedef { import('./index.js').ModuleDefinition } ModuleDefinition
10173 * @typedef { import('./index.js').InjectorContext } InjectorContext
10174 *
10175 * @typedef { import('./index.js').TypedDeclaration<any, any> } TypedDeclaration
10176 */
10177
10178 /**
10179 * Create a new injector with the given modules.
10180 *
10181 * @param {ModuleDefinition[]} modules
10182 * @param {InjectorContext} [_parent]
10183 */
10184 function Injector(modules, _parent) {
10185
10186 const parent = _parent || /** @type InjectorContext */ ({
10187 get: function(name, strict) {
10188 currentlyResolving.push(name);
10189
10190 if (strict === false) {
10191 return null;
10192 } else {
10193 throw error(`No provider for "${ name }"!`);
10194 }
10195 }
10196 });
10197
10198 const currentlyResolving = [];
10199 const providers = this._providers = Object.create(parent._providers || null);
10200 const instances = this._instances = Object.create(null);
10201
10202 const self = instances.injector = this;
10203
10204 const error = function(msg) {
10205 const stack = currentlyResolving.join(' -> ');
10206 currentlyResolving.length = 0;
10207 return new Error(stack ? `${ msg } (Resolving: ${ stack })` : msg);
10208 };
10209
10210 /**
10211 * Return a named service.
10212 *
10213 * @param {string} name
10214 * @param {boolean} [strict=true] if false, resolve missing services to null
10215 *
10216 * @return {any}
10217 */
10218 function get(name, strict) {
10219 if (!providers[name] && name.includes('.')) {
10220
10221 const parts = name.split('.');
10222 let pivot = get(/** @type { string } */ (parts.shift()));
10223
10224 while (parts.length) {
10225 pivot = pivot[/** @type { string } */ (parts.shift())];
10226 }
10227
10228 return pivot;
10229 }
10230
10231 if (hasOwnProp(instances, name)) {
10232 return instances[name];
10233 }
10234
10235 if (hasOwnProp(providers, name)) {
10236 if (currentlyResolving.indexOf(name) !== -1) {
10237 currentlyResolving.push(name);
10238 throw error('Cannot resolve circular dependency!');
10239 }
10240
10241 currentlyResolving.push(name);
10242 instances[name] = providers[name][0](providers[name][1]);
10243 currentlyResolving.pop();
10244
10245 return instances[name];
10246 }
10247
10248 return parent.get(name, strict);
10249 }
10250
10251 function fnDef(fn, locals) {
10252
10253 if (typeof locals === 'undefined') {
10254 locals = {};
10255 }
10256
10257 if (typeof fn !== 'function') {
10258 if (isArray(fn)) {
10259 fn = annotate(fn.slice());
10260 } else {
10261 throw error(`Cannot invoke "${ fn }". Expected a function!`);
10262 }
10263 }
10264
10265 /**
10266 * @type {string[]}
10267 */
10268 const inject = fn.$inject || parseAnnotations(fn);
10269 const dependencies = inject.map(dep => {
10270 if (hasOwnProp(locals, dep)) {
10271 return locals[dep];
10272 } else {
10273 return get(dep);
10274 }
10275 });
10276
10277 return {
10278 fn: fn,
10279 dependencies
10280 };
10281 }
10282
10283 /**
10284 * Instantiate the given type, injecting dependencies.
10285 *
10286 * @template T
10287 *
10288 * @param { Function | [...string[], Function ]} type
10289 *
10290 * @return T
10291 */
10292 function instantiate(type) {
10293 const {
10294 fn,
10295 dependencies
10296 } = fnDef(type);
10297
10298 // instantiate var args constructor
10299 const Constructor = Function.prototype.bind.call(fn, null, ...dependencies);
10300
10301 return new Constructor();
10302 }
10303
10304 /**
10305 * Invoke the given function, injecting dependencies. Return the result.
10306 *
10307 * @template T
10308 *
10309 * @param { Function | [...string[], Function ]} func
10310 * @param { Object } [context]
10311 * @param { Object } [locals]
10312 *
10313 * @return {T} invocation result
10314 */
10315 function invoke(func, context, locals) {
10316 const {
10317 fn,
10318 dependencies
10319 } = fnDef(func, locals);
10320
10321 return fn.apply(context, dependencies);
10322 }
10323
10324 /**
10325 * @param {Injector} childInjector
10326 *
10327 * @return {Function}
10328 */
10329 function createPrivateInjectorFactory(childInjector) {
10330 return annotate(key => childInjector.get(key));
10331 }
10332
10333 /**
10334 * @param {ModuleDefinition[]} modules
10335 * @param {string[]} [forceNewInstances]
10336 *
10337 * @return {Injector}
10338 */
10339 function createChild(modules, forceNewInstances) {
10340 if (forceNewInstances && forceNewInstances.length) {
10341 const fromParentModule = Object.create(null);
10342 const matchedScopes = Object.create(null);
10343
10344 const privateInjectorsCache = [];
10345 const privateChildInjectors = [];
10346 const privateChildFactories = [];
10347
10348 let provider;
10349 let cacheIdx;
10350 let privateChildInjector;
10351 let privateChildInjectorFactory;
10352
10353 for (let name in providers) {
10354 provider = providers[name];
10355
10356 if (forceNewInstances.indexOf(name) !== -1) {
10357 if (provider[2] === 'private') {
10358 cacheIdx = privateInjectorsCache.indexOf(provider[3]);
10359 if (cacheIdx === -1) {
10360 privateChildInjector = provider[3].createChild([], forceNewInstances);
10361 privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
10362 privateInjectorsCache.push(provider[3]);
10363 privateChildInjectors.push(privateChildInjector);
10364 privateChildFactories.push(privateChildInjectorFactory);
10365 fromParentModule[name] = [ privateChildInjectorFactory, name, 'private', privateChildInjector ];
10366 } else {
10367 fromParentModule[name] = [ privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx] ];
10368 }
10369 } else {
10370 fromParentModule[name] = [ provider[2], provider[1] ];
10371 }
10372 matchedScopes[name] = true;
10373 }
10374
10375 if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
10376 /* jshint -W083 */
10377 forceNewInstances.forEach(scope => {
10378 if (provider[1].$scope.indexOf(scope) !== -1) {
10379 fromParentModule[name] = [ provider[2], provider[1] ];
10380 matchedScopes[scope] = true;
10381 }
10382 });
10383 }
10384 }
10385
10386 forceNewInstances.forEach(scope => {
10387 if (!matchedScopes[scope]) {
10388 throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
10389 }
10390 });
10391
10392 modules.unshift(fromParentModule);
10393 }
10394
10395 return new Injector(modules, self);
10396 }
10397
10398 const factoryMap = {
10399 factory: invoke,
10400 type: instantiate,
10401 value: function(value) {
10402 return value;
10403 }
10404 };
10405
10406 /**
10407 * @param {ModuleDefinition} moduleDefinition
10408 * @param {Injector} injector
10409 */
10410 function createInitializer(moduleDefinition, injector) {
10411
10412 const initializers = moduleDefinition.__init__ || [];
10413
10414 return function() {
10415 initializers.forEach(initializer => {
10416
10417 // eagerly resolve component (fn or string)
10418 if (typeof initializer === 'string') {
10419 injector.get(initializer);
10420 } else {
10421 injector.invoke(initializer);
10422 }
10423 });
10424 };
10425 }
10426
10427 /**
10428 * @param {ModuleDefinition} moduleDefinition
10429 */
10430 function loadModule(moduleDefinition) {
10431
10432 const moduleExports = moduleDefinition.__exports__;
10433
10434 // private module
10435 if (moduleExports) {
10436 const nestedModules = moduleDefinition.__modules__;
10437
10438 const clonedModule = Object.keys(moduleDefinition).reduce((clonedModule, key) => {
10439
10440 if (key !== '__exports__' && key !== '__modules__' && key !== '__init__' && key !== '__depends__') {
10441 clonedModule[key] = moduleDefinition[key];
10442 }
10443
10444 return clonedModule;
10445 }, Object.create(null));
10446
10447 const childModules = (nestedModules || []).concat(clonedModule);
10448
10449 const privateInjector = createChild(childModules);
10450 const getFromPrivateInjector = annotate(function(key) {
10451 return privateInjector.get(key);
10452 });
10453
10454 moduleExports.forEach(function(key) {
10455 providers[key] = [ getFromPrivateInjector, key, 'private', privateInjector ];
10456 });
10457
10458 // ensure child injector initializes
10459 const initializers = (moduleDefinition.__init__ || []).slice();
10460
10461 initializers.unshift(function() {
10462 privateInjector.init();
10463 });
10464
10465 moduleDefinition = Object.assign({}, moduleDefinition, {
10466 __init__: initializers
10467 });
10468
10469 return createInitializer(moduleDefinition, privateInjector);
10470 }
10471
10472 // normal module
10473 Object.keys(moduleDefinition).forEach(function(key) {
10474
10475 if (key === '__init__' || key === '__depends__') {
10476 return;
10477 }
10478
10479 const typeDeclaration = /** @type { TypedDeclaration } */ (
10480 moduleDefinition[key]
10481 );
10482
10483 if (typeDeclaration[2] === 'private') {
10484 providers[key] = typeDeclaration;
10485 return;
10486 }
10487
10488 const type = typeDeclaration[0];
10489 const value = typeDeclaration[1];
10490
10491 providers[key] = [ factoryMap[type], arrayUnwrap(type, value), type ];
10492 });
10493
10494 return createInitializer(moduleDefinition, self);
10495 }
10496
10497 /**
10498 * @param {ModuleDefinition[]} moduleDefinitions
10499 * @param {ModuleDefinition} moduleDefinition
10500 *
10501 * @return {ModuleDefinition[]}
10502 */
10503 function resolveDependencies(moduleDefinitions, moduleDefinition) {
10504
10505 if (moduleDefinitions.indexOf(moduleDefinition) !== -1) {
10506 return moduleDefinitions;
10507 }
10508
10509 moduleDefinitions = (moduleDefinition.__depends__ || []).reduce(resolveDependencies, moduleDefinitions);
10510
10511 if (moduleDefinitions.indexOf(moduleDefinition) !== -1) {
10512 return moduleDefinitions;
10513 }
10514
10515 return moduleDefinitions.concat(moduleDefinition);
10516 }
10517
10518 /**
10519 * @param {ModuleDefinition[]} moduleDefinitions
10520 *
10521 * @return { () => void } initializerFn
10522 */
10523 function bootstrap(moduleDefinitions) {
10524
10525 const initializers = moduleDefinitions
10526 .reduce(resolveDependencies, [])
10527 .map(loadModule);
10528
10529 let initialized = false;
10530
10531 return function() {
10532
10533 if (initialized) {
10534 return;
10535 }
10536
10537 initialized = true;
10538
10539 initializers.forEach(initializer => initializer());
10540 };
10541 }
10542
10543 // public API
10544 this.get = get;
10545 this.invoke = invoke;
10546 this.instantiate = instantiate;
10547 this.createChild = createChild;
10548
10549 // setup
10550 this.init = bootstrap(modules);
10551 }
10552
10553
10554 // helpers ///////////////
10555
10556 function arrayUnwrap(type, value) {
10557 if (type !== 'value' && isArray(value)) {
10558 value = annotate(value.slice());
10559 }
10560
10561 return value;
10562 }
10563
10564 /**
10565 * @typedef {import('../core/EventBus').default} EventBus
10566 * @typedef {import('./Styles').default} Styles
10567 */
10568
10569 // apply default renderer with lowest possible priority
10570 // so that it only kicks in if noone else could render
10571 var DEFAULT_RENDER_PRIORITY = 1;
10572
10573 /**
10574 * The default renderer used for shapes and connections.
10575 *
10576 * @param {EventBus} eventBus
10577 * @param {Styles} styles
10578 */
10579 function DefaultRenderer(eventBus, styles) {
10580
10581 BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY);
10582
10583 this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
10584 this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
10585 this.FRAME_STYLE = styles.style([ 'no-fill' ], { stroke: 'fuchsia', strokeDasharray: 4, strokeWidth: 2 });
10586 }
10587
10588 e(DefaultRenderer, BaseRenderer);
10589
10590
10591 /**
10592 * @private
10593 */
10594 DefaultRenderer.prototype.canRender = function() {
10595 return true;
10596 };
10597
10598 /**
10599 * @private
10600 */
10601 DefaultRenderer.prototype.drawShape = function drawShape(visuals, element, attrs) {
10602 var rect = create$1('rect');
10603
10604 attr$1(rect, {
10605 x: 0,
10606 y: 0,
10607 width: element.width || 0,
10608 height: element.height || 0
10609 });
10610
10611 if (isFrameElement(element)) {
10612 attr$1(rect, assign$1({}, this.FRAME_STYLE, attrs || {}));
10613 } else {
10614 attr$1(rect, assign$1({}, this.SHAPE_STYLE, attrs || {}));
10615 }
10616
10617 append(visuals, rect);
10618
10619 return rect;
10620 };
10621
10622 /**
10623 * @private
10624 */
10625 DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection, attrs) {
10626
10627 var line = createLine(connection.waypoints, assign$1({}, this.CONNECTION_STYLE, attrs || {}));
10628 append(visuals, line);
10629
10630 return line;
10631 };
10632
10633 /**
10634 * @private
10635 */
10636 DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {
10637
10638 var x = shape.x,
10639 y = shape.y,
10640 width = shape.width,
10641 height = shape.height;
10642
10643 var shapePath = [
10644 [ 'M', x, y ],
10645 [ 'l', width, 0 ],
10646 [ 'l', 0, height ],
10647 [ 'l', -width, 0 ],
10648 [ 'z' ]
10649 ];
10650
10651 return componentsToPath(shapePath);
10652 };
10653
10654 /**
10655 * @private
10656 */
10657 DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
10658 var waypoints = connection.waypoints;
10659
10660 var idx, point, connectionPath = [];
10661
10662 for (idx = 0; (point = waypoints[idx]); idx++) {
10663
10664 // take invisible docking into account
10665 // when creating the path
10666 point = point.original || point;
10667
10668 connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
10669 }
10670
10671 return componentsToPath(connectionPath);
10672 };
10673
10674 DefaultRenderer.$inject = [ 'eventBus', 'styles' ];
10675
10676 /**
10677 * A component that manages shape styles
10678 */
10679 function Styles() {
10680
10681 var defaultTraits = {
10682
10683 'no-fill': {
10684 fill: 'none'
10685 },
10686 'no-border': {
10687 strokeOpacity: 0.0
10688 },
10689 'no-events': {
10690 pointerEvents: 'none'
10691 }
10692 };
10693
10694 var self = this;
10695
10696 /**
10697 * Builds a style definition from a className, a list of traits and an object
10698 * of additional attributes.
10699 *
10700 * @param {string} className
10701 * @param {string[]} [traits]
10702 * @param {Object} [additionalAttrs]
10703 *
10704 * @return {Object} the style definition
10705 */
10706 this.cls = function(className, traits, additionalAttrs) {
10707 var attrs = this.style(traits, additionalAttrs);
10708
10709 return assign$1(attrs, { 'class': className });
10710 };
10711
10712 /**
10713 * Builds a style definition from a list of traits and an object of additional
10714 * attributes.
10715 *
10716 * @param {string[]} [traits]
10717 * @param {Object} additionalAttrs
10718 *
10719 * @return {Object} the style definition
10720 */
10721 this.style = function(traits, additionalAttrs) {
10722
10723 if (!isArray$2(traits) && !additionalAttrs) {
10724 additionalAttrs = traits;
10725 traits = [];
10726 }
10727
10728 var attrs = reduce(traits, function(attrs, t) {
10729 return assign$1(attrs, defaultTraits[t] || {});
10730 }, {});
10731
10732 return additionalAttrs ? assign$1(attrs, additionalAttrs) : attrs;
10733 };
10734
10735
10736 /**
10737 * Computes a style definition from a list of traits and an object of
10738 * additional attributes, with custom style definition object.
10739 *
10740 * @param {Object} custom
10741 * @param {string[]} [traits]
10742 * @param {Object} defaultStyles
10743 *
10744 * @return {Object} the style definition
10745 */
10746 this.computeStyle = function(custom, traits, defaultStyles) {
10747 if (!isArray$2(traits)) {
10748 defaultStyles = traits;
10749 traits = [];
10750 }
10751
10752 return self.style(traits || [], assign$1({}, defaultStyles, custom || {}));
10753 };
10754 }
10755
10756 /**
10757 * @type { import('didi').ModuleDeclaration }
10758 */
10759 var DrawModule = {
10760 __init__: [ 'defaultRenderer' ],
10761 defaultRenderer: [ 'type', DefaultRenderer ],
10762 styles: [ 'type', Styles ]
10763 };
10764
10765 /**
10766 * Failsafe remove an element from a collection
10767 *
10768 * @param {Array<Object>} [collection]
10769 * @param {Object} [element]
10770 *
10771 * @return {number} the previous index of the element
10772 */
10773 function remove(collection, element) {
10774
10775 if (!collection || !element) {
10776 return -1;
10777 }
10778
10779 var idx = collection.indexOf(element);
10780
10781 if (idx !== -1) {
10782 collection.splice(idx, 1);
10783 }
10784
10785 return idx;
10786 }
10787
10788 /**
10789 * Fail save add an element to the given connection, ensuring
10790 * it does not yet exist.
10791 *
10792 * @param {Array<Object>} collection
10793 * @param {Object} element
10794 * @param {number} [idx]
10795 */
10796 function add(collection, element, idx) {
10797
10798 if (!collection || !element) {
10799 return;
10800 }
10801
10802 if (typeof idx !== 'number') {
10803 idx = -1;
10804 }
10805
10806 var currentIdx = collection.indexOf(element);
10807
10808 if (currentIdx !== -1) {
10809
10810 if (currentIdx === idx) {
10811
10812 // nothing to do, position has not changed
10813 return;
10814 } else {
10815
10816 if (idx !== -1) {
10817
10818 // remove from current position
10819 collection.splice(currentIdx, 1);
10820 } else {
10821
10822 // already exists in collection
10823 return;
10824 }
10825 }
10826 }
10827
10828 if (idx !== -1) {
10829
10830 // insert at specified position
10831 collection.splice(idx, 0, element);
10832 } else {
10833
10834 // push to end
10835 collection.push(element);
10836 }
10837 }
10838
10839 /**
10840 * @typedef {import('./Types').ConnectionLike} ConnectionLike
10841 * @typedef {import('./Types').RootLike} RootLike
10842 * @typedef {import('./Types').ParentLike } ParentLike
10843 * @typedef {import('./Types').ShapeLike} ShapeLike
10844 *
10845 * @typedef { {
10846 * container?: HTMLElement;
10847 * deferUpdate?: boolean;
10848 * width?: number;
10849 * height?: number;
10850 * } } CanvasConfig
10851 * @typedef { {
10852 * group: SVGElement;
10853 * index: number;
10854 * visible: boolean;
10855 * } } CanvasLayer
10856 * @typedef { {
10857 * [key: string]: CanvasLayer;
10858 * } } CanvasLayers
10859 * @typedef { {
10860 * rootElement: ShapeLike;
10861 * layer: CanvasLayer;
10862 * } } CanvasPlane
10863 * @typedef { {
10864 * scale: number;
10865 * inner: Rect;
10866 * outer: Dimensions;
10867 * } & Rect } CanvasViewbox
10868 *
10869 * @typedef {import('./ElementRegistry').default} ElementRegistry
10870 * @typedef {import('./EventBus').default} EventBus
10871 * @typedef {import('./GraphicsFactory').default} GraphicsFactory
10872 *
10873 * @typedef {import('../util/Types').Dimensions} Dimensions
10874 * @typedef {import('../util/Types').Point} Point
10875 * @typedef {import('../util/Types').Rect} Rect
10876 * @typedef {import('../util/Types').RectTRBL} RectTRBL
10877 * @typedef {import('../util/Types').ScrollDelta} ScrollDelta
10878 */
10879
10880 function round(number, resolution) {
10881 return Math.round(number * resolution) / resolution;
10882 }
10883
10884 function ensurePx(number) {
10885 return isNumber(number) ? number + 'px' : number;
10886 }
10887
10888 function findRoot(element) {
10889 while (element.parent) {
10890 element = element.parent;
10891 }
10892
10893 return element;
10894 }
10895
10896 /**
10897 * Creates a HTML container element for a SVG element with
10898 * the given configuration
10899 *
10900 * @param {CanvasConfig} options
10901 *
10902 * @return {HTMLElement} the container element
10903 */
10904 function createContainer(options) {
10905
10906 options = assign$1({}, { width: '100%', height: '100%' }, options);
10907
10908 const container = options.container || document.body;
10909
10910 // create a <div> around the svg element with the respective size
10911 // this way we can always get the correct container size
10912 // (this is impossible for <svg> elements at the moment)
10913 const parent = document.createElement('div');
10914 parent.setAttribute('class', 'djs-container djs-parent');
10915
10916 assign(parent, {
10917 position: 'relative',
10918 overflow: 'hidden',
10919 width: ensurePx(options.width),
10920 height: ensurePx(options.height)
10921 });
10922
10923 container.appendChild(parent);
10924
10925 return parent;
10926 }
10927
10928 function createGroup(parent, cls, childIndex) {
10929 const group = create$1('g');
10930 classes$1(group).add(cls);
10931
10932 const index = childIndex !== undefined ? childIndex : parent.childNodes.length - 1;
10933
10934 // must ensure second argument is node or _null_
10935 // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
10936 parent.insertBefore(group, parent.childNodes[index] || null);
10937
10938 return group;
10939 }
10940
10941 const BASE_LAYER = 'base';
10942
10943 // render plane contents behind utility layers
10944 const PLANE_LAYER_INDEX = 0;
10945 const UTILITY_LAYER_INDEX = 1;
10946
10947
10948 const REQUIRED_MODEL_ATTRS = {
10949 shape: [ 'x', 'y', 'width', 'height' ],
10950 connection: [ 'waypoints' ]
10951 };
10952
10953 /**
10954 * The main drawing canvas.
10955 *
10956 * @class
10957 * @constructor
10958 *
10959 * @emits Canvas#canvas.init
10960 *
10961 * @param {CanvasConfig|null} config
10962 * @param {EventBus} eventBus
10963 * @param {GraphicsFactory} graphicsFactory
10964 * @param {ElementRegistry} elementRegistry
10965 */
10966 function Canvas(config, eventBus, graphicsFactory, elementRegistry) {
10967 this._eventBus = eventBus;
10968 this._elementRegistry = elementRegistry;
10969 this._graphicsFactory = graphicsFactory;
10970
10971 /**
10972 * @type {number}
10973 */
10974 this._rootsIdx = 0;
10975
10976 /**
10977 * @type {CanvasLayers}
10978 */
10979 this._layers = {};
10980
10981 /**
10982 * @type {CanvasPlane[]}
10983 */
10984 this._planes = [];
10985
10986 /**
10987 * @type {RootLike|null}
10988 */
10989 this._rootElement = null;
10990
10991 this._init(config || {});
10992 }
10993
10994 Canvas.$inject = [
10995 'config.canvas',
10996 'eventBus',
10997 'graphicsFactory',
10998 'elementRegistry'
10999 ];
11000
11001 /**
11002 * Creates a <svg> element that is wrapped into a <div>.
11003 * This way we are always able to correctly figure out the size of the svg element
11004 * by querying the parent node.
11005
11006 * (It is not possible to get the size of a svg element cross browser @ 2014-04-01)
11007
11008 * <div class="djs-container" style="width: {desired-width}, height: {desired-height}">
11009 * <svg width="100%" height="100%">
11010 * ...
11011 * </svg>
11012 * </div>
11013 *
11014 * @param {CanvasConfig} config
11015 */
11016 Canvas.prototype._init = function(config) {
11017
11018 const eventBus = this._eventBus;
11019
11020 // html container
11021 const container = this._container = createContainer(config);
11022
11023 const svg = this._svg = create$1('svg');
11024 attr$1(svg, { width: '100%', height: '100%' });
11025
11026 append(container, svg);
11027
11028 const viewport = this._viewport = createGroup(svg, 'viewport');
11029
11030 // debounce canvas.viewbox.changed events when deferUpdate is set
11031 // to help with potential performance issues
11032 if (config.deferUpdate) {
11033 this._viewboxChanged = debounce(bind$2(this._viewboxChanged, this), 300);
11034 }
11035
11036 eventBus.on('diagram.init', () => {
11037
11038 /**
11039 * An event indicating that the canvas is ready to be drawn on.
11040 *
11041 * @memberOf Canvas
11042 *
11043 * @event canvas.init
11044 *
11045 * @type {Object}
11046 * @property {SVGElement} svg the created svg element
11047 * @property {SVGElement} viewport the direct parent of diagram elements and shapes
11048 */
11049 eventBus.fire('canvas.init', {
11050 svg: svg,
11051 viewport: viewport
11052 });
11053
11054 });
11055
11056 // reset viewbox on shape changes to
11057 // recompute the viewbox
11058 eventBus.on([
11059 'shape.added',
11060 'connection.added',
11061 'shape.removed',
11062 'connection.removed',
11063 'elements.changed',
11064 'root.set'
11065 ], () => {
11066 delete this._cachedViewbox;
11067 });
11068
11069 eventBus.on('diagram.destroy', 500, this._destroy, this);
11070 eventBus.on('diagram.clear', 500, this._clear, this);
11071 };
11072
11073 Canvas.prototype._destroy = function() {
11074 this._eventBus.fire('canvas.destroy', {
11075 svg: this._svg,
11076 viewport: this._viewport
11077 });
11078
11079 const parent = this._container.parentNode;
11080
11081 if (parent) {
11082 parent.removeChild(this._container);
11083 }
11084
11085 delete this._svg;
11086 delete this._container;
11087 delete this._layers;
11088 delete this._planes;
11089 delete this._rootElement;
11090 delete this._viewport;
11091 };
11092
11093 Canvas.prototype._clear = function() {
11094
11095 const allElements = this._elementRegistry.getAll();
11096
11097 // remove all elements
11098 allElements.forEach(element => {
11099 const type = getType(element);
11100
11101 if (type === 'root') {
11102 this.removeRootElement(element);
11103 } else {
11104 this._removeElement(element, type);
11105 }
11106 });
11107
11108 // remove all planes
11109 this._planes = [];
11110 this._rootElement = null;
11111
11112 // force recomputation of view box
11113 delete this._cachedViewbox;
11114 };
11115
11116 /**
11117 * Returns the default layer on which
11118 * all elements are drawn.
11119 *
11120 * @return {SVGElement} The SVG element of the layer.
11121 */
11122 Canvas.prototype.getDefaultLayer = function() {
11123 return this.getLayer(BASE_LAYER, PLANE_LAYER_INDEX);
11124 };
11125
11126 /**
11127 * Returns a layer that is used to draw elements
11128 * or annotations on it.
11129 *
11130 * Non-existing layers retrieved through this method
11131 * will be created. During creation, the optional index
11132 * may be used to create layers below or above existing layers.
11133 * A layer with a certain index is always created above all
11134 * existing layers with the same index.
11135 *
11136 * @param {string} name The name of the layer.
11137 * @param {number} [index] The index of the layer.
11138 *
11139 * @return {SVGElement} The SVG element of the layer.
11140 */
11141 Canvas.prototype.getLayer = function(name, index) {
11142
11143 if (!name) {
11144 throw new Error('must specify a name');
11145 }
11146
11147 let layer = this._layers[name];
11148
11149 if (!layer) {
11150 layer = this._layers[name] = this._createLayer(name, index);
11151 }
11152
11153 // throw an error if layer creation / retrival is
11154 // requested on different index
11155 if (typeof index !== 'undefined' && layer.index !== index) {
11156 throw new Error('layer <' + name + '> already created at index <' + index + '>');
11157 }
11158
11159 return layer.group;
11160 };
11161
11162 /**
11163 * For a given index, return the number of layers that have a higher index and
11164 * are visible.
11165 *
11166 * This is used to determine the node a layer should be inserted at.
11167 *
11168 * @param {number} index
11169 *
11170 * @return {number}
11171 */
11172 Canvas.prototype._getChildIndex = function(index) {
11173 return reduce(this._layers, function(childIndex, layer) {
11174 if (layer.visible && index >= layer.index) {
11175 childIndex++;
11176 }
11177
11178 return childIndex;
11179 }, 0);
11180 };
11181
11182 /**
11183 * Creates a given layer and returns it.
11184 *
11185 * @param {string} name
11186 * @param {number} [index=0]
11187 *
11188 * @return {CanvasLayer}
11189 */
11190 Canvas.prototype._createLayer = function(name, index) {
11191
11192 if (typeof index === 'undefined') {
11193 index = UTILITY_LAYER_INDEX;
11194 }
11195
11196 const childIndex = this._getChildIndex(index);
11197
11198 return {
11199 group: createGroup(this._viewport, 'layer-' + name, childIndex),
11200 index: index,
11201 visible: true
11202 };
11203 };
11204
11205
11206 /**
11207 * Shows a given layer.
11208 *
11209 * @param {string} name The name of the layer.
11210 *
11211 * @return {SVGElement} The SVG element of the layer.
11212 */
11213 Canvas.prototype.showLayer = function(name) {
11214
11215 if (!name) {
11216 throw new Error('must specify a name');
11217 }
11218
11219 const layer = this._layers[name];
11220
11221 if (!layer) {
11222 throw new Error('layer <' + name + '> does not exist');
11223 }
11224
11225 const viewport = this._viewport;
11226 const group = layer.group;
11227 const index = layer.index;
11228
11229 if (layer.visible) {
11230 return group;
11231 }
11232
11233 const childIndex = this._getChildIndex(index);
11234
11235 viewport.insertBefore(group, viewport.childNodes[childIndex] || null);
11236
11237 layer.visible = true;
11238
11239 return group;
11240 };
11241
11242 /**
11243 * Hides a given layer.
11244 *
11245 * @param {string} name The name of the layer.
11246 *
11247 * @return {SVGElement} The SVG element of the layer.
11248 */
11249 Canvas.prototype.hideLayer = function(name) {
11250
11251 if (!name) {
11252 throw new Error('must specify a name');
11253 }
11254
11255 const layer = this._layers[name];
11256
11257 if (!layer) {
11258 throw new Error('layer <' + name + '> does not exist');
11259 }
11260
11261 const group = layer.group;
11262
11263 if (!layer.visible) {
11264 return group;
11265 }
11266
11267 remove$2(group);
11268
11269 layer.visible = false;
11270
11271 return group;
11272 };
11273
11274
11275 Canvas.prototype._removeLayer = function(name) {
11276
11277 const layer = this._layers[name];
11278
11279 if (layer) {
11280 delete this._layers[name];
11281
11282 remove$2(layer.group);
11283 }
11284 };
11285
11286 /**
11287 * Returns the currently active layer. Can be null.
11288 *
11289 * @return {CanvasLayer|null} The active layer of `null`.
11290 */
11291 Canvas.prototype.getActiveLayer = function() {
11292 const plane = this._findPlaneForRoot(this.getRootElement());
11293
11294 if (!plane) {
11295 return null;
11296 }
11297
11298 return plane.layer;
11299 };
11300
11301
11302 /**
11303 * Returns the plane which contains the given element.
11304 *
11305 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11306 *
11307 * @return {RootLike|undefined} The root of the element.
11308 */
11309 Canvas.prototype.findRoot = function(element) {
11310 if (typeof element === 'string') {
11311 element = this._elementRegistry.get(element);
11312 }
11313
11314 if (!element) {
11315 return;
11316 }
11317
11318 const plane = this._findPlaneForRoot(
11319 findRoot(element)
11320 ) || {};
11321
11322 return plane.rootElement;
11323 };
11324
11325 /**
11326 * Return a list of all root elements on the diagram.
11327 *
11328 * @return {(RootLike)[]} The list of root elements.
11329 */
11330 Canvas.prototype.getRootElements = function() {
11331 return this._planes.map(function(plane) {
11332 return plane.rootElement;
11333 });
11334 };
11335
11336 Canvas.prototype._findPlaneForRoot = function(rootElement) {
11337 return find(this._planes, function(plane) {
11338 return plane.rootElement === rootElement;
11339 });
11340 };
11341
11342
11343 /**
11344 * Returns the html element that encloses the
11345 * drawing canvas.
11346 *
11347 * @return {HTMLElement} The HTML element of the container.
11348 */
11349 Canvas.prototype.getContainer = function() {
11350 return this._container;
11351 };
11352
11353
11354 // markers //////////////////////
11355
11356 Canvas.prototype._updateMarker = function(element, marker, add) {
11357 let container;
11358
11359 if (!element.id) {
11360 element = this._elementRegistry.get(element);
11361 }
11362
11363 // we need to access all
11364 container = this._elementRegistry._elements[element.id];
11365
11366 if (!container) {
11367 return;
11368 }
11369
11370 forEach$1([ container.gfx, container.secondaryGfx ], function(gfx) {
11371 if (gfx) {
11372
11373 // invoke either addClass or removeClass based on mode
11374 if (add) {
11375 classes$1(gfx).add(marker);
11376 } else {
11377 classes$1(gfx).remove(marker);
11378 }
11379 }
11380 });
11381
11382 /**
11383 * An event indicating that a marker has been updated for an element
11384 *
11385 * @event element.marker.update
11386 * @type {Object}
11387 * @property {Element} element the shape
11388 * @property {SVGElement} gfx the graphical representation of the shape
11389 * @property {string} marker
11390 * @property {boolean} add true if the marker was added, false if it got removed
11391 */
11392 this._eventBus.fire('element.marker.update', { element: element, gfx: container.gfx, marker: marker, add: !!add });
11393 };
11394
11395
11396 /**
11397 * Adds a marker to an element (basically a css class).
11398 *
11399 * Fires the element.marker.update event, making it possible to
11400 * integrate extension into the marker life-cycle, too.
11401 *
11402 * @example
11403 *
11404 * ```javascript
11405 * canvas.addMarker('foo', 'some-marker');
11406 *
11407 * const fooGfx = canvas.getGraphics('foo');
11408 *
11409 * fooGfx; // <g class="... some-marker"> ... </g>
11410 * ```
11411 *
11412 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11413 * @param {string} marker The marker.
11414 */
11415 Canvas.prototype.addMarker = function(element, marker) {
11416 this._updateMarker(element, marker, true);
11417 };
11418
11419
11420 /**
11421 * Remove a marker from an element.
11422 *
11423 * Fires the element.marker.update event, making it possible to
11424 * integrate extension into the marker life-cycle, too.
11425 *
11426 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11427 * @param {string} marker The marker.
11428 */
11429 Canvas.prototype.removeMarker = function(element, marker) {
11430 this._updateMarker(element, marker, false);
11431 };
11432
11433 /**
11434 * Check whether an element has a given marker.
11435 *
11436 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11437 * @param {string} marker The marker.
11438 */
11439 Canvas.prototype.hasMarker = function(element, marker) {
11440 if (!element.id) {
11441 element = this._elementRegistry.get(element);
11442 }
11443
11444 const gfx = this.getGraphics(element);
11445
11446 return classes$1(gfx).has(marker);
11447 };
11448
11449 /**
11450 * Toggles a marker on an element.
11451 *
11452 * Fires the element.marker.update event, making it possible to
11453 * integrate extension into the marker life-cycle, too.
11454 *
11455 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11456 * @param {string} marker The marker.
11457 */
11458 Canvas.prototype.toggleMarker = function(element, marker) {
11459 if (this.hasMarker(element, marker)) {
11460 this.removeMarker(element, marker);
11461 } else {
11462 this.addMarker(element, marker);
11463 }
11464 };
11465
11466 /**
11467 * Returns the current root element.
11468 *
11469 * Supports two different modes for handling root elements:
11470 *
11471 * 1. if no root element has been added before, an implicit root will be added
11472 * and returned. This is used in applications that don't require explicit
11473 * root elements.
11474 *
11475 * 2. when root elements have been added before calling `getRootElement`,
11476 * root elements can be null. This is used for applications that want to manage
11477 * root elements themselves.
11478 *
11479 * @return {RootLike} The current root element.
11480 */
11481 Canvas.prototype.getRootElement = function() {
11482 const rootElement = this._rootElement;
11483
11484 // can return null if root elements are present but none was set yet
11485 if (rootElement || this._planes.length) {
11486 return rootElement;
11487 }
11488
11489 return this.setRootElement(this.addRootElement(null));
11490 };
11491
11492 /**
11493 * Adds a given root element and returns it.
11494 *
11495 * @param {RootLike} [rootElement] The root element to be added.
11496 *
11497 * @return {RootLike} The added root element or an implicit root element.
11498 */
11499 Canvas.prototype.addRootElement = function(rootElement) {
11500 const idx = this._rootsIdx++;
11501
11502 if (!rootElement) {
11503 rootElement = {
11504 id: '__implicitroot_' + idx,
11505 children: [],
11506 isImplicit: true
11507 };
11508 }
11509
11510 const layerName = rootElement.layer = 'root-' + idx;
11511
11512 this._ensureValid('root', rootElement);
11513
11514 const layer = this.getLayer(layerName, PLANE_LAYER_INDEX);
11515
11516 this.hideLayer(layerName);
11517
11518 this._addRoot(rootElement, layer);
11519
11520 this._planes.push({
11521 rootElement: rootElement,
11522 layer: layer
11523 });
11524
11525 return rootElement;
11526 };
11527
11528 /**
11529 * Removes a given root element and returns it.
11530 *
11531 * @param {RootLike|string} rootElement element or element ID
11532 *
11533 * @return {RootLike|undefined} removed element
11534 */
11535 Canvas.prototype.removeRootElement = function(rootElement) {
11536
11537 if (typeof rootElement === 'string') {
11538 rootElement = this._elementRegistry.get(rootElement);
11539 }
11540
11541 const plane = this._findPlaneForRoot(rootElement);
11542
11543 if (!plane) {
11544 return;
11545 }
11546
11547 // hook up life-cycle events
11548 this._removeRoot(rootElement);
11549
11550 // clean up layer
11551 this._removeLayer(rootElement.layer);
11552
11553 // clean up plane
11554 this._planes = this._planes.filter(function(plane) {
11555 return plane.rootElement !== rootElement;
11556 });
11557
11558 // clean up active root
11559 if (this._rootElement === rootElement) {
11560 this._rootElement = null;
11561 }
11562
11563 return rootElement;
11564 };
11565
11566
11567 /**
11568 * Sets a given element as the new root element for the canvas
11569 * and returns the new root element.
11570 *
11571 * @param {RootLike} rootElement The root element to be set.
11572 *
11573 * @return {RootLike} The set root element.
11574 */
11575 Canvas.prototype.setRootElement = function(rootElement) {
11576
11577 if (rootElement === this._rootElement) {
11578 return rootElement;
11579 }
11580
11581 let plane;
11582
11583 if (!rootElement) {
11584 throw new Error('rootElement required');
11585 }
11586
11587 plane = this._findPlaneForRoot(rootElement);
11588
11589 // give set add semantics for backwards compatibility
11590 if (!plane) {
11591 rootElement = this.addRootElement(rootElement);
11592 }
11593
11594 this._setRoot(rootElement);
11595
11596 return rootElement;
11597 };
11598
11599
11600 Canvas.prototype._removeRoot = function(element) {
11601 const elementRegistry = this._elementRegistry,
11602 eventBus = this._eventBus;
11603
11604 // simulate element remove event sequence
11605 eventBus.fire('root.remove', { element: element });
11606 eventBus.fire('root.removed', { element: element });
11607
11608 elementRegistry.remove(element);
11609 };
11610
11611
11612 Canvas.prototype._addRoot = function(element, gfx) {
11613 const elementRegistry = this._elementRegistry,
11614 eventBus = this._eventBus;
11615
11616 // resemble element add event sequence
11617 eventBus.fire('root.add', { element: element });
11618
11619 elementRegistry.add(element, gfx);
11620
11621 eventBus.fire('root.added', { element: element, gfx: gfx });
11622 };
11623
11624
11625 Canvas.prototype._setRoot = function(rootElement, layer) {
11626
11627 const currentRoot = this._rootElement;
11628
11629 if (currentRoot) {
11630
11631 // un-associate previous root element <svg>
11632 this._elementRegistry.updateGraphics(currentRoot, null, true);
11633
11634 // hide previous layer
11635 this.hideLayer(currentRoot.layer);
11636 }
11637
11638 if (rootElement) {
11639
11640 if (!layer) {
11641 layer = this._findPlaneForRoot(rootElement).layer;
11642 }
11643
11644 // associate element with <svg>
11645 this._elementRegistry.updateGraphics(rootElement, this._svg, true);
11646
11647 // show root layer
11648 this.showLayer(rootElement.layer);
11649 }
11650
11651 this._rootElement = rootElement;
11652
11653 this._eventBus.fire('root.set', { element: rootElement });
11654 };
11655
11656 Canvas.prototype._ensureValid = function(type, element) {
11657 if (!element.id) {
11658 throw new Error('element must have an id');
11659 }
11660
11661 if (this._elementRegistry.get(element.id)) {
11662 throw new Error('element <' + element.id + '> already exists');
11663 }
11664
11665 const requiredAttrs = REQUIRED_MODEL_ATTRS[type];
11666
11667 const valid = every(requiredAttrs, function(attr) {
11668 return typeof element[attr] !== 'undefined';
11669 });
11670
11671 if (!valid) {
11672 throw new Error(
11673 'must supply { ' + requiredAttrs.join(', ') + ' } with ' + type);
11674 }
11675 };
11676
11677 Canvas.prototype._setParent = function(element, parent, parentIndex) {
11678 add(parent.children, element, parentIndex);
11679 element.parent = parent;
11680 };
11681
11682 /**
11683 * Adds an element to the canvas.
11684 *
11685 * This wires the parent <-> child relationship between the element and
11686 * a explicitly specified parent or an implicit root element.
11687 *
11688 * During add it emits the events
11689 *
11690 * * <{type}.add> (element, parent)
11691 * * <{type}.added> (element, gfx)
11692 *
11693 * Extensions may hook into these events to perform their magic.
11694 *
11695 * @param {string} type
11696 * @param {ConnectionLike|ShapeLike} element
11697 * @param {ShapeLike} [parent]
11698 * @param {number} [parentIndex]
11699 *
11700 * @return {ConnectionLike|ShapeLike} The added element.
11701 */
11702 Canvas.prototype._addElement = function(type, element, parent, parentIndex) {
11703
11704 parent = parent || this.getRootElement();
11705
11706 const eventBus = this._eventBus,
11707 graphicsFactory = this._graphicsFactory;
11708
11709 this._ensureValid(type, element);
11710
11711 eventBus.fire(type + '.add', { element: element, parent: parent });
11712
11713 this._setParent(element, parent, parentIndex);
11714
11715 // create graphics
11716 const gfx = graphicsFactory.create(type, element, parentIndex);
11717
11718 this._elementRegistry.add(element, gfx);
11719
11720 // update its visual
11721 graphicsFactory.update(type, element, gfx);
11722
11723 eventBus.fire(type + '.added', { element: element, gfx: gfx });
11724
11725 return element;
11726 };
11727
11728 /**
11729 * Adds a shape to the canvas.
11730 *
11731 * @param {ShapeLike} shape The shape to be added
11732 * @param {ParentLike} [parent] The shape's parent.
11733 * @param {number} [parentIndex] The index at which to add the shape to the parent's children.
11734 *
11735 * @return {ShapeLike} The added shape.
11736 */
11737 Canvas.prototype.addShape = function(shape, parent, parentIndex) {
11738 return this._addElement('shape', shape, parent, parentIndex);
11739 };
11740
11741 /**
11742 * Adds a connection to the canvas.
11743 *
11744 * @param {ConnectionLike} connection The connection to be added.
11745 * @param {ParentLike} [parent] The connection's parent.
11746 * @param {number} [parentIndex] The index at which to add the connection to the parent's children.
11747 *
11748 * @return {ConnectionLike} The added connection.
11749 */
11750 Canvas.prototype.addConnection = function(connection, parent, parentIndex) {
11751 return this._addElement('connection', connection, parent, parentIndex);
11752 };
11753
11754
11755 /**
11756 * Internal remove element
11757 */
11758 Canvas.prototype._removeElement = function(element, type) {
11759
11760 const elementRegistry = this._elementRegistry,
11761 graphicsFactory = this._graphicsFactory,
11762 eventBus = this._eventBus;
11763
11764 element = elementRegistry.get(element.id || element);
11765
11766 if (!element) {
11767
11768 // element was removed already
11769 return;
11770 }
11771
11772 eventBus.fire(type + '.remove', { element: element });
11773
11774 graphicsFactory.remove(element);
11775
11776 // unset parent <-> child relationship
11777 remove(element.parent && element.parent.children, element);
11778 element.parent = null;
11779
11780 eventBus.fire(type + '.removed', { element: element });
11781
11782 elementRegistry.remove(element);
11783
11784 return element;
11785 };
11786
11787
11788 /**
11789 * Removes a shape from the canvas.
11790 *
11791 * @fires ShapeRemoveEvent
11792 * @fires ShapeRemovedEvent
11793 *
11794 * @param {ShapeLike|string} shape The shape or its ID.
11795 *
11796 * @return {ShapeLike} The removed shape.
11797 */
11798 Canvas.prototype.removeShape = function(shape) {
11799
11800 /**
11801 * An event indicating that a shape is about to be removed from the canvas.
11802 *
11803 * @memberOf Canvas
11804 *
11805 * @event ShapeRemoveEvent
11806 * @type {Object}
11807 * @property {ShapeLike} element The shape.
11808 * @property {SVGElement} gfx The graphical element.
11809 */
11810
11811 /**
11812 * An event indicating that a shape has been removed from the canvas.
11813 *
11814 * @memberOf Canvas
11815 *
11816 * @event ShapeRemovedEvent
11817 * @type {Object}
11818 * @property {ShapeLike} element The shape.
11819 * @property {SVGElement} gfx The graphical element.
11820 */
11821 return this._removeElement(shape, 'shape');
11822 };
11823
11824
11825 /**
11826 * Removes a connection from the canvas.
11827 *
11828 * @fires ConnectionRemoveEvent
11829 * @fires ConnectionRemovedEvent
11830 *
11831 * @param {ConnectionLike|string} connection The connection or its ID.
11832 *
11833 * @return {ConnectionLike} The removed connection.
11834 */
11835 Canvas.prototype.removeConnection = function(connection) {
11836
11837 /**
11838 * An event indicating that a connection is about to be removed from the canvas.
11839 *
11840 * @memberOf Canvas
11841 *
11842 * @event ConnectionRemoveEvent
11843 * @type {Object}
11844 * @property {ConnectionLike} element The connection.
11845 * @property {SVGElement} gfx The graphical element.
11846 */
11847
11848 /**
11849 * An event indicating that a connection has been removed from the canvas.
11850 *
11851 * @memberOf Canvas
11852 *
11853 * @event ConnectionRemovedEvent
11854 * @type {Object}
11855 * @property {ConnectionLike} element The connection.
11856 * @property {SVGElement} gfx The graphical element.
11857 */
11858 return this._removeElement(connection, 'connection');
11859 };
11860
11861
11862 /**
11863 * Returns the graphical element of an element.
11864 *
11865 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11866 * @param {boolean} [secondary=false] Whether to return the secondary graphical element.
11867 *
11868 * @return {SVGElement} The graphical element.
11869 */
11870 Canvas.prototype.getGraphics = function(element, secondary) {
11871 return this._elementRegistry.getGraphics(element, secondary);
11872 };
11873
11874
11875 /**
11876 * Perform a viewbox update via a given change function.
11877 *
11878 * @param {Function} changeFn
11879 */
11880 Canvas.prototype._changeViewbox = function(changeFn) {
11881
11882 // notify others of the upcoming viewbox change
11883 this._eventBus.fire('canvas.viewbox.changing');
11884
11885 // perform actual change
11886 changeFn.apply(this);
11887
11888 // reset the cached viewbox so that
11889 // a new get operation on viewbox or zoom
11890 // triggers a viewbox re-computation
11891 this._cachedViewbox = null;
11892
11893 // notify others of the change; this step
11894 // may or may not be debounced
11895 this._viewboxChanged();
11896 };
11897
11898 Canvas.prototype._viewboxChanged = function() {
11899 this._eventBus.fire('canvas.viewbox.changed', { viewbox: this.viewbox() });
11900 };
11901
11902
11903 /**
11904 * Gets or sets the view box of the canvas, i.e. the
11905 * area that is currently displayed.
11906 *
11907 * The getter may return a cached viewbox (if it is currently
11908 * changing). To force a recomputation, pass `false` as the first argument.
11909 *
11910 * @example
11911 *
11912 * ```javascript
11913 * canvas.viewbox({ x: 100, y: 100, width: 500, height: 500 })
11914 *
11915 * // sets the visible area of the diagram to (100|100) -> (600|100)
11916 * // and and scales it according to the diagram width
11917 *
11918 * const viewbox = canvas.viewbox(); // pass `false` to force recomputing the box.
11919 *
11920 * console.log(viewbox);
11921 * // {
11922 * // inner: Dimensions,
11923 * // outer: Dimensions,
11924 * // scale,
11925 * // x, y,
11926 * // width, height
11927 * // }
11928 *
11929 * // if the current diagram is zoomed and scrolled, you may reset it to the
11930 * // default zoom via this method, too:
11931 *
11932 * const zoomedAndScrolledViewbox = canvas.viewbox();
11933 *
11934 * canvas.viewbox({
11935 * x: 0,
11936 * y: 0,
11937 * width: zoomedAndScrolledViewbox.outer.width,
11938 * height: zoomedAndScrolledViewbox.outer.height
11939 * });
11940 * ```
11941 *
11942 * @param {Rect} [box] The viewbox to be set.
11943 *
11944 * @return {CanvasViewbox} The set viewbox.
11945 */
11946 Canvas.prototype.viewbox = function(box) {
11947
11948 if (box === undefined && this._cachedViewbox) {
11949 return this._cachedViewbox;
11950 }
11951
11952 const viewport = this._viewport,
11953 outerBox = this.getSize();
11954 let innerBox,
11955 matrix,
11956 activeLayer,
11957 transform,
11958 scale,
11959 x, y;
11960
11961 if (!box) {
11962
11963 // compute the inner box based on the
11964 // diagrams active layer. This allows us to exclude
11965 // external components, such as overlays
11966
11967 activeLayer = this._rootElement ? this.getActiveLayer() : null;
11968 innerBox = activeLayer && activeLayer.getBBox() || {};
11969
11970 transform = transform$1(viewport);
11971 matrix = transform ? transform.matrix : createMatrix();
11972 scale = round(matrix.a, 1000);
11973
11974 x = round(-matrix.e || 0, 1000);
11975 y = round(-matrix.f || 0, 1000);
11976
11977 box = this._cachedViewbox = {
11978 x: x ? x / scale : 0,
11979 y: y ? y / scale : 0,
11980 width: outerBox.width / scale,
11981 height: outerBox.height / scale,
11982 scale: scale,
11983 inner: {
11984 width: innerBox.width || 0,
11985 height: innerBox.height || 0,
11986 x: innerBox.x || 0,
11987 y: innerBox.y || 0
11988 },
11989 outer: outerBox
11990 };
11991
11992 return box;
11993 } else {
11994
11995 this._changeViewbox(function() {
11996 scale = Math.min(outerBox.width / box.width, outerBox.height / box.height);
11997
11998 const matrix = this._svg.createSVGMatrix()
11999 .scale(scale)
12000 .translate(-box.x, -box.y);
12001
12002 transform$1(viewport, matrix);
12003 });
12004 }
12005
12006 return box;
12007 };
12008
12009
12010 /**
12011 * Gets or sets the scroll of the canvas.
12012 *
12013 * @param {ScrollDelta} [delta] The scroll to be set.
12014 *
12015 * @return {Point}
12016 */
12017 Canvas.prototype.scroll = function(delta) {
12018
12019 const node = this._viewport;
12020 let matrix = node.getCTM();
12021
12022 if (delta) {
12023 this._changeViewbox(function() {
12024 delta = assign$1({ dx: 0, dy: 0 }, delta || {});
12025
12026 matrix = this._svg.createSVGMatrix().translate(delta.dx, delta.dy).multiply(matrix);
12027
12028 setCTM(node, matrix);
12029 });
12030 }
12031
12032 return { x: matrix.e, y: matrix.f };
12033 };
12034
12035 /**
12036 * Scrolls the viewbox to contain the given element.
12037 * Optionally specify a padding to be applied to the edges.
12038 *
12039 * @param {ShapeLike|ConnectionLike|string} element The element to scroll to or its ID.
12040 * @param {RectTRBL|number} [padding=100] The padding to be applied. Can also specify top, bottom, left and right.
12041 */
12042 Canvas.prototype.scrollToElement = function(element, padding) {
12043 let defaultPadding = 100;
12044
12045 if (typeof element === 'string') {
12046 element = this._elementRegistry.get(element);
12047 }
12048
12049 // set to correct rootElement
12050 const rootElement = this.findRoot(element);
12051
12052 if (rootElement !== this.getRootElement()) {
12053 this.setRootElement(rootElement);
12054 }
12055
12056 // element is rootElement, do not change viewport
12057 if (rootElement === element) {
12058 return;
12059 }
12060
12061 if (!padding) {
12062 padding = {};
12063 }
12064 if (typeof padding === 'number') {
12065 defaultPadding = padding;
12066 }
12067
12068 padding = {
12069 top: padding.top || defaultPadding,
12070 right: padding.right || defaultPadding,
12071 bottom: padding.bottom || defaultPadding,
12072 left: padding.left || defaultPadding
12073 };
12074
12075 const elementBounds = getBBox(element),
12076 elementTrbl = asTRBL(elementBounds),
12077 viewboxBounds = this.viewbox(),
12078 zoom = this.zoom();
12079 let dx, dy;
12080
12081 // shrink viewboxBounds with padding
12082 viewboxBounds.y += padding.top / zoom;
12083 viewboxBounds.x += padding.left / zoom;
12084 viewboxBounds.width -= (padding.right + padding.left) / zoom;
12085 viewboxBounds.height -= (padding.bottom + padding.top) / zoom;
12086
12087 const viewboxTrbl = asTRBL(viewboxBounds);
12088
12089 const canFit = elementBounds.width < viewboxBounds.width && elementBounds.height < viewboxBounds.height;
12090
12091 if (!canFit) {
12092
12093 // top-left when element can't fit
12094 dx = elementBounds.x - viewboxBounds.x;
12095 dy = elementBounds.y - viewboxBounds.y;
12096
12097 } else {
12098
12099 const dRight = Math.max(0, elementTrbl.right - viewboxTrbl.right),
12100 dLeft = Math.min(0, elementTrbl.left - viewboxTrbl.left),
12101 dBottom = Math.max(0, elementTrbl.bottom - viewboxTrbl.bottom),
12102 dTop = Math.min(0, elementTrbl.top - viewboxTrbl.top);
12103
12104 dx = dRight || dLeft;
12105 dy = dBottom || dTop;
12106
12107 }
12108
12109 this.scroll({ dx: -dx * zoom, dy: -dy * zoom });
12110 };
12111
12112 /**
12113 * Gets or sets the current zoom of the canvas, optionally zooming to the
12114 * specified position.
12115 *
12116 * The getter may return a cached zoom level. Call it with `false` as the first
12117 * argument to force recomputation of the current level.
12118 *
12119 * @param {number|'fit-viewport'} [newScale] The new zoom level, either a number,
12120 * i.e. 0.9, or `fit-viewport` to adjust the size to fit the current viewport.
12121 * @param {Point} [center] The reference point { x: ..., y: ...} to zoom to.
12122 *
12123 * @return {number} The set zoom level.
12124 */
12125 Canvas.prototype.zoom = function(newScale, center) {
12126
12127 if (!newScale) {
12128 return this.viewbox(newScale).scale;
12129 }
12130
12131 if (newScale === 'fit-viewport') {
12132 return this._fitViewport(center);
12133 }
12134
12135 let outer,
12136 matrix;
12137
12138 this._changeViewbox(function() {
12139
12140 if (typeof center !== 'object') {
12141 outer = this.viewbox().outer;
12142
12143 center = {
12144 x: outer.width / 2,
12145 y: outer.height / 2
12146 };
12147 }
12148
12149 matrix = this._setZoom(newScale, center);
12150 });
12151
12152 return round(matrix.a, 1000);
12153 };
12154
12155 function setCTM(node, m) {
12156 const mstr = 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.e + ',' + m.f + ')';
12157 node.setAttribute('transform', mstr);
12158 }
12159
12160 Canvas.prototype._fitViewport = function(center) {
12161
12162 const vbox = this.viewbox(),
12163 outer = vbox.outer,
12164 inner = vbox.inner;
12165 let newScale,
12166 newViewbox;
12167
12168 // display the complete diagram without zooming in.
12169 // instead of relying on internal zoom, we perform a
12170 // hard reset on the canvas viewbox to realize this
12171 //
12172 // if diagram does not need to be zoomed in, we focus it around
12173 // the diagram origin instead
12174
12175 if (inner.x >= 0 &&
12176 inner.y >= 0 &&
12177 inner.x + inner.width <= outer.width &&
12178 inner.y + inner.height <= outer.height &&
12179 !center) {
12180
12181 newViewbox = {
12182 x: 0,
12183 y: 0,
12184 width: Math.max(inner.width + inner.x, outer.width),
12185 height: Math.max(inner.height + inner.y, outer.height)
12186 };
12187 } else {
12188
12189 newScale = Math.min(1, outer.width / inner.width, outer.height / inner.height);
12190 newViewbox = {
12191 x: inner.x + (center ? inner.width / 2 - outer.width / newScale / 2 : 0),
12192 y: inner.y + (center ? inner.height / 2 - outer.height / newScale / 2 : 0),
12193 width: outer.width / newScale,
12194 height: outer.height / newScale
12195 };
12196 }
12197
12198 this.viewbox(newViewbox);
12199
12200 return this.viewbox(false).scale;
12201 };
12202
12203
12204 Canvas.prototype._setZoom = function(scale, center) {
12205
12206 const svg = this._svg,
12207 viewport = this._viewport;
12208
12209 const matrix = svg.createSVGMatrix();
12210 const point = svg.createSVGPoint();
12211
12212 let centerPoint,
12213 originalPoint,
12214 currentMatrix,
12215 scaleMatrix,
12216 newMatrix;
12217
12218 currentMatrix = viewport.getCTM();
12219
12220 const currentScale = currentMatrix.a;
12221
12222 if (center) {
12223 centerPoint = assign$1(point, center);
12224
12225 // revert applied viewport transformations
12226 originalPoint = centerPoint.matrixTransform(currentMatrix.inverse());
12227
12228 // create scale matrix
12229 scaleMatrix = matrix
12230 .translate(originalPoint.x, originalPoint.y)
12231 .scale(1 / currentScale * scale)
12232 .translate(-originalPoint.x, -originalPoint.y);
12233
12234 newMatrix = currentMatrix.multiply(scaleMatrix);
12235 } else {
12236 newMatrix = matrix.scale(scale);
12237 }
12238
12239 setCTM(this._viewport, newMatrix);
12240
12241 return newMatrix;
12242 };
12243
12244
12245 /**
12246 * Returns the size of the canvas.
12247 *
12248 * @return {Dimensions} The size of the canvas.
12249 */
12250 Canvas.prototype.getSize = function() {
12251 return {
12252 width: this._container.clientWidth,
12253 height: this._container.clientHeight
12254 };
12255 };
12256
12257
12258 /**
12259 * Returns the absolute bounding box of an element.
12260 *
12261 * The absolute bounding box may be used to display overlays in the callers
12262 * (browser) coordinate system rather than the zoomed in/out canvas coordinates.
12263 *
12264 * @param {ShapeLike|ConnectionLike} element The element.
12265 *
12266 * @return {Rect} The element's absolute bounding box.
12267 */
12268 Canvas.prototype.getAbsoluteBBox = function(element) {
12269 const vbox = this.viewbox();
12270 let bbox;
12271
12272 // connection
12273 // use svg bbox
12274 if (element.waypoints) {
12275 const gfx = this.getGraphics(element);
12276
12277 bbox = gfx.getBBox();
12278 }
12279
12280 // shapes
12281 // use data
12282 else {
12283 bbox = element;
12284 }
12285
12286 const x = bbox.x * vbox.scale - vbox.x * vbox.scale;
12287 const y = bbox.y * vbox.scale - vbox.y * vbox.scale;
12288
12289 const width = bbox.width * vbox.scale;
12290 const height = bbox.height * vbox.scale;
12291
12292 return {
12293 x: x,
12294 y: y,
12295 width: width,
12296 height: height
12297 };
12298 };
12299
12300 /**
12301 * Fires an event so other modules can react to the canvas resizing.
12302 */
12303 Canvas.prototype.resized = function() {
12304
12305 // force recomputation of view box
12306 delete this._cachedViewbox;
12307
12308 this._eventBus.fire('canvas.resized');
12309 };
12310
12311 var ELEMENT_ID = 'data-element-id';
12312
12313 /**
12314 * @typedef {import('./Types').ElementLike} ElementLike
12315 *
12316 * @typedef {import('./EventBus').default} EventBus
12317 *
12318 * @typedef { (element: ElementLike, gfx: SVGElement) => boolean|any } ElementRegistryFilterCallback
12319 * @typedef { (element: ElementLike, gfx: SVGElement) => any } ElementRegistryForEachCallback
12320 */
12321
12322 /**
12323 * A registry that keeps track of all shapes in the diagram.
12324 *
12325 * @class
12326 * @constructor
12327 *
12328 * @param {EventBus} eventBus
12329 */
12330 function ElementRegistry(eventBus) {
12331
12332 /**
12333 * @type { {
12334 * [id: string]: {
12335 * element: ElementLike;
12336 * gfx?: SVGElement;
12337 * secondaryGfx?: SVGElement;
12338 * }
12339 * } }
12340 */
12341 this._elements = {};
12342
12343 this._eventBus = eventBus;
12344 }
12345
12346 ElementRegistry.$inject = [ 'eventBus' ];
12347
12348 /**
12349 * Add an element and its graphical representation(s) to the registry.
12350 *
12351 * @param {ElementLike} element The element to be added.
12352 * @param {SVGElement} gfx The primary graphical representation.
12353 * @param {SVGElement} [secondaryGfx] The secondary graphical representation.
12354 */
12355 ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) {
12356
12357 var id = element.id;
12358
12359 this._validateId(id);
12360
12361 // associate dom node with element
12362 attr$1(gfx, ELEMENT_ID, id);
12363
12364 if (secondaryGfx) {
12365 attr$1(secondaryGfx, ELEMENT_ID, id);
12366 }
12367
12368 this._elements[id] = { element: element, gfx: gfx, secondaryGfx: secondaryGfx };
12369 };
12370
12371 /**
12372 * Remove an element from the registry.
12373 *
12374 * @param {ElementLike|string} element
12375 */
12376 ElementRegistry.prototype.remove = function(element) {
12377 var elements = this._elements,
12378 id = element.id || element,
12379 container = id && elements[id];
12380
12381 if (container) {
12382
12383 // unset element id on gfx
12384 attr$1(container.gfx, ELEMENT_ID, '');
12385
12386 if (container.secondaryGfx) {
12387 attr$1(container.secondaryGfx, ELEMENT_ID, '');
12388 }
12389
12390 delete elements[id];
12391 }
12392 };
12393
12394 /**
12395 * Update an elements ID.
12396 *
12397 * @param {ElementLike|string} element The element or its ID.
12398 * @param {string} newId The new ID.
12399 */
12400 ElementRegistry.prototype.updateId = function(element, newId) {
12401
12402 this._validateId(newId);
12403
12404 if (typeof element === 'string') {
12405 element = this.get(element);
12406 }
12407
12408 this._eventBus.fire('element.updateId', {
12409 element: element,
12410 newId: newId
12411 });
12412
12413 var gfx = this.getGraphics(element),
12414 secondaryGfx = this.getGraphics(element, true);
12415
12416 this.remove(element);
12417
12418 element.id = newId;
12419
12420 this.add(element, gfx, secondaryGfx);
12421 };
12422
12423 /**
12424 * Update the graphical representation of an element.
12425 *
12426 * @param {ElementLike|string} filter The element or its ID.
12427 * @param {SVGElement} gfx The new graphical representation.
12428 * @param {boolean} [secondary=false] Whether to update the secondary graphical representation.
12429 */
12430 ElementRegistry.prototype.updateGraphics = function(filter, gfx, secondary) {
12431 var id = filter.id || filter;
12432
12433 var container = this._elements[id];
12434
12435 if (secondary) {
12436 container.secondaryGfx = gfx;
12437 } else {
12438 container.gfx = gfx;
12439 }
12440
12441 if (gfx) {
12442 attr$1(gfx, ELEMENT_ID, id);
12443 }
12444
12445 return gfx;
12446 };
12447
12448 /**
12449 * Get the element with the given ID or graphical representation.
12450 *
12451 * @example
12452 *
12453 * ```javascript
12454 * elementRegistry.get('SomeElementId_1');
12455 *
12456 * elementRegistry.get(gfx);
12457 * ```
12458 *
12459 * @param {string|SVGElement} filter The elements ID or graphical representation.
12460 *
12461 * @return {ElementLike|undefined} The element.
12462 */
12463 ElementRegistry.prototype.get = function(filter) {
12464 var id;
12465
12466 if (typeof filter === 'string') {
12467 id = filter;
12468 } else {
12469 id = filter && attr$1(filter, ELEMENT_ID);
12470 }
12471
12472 var container = this._elements[id];
12473 return container && container.element;
12474 };
12475
12476 /**
12477 * Return all elements that match a given filter function.
12478 *
12479 * @param {ElementRegistryFilterCallback} fn The filter function.
12480 *
12481 * @return {ElementLike[]} The matching elements.
12482 */
12483 ElementRegistry.prototype.filter = function(fn) {
12484
12485 var filtered = [];
12486
12487 this.forEach(function(element, gfx) {
12488 if (fn(element, gfx)) {
12489 filtered.push(element);
12490 }
12491 });
12492
12493 return filtered;
12494 };
12495
12496 /**
12497 * Return the first element that matches the given filter function.
12498 *
12499 * @param {ElementRegistryFilterCallback} fn The filter function.
12500 *
12501 * @return {ElementLike|undefined} The matching element.
12502 */
12503 ElementRegistry.prototype.find = function(fn) {
12504 var map = this._elements,
12505 keys = Object.keys(map);
12506
12507 for (var i = 0; i < keys.length; i++) {
12508 var id = keys[i],
12509 container = map[id],
12510 element = container.element,
12511 gfx = container.gfx;
12512
12513 if (fn(element, gfx)) {
12514 return element;
12515 }
12516 }
12517 };
12518
12519 /**
12520 * Get all elements.
12521 *
12522 * @return {ElementLike[]} All elements.
12523 */
12524 ElementRegistry.prototype.getAll = function() {
12525 return this.filter(function(e) { return e; });
12526 };
12527
12528 /**
12529 * Execute a given function for each element.
12530 *
12531 * @param {ElementRegistryForEachCallback} fn The function to execute.
12532 */
12533 ElementRegistry.prototype.forEach = function(fn) {
12534
12535 var map = this._elements;
12536
12537 Object.keys(map).forEach(function(id) {
12538 var container = map[id],
12539 element = container.element,
12540 gfx = container.gfx;
12541
12542 return fn(element, gfx);
12543 });
12544 };
12545
12546 /**
12547 * Return the graphical representation of an element.
12548 *
12549 * @example
12550 *
12551 * ```javascript
12552 * elementRegistry.getGraphics('SomeElementId_1');
12553 *
12554 * elementRegistry.getGraphics(rootElement); // <g ...>
12555 *
12556 * elementRegistry.getGraphics(rootElement, true); // <svg ...>
12557 * ```
12558 *
12559 * @param {ElementLike|string} filter The element or its ID.
12560 * @param {boolean} [secondary=false] Whether to return the secondary graphical representation.
12561 *
12562 * @return {SVGElement} The graphical representation.
12563 */
12564 ElementRegistry.prototype.getGraphics = function(filter, secondary) {
12565 var id = filter.id || filter;
12566
12567 var container = this._elements[id];
12568 return container && (secondary ? container.secondaryGfx : container.gfx);
12569 };
12570
12571 /**
12572 * Validate an ID and throw an error if invalid.
12573 *
12574 * @param {string} id
12575 *
12576 * @throws {Error} Error indicating that the ID is invalid or already assigned.
12577 */
12578 ElementRegistry.prototype._validateId = function(id) {
12579 if (!id) {
12580 throw new Error('element must have an id');
12581 }
12582
12583 if (this._elements[id]) {
12584 throw new Error('element with id ' + id + ' already added');
12585 }
12586 };
12587
12588 /**
12589 * Extends a collection with {@link Refs} aware methods
12590 *
12591 * @param {Array<Object>} collection
12592 * @param {Refs} refs instance
12593 * @param {Object} property represented by the collection
12594 * @param {Object} target object the collection is attached to
12595 *
12596 * @return {RefsCollection<Object>} the extended array
12597 */
12598 function extend(collection, refs, property, target) {
12599 var inverseProperty = property.inverse;
12600
12601 /**
12602 * Removes the given element from the array and returns it.
12603 *
12604 * @method RefsCollection#remove
12605 *
12606 * @param {Object} element the element to remove
12607 */
12608 Object.defineProperty(collection, 'remove', {
12609 value: function (element) {
12610 var idx = this.indexOf(element);
12611 if (idx !== -1) {
12612 this.splice(idx, 1);
12613
12614 // unset inverse
12615 refs.unset(element, inverseProperty, target);
12616 }
12617 return element;
12618 }
12619 });
12620
12621 /**
12622 * Returns true if the collection contains the given element
12623 *
12624 * @method RefsCollection#contains
12625 *
12626 * @param {Object} element the element to check for
12627 */
12628 Object.defineProperty(collection, 'contains', {
12629 value: function (element) {
12630 return this.indexOf(element) !== -1;
12631 }
12632 });
12633
12634 /**
12635 * Adds an element to the array, unless it exists already (set semantics).
12636 *
12637 * @method RefsCollection#add
12638 *
12639 * @param {Object} element the element to add
12640 * @param {Number} optional index to add element to
12641 * (possibly moving other elements around)
12642 */
12643 Object.defineProperty(collection, 'add', {
12644 value: function (element, idx) {
12645 var currentIdx = this.indexOf(element);
12646 if (typeof idx === 'undefined') {
12647 if (currentIdx !== -1) {
12648 // element already in collection (!)
12649 return;
12650 }
12651
12652 // add to end of array, as no idx is specified
12653 idx = this.length;
12654 }
12655
12656 // handle already in collection
12657 if (currentIdx !== -1) {
12658 // remove element from currentIdx
12659 this.splice(currentIdx, 1);
12660 }
12661
12662 // add element at idx
12663 this.splice(idx, 0, element);
12664 if (currentIdx === -1) {
12665 // set inverse, unless element was
12666 // in collection already
12667 refs.set(element, inverseProperty, target);
12668 }
12669 }
12670 });
12671
12672 // a simple marker, identifying this element
12673 // as being a refs collection
12674 Object.defineProperty(collection, '__refs_collection', {
12675 value: true
12676 });
12677 return collection;
12678 }
12679
12680 /**
12681 * Checks if a given collection is extended
12682 *
12683 * @param {Array<Object>} collection
12684 *
12685 * @return {boolean}
12686 */
12687 function isExtended(collection) {
12688 return collection.__refs_collection === true;
12689 }
12690
12691 function hasOwnProperty$1(e, property) {
12692 return Object.prototype.hasOwnProperty.call(e, property.name || property);
12693 }
12694 function defineCollectionProperty(ref, property, target) {
12695 var collection = extend(target[property.name] || [], ref, property, target);
12696 Object.defineProperty(target, property.name, {
12697 enumerable: property.enumerable,
12698 value: collection
12699 });
12700 if (collection.length) {
12701 collection.forEach(function (o) {
12702 ref.set(o, property.inverse, target);
12703 });
12704 }
12705 }
12706 function defineProperty$1(ref, property, target) {
12707 var inverseProperty = property.inverse;
12708 var _value = target[property.name];
12709 Object.defineProperty(target, property.name, {
12710 configurable: property.configurable,
12711 enumerable: property.enumerable,
12712 get: function () {
12713 return _value;
12714 },
12715 set: function (value) {
12716 // return if we already performed all changes
12717 if (value === _value) {
12718 return;
12719 }
12720 var old = _value;
12721
12722 // temporary set null
12723 _value = null;
12724 if (old) {
12725 ref.unset(old, inverseProperty, target);
12726 }
12727
12728 // set new value
12729 _value = value;
12730
12731 // set inverse value
12732 ref.set(_value, inverseProperty, target);
12733 }
12734 });
12735 }
12736
12737 /**
12738 * Creates a new references object defining two inversly related
12739 * attribute descriptors a and b.
12740 *
12741 * <p>
12742 * When bound to an object using {@link Refs#bind} the references
12743 * get activated and ensure that add and remove operations are applied
12744 * reversely, too.
12745 * </p>
12746 *
12747 * <p>
12748 * For attributes represented as collections {@link Refs} provides the
12749 * {@link RefsCollection#add}, {@link RefsCollection#remove} and {@link RefsCollection#contains} extensions
12750 * that must be used to properly hook into the inverse change mechanism.
12751 * </p>
12752 *
12753 * @class Refs
12754 *
12755 * @classdesc A bi-directional reference between two attributes.
12756 *
12757 * @param {Refs.AttributeDescriptor} a property descriptor
12758 * @param {Refs.AttributeDescriptor} b property descriptor
12759 *
12760 * @example
12761 *
12762 * var refs = Refs({ name: 'wheels', collection: true, enumerable: true }, { name: 'car' });
12763 *
12764 * var car = { name: 'toyota' };
12765 * var wheels = [{ pos: 'front-left' }, { pos: 'front-right' }];
12766 *
12767 * refs.bind(car, 'wheels');
12768 *
12769 * car.wheels // []
12770 * car.wheels.add(wheels[0]);
12771 * car.wheels.add(wheels[1]);
12772 *
12773 * car.wheels // [{ pos: 'front-left' }, { pos: 'front-right' }]
12774 *
12775 * wheels[0].car // { name: 'toyota' };
12776 * car.wheels.remove(wheels[0]);
12777 *
12778 * wheels[0].car // undefined
12779 */
12780 function Refs(a, b) {
12781 if (!(this instanceof Refs)) {
12782 return new Refs(a, b);
12783 }
12784
12785 // link
12786 a.inverse = b;
12787 b.inverse = a;
12788 this.props = {};
12789 this.props[a.name] = a;
12790 this.props[b.name] = b;
12791 }
12792
12793 /**
12794 * Binds one side of a bi-directional reference to a
12795 * target object.
12796 *
12797 * @memberOf Refs
12798 *
12799 * @param {Object} target
12800 * @param {String} property
12801 */
12802 Refs.prototype.bind = function (target, property) {
12803 if (typeof property === 'string') {
12804 if (!this.props[property]) {
12805 throw new Error('no property <' + property + '> in ref');
12806 }
12807 property = this.props[property];
12808 }
12809 if (property.collection) {
12810 defineCollectionProperty(this, property, target);
12811 } else {
12812 defineProperty$1(this, property, target);
12813 }
12814 };
12815 Refs.prototype.ensureRefsCollection = function (target, property) {
12816 var collection = target[property.name];
12817 if (!isExtended(collection)) {
12818 defineCollectionProperty(this, property, target);
12819 }
12820 return collection;
12821 };
12822 Refs.prototype.ensureBound = function (target, property) {
12823 if (!hasOwnProperty$1(target, property)) {
12824 this.bind(target, property);
12825 }
12826 };
12827 Refs.prototype.unset = function (target, property, value) {
12828 if (target) {
12829 this.ensureBound(target, property);
12830 if (property.collection) {
12831 this.ensureRefsCollection(target, property).remove(value);
12832 } else {
12833 target[property.name] = undefined;
12834 }
12835 }
12836 };
12837 Refs.prototype.set = function (target, property, value) {
12838 if (target) {
12839 this.ensureBound(target, property);
12840 if (property.collection) {
12841 this.ensureRefsCollection(target, property).add(value);
12842 } else {
12843 target[property.name] = value;
12844 }
12845 }
12846 };
12847
12848 var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
12849 labelRefs = new Refs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
12850 attacherRefs = new Refs({ name: 'attachers', collection: true }, { name: 'host' }),
12851 outgoingRefs = new Refs({ name: 'outgoing', collection: true }, { name: 'source' }),
12852 incomingRefs = new Refs({ name: 'incoming', collection: true }, { name: 'target' });
12853
12854 /**
12855 * @typedef {import('./Types').Element} Element
12856 * @typedef {import('./Types').Shape} Shape
12857 * @typedef {import('./Types').Root} Root
12858 * @typedef {import('./Types').Label} Label
12859 * @typedef {import('./Types').Connection} Connection
12860 */
12861
12862 /**
12863 * The basic graphical representation
12864 *
12865 * @class
12866 * @constructor
12867 */
12868 function ElementImpl() {
12869
12870 /**
12871 * The object that backs up the shape
12872 *
12873 * @name Element#businessObject
12874 * @type Object
12875 */
12876 Object.defineProperty(this, 'businessObject', {
12877 writable: true
12878 });
12879
12880
12881 /**
12882 * Single label support, will mapped to multi label array
12883 *
12884 * @name Element#label
12885 * @type Object
12886 */
12887 Object.defineProperty(this, 'label', {
12888 get: function() {
12889 return this.labels[0];
12890 },
12891 set: function(newLabel) {
12892
12893 var label = this.label,
12894 labels = this.labels;
12895
12896 if (!newLabel && label) {
12897 labels.remove(label);
12898 } else {
12899 labels.add(newLabel, 0);
12900 }
12901 }
12902 });
12903
12904 /**
12905 * The parent shape
12906 *
12907 * @name Element#parent
12908 * @type Shape
12909 */
12910 parentRefs.bind(this, 'parent');
12911
12912 /**
12913 * The list of labels
12914 *
12915 * @name Element#labels
12916 * @type Label
12917 */
12918 labelRefs.bind(this, 'labels');
12919
12920 /**
12921 * The list of outgoing connections
12922 *
12923 * @name Element#outgoing
12924 * @type Array<Connection>
12925 */
12926 outgoingRefs.bind(this, 'outgoing');
12927
12928 /**
12929 * The list of incoming connections
12930 *
12931 * @name Element#incoming
12932 * @type Array<Connection>
12933 */
12934 incomingRefs.bind(this, 'incoming');
12935 }
12936
12937
12938 /**
12939 * A graphical object
12940 *
12941 * @class
12942 * @constructor
12943 *
12944 * @extends ElementImpl
12945 */
12946 function ShapeImpl() {
12947 ElementImpl.call(this);
12948
12949 /**
12950 * Indicates frame shapes
12951 *
12952 * @name ShapeImpl#isFrame
12953 * @type boolean
12954 */
12955
12956 /**
12957 * The list of children
12958 *
12959 * @name ShapeImpl#children
12960 * @type Element[]
12961 */
12962 parentRefs.bind(this, 'children');
12963
12964 /**
12965 * @name ShapeImpl#host
12966 * @type Shape
12967 */
12968 attacherRefs.bind(this, 'host');
12969
12970 /**
12971 * @name ShapeImpl#attachers
12972 * @type Shape
12973 */
12974 attacherRefs.bind(this, 'attachers');
12975 }
12976
12977 e(ShapeImpl, ElementImpl);
12978
12979
12980 /**
12981 * A root graphical object
12982 *
12983 * @class
12984 * @constructor
12985 *
12986 * @extends ElementImpl
12987 */
12988 function RootImpl() {
12989 ElementImpl.call(this);
12990
12991 /**
12992 * The list of children
12993 *
12994 * @name RootImpl#children
12995 * @type Element[]
12996 */
12997 parentRefs.bind(this, 'children');
12998 }
12999
13000 e(RootImpl, ShapeImpl);
13001
13002
13003 /**
13004 * A label for an element
13005 *
13006 * @class
13007 * @constructor
13008 *
13009 * @extends ShapeImpl
13010 */
13011 function LabelImpl() {
13012 ShapeImpl.call(this);
13013
13014 /**
13015 * The labeled element
13016 *
13017 * @name LabelImpl#labelTarget
13018 * @type Element
13019 */
13020 labelRefs.bind(this, 'labelTarget');
13021 }
13022
13023 e(LabelImpl, ShapeImpl);
13024
13025
13026 /**
13027 * A connection between two elements
13028 *
13029 * @class
13030 * @constructor
13031 *
13032 * @extends ElementImpl
13033 */
13034 function ConnectionImpl() {
13035 ElementImpl.call(this);
13036
13037 /**
13038 * The element this connection originates from
13039 *
13040 * @name ConnectionImpl#source
13041 * @type Element
13042 */
13043 outgoingRefs.bind(this, 'source');
13044
13045 /**
13046 * The element this connection points to
13047 *
13048 * @name ConnectionImpl#target
13049 * @type Element
13050 */
13051 incomingRefs.bind(this, 'target');
13052 }
13053
13054 e(ConnectionImpl, ElementImpl);
13055
13056
13057 var types$6 = {
13058 connection: ConnectionImpl,
13059 shape: ShapeImpl,
13060 label: LabelImpl,
13061 root: RootImpl
13062 };
13063
13064 /**
13065 * Creates a root element.
13066 *
13067 * @overlord
13068 *
13069 * @example
13070 *
13071 * ```javascript
13072 * import * as Model from 'diagram-js/lib/model';
13073 *
13074 * const root = Model.create('root', {
13075 * x: 100,
13076 * y: 100,
13077 * width: 100,
13078 * height: 100
13079 * });
13080 * ```
13081 *
13082 * @param {'root'} type
13083 * @param {any} [attrs]
13084 *
13085 * @return {Root}
13086 */
13087
13088 /**
13089 * Creates a connection.
13090 *
13091 * @overlord
13092 *
13093 * @example
13094 *
13095 * ```javascript
13096 * import * as Model from 'diagram-js/lib/model';
13097 *
13098 * const connection = Model.create('connection', {
13099 * waypoints: [
13100 * { x: 100, y: 100 },
13101 * { x: 200, y: 100 }
13102 * ]
13103 * });
13104 * ```
13105 *
13106 * @param {'connection'} type
13107 * @param {any} [attrs]
13108 *
13109 * @return {Connection}
13110 */
13111
13112 /**
13113 * Creates a shape.
13114 *
13115 * @overlord
13116 *
13117 * @example
13118 *
13119 * ```javascript
13120 * import * as Model from 'diagram-js/lib/model';
13121 *
13122 * const shape = Model.create('shape', {
13123 * x: 100,
13124 * y: 100,
13125 * width: 100,
13126 * height: 100
13127 * });
13128 * ```
13129 *
13130 * @param {'shape'} type
13131 * @param {any} [attrs]
13132 *
13133 * @return {Shape}
13134 */
13135
13136 /**
13137 * Creates a label.
13138 *
13139 * @example
13140 *
13141 * ```javascript
13142 * import * as Model from 'diagram-js/lib/model';
13143 *
13144 * const label = Model.create('label', {
13145 * x: 100,
13146 * y: 100,
13147 * width: 100,
13148 * height: 100,
13149 * labelTarget: shape
13150 * });
13151 * ```
13152 *
13153 * @param {'label'} type
13154 * @param {Object} [attrs]
13155 *
13156 * @return {Label}
13157 */
13158 function create(type, attrs) {
13159 var Type = types$6[type];
13160 if (!Type) {
13161 throw new Error('unknown type: <' + type + '>');
13162 }
13163 return assign$1(new Type(), attrs);
13164 }
13165
13166 /**
13167 * @typedef {import('../model/Types').Element} Element
13168 * @typedef {import('../model/Types').Connection} Connection
13169 * @typedef {import('../model/Types').Label} Label
13170 * @typedef {import('../model/Types').Root} Root
13171 * @typedef {import('../model/Types').Shape} Shape
13172 */
13173
13174 /**
13175 * A factory for model elements.
13176 *
13177 * @template {Connection} [T=Connection]
13178 * @template {Label} [U=Label]
13179 * @template {Root} [V=Root]
13180 * @template {Shape} [W=Shape]
13181 */
13182 function ElementFactory() {
13183 this._uid = 12;
13184 }
13185
13186 /**
13187 * Create a root element.
13188 *
13189 * @param {Partial<Root>} [attrs]
13190 *
13191 * @return {V} The created root element.
13192 */
13193 ElementFactory.prototype.createRoot = function(attrs) {
13194 return this.create('root', attrs);
13195 };
13196
13197 /**
13198 * Create a label.
13199 *
13200 * @param {Partial<Label>} [attrs]
13201 *
13202 * @return {U} The created label.
13203 */
13204 ElementFactory.prototype.createLabel = function(attrs) {
13205 return this.create('label', attrs);
13206 };
13207
13208 /**
13209 * Create a shape.
13210 *
13211 * @param {Partial<Shape>} [attrs]
13212 *
13213 * @return {W} The created shape.
13214 */
13215 ElementFactory.prototype.createShape = function(attrs) {
13216 return this.create('shape', attrs);
13217 };
13218
13219 /**
13220 * Create a connection.
13221 *
13222 * @param {Partial<Connection>} [attrs]
13223 *
13224 * @return {T} The created connection.
13225 */
13226 ElementFactory.prototype.createConnection = function(attrs) {
13227 return this.create('connection', attrs);
13228 };
13229
13230 /**
13231 * Create a root element.
13232 *
13233 * @overlord
13234 * @param {'root'} type
13235 * @param {Partial<Root>} [attrs]
13236 * @return {V}
13237 */
13238 /**
13239 * Create a shape.
13240 *
13241 * @overlord
13242 * @param {'shape'} type
13243 * @param {Partial<Shape>} [attrs]
13244 * @return {W}
13245 */
13246 /**
13247 * Create a connection.
13248 *
13249 * @overlord
13250 * @param {'connection'} type
13251 * @param {Partial<Connection>} [attrs]
13252 * @return {T}
13253 */
13254 /**
13255 * Create a label.
13256 *
13257 * @param {'label'} type
13258 * @param {Partial<Label>} [attrs]
13259 * @return {U}
13260 */
13261 ElementFactory.prototype.create = function(type, attrs) {
13262
13263 attrs = assign$1({}, attrs || {});
13264
13265 if (!attrs.id) {
13266 attrs.id = type + '_' + (this._uid++);
13267 }
13268
13269 return create(type, attrs);
13270 };
13271
13272 var FN_REF = '__fn';
13273
13274 var DEFAULT_PRIORITY = 1000;
13275
13276 var slice = Array.prototype.slice;
13277
13278 /**
13279 * @typedef { {
13280 * stopPropagation(): void;
13281 * preventDefault(): void;
13282 * cancelBubble: boolean;
13283 * defaultPrevented: boolean;
13284 * returnValue: any;
13285 * } } Event
13286 */
13287
13288 /**
13289 * @template E
13290 *
13291 * @typedef { (event: E & Event, ...any) => any } EventBusEventCallback
13292 */
13293
13294 /**
13295 * @typedef { {
13296 * priority: number;
13297 * next: EventBusListener | null;
13298 * callback: EventBusEventCallback<any>;
13299 * } } EventBusListener
13300 */
13301
13302 /**
13303 * A general purpose event bus.
13304 *
13305 * This component is used to communicate across a diagram instance.
13306 * Other parts of a diagram can use it to listen to and broadcast events.
13307 *
13308 *
13309 * ## Registering for Events
13310 *
13311 * The event bus provides the {@link EventBus#on} and {@link EventBus#once}
13312 * methods to register for events. {@link EventBus#off} can be used to
13313 * remove event registrations. Listeners receive an instance of {@link Event}
13314 * as the first argument. It allows them to hook into the event execution.
13315 *
13316 * ```javascript
13317 *
13318 * // listen for event
13319 * eventBus.on('foo', function(event) {
13320 *
13321 * // access event type
13322 * event.type; // 'foo'
13323 *
13324 * // stop propagation to other listeners
13325 * event.stopPropagation();
13326 *
13327 * // prevent event default
13328 * event.preventDefault();
13329 * });
13330 *
13331 * // listen for event with custom payload
13332 * eventBus.on('bar', function(event, payload) {
13333 * console.log(payload);
13334 * });
13335 *
13336 * // listen for event returning value
13337 * eventBus.on('foobar', function(event) {
13338 *
13339 * // stop event propagation + prevent default
13340 * return false;
13341 *
13342 * // stop event propagation + return custom result
13343 * return {
13344 * complex: 'listening result'
13345 * };
13346 * });
13347 *
13348 *
13349 * // listen with custom priority (default=1000, higher is better)
13350 * eventBus.on('priorityfoo', 1500, function(event) {
13351 * console.log('invoked first!');
13352 * });
13353 *
13354 *
13355 * // listen for event and pass the context (`this`)
13356 * eventBus.on('foobar', function(event) {
13357 * this.foo();
13358 * }, this);
13359 * ```
13360 *
13361 *
13362 * ## Emitting Events
13363 *
13364 * Events can be emitted via the event bus using {@link EventBus#fire}.
13365 *
13366 * ```javascript
13367 *
13368 * // false indicates that the default action
13369 * // was prevented by listeners
13370 * if (eventBus.fire('foo') === false) {
13371 * console.log('default has been prevented!');
13372 * };
13373 *
13374 *
13375 * // custom args + return value listener
13376 * eventBus.on('sum', function(event, a, b) {
13377 * return a + b;
13378 * });
13379 *
13380 * // you can pass custom arguments + retrieve result values.
13381 * var sum = eventBus.fire('sum', 1, 2);
13382 * console.log(sum); // 3
13383 * ```
13384 *
13385 * @template [EventMap=null]
13386 */
13387 function EventBus() {
13388
13389 /**
13390 * @type { Record<string, EventBusListener> }
13391 */
13392 this._listeners = {};
13393
13394 // cleanup on destroy on lowest priority to allow
13395 // message passing until the bitter end
13396 this.on('diagram.destroy', 1, this._destroy, this);
13397 }
13398
13399 /**
13400 * @overlord
13401 *
13402 * Register an event listener for events with the given name.
13403 *
13404 * The callback will be invoked with `event, ...additionalArguments`
13405 * that have been passed to {@link EventBus#fire}.
13406 *
13407 * Returning false from a listener will prevent the events default action
13408 * (if any is specified). To stop an event from being processed further in
13409 * other listeners execute {@link Event#stopPropagation}.
13410 *
13411 * Returning anything but `undefined` from a listener will stop the listener propagation.
13412 *
13413 * @template T
13414 *
13415 * @param {string|string[]} events to subscribe to
13416 * @param {number} [priority=1000] listen priority
13417 * @param {EventBusEventCallback<T>} callback
13418 * @param {any} [that] callback context
13419 */
13420 /**
13421 * Register an event listener for events with the given name.
13422 *
13423 * The callback will be invoked with `event, ...additionalArguments`
13424 * that have been passed to {@link EventBus#fire}.
13425 *
13426 * Returning false from a listener will prevent the events default action
13427 * (if any is specified). To stop an event from being processed further in
13428 * other listeners execute {@link Event#stopPropagation}.
13429 *
13430 * Returning anything but `undefined` from a listener will stop the listener propagation.
13431 *
13432 * @template {keyof EventMap} EventName
13433 *
13434 * @param {EventName} events to subscribe to
13435 * @param {number} [priority=1000] listen priority
13436 * @param {EventBusEventCallback<EventMap[EventName]>} callback
13437 * @param {any} [that] callback context
13438 */
13439 EventBus.prototype.on = function(events, priority, callback, that) {
13440
13441 events = isArray$2(events) ? events : [ events ];
13442
13443 if (isFunction(priority)) {
13444 that = callback;
13445 callback = priority;
13446 priority = DEFAULT_PRIORITY;
13447 }
13448
13449 if (!isNumber(priority)) {
13450 throw new Error('priority must be a number');
13451 }
13452
13453 var actualCallback = callback;
13454
13455 if (that) {
13456 actualCallback = bind$2(callback, that);
13457
13458 // make sure we remember and are able to remove
13459 // bound callbacks via {@link #off} using the original
13460 // callback
13461 actualCallback[FN_REF] = callback[FN_REF] || callback;
13462 }
13463
13464 var self = this;
13465
13466 events.forEach(function(e) {
13467 self._addListener(e, {
13468 priority: priority,
13469 callback: actualCallback,
13470 next: null
13471 });
13472 });
13473 };
13474
13475 /**
13476 * @overlord
13477 *
13478 * Register an event listener that is called only once.
13479 *
13480 * @template T
13481 *
13482 * @param {string|string[]} events to subscribe to
13483 * @param {number} [priority=1000] the listen priority
13484 * @param {EventBusEventCallback<T>} callback
13485 * @param {any} [that] callback context
13486 */
13487 /**
13488 * Register an event listener that is called only once.
13489 *
13490 * @template {keyof EventMap} EventName
13491 *
13492 * @param {EventName} events to subscribe to
13493 * @param {number} [priority=1000] listen priority
13494 * @param {EventBusEventCallback<EventMap[EventName]>} callback
13495 * @param {any} [that] callback context
13496 */
13497 EventBus.prototype.once = function(events, priority, callback, that) {
13498 var self = this;
13499
13500 if (isFunction(priority)) {
13501 that = callback;
13502 callback = priority;
13503 priority = DEFAULT_PRIORITY;
13504 }
13505
13506 if (!isNumber(priority)) {
13507 throw new Error('priority must be a number');
13508 }
13509
13510 function wrappedCallback() {
13511 wrappedCallback.__isTomb = true;
13512
13513 var result = callback.apply(that, arguments);
13514
13515 self.off(events, wrappedCallback);
13516
13517 return result;
13518 }
13519
13520 // make sure we remember and are able to remove
13521 // bound callbacks via {@link #off} using the original
13522 // callback
13523 wrappedCallback[FN_REF] = callback;
13524
13525 this.on(events, priority, wrappedCallback);
13526 };
13527
13528
13529 /**
13530 * Removes event listeners by event and callback.
13531 *
13532 * If no callback is given, all listeners for a given event name are being removed.
13533 *
13534 * @param {string|string[]} events
13535 * @param {EventBusEventCallback} [callback]
13536 */
13537 EventBus.prototype.off = function(events, callback) {
13538
13539 events = isArray$2(events) ? events : [ events ];
13540
13541 var self = this;
13542
13543 events.forEach(function(event) {
13544 self._removeListener(event, callback);
13545 });
13546
13547 };
13548
13549
13550 /**
13551 * Create an event recognized be the event bus.
13552 *
13553 * @param {Object} data Event data.
13554 *
13555 * @return {Event} An event that will be recognized by the event bus.
13556 */
13557 EventBus.prototype.createEvent = function(data) {
13558 var event = new InternalEvent();
13559
13560 event.init(data);
13561
13562 return event;
13563 };
13564
13565
13566 /**
13567 * Fires an event.
13568 *
13569 * @example
13570 *
13571 * ```javascript
13572 * // fire event by name
13573 * events.fire('foo');
13574 *
13575 * // fire event object with nested type
13576 * var event = { type: 'foo' };
13577 * events.fire(event);
13578 *
13579 * // fire event with explicit type
13580 * var event = { x: 10, y: 20 };
13581 * events.fire('element.moved', event);
13582 *
13583 * // pass additional arguments to the event
13584 * events.on('foo', function(event, bar) {
13585 * alert(bar);
13586 * });
13587 *
13588 * events.fire({ type: 'foo' }, 'I am bar!');
13589 * ```
13590 *
13591 * @param {string} [type] event type
13592 * @param {Object} [data] event or event data
13593 * @param {...any} [args] additional arguments the callback will be called with.
13594 *
13595 * @return {any} The return value. Will be set to `false` if the default was prevented.
13596 */
13597 EventBus.prototype.fire = function(type, data) {
13598 var event,
13599 firstListener,
13600 returnValue,
13601 args;
13602
13603 args = slice.call(arguments);
13604
13605 if (typeof type === 'object') {
13606 data = type;
13607 type = data.type;
13608 }
13609
13610 if (!type) {
13611 throw new Error('no event type specified');
13612 }
13613
13614 firstListener = this._listeners[type];
13615
13616 if (!firstListener) {
13617 return;
13618 }
13619
13620 // we make sure we fire instances of our home made
13621 // events here. We wrap them only once, though
13622 if (data instanceof InternalEvent) {
13623
13624 // we are fine, we alread have an event
13625 event = data;
13626 } else {
13627 event = this.createEvent(data);
13628 }
13629
13630 // ensure we pass the event as the first parameter
13631 args[0] = event;
13632
13633 // original event type (in case we delegate)
13634 var originalType = event.type;
13635
13636 // update event type before delegation
13637 if (type !== originalType) {
13638 event.type = type;
13639 }
13640
13641 try {
13642 returnValue = this._invokeListeners(event, args, firstListener);
13643 } finally {
13644
13645 // reset event type after delegation
13646 if (type !== originalType) {
13647 event.type = originalType;
13648 }
13649 }
13650
13651 // set the return value to false if the event default
13652 // got prevented and no other return value exists
13653 if (returnValue === undefined && event.defaultPrevented) {
13654 returnValue = false;
13655 }
13656
13657 return returnValue;
13658 };
13659
13660 /**
13661 * Handle an error by firing an event.
13662 *
13663 * @param {Error} error The error to be handled.
13664 *
13665 * @return {boolean} Whether the error was handled.
13666 */
13667 EventBus.prototype.handleError = function(error) {
13668 return this.fire('error', { error: error }) === false;
13669 };
13670
13671
13672 EventBus.prototype._destroy = function() {
13673 this._listeners = {};
13674 };
13675
13676 /**
13677 * @param {Event} event
13678 * @param {any[]} args
13679 * @param {EventBusListener} listener
13680 *
13681 * @return {any}
13682 */
13683 EventBus.prototype._invokeListeners = function(event, args, listener) {
13684
13685 var returnValue;
13686
13687 while (listener) {
13688
13689 // handle stopped propagation
13690 if (event.cancelBubble) {
13691 break;
13692 }
13693
13694 returnValue = this._invokeListener(event, args, listener);
13695
13696 listener = listener.next;
13697 }
13698
13699 return returnValue;
13700 };
13701
13702 /**
13703 * @param {Event} event
13704 * @param {any[]} args
13705 * @param {EventBusListener} listener
13706 *
13707 * @return {any}
13708 */
13709 EventBus.prototype._invokeListener = function(event, args, listener) {
13710
13711 var returnValue;
13712
13713 if (listener.callback.__isTomb) {
13714 return returnValue;
13715 }
13716
13717 try {
13718
13719 // returning false prevents the default action
13720 returnValue = invokeFunction(listener.callback, args);
13721
13722 // stop propagation on return value
13723 if (returnValue !== undefined) {
13724 event.returnValue = returnValue;
13725 event.stopPropagation();
13726 }
13727
13728 // prevent default on return false
13729 if (returnValue === false) {
13730 event.preventDefault();
13731 }
13732 } catch (error) {
13733 if (!this.handleError(error)) {
13734 console.error('unhandled error in event listener', error);
13735
13736 throw error;
13737 }
13738 }
13739
13740 return returnValue;
13741 };
13742
13743 /**
13744 * Add new listener with a certain priority to the list
13745 * of listeners (for the given event).
13746 *
13747 * The semantics of listener registration / listener execution are
13748 * first register, first serve: New listeners will always be inserted
13749 * after existing listeners with the same priority.
13750 *
13751 * Example: Inserting two listeners with priority 1000 and 1300
13752 *
13753 * * before: [ 1500, 1500, 1000, 1000 ]
13754 * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
13755 *
13756 * @param {string} event
13757 * @param {EventBusListener} newListener
13758 */
13759 EventBus.prototype._addListener = function(event, newListener) {
13760
13761 var listener = this._getListeners(event),
13762 previousListener;
13763
13764 // no prior listeners
13765 if (!listener) {
13766 this._setListeners(event, newListener);
13767
13768 return;
13769 }
13770
13771 // ensure we order listeners by priority from
13772 // 0 (high) to n > 0 (low)
13773 while (listener) {
13774
13775 if (listener.priority < newListener.priority) {
13776
13777 newListener.next = listener;
13778
13779 if (previousListener) {
13780 previousListener.next = newListener;
13781 } else {
13782 this._setListeners(event, newListener);
13783 }
13784
13785 return;
13786 }
13787
13788 previousListener = listener;
13789 listener = listener.next;
13790 }
13791
13792 // add new listener to back
13793 previousListener.next = newListener;
13794 };
13795
13796
13797 /**
13798 * @param {string} name
13799 *
13800 * @return {EventBusListener}
13801 */
13802 EventBus.prototype._getListeners = function(name) {
13803 return this._listeners[name];
13804 };
13805
13806 /**
13807 * @param {string} name
13808 * @param {EventBusListener} listener
13809 */
13810 EventBus.prototype._setListeners = function(name, listener) {
13811 this._listeners[name] = listener;
13812 };
13813
13814 EventBus.prototype._removeListener = function(event, callback) {
13815
13816 var listener = this._getListeners(event),
13817 nextListener,
13818 previousListener,
13819 listenerCallback;
13820
13821 if (!callback) {
13822
13823 // clear listeners
13824 this._setListeners(event, null);
13825
13826 return;
13827 }
13828
13829 while (listener) {
13830
13831 nextListener = listener.next;
13832
13833 listenerCallback = listener.callback;
13834
13835 if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
13836 if (previousListener) {
13837 previousListener.next = nextListener;
13838 } else {
13839
13840 // new first listener
13841 this._setListeners(event, nextListener);
13842 }
13843 }
13844
13845 previousListener = listener;
13846 listener = nextListener;
13847 }
13848 };
13849
13850 /**
13851 * A event that is emitted via the event bus.
13852 */
13853 function InternalEvent() { }
13854
13855 InternalEvent.prototype.stopPropagation = function() {
13856 this.cancelBubble = true;
13857 };
13858
13859 InternalEvent.prototype.preventDefault = function() {
13860 this.defaultPrevented = true;
13861 };
13862
13863 InternalEvent.prototype.init = function(data) {
13864 assign$1(this, data || {});
13865 };
13866
13867
13868 /**
13869 * Invoke function. Be fast...
13870 *
13871 * @param {Function} fn
13872 * @param {any[]} args
13873 *
13874 * @return {any}
13875 */
13876 function invokeFunction(fn, args) {
13877 return fn.apply(null, args);
13878 }
13879
13880 /**
13881 * SVGs for elements are generated by the {@link GraphicsFactory}.
13882 *
13883 * This utility gives quick access to the important semantic
13884 * parts of an element.
13885 */
13886
13887 /**
13888 * Returns the visual part of a diagram element.
13889 *
13890 * @param {SVGElement} gfx
13891 *
13892 * @return {SVGElement}
13893 */
13894 function getVisual(gfx) {
13895 return gfx.childNodes[0];
13896 }
13897
13898 /**
13899 * Returns the children for a given diagram element.
13900 *
13901 * @param {SVGElement} gfx
13902 * @return {SVGElement}
13903 */
13904 function getChildren(gfx) {
13905 return gfx.parentNode.childNodes[1];
13906 }
13907
13908 /**
13909 * @typedef {import('./Types').ConnectionLike} ConnectionLike
13910 * @typedef {import('./Types').ElementLike} ElementLike
13911 * @typedef {import('./Types').ShapeLike} ShapeLike
13912 *
13913 * @typedef {import('./ElementRegistry').default} ElementRegistry
13914 * @typedef {import('./EventBus').default} EventBus
13915 */
13916
13917 /**
13918 * A factory that creates graphical elements.
13919 *
13920 * @param {EventBus} eventBus
13921 * @param {ElementRegistry} elementRegistry
13922 */
13923 function GraphicsFactory(eventBus, elementRegistry) {
13924 this._eventBus = eventBus;
13925 this._elementRegistry = elementRegistry;
13926 }
13927
13928 GraphicsFactory.$inject = [ 'eventBus' , 'elementRegistry' ];
13929
13930 /**
13931 * @param { { parent?: any } } element
13932 * @return {SVGElement}
13933 */
13934 GraphicsFactory.prototype._getChildrenContainer = function(element) {
13935
13936 var gfx = this._elementRegistry.getGraphics(element);
13937
13938 var childrenGfx;
13939
13940 // root element
13941 if (!element.parent) {
13942 childrenGfx = gfx;
13943 } else {
13944 childrenGfx = getChildren(gfx);
13945 if (!childrenGfx) {
13946 childrenGfx = create$1('g');
13947 classes$1(childrenGfx).add('djs-children');
13948
13949 append(gfx.parentNode, childrenGfx);
13950 }
13951 }
13952
13953 return childrenGfx;
13954 };
13955
13956 /**
13957 * Clears the graphical representation of the element and returns the
13958 * cleared visual (the <g class="djs-visual" /> element).
13959 */
13960 GraphicsFactory.prototype._clear = function(gfx) {
13961 var visual = getVisual(gfx);
13962
13963 clear(visual);
13964
13965 return visual;
13966 };
13967
13968 /**
13969 * Creates a gfx container for shapes and connections
13970 *
13971 * The layout is as follows:
13972 *
13973 * <g class="djs-group">
13974 *
13975 * <!-- the gfx -->
13976 * <g class="djs-element djs-(shape|connection|frame)">
13977 * <g class="djs-visual">
13978 * <!-- the renderer draws in here -->
13979 * </g>
13980 *
13981 * <!-- extensions (overlays, click box, ...) goes here
13982 * </g>
13983 *
13984 * <!-- the gfx child nodes -->
13985 * <g class="djs-children"></g>
13986 * </g>
13987 *
13988 * @param {string} type the type of the element, i.e. shape | connection
13989 * @param {SVGElement} childrenGfx
13990 * @param {number} [parentIndex] position to create container in parent
13991 * @param {boolean} [isFrame] is frame element
13992 *
13993 * @return {SVGElement}
13994 */
13995 GraphicsFactory.prototype._createContainer = function(
13996 type, childrenGfx, parentIndex, isFrame
13997 ) {
13998 var outerGfx = create$1('g');
13999 classes$1(outerGfx).add('djs-group');
14000
14001 // insert node at position
14002 if (typeof parentIndex !== 'undefined') {
14003 prependTo(outerGfx, childrenGfx, childrenGfx.childNodes[parentIndex]);
14004 } else {
14005 append(childrenGfx, outerGfx);
14006 }
14007
14008 var gfx = create$1('g');
14009 classes$1(gfx).add('djs-element');
14010 classes$1(gfx).add('djs-' + type);
14011
14012 if (isFrame) {
14013 classes$1(gfx).add('djs-frame');
14014 }
14015
14016 append(outerGfx, gfx);
14017
14018 // create visual
14019 var visual = create$1('g');
14020 classes$1(visual).add('djs-visual');
14021
14022 append(gfx, visual);
14023
14024 return gfx;
14025 };
14026
14027 /**
14028 * Create a graphical element.
14029 *
14030 * @param { 'shape' | 'connection' | 'label' | 'root' } type The type of the element.
14031 * @param {ElementLike} element The element.
14032 * @param {number} [parentIndex] The index at which to add the graphical element to its parent's children.
14033 *
14034 * @return {SVGElement} The graphical element.
14035 */
14036 GraphicsFactory.prototype.create = function(type, element, parentIndex) {
14037 var childrenGfx = this._getChildrenContainer(element.parent);
14038 return this._createContainer(type, childrenGfx, parentIndex, isFrameElement(element));
14039 };
14040
14041 /**
14042 * Update the containments of the given elements.
14043 *
14044 * @param {ElementLike[]} elements The elements.
14045 */
14046 GraphicsFactory.prototype.updateContainments = function(elements) {
14047
14048 var self = this,
14049 elementRegistry = this._elementRegistry,
14050 parents;
14051
14052 parents = reduce(elements, function(map, e) {
14053
14054 if (e.parent) {
14055 map[e.parent.id] = e.parent;
14056 }
14057
14058 return map;
14059 }, {});
14060
14061 // update all parents of changed and reorganized their children
14062 // in the correct order (as indicated in our model)
14063 forEach$1(parents, function(parent) {
14064
14065 var children = parent.children;
14066
14067 if (!children) {
14068 return;
14069 }
14070
14071 var childrenGfx = self._getChildrenContainer(parent);
14072
14073 forEach$1(children.slice().reverse(), function(child) {
14074 var childGfx = elementRegistry.getGraphics(child);
14075
14076 prependTo(childGfx.parentNode, childrenGfx);
14077 });
14078 });
14079 };
14080
14081 /**
14082 * Draw a shape.
14083 *
14084 * @param {SVGElement} visual The graphical element.
14085 * @param {ShapeLike} element The shape.
14086 * @param {Object} attrs Optional attributes.
14087 *
14088 * @return {SVGElement}
14089 */
14090 GraphicsFactory.prototype.drawShape = function(visual, element, attrs = {}) {
14091 var eventBus = this._eventBus;
14092
14093 return eventBus.fire('render.shape', { gfx: visual, element, attrs });
14094 };
14095
14096 /**
14097 * Get the path of a shape.
14098 *
14099 * @param {ShapeLike} element The shape.
14100 *
14101 * @return {string} The path of the shape.
14102 */
14103 GraphicsFactory.prototype.getShapePath = function(element) {
14104 var eventBus = this._eventBus;
14105
14106 return eventBus.fire('render.getShapePath', element);
14107 };
14108
14109 /**
14110 * Draw a connection.
14111 *
14112 * @param {SVGElement} visual The graphical element.
14113 * @param {ConnectionLike} element The connection.
14114 * @param {Object} attrs Optional attributes.
14115 *
14116 * @return {SVGElement}
14117 */
14118 GraphicsFactory.prototype.drawConnection = function(visual, element, attrs = {}) {
14119 var eventBus = this._eventBus;
14120
14121 return eventBus.fire('render.connection', { gfx: visual, element, attrs });
14122 };
14123
14124 /**
14125 * Get the path of a connection.
14126 *
14127 * @param {ConnectionLike} connection The connection.
14128 *
14129 * @return {string} The path of the connection.
14130 */
14131 GraphicsFactory.prototype.getConnectionPath = function(connection) {
14132 var eventBus = this._eventBus;
14133
14134 return eventBus.fire('render.getConnectionPath', connection);
14135 };
14136
14137 /**
14138 * Update an elements graphical representation.
14139 *
14140 * @param {'shape'|'connection'} type
14141 * @param {ElementLike} element
14142 * @param {SVGElement} gfx
14143 */
14144 GraphicsFactory.prototype.update = function(type, element, gfx) {
14145
14146 // do NOT update root element
14147 if (!element.parent) {
14148 return;
14149 }
14150
14151 var visual = this._clear(gfx);
14152
14153 // redraw
14154 if (type === 'shape') {
14155 this.drawShape(visual, element);
14156
14157 // update positioning
14158 translate$1(gfx, element.x, element.y);
14159 } else if (type === 'connection') {
14160 this.drawConnection(visual, element);
14161 } else {
14162 throw new Error('unknown type: ' + type);
14163 }
14164
14165 if (element.hidden) {
14166 attr$1(gfx, 'display', 'none');
14167 } else {
14168 attr$1(gfx, 'display', 'block');
14169 }
14170 };
14171
14172 /**
14173 * Remove a graphical element.
14174 *
14175 * @param {ElementLike} element The element.
14176 */
14177 GraphicsFactory.prototype.remove = function(element) {
14178 var gfx = this._elementRegistry.getGraphics(element);
14179
14180 // remove
14181 remove$2(gfx.parentNode);
14182 };
14183
14184
14185 // helpers //////////
14186
14187 function prependTo(newNode, parentNode, siblingNode) {
14188 var node = siblingNode || parentNode.firstChild;
14189
14190 // do not prepend node to itself to prevent IE from crashing
14191 // https://github.com/bpmn-io/bpmn-js/issues/746
14192 if (newNode === node) {
14193 return;
14194 }
14195
14196 parentNode.insertBefore(newNode, node);
14197 }
14198
14199 /**
14200 * @type { import('didi').ModuleDeclaration }
14201 */
14202 var CoreModule = {
14203 __depends__: [ DrawModule ],
14204 __init__: [ 'canvas' ],
14205 canvas: [ 'type', Canvas ],
14206 elementRegistry: [ 'type', ElementRegistry ],
14207 elementFactory: [ 'type', ElementFactory ],
14208 eventBus: [ 'type', EventBus ],
14209 graphicsFactory: [ 'type', GraphicsFactory ]
14210 };
14211
14212 /**
14213 * @typedef {import('didi').InjectionContext} InjectionContext
14214 * @typedef {import('didi').LocalsMap} LocalsMap
14215 * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration
14216 *
14217 * @typedef { {
14218 * modules?: ModuleDeclaration[];
14219 * } & Record<string, any> } DiagramOptions
14220 */
14221
14222 /**
14223 * @template T
14224 * @typedef {import('didi').FactoryFunction<T>} FactoryFunction
14225 */
14226
14227 /**
14228 * @template T
14229 * @typedef {import('didi').ArrayFunc<T>} ArrayFunc
14230 */
14231
14232 /**
14233 * Bootstrap an injector from a list of modules, instantiating a number of default components
14234 *
14235 * @param {ModuleDeclaration[]} modules
14236 *
14237 * @return {Injector} a injector to use to access the components
14238 */
14239 function bootstrap(modules) {
14240 var injector = new Injector(modules);
14241
14242 injector.init();
14243
14244 return injector;
14245 }
14246
14247 /**
14248 * Creates an injector from passed options.
14249 *
14250 * @template ServiceMap
14251 * @param {DiagramOptions} [options]
14252 *
14253 * @return {Injector<ServiceMap>}
14254 */
14255 function createInjector(options) {
14256
14257 options = options || {};
14258
14259 /**
14260 * @type { ModuleDeclaration }
14261 */
14262 var configModule = {
14263 'config': [ 'value', options ]
14264 };
14265
14266 var modules = [ configModule, CoreModule ].concat(options.modules || []);
14267
14268 return bootstrap(modules);
14269 }
14270
14271
14272 /**
14273 * The main diagram-js entry point that bootstraps the diagram with the given
14274 * configuration.
14275 *
14276 * To register extensions with the diagram, pass them as Array<Module> to the constructor.
14277 *
14278 * @class
14279 * @constructor
14280 * @template [ServiceMap=null]
14281 *
14282 * @example Creating a plug-in that logs whenever a shape is added to the canvas.
14283 *
14284 * ```javascript
14285 * // plug-in implementation
14286 * function MyLoggingPlugin(eventBus) {
14287 * eventBus.on('shape.added', function(event) {
14288 * console.log('shape ', event.shape, ' was added to the diagram');
14289 * });
14290 * }
14291 *
14292 * // export as module
14293 * export default {
14294 * __init__: [ 'myLoggingPlugin' ],
14295 * myLoggingPlugin: [ 'type', MyLoggingPlugin ]
14296 * };
14297 * ```
14298 *
14299 * Use the plug-in in a Diagram instance:
14300 *
14301 * ```javascript
14302 * import MyLoggingModule from 'path-to-my-logging-plugin';
14303 *
14304 * var diagram = new Diagram({
14305 * modules: [
14306 * MyLoggingModule
14307 * ]
14308 * });
14309 *
14310 * diagram.invoke([ 'canvas', function(canvas) {
14311 * // add shape to drawing canvas
14312 * canvas.addShape({ x: 10, y: 10 });
14313 * });
14314 *
14315 * // 'shape ... was added to the diagram' logged to console
14316 * ```
14317 *
14318 * @param {DiagramOptions} [options]
14319 * @param {Injector<ServiceMap>} [injector] An (optional) injector to bootstrap the diagram with.
14320 */
14321 function Diagram(options, injector) {
14322
14323 /**
14324 * @type {Injector<ServiceMap>}
14325 */
14326 this._injector = injector || createInjector(options);
14327
14328 // init
14329
14330 /**
14331 * An event indicating that all plug-ins are loaded.
14332 *
14333 * Use this event to fire other events to interested plug-ins
14334 *
14335 * @memberOf Diagram
14336 *
14337 * @event diagram.init
14338 *
14339 * @example
14340 *
14341 * ```javascript
14342 * eventBus.on('diagram.init', function() {
14343 * eventBus.fire('my-custom-event', { foo: 'BAR' });
14344 * });
14345 * ```
14346 *
14347 * @type {Object}
14348 */
14349 this.get('eventBus').fire('diagram.init');
14350 }
14351
14352 /**
14353 * @overlord
14354 *
14355 * Resolves a diagram service.
14356 *
14357 * @template T
14358 *
14359 * @param {string} name The name of the service to get.
14360 *
14361 * @return {T}
14362 */
14363 /**
14364 * @overlord
14365 *
14366 * Resolves a diagram service.
14367 *
14368 * @template T
14369 *
14370 * @param {string} name The name of the service to get.
14371 * @param {true} strict If false, resolve missing services to null.
14372 *
14373 * @return {T}
14374 */
14375 /**
14376 * @overlord
14377 *
14378 * Resolves a diagram service.
14379 *
14380 * @template T
14381 *
14382 * @param {string} name The name of the service to get.
14383 * @param {boolean} strict If false, resolve missing services to null.
14384 *
14385 * @return {T|null}
14386 */
14387 /**
14388 * Resolves a diagram service.
14389 *
14390 * @template {keyof ServiceMap} Name
14391 *
14392 * @param {Name} name The name of the service to get.
14393 *
14394 * @return {ServiceMap[Name]}
14395 */
14396 Diagram.prototype.get = function(name, strict) {
14397 return this._injector.get(name, strict);
14398 };
14399
14400 /**
14401 * @overlord
14402 *
14403 * Invoke the given function, injecting dependencies. Return the result.
14404 *
14405 * @template T
14406 *
14407 * @param {FactoryFunction<T>} func
14408 * @param {InjectionContext} [context]
14409 * @param {LocalsMap} [locals]
14410 *
14411 * @return {T}
14412 */
14413 /**
14414 * Invoke the given function, injecting dependencies provided in
14415 * array notation. Return the result.
14416 *
14417 * @template T
14418 *
14419 * @param {ArrayFunc<T>} func function to be invoked
14420 * @param {InjectionContext} [context] context of the invocation
14421 * @param {LocalsMap} [locals] locals provided
14422 *
14423 * @return {T}
14424 */
14425 Diagram.prototype.invoke = function(func, context, locals) {
14426 return this._injector.invoke(func, context, locals);
14427 };
14428
14429 /**
14430 * Destroys the diagram
14431 */
14432 Diagram.prototype.destroy = function() {
14433 this.get('eventBus').fire('diagram.destroy');
14434 };
14435
14436 /**
14437 * Clear the diagram, removing all contents.
14438 */
14439 Diagram.prototype.clear = function() {
14440 this.get('eventBus').fire('diagram.clear');
14441 };
14442
14443 /**
14444 * Moddle base element.
14445 */
14446 function Base() { }
14447
14448 Base.prototype.get = function(name) {
14449 return this.$model.properties.get(this, name);
14450 };
14451
14452 Base.prototype.set = function(name, value) {
14453 this.$model.properties.set(this, name, value);
14454 };
14455
14456 /**
14457 * A model element factory.
14458 *
14459 * @param {Moddle} model
14460 * @param {Properties} properties
14461 */
14462 function Factory(model, properties) {
14463 this.model = model;
14464 this.properties = properties;
14465 }
14466
14467
14468 Factory.prototype.createType = function(descriptor) {
14469
14470 var model = this.model;
14471
14472 var props = this.properties,
14473 prototype = Object.create(Base.prototype);
14474
14475 // initialize default values
14476 forEach$1(descriptor.properties, function(p) {
14477 if (!p.isMany && p.default !== undefined) {
14478 prototype[p.name] = p.default;
14479 }
14480 });
14481
14482 props.defineModel(prototype, model);
14483 props.defineDescriptor(prototype, descriptor);
14484
14485 var name = descriptor.ns.name;
14486
14487 /**
14488 * The new type constructor
14489 */
14490 function ModdleElement(attrs) {
14491 props.define(this, '$type', { value: name, enumerable: true });
14492 props.define(this, '$attrs', { value: {} });
14493 props.define(this, '$parent', { writable: true });
14494
14495 forEach$1(attrs, bind$2(function(val, key) {
14496 this.set(key, val);
14497 }, this));
14498 }
14499
14500 ModdleElement.prototype = prototype;
14501
14502 ModdleElement.hasType = prototype.$instanceOf = this.model.hasType;
14503
14504 // static links
14505 props.defineModel(ModdleElement, model);
14506 props.defineDescriptor(ModdleElement, descriptor);
14507
14508 return ModdleElement;
14509 };
14510
14511 /**
14512 * Built-in moddle types
14513 */
14514 var BUILTINS = {
14515 String: true,
14516 Boolean: true,
14517 Integer: true,
14518 Real: true,
14519 Element: true
14520 };
14521
14522 /**
14523 * Converters for built in types from string representations
14524 */
14525 var TYPE_CONVERTERS = {
14526 String: function(s) { return s; },
14527 Boolean: function(s) { return s === 'true'; },
14528 Integer: function(s) { return parseInt(s, 10); },
14529 Real: function(s) { return parseFloat(s); }
14530 };
14531
14532 /**
14533 * Convert a type to its real representation
14534 */
14535 function coerceType(type, value) {
14536
14537 var converter = TYPE_CONVERTERS[type];
14538
14539 if (converter) {
14540 return converter(value);
14541 } else {
14542 return value;
14543 }
14544 }
14545
14546 /**
14547 * Return whether the given type is built-in
14548 */
14549 function isBuiltIn(type) {
14550 return !!BUILTINS[type];
14551 }
14552
14553 /**
14554 * Return whether the given type is simple
14555 */
14556 function isSimple(type) {
14557 return !!TYPE_CONVERTERS[type];
14558 }
14559
14560 /**
14561 * Parses a namespaced attribute name of the form (ns:)localName to an object,
14562 * given a default prefix to assume in case no explicit namespace is given.
14563 *
14564 * @param {String} name
14565 * @param {String} [defaultPrefix] the default prefix to take, if none is present.
14566 *
14567 * @return {Object} the parsed name
14568 */
14569 function parseName(name, defaultPrefix) {
14570 var parts = name.split(/:/),
14571 localName, prefix;
14572
14573 // no prefix (i.e. only local name)
14574 if (parts.length === 1) {
14575 localName = name;
14576 prefix = defaultPrefix;
14577 } else
14578
14579 // prefix + local name
14580 if (parts.length === 2) {
14581 localName = parts[1];
14582 prefix = parts[0];
14583 } else {
14584 throw new Error('expected <prefix:localName> or <localName>, got ' + name);
14585 }
14586
14587 name = (prefix ? prefix + ':' : '') + localName;
14588
14589 return {
14590 name: name,
14591 prefix: prefix,
14592 localName: localName
14593 };
14594 }
14595
14596 /**
14597 * A utility to build element descriptors.
14598 */
14599 function DescriptorBuilder(nameNs) {
14600 this.ns = nameNs;
14601 this.name = nameNs.name;
14602 this.allTypes = [];
14603 this.allTypesByName = {};
14604 this.properties = [];
14605 this.propertiesByName = {};
14606 }
14607
14608
14609 DescriptorBuilder.prototype.build = function() {
14610 return pick(this, [
14611 'ns',
14612 'name',
14613 'allTypes',
14614 'allTypesByName',
14615 'properties',
14616 'propertiesByName',
14617 'bodyProperty',
14618 'idProperty'
14619 ]);
14620 };
14621
14622 /**
14623 * Add property at given index.
14624 *
14625 * @param {Object} p
14626 * @param {Number} [idx]
14627 * @param {Boolean} [validate=true]
14628 */
14629 DescriptorBuilder.prototype.addProperty = function(p, idx, validate) {
14630
14631 if (typeof idx === 'boolean') {
14632 validate = idx;
14633 idx = undefined;
14634 }
14635
14636 this.addNamedProperty(p, validate !== false);
14637
14638 var properties = this.properties;
14639
14640 if (idx !== undefined) {
14641 properties.splice(idx, 0, p);
14642 } else {
14643 properties.push(p);
14644 }
14645 };
14646
14647
14648 DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty, replace) {
14649 var oldNameNs = oldProperty.ns;
14650
14651 var props = this.properties,
14652 propertiesByName = this.propertiesByName,
14653 rename = oldProperty.name !== newProperty.name;
14654
14655 if (oldProperty.isId) {
14656 if (!newProperty.isId) {
14657 throw new Error(
14658 'property <' + newProperty.ns.name + '> must be id property ' +
14659 'to refine <' + oldProperty.ns.name + '>');
14660 }
14661
14662 this.setIdProperty(newProperty, false);
14663 }
14664
14665 if (oldProperty.isBody) {
14666
14667 if (!newProperty.isBody) {
14668 throw new Error(
14669 'property <' + newProperty.ns.name + '> must be body property ' +
14670 'to refine <' + oldProperty.ns.name + '>');
14671 }
14672
14673 // TODO: Check compatibility
14674 this.setBodyProperty(newProperty, false);
14675 }
14676
14677 // validate existence and get location of old property
14678 var idx = props.indexOf(oldProperty);
14679 if (idx === -1) {
14680 throw new Error('property <' + oldNameNs.name + '> not found in property list');
14681 }
14682
14683 // remove old property
14684 props.splice(idx, 1);
14685
14686 // replacing the named property is intentional
14687 //
14688 // * validate only if this is a "rename" operation
14689 // * add at specific index unless we "replace"
14690 //
14691 this.addProperty(newProperty, replace ? undefined : idx, rename);
14692
14693 // make new property available under old name
14694 propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
14695 };
14696
14697
14698 DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, replace) {
14699
14700 var nsPrefix = p.ns.prefix;
14701 var parts = targetPropertyName.split('#');
14702
14703 var name = parseName(parts[0], nsPrefix);
14704 var attrName = parseName(parts[1], name.prefix).name;
14705
14706 var redefinedProperty = this.propertiesByName[attrName];
14707 if (!redefinedProperty) {
14708 throw new Error('refined property <' + attrName + '> not found');
14709 } else {
14710 this.replaceProperty(redefinedProperty, p, replace);
14711 }
14712
14713 delete p.redefines;
14714 };
14715
14716 DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
14717 var ns = p.ns,
14718 propsByName = this.propertiesByName;
14719
14720 if (validate) {
14721 this.assertNotDefined(p, ns.name);
14722 this.assertNotDefined(p, ns.localName);
14723 }
14724
14725 propsByName[ns.name] = propsByName[ns.localName] = p;
14726 };
14727
14728 DescriptorBuilder.prototype.removeNamedProperty = function(p) {
14729 var ns = p.ns,
14730 propsByName = this.propertiesByName;
14731
14732 delete propsByName[ns.name];
14733 delete propsByName[ns.localName];
14734 };
14735
14736 DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
14737
14738 if (validate && this.bodyProperty) {
14739 throw new Error(
14740 'body property defined multiple times ' +
14741 '(<' + this.bodyProperty.ns.name + '>, <' + p.ns.name + '>)');
14742 }
14743
14744 this.bodyProperty = p;
14745 };
14746
14747 DescriptorBuilder.prototype.setIdProperty = function(p, validate) {
14748
14749 if (validate && this.idProperty) {
14750 throw new Error(
14751 'id property defined multiple times ' +
14752 '(<' + this.idProperty.ns.name + '>, <' + p.ns.name + '>)');
14753 }
14754
14755 this.idProperty = p;
14756 };
14757
14758 DescriptorBuilder.prototype.assertNotTrait = function(typeDescriptor) {
14759
14760 const _extends = typeDescriptor.extends || [];
14761
14762 if (_extends.length) {
14763 throw new Error(
14764 `cannot create <${ typeDescriptor.name }> extending <${ typeDescriptor.extends }>`
14765 );
14766 }
14767 };
14768
14769 DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
14770 var propertyName = p.name,
14771 definedProperty = this.propertiesByName[propertyName];
14772
14773 if (definedProperty) {
14774 throw new Error(
14775 'property <' + propertyName + '> already defined; ' +
14776 'override of <' + definedProperty.definedBy.ns.name + '#' + definedProperty.ns.name + '> by ' +
14777 '<' + p.definedBy.ns.name + '#' + p.ns.name + '> not allowed without redefines');
14778 }
14779 };
14780
14781 DescriptorBuilder.prototype.hasProperty = function(name) {
14782 return this.propertiesByName[name];
14783 };
14784
14785 DescriptorBuilder.prototype.addTrait = function(t, inherited) {
14786
14787 if (inherited) {
14788 this.assertNotTrait(t);
14789 }
14790
14791 var typesByName = this.allTypesByName,
14792 types = this.allTypes;
14793
14794 var typeName = t.name;
14795
14796 if (typeName in typesByName) {
14797 return;
14798 }
14799
14800 forEach$1(t.properties, bind$2(function(p) {
14801
14802 // clone property to allow extensions
14803 p = assign$1({}, p, {
14804 name: p.ns.localName,
14805 inherited: inherited
14806 });
14807
14808 Object.defineProperty(p, 'definedBy', {
14809 value: t
14810 });
14811
14812 var replaces = p.replaces,
14813 redefines = p.redefines;
14814
14815 // add replace/redefine support
14816 if (replaces || redefines) {
14817 this.redefineProperty(p, replaces || redefines, replaces);
14818 } else {
14819 if (p.isBody) {
14820 this.setBodyProperty(p);
14821 }
14822 if (p.isId) {
14823 this.setIdProperty(p);
14824 }
14825 this.addProperty(p);
14826 }
14827 }, this));
14828
14829 types.push(t);
14830 typesByName[typeName] = t;
14831 };
14832
14833 /**
14834 * A registry of Moddle packages.
14835 *
14836 * @param {Array<Package>} packages
14837 * @param {Properties} properties
14838 */
14839 function Registry(packages, properties) {
14840 this.packageMap = {};
14841 this.typeMap = {};
14842
14843 this.packages = [];
14844
14845 this.properties = properties;
14846
14847 forEach$1(packages, bind$2(this.registerPackage, this));
14848 }
14849
14850
14851 Registry.prototype.getPackage = function(uriOrPrefix) {
14852 return this.packageMap[uriOrPrefix];
14853 };
14854
14855 Registry.prototype.getPackages = function() {
14856 return this.packages;
14857 };
14858
14859
14860 Registry.prototype.registerPackage = function(pkg) {
14861
14862 // copy package
14863 pkg = assign$1({}, pkg);
14864
14865 var pkgMap = this.packageMap;
14866
14867 ensureAvailable(pkgMap, pkg, 'prefix');
14868 ensureAvailable(pkgMap, pkg, 'uri');
14869
14870 // register types
14871 forEach$1(pkg.types, bind$2(function(descriptor) {
14872 this.registerType(descriptor, pkg);
14873 }, this));
14874
14875 pkgMap[pkg.uri] = pkgMap[pkg.prefix] = pkg;
14876 this.packages.push(pkg);
14877 };
14878
14879
14880 /**
14881 * Register a type from a specific package with us
14882 */
14883 Registry.prototype.registerType = function(type, pkg) {
14884
14885 type = assign$1({}, type, {
14886 superClass: (type.superClass || []).slice(),
14887 extends: (type.extends || []).slice(),
14888 properties: (type.properties || []).slice(),
14889 meta: assign$1((type.meta || {}))
14890 });
14891
14892 var ns = parseName(type.name, pkg.prefix),
14893 name = ns.name,
14894 propertiesByName = {};
14895
14896 // parse properties
14897 forEach$1(type.properties, bind$2(function(p) {
14898
14899 // namespace property names
14900 var propertyNs = parseName(p.name, ns.prefix),
14901 propertyName = propertyNs.name;
14902
14903 // namespace property types
14904 if (!isBuiltIn(p.type)) {
14905 p.type = parseName(p.type, propertyNs.prefix).name;
14906 }
14907
14908 assign$1(p, {
14909 ns: propertyNs,
14910 name: propertyName
14911 });
14912
14913 propertiesByName[propertyName] = p;
14914 }, this));
14915
14916 // update ns + name
14917 assign$1(type, {
14918 ns: ns,
14919 name: name,
14920 propertiesByName: propertiesByName
14921 });
14922
14923 forEach$1(type.extends, bind$2(function(extendsName) {
14924 var extendsNameNs = parseName(extendsName, ns.prefix);
14925
14926 var extended = this.typeMap[extendsNameNs.name];
14927
14928 extended.traits = extended.traits || [];
14929 extended.traits.push(name);
14930 }, this));
14931
14932 // link to package
14933 this.definePackage(type, pkg);
14934
14935 // register
14936 this.typeMap[name] = type;
14937 };
14938
14939
14940 /**
14941 * Traverse the type hierarchy from bottom to top,
14942 * calling iterator with (type, inherited) for all elements in
14943 * the inheritance chain.
14944 *
14945 * @param {Object} nsName
14946 * @param {Function} iterator
14947 * @param {Boolean} [trait=false]
14948 */
14949 Registry.prototype.mapTypes = function(nsName, iterator, trait) {
14950
14951 var type = isBuiltIn(nsName.name) ? { name: nsName.name } : this.typeMap[nsName.name];
14952
14953 var self = this;
14954
14955 /**
14956 * Traverse the selected super type or trait
14957 *
14958 * @param {String} cls
14959 * @param {Boolean} [trait=false]
14960 */
14961 function traverse(cls, trait) {
14962 var parentNs = parseName(cls, isBuiltIn(cls) ? '' : nsName.prefix);
14963 self.mapTypes(parentNs, iterator, trait);
14964 }
14965
14966 /**
14967 * Traverse the selected trait.
14968 *
14969 * @param {String} cls
14970 */
14971 function traverseTrait(cls) {
14972 return traverse(cls, true);
14973 }
14974
14975 /**
14976 * Traverse the selected super type
14977 *
14978 * @param {String} cls
14979 */
14980 function traverseSuper(cls) {
14981 return traverse(cls, false);
14982 }
14983
14984 if (!type) {
14985 throw new Error('unknown type <' + nsName.name + '>');
14986 }
14987
14988 forEach$1(type.superClass, trait ? traverseTrait : traverseSuper);
14989
14990 // call iterator with (type, inherited=!trait)
14991 iterator(type, !trait);
14992
14993 forEach$1(type.traits, traverseTrait);
14994 };
14995
14996
14997 /**
14998 * Returns the effective descriptor for a type.
14999 *
15000 * @param {String} type the namespaced name (ns:localName) of the type
15001 *
15002 * @return {Descriptor} the resulting effective descriptor
15003 */
15004 Registry.prototype.getEffectiveDescriptor = function(name) {
15005
15006 var nsName = parseName(name);
15007
15008 var builder = new DescriptorBuilder(nsName);
15009
15010 this.mapTypes(nsName, function(type, inherited) {
15011 builder.addTrait(type, inherited);
15012 });
15013
15014 var descriptor = builder.build();
15015
15016 // define package link
15017 this.definePackage(descriptor, descriptor.allTypes[descriptor.allTypes.length - 1].$pkg);
15018
15019 return descriptor;
15020 };
15021
15022
15023 Registry.prototype.definePackage = function(target, pkg) {
15024 this.properties.define(target, '$pkg', { value: pkg });
15025 };
15026
15027
15028
15029 // helpers ////////////////////////////
15030
15031 function ensureAvailable(packageMap, pkg, identifierKey) {
15032
15033 var value = pkg[identifierKey];
15034
15035 if (value in packageMap) {
15036 throw new Error('package with ' + identifierKey + ' <' + value + '> already defined');
15037 }
15038 }
15039
15040 /**
15041 * A utility that gets and sets properties of model elements.
15042 *
15043 * @param {Model} model
15044 */
15045 function Properties(model) {
15046 this.model = model;
15047 }
15048
15049
15050 /**
15051 * Sets a named property on the target element.
15052 * If the value is undefined, the property gets deleted.
15053 *
15054 * @param {Object} target
15055 * @param {String} name
15056 * @param {Object} value
15057 */
15058 Properties.prototype.set = function(target, name, value) {
15059
15060 if (!isString(name) || !name.length) {
15061 throw new TypeError('property name must be a non-empty string');
15062 }
15063
15064 var property = this.getProperty(target, name);
15065
15066 var propertyName = property && property.name;
15067
15068 if (isUndefined(value)) {
15069
15070 // unset the property, if the specified value is undefined;
15071 // delete from $attrs (for extensions) or the target itself
15072 if (property) {
15073 delete target[propertyName];
15074 } else {
15075 delete target.$attrs[stripGlobal(name)];
15076 }
15077 } else {
15078
15079 // set the property, defining well defined properties on the fly
15080 // or simply updating them in target.$attrs (for extensions)
15081 if (property) {
15082 if (propertyName in target) {
15083 target[propertyName] = value;
15084 } else {
15085 defineProperty(target, property, value);
15086 }
15087 } else {
15088 target.$attrs[stripGlobal(name)] = value;
15089 }
15090 }
15091 };
15092
15093 /**
15094 * Returns the named property of the given element
15095 *
15096 * @param {Object} target
15097 * @param {String} name
15098 *
15099 * @return {Object}
15100 */
15101 Properties.prototype.get = function(target, name) {
15102
15103 var property = this.getProperty(target, name);
15104
15105 if (!property) {
15106 return target.$attrs[stripGlobal(name)];
15107 }
15108
15109 var propertyName = property.name;
15110
15111 // check if access to collection property and lazily initialize it
15112 if (!target[propertyName] && property.isMany) {
15113 defineProperty(target, property, []);
15114 }
15115
15116 return target[propertyName];
15117 };
15118
15119
15120 /**
15121 * Define a property on the target element
15122 *
15123 * @param {Object} target
15124 * @param {String} name
15125 * @param {Object} options
15126 */
15127 Properties.prototype.define = function(target, name, options) {
15128
15129 if (!options.writable) {
15130
15131 var value = options.value;
15132
15133 // use getters for read-only variables to support ES6 proxies
15134 // cf. https://github.com/bpmn-io/internal-docs/issues/386
15135 options = assign$1({}, options, {
15136 get: function() { return value; }
15137 });
15138
15139 delete options.value;
15140 }
15141
15142 Object.defineProperty(target, name, options);
15143 };
15144
15145
15146 /**
15147 * Define the descriptor for an element
15148 */
15149 Properties.prototype.defineDescriptor = function(target, descriptor) {
15150 this.define(target, '$descriptor', { value: descriptor });
15151 };
15152
15153 /**
15154 * Define the model for an element
15155 */
15156 Properties.prototype.defineModel = function(target, model) {
15157 this.define(target, '$model', { value: model });
15158 };
15159
15160 /**
15161 * Return property with the given name on the element.
15162 *
15163 * @param {any} target
15164 * @param {string} name
15165 *
15166 * @return {object | null} property
15167 */
15168 Properties.prototype.getProperty = function(target, name) {
15169
15170 var model = this.model;
15171
15172 var property = model.getPropertyDescriptor(target, name);
15173
15174 if (property) {
15175 return property;
15176 }
15177
15178 if (name.includes(':')) {
15179 return null;
15180 }
15181
15182 const strict = model.config.strict;
15183
15184 if (typeof strict !== 'undefined') {
15185 const error = new TypeError(`unknown property <${ name }> on <${ target.$type }>`);
15186
15187 if (strict) {
15188 throw error;
15189 } else {
15190
15191 // eslint-disable-next-line no-undef
15192 typeof console !== 'undefined' && console.warn(error);
15193 }
15194 }
15195
15196 return null;
15197 };
15198
15199 function isUndefined(val) {
15200 return typeof val === 'undefined';
15201 }
15202
15203 function defineProperty(target, property, value) {
15204 Object.defineProperty(target, property.name, {
15205 enumerable: !property.isReference,
15206 writable: true,
15207 value: value,
15208 configurable: true
15209 });
15210 }
15211
15212 function stripGlobal(name) {
15213 return name.replace(/^:/, '');
15214 }
15215
15216 // Moddle implementation /////////////////////////////////////////////////
15217
15218 /**
15219 * @class Moddle
15220 *
15221 * A model that can be used to create elements of a specific type.
15222 *
15223 * @example
15224 *
15225 * var Moddle = require('moddle');
15226 *
15227 * var pkg = {
15228 * name: 'mypackage',
15229 * prefix: 'my',
15230 * types: [
15231 * { name: 'Root' }
15232 * ]
15233 * };
15234 *
15235 * var moddle = new Moddle([pkg]);
15236 *
15237 * @param {Array<Package>} packages the packages to contain
15238 *
15239 * @param { { strict?: boolean } } [config] moddle configuration
15240 */
15241 function Moddle(packages, config = {}) {
15242
15243 this.properties = new Properties(this);
15244
15245 this.factory = new Factory(this, this.properties);
15246 this.registry = new Registry(packages, this.properties);
15247
15248 this.typeCache = {};
15249
15250 this.config = config;
15251 }
15252
15253
15254 /**
15255 * Create an instance of the specified type.
15256 *
15257 * @method Moddle#create
15258 *
15259 * @example
15260 *
15261 * var foo = moddle.create('my:Foo');
15262 * var bar = moddle.create('my:Bar', { id: 'BAR_1' });
15263 *
15264 * @param {String|Object} descriptor the type descriptor or name know to the model
15265 * @param {Object} attrs a number of attributes to initialize the model instance with
15266 * @return {Object} model instance
15267 */
15268 Moddle.prototype.create = function(descriptor, attrs) {
15269 var Type = this.getType(descriptor);
15270
15271 if (!Type) {
15272 throw new Error('unknown type <' + descriptor + '>');
15273 }
15274
15275 return new Type(attrs);
15276 };
15277
15278
15279 /**
15280 * Returns the type representing a given descriptor
15281 *
15282 * @method Moddle#getType
15283 *
15284 * @example
15285 *
15286 * var Foo = moddle.getType('my:Foo');
15287 * var foo = new Foo({ 'id' : 'FOO_1' });
15288 *
15289 * @param {String|Object} descriptor the type descriptor or name know to the model
15290 * @return {Object} the type representing the descriptor
15291 */
15292 Moddle.prototype.getType = function(descriptor) {
15293
15294 var cache = this.typeCache;
15295
15296 var name = isString(descriptor) ? descriptor : descriptor.ns.name;
15297
15298 var type = cache[name];
15299
15300 if (!type) {
15301 descriptor = this.registry.getEffectiveDescriptor(name);
15302 type = cache[name] = this.factory.createType(descriptor);
15303 }
15304
15305 return type;
15306 };
15307
15308
15309 /**
15310 * Creates an any-element type to be used within model instances.
15311 *
15312 * This can be used to create custom elements that lie outside the meta-model.
15313 * The created element contains all the meta-data required to serialize it
15314 * as part of meta-model elements.
15315 *
15316 * @method Moddle#createAny
15317 *
15318 * @example
15319 *
15320 * var foo = moddle.createAny('vendor:Foo', 'http://vendor', {
15321 * value: 'bar'
15322 * });
15323 *
15324 * var container = moddle.create('my:Container', 'http://my', {
15325 * any: [ foo ]
15326 * });
15327 *
15328 * // go ahead and serialize the stuff
15329 *
15330 *
15331 * @param {String} name the name of the element
15332 * @param {String} nsUri the namespace uri of the element
15333 * @param {Object} [properties] a map of properties to initialize the instance with
15334 * @return {Object} the any type instance
15335 */
15336 Moddle.prototype.createAny = function(name, nsUri, properties) {
15337
15338 var nameNs = parseName(name);
15339
15340 var element = {
15341 $type: name,
15342 $instanceOf: function(type) {
15343 return type === this.$type;
15344 },
15345 get: function(key) {
15346 return this[key];
15347 },
15348 set: function(key, value) {
15349 set$1(this, [ key ], value);
15350 }
15351 };
15352
15353 var descriptor = {
15354 name: name,
15355 isGeneric: true,
15356 ns: {
15357 prefix: nameNs.prefix,
15358 localName: nameNs.localName,
15359 uri: nsUri
15360 }
15361 };
15362
15363 this.properties.defineDescriptor(element, descriptor);
15364 this.properties.defineModel(element, this);
15365 this.properties.define(element, 'get', { enumerable: false, writable: true });
15366 this.properties.define(element, 'set', { enumerable: false, writable: true });
15367 this.properties.define(element, '$parent', { enumerable: false, writable: true });
15368 this.properties.define(element, '$instanceOf', { enumerable: false, writable: true });
15369
15370 forEach$1(properties, function(a, key) {
15371 if (isObject(a) && a.value !== undefined) {
15372 element[a.name] = a.value;
15373 } else {
15374 element[key] = a;
15375 }
15376 });
15377
15378 return element;
15379 };
15380
15381 /**
15382 * Returns a registered package by uri or prefix
15383 *
15384 * @return {Object} the package
15385 */
15386 Moddle.prototype.getPackage = function(uriOrPrefix) {
15387 return this.registry.getPackage(uriOrPrefix);
15388 };
15389
15390 /**
15391 * Returns a snapshot of all known packages
15392 *
15393 * @return {Object} the package
15394 */
15395 Moddle.prototype.getPackages = function() {
15396 return this.registry.getPackages();
15397 };
15398
15399 /**
15400 * Returns the descriptor for an element
15401 */
15402 Moddle.prototype.getElementDescriptor = function(element) {
15403 return element.$descriptor;
15404 };
15405
15406 /**
15407 * Returns true if the given descriptor or instance
15408 * represents the given type.
15409 *
15410 * May be applied to this, if element is omitted.
15411 */
15412 Moddle.prototype.hasType = function(element, type) {
15413 if (type === undefined) {
15414 type = element;
15415 element = this;
15416 }
15417
15418 var descriptor = element.$model.getElementDescriptor(element);
15419
15420 return (type in descriptor.allTypesByName);
15421 };
15422
15423 /**
15424 * Returns the descriptor of an elements named property
15425 */
15426 Moddle.prototype.getPropertyDescriptor = function(element, property) {
15427 return this.getElementDescriptor(element).propertiesByName[property];
15428 };
15429
15430 /**
15431 * Returns a mapped type's descriptor
15432 */
15433 Moddle.prototype.getTypeDescriptor = function(type) {
15434 return this.registry.typeMap[type];
15435 };
15436
15437 var fromCharCode = String.fromCharCode;
15438
15439 var hasOwnProperty = Object.prototype.hasOwnProperty;
15440
15441 var ENTITY_PATTERN = /&#(\d+);|&#x([0-9a-f]+);|&(\w+);/ig;
15442
15443 var ENTITY_MAPPING = {
15444 'amp': '&',
15445 'apos': '\'',
15446 'gt': '>',
15447 'lt': '<',
15448 'quot': '"'
15449 };
15450
15451 // map UPPERCASE variants of supported special chars
15452 Object.keys(ENTITY_MAPPING).forEach(function(k) {
15453 ENTITY_MAPPING[k.toUpperCase()] = ENTITY_MAPPING[k];
15454 });
15455
15456
15457 function replaceEntities(_, d, x, z) {
15458
15459 // reserved names, i.e. &nbsp;
15460 if (z) {
15461 if (hasOwnProperty.call(ENTITY_MAPPING, z)) {
15462 return ENTITY_MAPPING[z];
15463 } else {
15464
15465 // fall back to original value
15466 return '&' + z + ';';
15467 }
15468 }
15469
15470 // decimal encoded char
15471 if (d) {
15472 return fromCharCode(d);
15473 }
15474
15475 // hex encoded char
15476 return fromCharCode(parseInt(x, 16));
15477 }
15478
15479
15480 /**
15481 * A basic entity decoder that can decode a minimal
15482 * sub-set of reserved names (&amp;) as well as
15483 * hex (&#xaaf;) and decimal (&#1231;) encoded characters.
15484 *
15485 * @param {string} str
15486 *
15487 * @return {string} decoded string
15488 */
15489 function decodeEntities(s) {
15490 if (s.length > 3 && s.indexOf('&') !== -1) {
15491 return s.replace(ENTITY_PATTERN, replaceEntities);
15492 }
15493
15494 return s;
15495 }
15496
15497 var XSI_URI = 'http://www.w3.org/2001/XMLSchema-instance';
15498 var XSI_PREFIX = 'xsi';
15499 var XSI_TYPE$1 = 'xsi:type';
15500
15501 var NON_WHITESPACE_OUTSIDE_ROOT_NODE = 'non-whitespace outside of root node';
15502
15503 function error$1(msg) {
15504 return new Error(msg);
15505 }
15506
15507 function missingNamespaceForPrefix(prefix) {
15508 return 'missing namespace for prefix <' + prefix + '>';
15509 }
15510
15511 function getter(getFn) {
15512 return {
15513 'get': getFn,
15514 'enumerable': true
15515 };
15516 }
15517
15518 function cloneNsMatrix(nsMatrix) {
15519 var clone = {}, key;
15520 for (key in nsMatrix) {
15521 clone[key] = nsMatrix[key];
15522 }
15523 return clone;
15524 }
15525
15526 function uriPrefix(prefix) {
15527 return prefix + '$uri';
15528 }
15529
15530 function buildNsMatrix(nsUriToPrefix) {
15531 var nsMatrix = {},
15532 uri,
15533 prefix;
15534
15535 for (uri in nsUriToPrefix) {
15536 prefix = nsUriToPrefix[uri];
15537 nsMatrix[prefix] = prefix;
15538 nsMatrix[uriPrefix(prefix)] = uri;
15539 }
15540
15541 return nsMatrix;
15542 }
15543
15544 function noopGetContext() {
15545 return { 'line': 0, 'column': 0 };
15546 }
15547
15548 function throwFunc(err) {
15549 throw err;
15550 }
15551
15552 /**
15553 * Creates a new parser with the given options.
15554 *
15555 * @constructor
15556 *
15557 * @param {!Object<string, ?>=} options
15558 */
15559 function Parser(options) {
15560
15561 if (!this) {
15562 return new Parser(options);
15563 }
15564
15565 var proxy = options && options['proxy'];
15566
15567 var onText,
15568 onOpenTag,
15569 onCloseTag,
15570 onCDATA,
15571 onError = throwFunc,
15572 onWarning,
15573 onComment,
15574 onQuestion,
15575 onAttention;
15576
15577 var getContext = noopGetContext;
15578
15579 /**
15580 * Do we need to parse the current elements attributes for namespaces?
15581 *
15582 * @type {boolean}
15583 */
15584 var maybeNS = false;
15585
15586 /**
15587 * Do we process namespaces at all?
15588 *
15589 * @type {boolean}
15590 */
15591 var isNamespace = false;
15592
15593 /**
15594 * The caught error returned on parse end
15595 *
15596 * @type {Error}
15597 */
15598 var returnError = null;
15599
15600 /**
15601 * Should we stop parsing?
15602 *
15603 * @type {boolean}
15604 */
15605 var parseStop = false;
15606
15607 /**
15608 * A map of { uri: prefix } used by the parser.
15609 *
15610 * This map will ensure we can normalize prefixes during processing;
15611 * for each uri, only one prefix will be exposed to the handlers.
15612 *
15613 * @type {!Object<string, string>}}
15614 */
15615 var nsUriToPrefix;
15616
15617 /**
15618 * Handle parse error.
15619 *
15620 * @param {string|Error} err
15621 */
15622 function handleError(err) {
15623 if (!(err instanceof Error)) {
15624 err = error$1(err);
15625 }
15626
15627 returnError = err;
15628
15629 onError(err, getContext);
15630 }
15631
15632 /**
15633 * Handle parse error.
15634 *
15635 * @param {string|Error} err
15636 */
15637 function handleWarning(err) {
15638
15639 if (!onWarning) {
15640 return;
15641 }
15642
15643 if (!(err instanceof Error)) {
15644 err = error$1(err);
15645 }
15646
15647 onWarning(err, getContext);
15648 }
15649
15650 /**
15651 * Register parse listener.
15652 *
15653 * @param {string} name
15654 * @param {Function} cb
15655 *
15656 * @return {Parser}
15657 */
15658 this['on'] = function(name, cb) {
15659
15660 if (typeof cb !== 'function') {
15661 throw error$1('required args <name, cb>');
15662 }
15663
15664 switch (name) {
15665 case 'openTag': onOpenTag = cb; break;
15666 case 'text': onText = cb; break;
15667 case 'closeTag': onCloseTag = cb; break;
15668 case 'error': onError = cb; break;
15669 case 'warn': onWarning = cb; break;
15670 case 'cdata': onCDATA = cb; break;
15671 case 'attention': onAttention = cb; break; // <!XXXXX zzzz="eeee">
15672 case 'question': onQuestion = cb; break; // <? .... ?>
15673 case 'comment': onComment = cb; break;
15674 default:
15675 throw error$1('unsupported event: ' + name);
15676 }
15677
15678 return this;
15679 };
15680
15681 /**
15682 * Set the namespace to prefix mapping.
15683 *
15684 * @example
15685 *
15686 * parser.ns({
15687 * 'http://foo': 'foo',
15688 * 'http://bar': 'bar'
15689 * });
15690 *
15691 * @param {!Object<string, string>} nsMap
15692 *
15693 * @return {Parser}
15694 */
15695 this['ns'] = function(nsMap) {
15696
15697 if (typeof nsMap === 'undefined') {
15698 nsMap = {};
15699 }
15700
15701 if (typeof nsMap !== 'object') {
15702 throw error$1('required args <nsMap={}>');
15703 }
15704
15705 var _nsUriToPrefix = {}, k;
15706
15707 for (k in nsMap) {
15708 _nsUriToPrefix[k] = nsMap[k];
15709 }
15710
15711 // FORCE default mapping for schema instance
15712 _nsUriToPrefix[XSI_URI] = XSI_PREFIX;
15713
15714 isNamespace = true;
15715 nsUriToPrefix = _nsUriToPrefix;
15716
15717 return this;
15718 };
15719
15720 /**
15721 * Parse xml string.
15722 *
15723 * @param {string} xml
15724 *
15725 * @return {Error} returnError, if not thrown
15726 */
15727 this['parse'] = function(xml) {
15728 if (typeof xml !== 'string') {
15729 throw error$1('required args <xml=string>');
15730 }
15731
15732 returnError = null;
15733
15734 parse(xml);
15735
15736 getContext = noopGetContext;
15737 parseStop = false;
15738
15739 return returnError;
15740 };
15741
15742 /**
15743 * Stop parsing.
15744 */
15745 this['stop'] = function() {
15746 parseStop = true;
15747 };
15748
15749 /**
15750 * Parse string, invoking configured listeners on element.
15751 *
15752 * @param {string} xml
15753 */
15754 function parse(xml) {
15755 var nsMatrixStack = isNamespace ? [] : null,
15756 nsMatrix = isNamespace ? buildNsMatrix(nsUriToPrefix) : null,
15757 _nsMatrix,
15758 nodeStack = [],
15759 anonymousNsCount = 0,
15760 tagStart = false,
15761 tagEnd = false,
15762 i = 0, j = 0,
15763 x, y, q, w, v,
15764 xmlns,
15765 elementName,
15766 _elementName,
15767 elementProxy
15768 ;
15769
15770 var attrsString = '',
15771 attrsStart = 0,
15772 cachedAttrs // false = parsed with errors, null = needs parsing
15773 ;
15774
15775 /**
15776 * Parse attributes on demand and returns the parsed attributes.
15777 *
15778 * Return semantics: (1) `false` on attribute parse error,
15779 * (2) object hash on extracted attrs.
15780 *
15781 * @return {boolean|Object}
15782 */
15783 function getAttrs() {
15784 if (cachedAttrs !== null) {
15785 return cachedAttrs;
15786 }
15787
15788 var nsUri,
15789 nsUriPrefix,
15790 nsName,
15791 defaultAlias = isNamespace && nsMatrix['xmlns'],
15792 attrList = isNamespace && maybeNS ? [] : null,
15793 i = attrsStart,
15794 s = attrsString,
15795 l = s.length,
15796 hasNewMatrix,
15797 newalias,
15798 value,
15799 alias,
15800 name,
15801 attrs = {},
15802 seenAttrs = {},
15803 skipAttr,
15804 w,
15805 j;
15806
15807 parseAttr:
15808 for (; i < l; i++) {
15809 skipAttr = false;
15810 w = s.charCodeAt(i);
15811
15812 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE={ \f\n\r\t\v}
15813 continue;
15814 }
15815
15816 // wait for non whitespace character
15817 if (w < 65 || w > 122 || (w > 90 && w < 97)) {
15818 if (w !== 95 && w !== 58) { // char 95"_" 58":"
15819 handleWarning('illegal first char attribute name');
15820 skipAttr = true;
15821 }
15822 }
15823
15824 // parse attribute name
15825 for (j = i + 1; j < l; j++) {
15826 w = s.charCodeAt(j);
15827
15828 if (
15829 w > 96 && w < 123 ||
15830 w > 64 && w < 91 ||
15831 w > 47 && w < 59 ||
15832 w === 46 || // '.'
15833 w === 45 || // '-'
15834 w === 95 // '_'
15835 ) {
15836 continue;
15837 }
15838
15839 // unexpected whitespace
15840 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15841 handleWarning('missing attribute value');
15842 i = j;
15843
15844 continue parseAttr;
15845 }
15846
15847 // expected "="
15848 if (w === 61) { // "=" == 61
15849 break;
15850 }
15851
15852 handleWarning('illegal attribute name char');
15853 skipAttr = true;
15854 }
15855
15856 name = s.substring(i, j);
15857
15858 if (name === 'xmlns:xmlns') {
15859 handleWarning('illegal declaration of xmlns');
15860 skipAttr = true;
15861 }
15862
15863 w = s.charCodeAt(j + 1);
15864
15865 if (w === 34) { // '"'
15866 j = s.indexOf('"', i = j + 2);
15867
15868 if (j === -1) {
15869 j = s.indexOf('\'', i);
15870
15871 if (j !== -1) {
15872 handleWarning('attribute value quote missmatch');
15873 skipAttr = true;
15874 }
15875 }
15876
15877 } else if (w === 39) { // "'"
15878 j = s.indexOf('\'', i = j + 2);
15879
15880 if (j === -1) {
15881 j = s.indexOf('"', i);
15882
15883 if (j !== -1) {
15884 handleWarning('attribute value quote missmatch');
15885 skipAttr = true;
15886 }
15887 }
15888
15889 } else {
15890 handleWarning('missing attribute value quotes');
15891 skipAttr = true;
15892
15893 // skip to next space
15894 for (j = j + 1; j < l; j++) {
15895 w = s.charCodeAt(j + 1);
15896
15897 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15898 break;
15899 }
15900 }
15901
15902 }
15903
15904 if (j === -1) {
15905 handleWarning('missing closing quotes');
15906
15907 j = l;
15908 skipAttr = true;
15909 }
15910
15911 if (!skipAttr) {
15912 value = s.substring(i, j);
15913 }
15914
15915 i = j;
15916
15917 // ensure SPACE follows attribute
15918 // skip illegal content otherwise
15919 // example a="b"c
15920 for (; j + 1 < l; j++) {
15921 w = s.charCodeAt(j + 1);
15922
15923 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15924 break;
15925 }
15926
15927 // FIRST ILLEGAL CHAR
15928 if (i === j) {
15929 handleWarning('illegal character after attribute end');
15930 skipAttr = true;
15931 }
15932 }
15933
15934 // advance cursor to next attribute
15935 i = j + 1;
15936
15937 if (skipAttr) {
15938 continue parseAttr;
15939 }
15940
15941 // check attribute re-declaration
15942 if (name in seenAttrs) {
15943 handleWarning('attribute <' + name + '> already defined');
15944 continue;
15945 }
15946
15947 seenAttrs[name] = true;
15948
15949 if (!isNamespace) {
15950 attrs[name] = value;
15951 continue;
15952 }
15953
15954 // try to extract namespace information
15955 if (maybeNS) {
15956 newalias = (
15957 name === 'xmlns'
15958 ? 'xmlns'
15959 : (name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:')
15960 ? name.substr(6)
15961 : null
15962 );
15963
15964 // handle xmlns(:alias) assignment
15965 if (newalias !== null) {
15966 nsUri = decodeEntities(value);
15967 nsUriPrefix = uriPrefix(newalias);
15968
15969 alias = nsUriToPrefix[nsUri];
15970
15971 if (!alias) {
15972
15973 // no prefix defined or prefix collision
15974 if (
15975 (newalias === 'xmlns') ||
15976 (nsUriPrefix in nsMatrix && nsMatrix[nsUriPrefix] !== nsUri)
15977 ) {
15978
15979 // alocate free ns prefix
15980 do {
15981 alias = 'ns' + (anonymousNsCount++);
15982 } while (typeof nsMatrix[alias] !== 'undefined');
15983 } else {
15984 alias = newalias;
15985 }
15986
15987 nsUriToPrefix[nsUri] = alias;
15988 }
15989
15990 if (nsMatrix[newalias] !== alias) {
15991 if (!hasNewMatrix) {
15992 nsMatrix = cloneNsMatrix(nsMatrix);
15993 hasNewMatrix = true;
15994 }
15995
15996 nsMatrix[newalias] = alias;
15997 if (newalias === 'xmlns') {
15998 nsMatrix[uriPrefix(alias)] = nsUri;
15999 defaultAlias = alias;
16000 }
16001
16002 nsMatrix[nsUriPrefix] = nsUri;
16003 }
16004
16005 // expose xmlns(:asd)="..." in attributes
16006 attrs[name] = value;
16007 continue;
16008 }
16009
16010 // collect attributes until all namespace
16011 // declarations are processed
16012 attrList.push(name, value);
16013 continue;
16014
16015 } /** end if (maybeNs) */
16016
16017 // handle attributes on element without
16018 // namespace declarations
16019 w = name.indexOf(':');
16020 if (w === -1) {
16021 attrs[name] = value;
16022 continue;
16023 }
16024
16025 // normalize ns attribute name
16026 if (!(nsName = nsMatrix[name.substring(0, w)])) {
16027 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
16028 continue;
16029 }
16030
16031 name = defaultAlias === nsName
16032 ? name.substr(w + 1)
16033 : nsName + name.substr(w);
16034
16035 // end: normalize ns attribute name
16036
16037 // normalize xsi:type ns attribute value
16038 if (name === XSI_TYPE$1) {
16039 w = value.indexOf(':');
16040
16041 if (w !== -1) {
16042 nsName = value.substring(0, w);
16043
16044 // handle default prefixes, i.e. xs:String gracefully
16045 nsName = nsMatrix[nsName] || nsName;
16046 value = nsName + value.substring(w);
16047 } else {
16048 value = defaultAlias + ':' + value;
16049 }
16050 }
16051
16052 // end: normalize xsi:type ns attribute value
16053
16054 attrs[name] = value;
16055 }
16056
16057
16058 // handle deferred, possibly namespaced attributes
16059 if (maybeNS) {
16060
16061 // normalize captured attributes
16062 for (i = 0, l = attrList.length; i < l; i++) {
16063
16064 name = attrList[i++];
16065 value = attrList[i];
16066
16067 w = name.indexOf(':');
16068
16069 if (w !== -1) {
16070
16071 // normalize ns attribute name
16072 if (!(nsName = nsMatrix[name.substring(0, w)])) {
16073 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
16074 continue;
16075 }
16076
16077 name = defaultAlias === nsName
16078 ? name.substr(w + 1)
16079 : nsName + name.substr(w);
16080
16081 // end: normalize ns attribute name
16082
16083 // normalize xsi:type ns attribute value
16084 if (name === XSI_TYPE$1) {
16085 w = value.indexOf(':');
16086
16087 if (w !== -1) {
16088 nsName = value.substring(0, w);
16089
16090 // handle default prefixes, i.e. xs:String gracefully
16091 nsName = nsMatrix[nsName] || nsName;
16092 value = nsName + value.substring(w);
16093 } else {
16094 value = defaultAlias + ':' + value;
16095 }
16096 }
16097
16098 // end: normalize xsi:type ns attribute value
16099 }
16100
16101 attrs[name] = value;
16102 }
16103
16104 // end: normalize captured attributes
16105 }
16106
16107 return cachedAttrs = attrs;
16108 }
16109
16110 /**
16111 * Extract the parse context { line, column, part }
16112 * from the current parser position.
16113 *
16114 * @return {Object} parse context
16115 */
16116 function getParseContext() {
16117 var splitsRe = /(\r\n|\r|\n)/g;
16118
16119 var line = 0;
16120 var column = 0;
16121 var startOfLine = 0;
16122 var endOfLine = j;
16123 var match;
16124 var data;
16125
16126 while (i >= startOfLine) {
16127
16128 match = splitsRe.exec(xml);
16129
16130 if (!match) {
16131 break;
16132 }
16133
16134 // end of line = (break idx + break chars)
16135 endOfLine = match[0].length + match.index;
16136
16137 if (endOfLine > i) {
16138 break;
16139 }
16140
16141 // advance to next line
16142 line += 1;
16143
16144 startOfLine = endOfLine;
16145 }
16146
16147 // EOF errors
16148 if (i == -1) {
16149 column = endOfLine;
16150 data = xml.substring(j);
16151 } else
16152
16153 // start errors
16154 if (j === 0) {
16155 data = xml.substring(j, i);
16156 }
16157
16158 // other errors
16159 else {
16160 column = i - startOfLine;
16161 data = (j == -1 ? xml.substring(i) : xml.substring(i, j + 1));
16162 }
16163
16164 return {
16165 'data': data,
16166 'line': line,
16167 'column': column
16168 };
16169 }
16170
16171 getContext = getParseContext;
16172
16173
16174 if (proxy) {
16175 elementProxy = Object.create({}, {
16176 'name': getter(function() {
16177 return elementName;
16178 }),
16179 'originalName': getter(function() {
16180 return _elementName;
16181 }),
16182 'attrs': getter(getAttrs),
16183 'ns': getter(function() {
16184 return nsMatrix;
16185 })
16186 });
16187 }
16188
16189 // actual parse logic
16190 while (j !== -1) {
16191
16192 if (xml.charCodeAt(j) === 60) { // "<"
16193 i = j;
16194 } else {
16195 i = xml.indexOf('<', j);
16196 }
16197
16198 // parse end
16199 if (i === -1) {
16200 if (nodeStack.length) {
16201 return handleError('unexpected end of file');
16202 }
16203
16204 if (j === 0) {
16205 return handleError('missing start tag');
16206 }
16207
16208 if (j < xml.length) {
16209 if (xml.substring(j).trim()) {
16210 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
16211 }
16212 }
16213
16214 return;
16215 }
16216
16217 // parse text
16218 if (j !== i) {
16219
16220 if (nodeStack.length) {
16221 if (onText) {
16222 onText(xml.substring(j, i), decodeEntities, getContext);
16223
16224 if (parseStop) {
16225 return;
16226 }
16227 }
16228 } else {
16229 if (xml.substring(j, i).trim()) {
16230 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
16231
16232 if (parseStop) {
16233 return;
16234 }
16235 }
16236 }
16237 }
16238
16239 w = xml.charCodeAt(i+1);
16240
16241 // parse comments + CDATA
16242 if (w === 33) { // "!"
16243 q = xml.charCodeAt(i+2);
16244
16245 // CDATA section
16246 if (q === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
16247 j = xml.indexOf(']]>', i);
16248 if (j === -1) {
16249 return handleError('unclosed cdata');
16250 }
16251
16252 if (onCDATA) {
16253 onCDATA(xml.substring(i + 9, j), getContext);
16254 if (parseStop) {
16255 return;
16256 }
16257 }
16258
16259 j += 3;
16260 continue;
16261 }
16262
16263 // comment
16264 if (q === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
16265 j = xml.indexOf('-->', i);
16266 if (j === -1) {
16267 return handleError('unclosed comment');
16268 }
16269
16270
16271 if (onComment) {
16272 onComment(xml.substring(i + 4, j), decodeEntities, getContext);
16273 if (parseStop) {
16274 return;
16275 }
16276 }
16277
16278 j += 3;
16279 continue;
16280 }
16281 }
16282
16283 // parse question <? ... ?>
16284 if (w === 63) { // "?"
16285 j = xml.indexOf('?>', i);
16286 if (j === -1) {
16287 return handleError('unclosed question');
16288 }
16289
16290 if (onQuestion) {
16291 onQuestion(xml.substring(i, j + 2), getContext);
16292 if (parseStop) {
16293 return;
16294 }
16295 }
16296
16297 j += 2;
16298 continue;
16299 }
16300
16301 // find matching closing tag for attention or standard tags
16302 // for that we must skip through attribute values
16303 // (enclosed in single or double quotes)
16304 for (x = i + 1; ; x++) {
16305 v = xml.charCodeAt(x);
16306 if (isNaN(v)) {
16307 j = -1;
16308 return handleError('unclosed tag');
16309 }
16310
16311 // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
16312 // skips the quoted string
16313 // (double quotes) does not appear in a literal enclosed by (double quotes)
16314 // (single quote) does not appear in a literal enclosed by (single quote)
16315 if (v === 34) { // '"'
16316 q = xml.indexOf('"', x + 1);
16317 x = q !== -1 ? q : x;
16318 } else if (v === 39) { // "'"
16319 q = xml.indexOf("'", x + 1);
16320 x = q !== -1 ? q : x;
16321 } else if (v === 62) { // '>'
16322 j = x;
16323 break;
16324 }
16325 }
16326
16327
16328 // parse attention <! ...>
16329 // previously comment and CDATA have already been parsed
16330 if (w === 33) { // "!"
16331
16332 if (onAttention) {
16333 onAttention(xml.substring(i, j + 1), decodeEntities, getContext);
16334 if (parseStop) {
16335 return;
16336 }
16337 }
16338
16339 j += 1;
16340 continue;
16341 }
16342
16343 // don't process attributes;
16344 // there are none
16345 cachedAttrs = {};
16346
16347 // if (xml.charCodeAt(i+1) === 47) { // </...
16348 if (w === 47) { // </...
16349 tagStart = false;
16350 tagEnd = true;
16351
16352 if (!nodeStack.length) {
16353 return handleError('missing open tag');
16354 }
16355
16356 // verify open <-> close tag match
16357 x = elementName = nodeStack.pop();
16358 q = i + 2 + x.length;
16359
16360 if (xml.substring(i + 2, q) !== x) {
16361 return handleError('closing tag mismatch');
16362 }
16363
16364 // verify chars in close tag
16365 for (; q < j; q++) {
16366 w = xml.charCodeAt(q);
16367
16368 if (w === 32 || (w > 8 && w < 14)) { // \f\n\r\t\v space
16369 continue;
16370 }
16371
16372 return handleError('close tag');
16373 }
16374
16375 } else {
16376 if (xml.charCodeAt(j - 1) === 47) { // .../>
16377 x = elementName = xml.substring(i + 1, j - 1);
16378
16379 tagStart = true;
16380 tagEnd = true;
16381
16382 } else {
16383 x = elementName = xml.substring(i + 1, j);
16384
16385 tagStart = true;
16386 tagEnd = false;
16387 }
16388
16389 if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) { // char 95"_" 58":"
16390 return handleError('illegal first char nodeName');
16391 }
16392
16393 for (q = 1, y = x.length; q < y; q++) {
16394 w = x.charCodeAt(q);
16395
16396 if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w == 46) {
16397 continue;
16398 }
16399
16400 if (w === 32 || (w < 14 && w > 8)) { // \f\n\r\t\v space
16401 elementName = x.substring(0, q);
16402
16403 // maybe there are attributes
16404 cachedAttrs = null;
16405 break;
16406 }
16407
16408 return handleError('invalid nodeName');
16409 }
16410
16411 if (!tagEnd) {
16412 nodeStack.push(elementName);
16413 }
16414 }
16415
16416 if (isNamespace) {
16417
16418 _nsMatrix = nsMatrix;
16419
16420 if (tagStart) {
16421
16422 // remember old namespace
16423 // unless we're self-closing
16424 if (!tagEnd) {
16425 nsMatrixStack.push(_nsMatrix);
16426 }
16427
16428 if (cachedAttrs === null) {
16429
16430 // quick check, whether there may be namespace
16431 // declarations on the node; if that is the case
16432 // we need to eagerly parse the node attributes
16433 if ((maybeNS = x.indexOf('xmlns', q) !== -1)) {
16434 attrsStart = q;
16435 attrsString = x;
16436
16437 getAttrs();
16438
16439 maybeNS = false;
16440 }
16441 }
16442 }
16443
16444 _elementName = elementName;
16445
16446 w = elementName.indexOf(':');
16447 if (w !== -1) {
16448 xmlns = nsMatrix[elementName.substring(0, w)];
16449
16450 // prefix given; namespace must exist
16451 if (!xmlns) {
16452 return handleError('missing namespace on <' + _elementName + '>');
16453 }
16454
16455 elementName = elementName.substr(w + 1);
16456 } else {
16457 xmlns = nsMatrix['xmlns'];
16458
16459 // if no default namespace is defined,
16460 // we'll import the element as anonymous.
16461 //
16462 // it is up to users to correct that to the document defined
16463 // targetNamespace, or whatever their undersanding of the
16464 // XML spec mandates.
16465 }
16466
16467 // adjust namespace prefixs as configured
16468 if (xmlns) {
16469 elementName = xmlns + ':' + elementName;
16470 }
16471
16472 }
16473
16474 if (tagStart) {
16475 attrsStart = q;
16476 attrsString = x;
16477
16478 if (onOpenTag) {
16479 if (proxy) {
16480 onOpenTag(elementProxy, decodeEntities, tagEnd, getContext);
16481 } else {
16482 onOpenTag(elementName, getAttrs, decodeEntities, tagEnd, getContext);
16483 }
16484
16485 if (parseStop) {
16486 return;
16487 }
16488 }
16489
16490 }
16491
16492 if (tagEnd) {
16493
16494 if (onCloseTag) {
16495 onCloseTag(proxy ? elementProxy : elementName, decodeEntities, tagStart, getContext);
16496
16497 if (parseStop) {
16498 return;
16499 }
16500 }
16501
16502 // restore old namespace
16503 if (isNamespace) {
16504 if (!tagStart) {
16505 nsMatrix = nsMatrixStack.pop();
16506 } else {
16507 nsMatrix = _nsMatrix;
16508 }
16509 }
16510 }
16511
16512 j += 1;
16513 }
16514 } /** end parse */
16515
16516 }
16517
16518 function hasLowerCaseAlias(pkg) {
16519 return pkg.xml && pkg.xml.tagAlias === 'lowerCase';
16520 }
16521
16522 var DEFAULT_NS_MAP = {
16523 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
16524 'xml': 'http://www.w3.org/XML/1998/namespace'
16525 };
16526
16527 var XSI_TYPE = 'xsi:type';
16528
16529 function serializeFormat(element) {
16530 return element.xml && element.xml.serialize;
16531 }
16532
16533 function serializeAsType(element) {
16534 return serializeFormat(element) === XSI_TYPE;
16535 }
16536
16537 function serializeAsProperty(element) {
16538 return serializeFormat(element) === 'property';
16539 }
16540
16541 function capitalize(str) {
16542 return str.charAt(0).toUpperCase() + str.slice(1);
16543 }
16544
16545 function aliasToName(aliasNs, pkg) {
16546
16547 if (!hasLowerCaseAlias(pkg)) {
16548 return aliasNs.name;
16549 }
16550
16551 return aliasNs.prefix + ':' + capitalize(aliasNs.localName);
16552 }
16553
16554 function prefixedToName(nameNs, pkg) {
16555
16556 var name = nameNs.name,
16557 localName = nameNs.localName;
16558
16559 var typePrefix = pkg.xml && pkg.xml.typePrefix;
16560
16561 if (typePrefix && localName.indexOf(typePrefix) === 0) {
16562 return nameNs.prefix + ':' + localName.slice(typePrefix.length);
16563 } else {
16564 return name;
16565 }
16566 }
16567
16568 function normalizeXsiTypeName(name, model) {
16569
16570 var nameNs = parseName(name);
16571 var pkg = model.getPackage(nameNs.prefix);
16572
16573 return prefixedToName(nameNs, pkg);
16574 }
16575
16576 function error(message) {
16577 return new Error(message);
16578 }
16579
16580 /**
16581 * Get the moddle descriptor for a given instance or type.
16582 *
16583 * @param {ModdleElement|Function} element
16584 *
16585 * @return {Object} the moddle descriptor
16586 */
16587 function getModdleDescriptor(element) {
16588 return element.$descriptor;
16589 }
16590
16591
16592 /**
16593 * A parse context.
16594 *
16595 * @class
16596 *
16597 * @param {Object} options
16598 * @param {ElementHandler} options.rootHandler the root handler for parsing a document
16599 * @param {boolean} [options.lax=false] whether or not to ignore invalid elements
16600 */
16601 function Context(options) {
16602
16603 /**
16604 * @property {ElementHandler} rootHandler
16605 */
16606
16607 /**
16608 * @property {Boolean} lax
16609 */
16610
16611 assign$1(this, options);
16612
16613 this.elementsById = {};
16614 this.references = [];
16615 this.warnings = [];
16616
16617 /**
16618 * Add an unresolved reference.
16619 *
16620 * @param {Object} reference
16621 */
16622 this.addReference = function(reference) {
16623 this.references.push(reference);
16624 };
16625
16626 /**
16627 * Add a processed element.
16628 *
16629 * @param {ModdleElement} element
16630 */
16631 this.addElement = function(element) {
16632
16633 if (!element) {
16634 throw error('expected element');
16635 }
16636
16637 var elementsById = this.elementsById;
16638
16639 var descriptor = getModdleDescriptor(element);
16640
16641 var idProperty = descriptor.idProperty,
16642 id;
16643
16644 if (idProperty) {
16645 id = element.get(idProperty.name);
16646
16647 if (id) {
16648
16649 // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
16650 if (!/^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i.test(id)) {
16651 throw new Error('illegal ID <' + id + '>');
16652 }
16653
16654 if (elementsById[id]) {
16655 throw error('duplicate ID <' + id + '>');
16656 }
16657
16658 elementsById[id] = element;
16659 }
16660 }
16661 };
16662
16663 /**
16664 * Add an import warning.
16665 *
16666 * @param {Object} warning
16667 * @param {String} warning.message
16668 * @param {Error} [warning.error]
16669 */
16670 this.addWarning = function(warning) {
16671 this.warnings.push(warning);
16672 };
16673 }
16674
16675 function BaseHandler() {}
16676
16677 BaseHandler.prototype.handleEnd = function() {};
16678 BaseHandler.prototype.handleText = function() {};
16679 BaseHandler.prototype.handleNode = function() {};
16680
16681
16682 /**
16683 * A simple pass through handler that does nothing except for
16684 * ignoring all input it receives.
16685 *
16686 * This is used to ignore unknown elements and
16687 * attributes.
16688 */
16689 function NoopHandler() { }
16690
16691 NoopHandler.prototype = Object.create(BaseHandler.prototype);
16692
16693 NoopHandler.prototype.handleNode = function() {
16694 return this;
16695 };
16696
16697 function BodyHandler() {}
16698
16699 BodyHandler.prototype = Object.create(BaseHandler.prototype);
16700
16701 BodyHandler.prototype.handleText = function(text) {
16702 this.body = (this.body || '') + text;
16703 };
16704
16705 function ReferenceHandler(property, context) {
16706 this.property = property;
16707 this.context = context;
16708 }
16709
16710 ReferenceHandler.prototype = Object.create(BodyHandler.prototype);
16711
16712 ReferenceHandler.prototype.handleNode = function(node) {
16713
16714 if (this.element) {
16715 throw error('expected no sub nodes');
16716 } else {
16717 this.element = this.createReference(node);
16718 }
16719
16720 return this;
16721 };
16722
16723 ReferenceHandler.prototype.handleEnd = function() {
16724 this.element.id = this.body;
16725 };
16726
16727 ReferenceHandler.prototype.createReference = function(node) {
16728 return {
16729 property: this.property.ns.name,
16730 id: ''
16731 };
16732 };
16733
16734 function ValueHandler(propertyDesc, element) {
16735 this.element = element;
16736 this.propertyDesc = propertyDesc;
16737 }
16738
16739 ValueHandler.prototype = Object.create(BodyHandler.prototype);
16740
16741 ValueHandler.prototype.handleEnd = function() {
16742
16743 var value = this.body || '',
16744 element = this.element,
16745 propertyDesc = this.propertyDesc;
16746
16747 value = coerceType(propertyDesc.type, value);
16748
16749 if (propertyDesc.isMany) {
16750 element.get(propertyDesc.name).push(value);
16751 } else {
16752 element.set(propertyDesc.name, value);
16753 }
16754 };
16755
16756
16757 function BaseElementHandler() {}
16758
16759 BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
16760
16761 BaseElementHandler.prototype.handleNode = function(node) {
16762 var parser = this,
16763 element = this.element;
16764
16765 if (!element) {
16766 element = this.element = this.createElement(node);
16767
16768 this.context.addElement(element);
16769 } else {
16770 parser = this.handleChild(node);
16771 }
16772
16773 return parser;
16774 };
16775
16776 /**
16777 * @class Reader.ElementHandler
16778 *
16779 */
16780 function ElementHandler(model, typeName, context) {
16781 this.model = model;
16782 this.type = model.getType(typeName);
16783 this.context = context;
16784 }
16785
16786 ElementHandler.prototype = Object.create(BaseElementHandler.prototype);
16787
16788 ElementHandler.prototype.addReference = function(reference) {
16789 this.context.addReference(reference);
16790 };
16791
16792 ElementHandler.prototype.handleText = function(text) {
16793
16794 var element = this.element,
16795 descriptor = getModdleDescriptor(element),
16796 bodyProperty = descriptor.bodyProperty;
16797
16798 if (!bodyProperty) {
16799 throw error('unexpected body text <' + text + '>');
16800 }
16801
16802 BodyHandler.prototype.handleText.call(this, text);
16803 };
16804
16805 ElementHandler.prototype.handleEnd = function() {
16806
16807 var value = this.body,
16808 element = this.element,
16809 descriptor = getModdleDescriptor(element),
16810 bodyProperty = descriptor.bodyProperty;
16811
16812 if (bodyProperty && value !== undefined) {
16813 value = coerceType(bodyProperty.type, value);
16814 element.set(bodyProperty.name, value);
16815 }
16816 };
16817
16818 /**
16819 * Create an instance of the model from the given node.
16820 *
16821 * @param {Element} node the xml node
16822 */
16823 ElementHandler.prototype.createElement = function(node) {
16824 var attributes = node.attributes,
16825 Type = this.type,
16826 descriptor = getModdleDescriptor(Type),
16827 context = this.context,
16828 instance = new Type({}),
16829 model = this.model,
16830 propNameNs;
16831
16832 forEach$1(attributes, function(value, name) {
16833
16834 var prop = descriptor.propertiesByName[name],
16835 values;
16836
16837 if (prop && prop.isReference) {
16838
16839 if (!prop.isMany) {
16840 context.addReference({
16841 element: instance,
16842 property: prop.ns.name,
16843 id: value
16844 });
16845 } else {
16846
16847 // IDREFS: parse references as whitespace-separated list
16848 values = value.split(' ');
16849
16850 forEach$1(values, function(v) {
16851 context.addReference({
16852 element: instance,
16853 property: prop.ns.name,
16854 id: v
16855 });
16856 });
16857 }
16858
16859 } else {
16860 if (prop) {
16861 value = coerceType(prop.type, value);
16862 } else
16863 if (name !== 'xmlns') {
16864 propNameNs = parseName(name, descriptor.ns.prefix);
16865
16866 // check whether attribute is defined in a well-known namespace
16867 // if that is the case we emit a warning to indicate potential misuse
16868 if (model.getPackage(propNameNs.prefix)) {
16869
16870 context.addWarning({
16871 message: 'unknown attribute <' + name + '>',
16872 element: instance,
16873 property: name,
16874 value: value
16875 });
16876 }
16877 }
16878
16879 instance.set(name, value);
16880 }
16881 });
16882
16883 return instance;
16884 };
16885
16886 ElementHandler.prototype.getPropertyForNode = function(node) {
16887
16888 var name = node.name;
16889 var nameNs = parseName(name);
16890
16891 var type = this.type,
16892 model = this.model,
16893 descriptor = getModdleDescriptor(type);
16894
16895 var propertyName = nameNs.name,
16896 property = descriptor.propertiesByName[propertyName],
16897 elementTypeName,
16898 elementType;
16899
16900 // search for properties by name first
16901
16902 if (property && !property.isAttr) {
16903
16904 if (serializeAsType(property)) {
16905 elementTypeName = node.attributes[XSI_TYPE];
16906
16907 // xsi type is optional, if it does not exists the
16908 // default type is assumed
16909 if (elementTypeName) {
16910
16911 // take possible type prefixes from XML
16912 // into account, i.e.: xsi:type="t{ActualType}"
16913 elementTypeName = normalizeXsiTypeName(elementTypeName, model);
16914
16915 elementType = model.getType(elementTypeName);
16916
16917 return assign$1({}, property, {
16918 effectiveType: getModdleDescriptor(elementType).name
16919 });
16920 }
16921 }
16922
16923 // search for properties by name first
16924 return property;
16925 }
16926
16927 var pkg = model.getPackage(nameNs.prefix);
16928
16929 if (pkg) {
16930 elementTypeName = aliasToName(nameNs, pkg);
16931 elementType = model.getType(elementTypeName);
16932
16933 // search for collection members later
16934 property = find(descriptor.properties, function(p) {
16935 return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
16936 });
16937
16938 if (property) {
16939 return assign$1({}, property, {
16940 effectiveType: getModdleDescriptor(elementType).name
16941 });
16942 }
16943 } else {
16944
16945 // parse unknown element (maybe extension)
16946 property = find(descriptor.properties, function(p) {
16947 return !p.isReference && !p.isAttribute && p.type === 'Element';
16948 });
16949
16950 if (property) {
16951 return property;
16952 }
16953 }
16954
16955 throw error('unrecognized element <' + nameNs.name + '>');
16956 };
16957
16958 ElementHandler.prototype.toString = function() {
16959 return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';
16960 };
16961
16962 ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
16963 return new ValueHandler(propertyDesc, element);
16964 };
16965
16966 ElementHandler.prototype.referenceHandler = function(propertyDesc) {
16967 return new ReferenceHandler(propertyDesc, this.context);
16968 };
16969
16970 ElementHandler.prototype.handler = function(type) {
16971 if (type === 'Element') {
16972 return new GenericElementHandler(this.model, type, this.context);
16973 } else {
16974 return new ElementHandler(this.model, type, this.context);
16975 }
16976 };
16977
16978 /**
16979 * Handle the child element parsing
16980 *
16981 * @param {Element} node the xml node
16982 */
16983 ElementHandler.prototype.handleChild = function(node) {
16984 var propertyDesc, type, element, childHandler;
16985
16986 propertyDesc = this.getPropertyForNode(node);
16987 element = this.element;
16988
16989 type = propertyDesc.effectiveType || propertyDesc.type;
16990
16991 if (isSimple(type)) {
16992 return this.valueHandler(propertyDesc, element);
16993 }
16994
16995 if (propertyDesc.isReference) {
16996 childHandler = this.referenceHandler(propertyDesc).handleNode(node);
16997 } else {
16998 childHandler = this.handler(type).handleNode(node);
16999 }
17000
17001 var newElement = childHandler.element;
17002
17003 // child handles may decide to skip elements
17004 // by not returning anything
17005 if (newElement !== undefined) {
17006
17007 if (propertyDesc.isMany) {
17008 element.get(propertyDesc.name).push(newElement);
17009 } else {
17010 element.set(propertyDesc.name, newElement);
17011 }
17012
17013 if (propertyDesc.isReference) {
17014 assign$1(newElement, {
17015 element: element
17016 });
17017
17018 this.context.addReference(newElement);
17019 } else {
17020
17021 // establish child -> parent relationship
17022 newElement.$parent = element;
17023 }
17024 }
17025
17026 return childHandler;
17027 };
17028
17029 /**
17030 * An element handler that performs special validation
17031 * to ensure the node it gets initialized with matches
17032 * the handlers type (namespace wise).
17033 *
17034 * @param {Moddle} model
17035 * @param {String} typeName
17036 * @param {Context} context
17037 */
17038 function RootElementHandler(model, typeName, context) {
17039 ElementHandler.call(this, model, typeName, context);
17040 }
17041
17042 RootElementHandler.prototype = Object.create(ElementHandler.prototype);
17043
17044 RootElementHandler.prototype.createElement = function(node) {
17045
17046 var name = node.name,
17047 nameNs = parseName(name),
17048 model = this.model,
17049 type = this.type,
17050 pkg = model.getPackage(nameNs.prefix),
17051 typeName = pkg && aliasToName(nameNs, pkg) || name;
17052
17053 // verify the correct namespace if we parse
17054 // the first element in the handler tree
17055 //
17056 // this ensures we don't mistakenly import wrong namespace elements
17057 if (!type.hasType(typeName)) {
17058 throw error('unexpected element <' + node.originalName + '>');
17059 }
17060
17061 return ElementHandler.prototype.createElement.call(this, node);
17062 };
17063
17064
17065 function GenericElementHandler(model, typeName, context) {
17066 this.model = model;
17067 this.context = context;
17068 }
17069
17070 GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
17071
17072 GenericElementHandler.prototype.createElement = function(node) {
17073
17074 var name = node.name,
17075 ns = parseName(name),
17076 prefix = ns.prefix,
17077 uri = node.ns[prefix + '$uri'],
17078 attributes = node.attributes;
17079
17080 return this.model.createAny(name, uri, attributes);
17081 };
17082
17083 GenericElementHandler.prototype.handleChild = function(node) {
17084
17085 var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
17086 element = this.element;
17087
17088 var newElement = handler.element,
17089 children;
17090
17091 if (newElement !== undefined) {
17092 children = element.$children = element.$children || [];
17093 children.push(newElement);
17094
17095 // establish child -> parent relationship
17096 newElement.$parent = element;
17097 }
17098
17099 return handler;
17100 };
17101
17102 GenericElementHandler.prototype.handleEnd = function() {
17103 if (this.body) {
17104 this.element.$body = this.body;
17105 }
17106 };
17107
17108 /**
17109 * A reader for a meta-model
17110 *
17111 * @param {Object} options
17112 * @param {Model} options.model used to read xml files
17113 * @param {Boolean} options.lax whether to make parse errors warnings
17114 */
17115 function Reader(options) {
17116
17117 if (options instanceof Moddle) {
17118 options = {
17119 model: options
17120 };
17121 }
17122
17123 assign$1(this, { lax: false }, options);
17124 }
17125
17126 /**
17127 * The fromXML result.
17128 *
17129 * @typedef {Object} ParseResult
17130 *
17131 * @property {ModdleElement} rootElement
17132 * @property {Array<Object>} references
17133 * @property {Array<Error>} warnings
17134 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
17135 */
17136
17137 /**
17138 * The fromXML result.
17139 *
17140 * @typedef {Error} ParseError
17141 *
17142 * @property {Array<Error>} warnings
17143 */
17144
17145 /**
17146 * Parse the given XML into a moddle document tree.
17147 *
17148 * @param {String} xml
17149 * @param {ElementHandler|Object} options or rootHandler
17150 *
17151 * @returns {Promise<ParseResult, ParseError>}
17152 */
17153 Reader.prototype.fromXML = function(xml, options, done) {
17154
17155 var rootHandler = options.rootHandler;
17156
17157 if (options instanceof ElementHandler) {
17158
17159 // root handler passed via (xml, { rootHandler: ElementHandler }, ...)
17160 rootHandler = options;
17161 options = {};
17162 } else {
17163 if (typeof options === 'string') {
17164
17165 // rootHandler passed via (xml, 'someString', ...)
17166 rootHandler = this.handler(options);
17167 options = {};
17168 } else if (typeof rootHandler === 'string') {
17169
17170 // rootHandler passed via (xml, { rootHandler: 'someString' }, ...)
17171 rootHandler = this.handler(rootHandler);
17172 }
17173 }
17174
17175 var model = this.model,
17176 lax = this.lax;
17177
17178 var context = new Context(assign$1({}, options, { rootHandler: rootHandler })),
17179 parser = new Parser({ proxy: true }),
17180 stack = createStack();
17181
17182 rootHandler.context = context;
17183
17184 // push root handler
17185 stack.push(rootHandler);
17186
17187
17188 /**
17189 * Handle error.
17190 *
17191 * @param {Error} err
17192 * @param {Function} getContext
17193 * @param {boolean} lax
17194 *
17195 * @return {boolean} true if handled
17196 */
17197 function handleError(err, getContext, lax) {
17198
17199 var ctx = getContext();
17200
17201 var line = ctx.line,
17202 column = ctx.column,
17203 data = ctx.data;
17204
17205 // we receive the full context data here,
17206 // for elements trim down the information
17207 // to the tag name, only
17208 if (data.charAt(0) === '<' && data.indexOf(' ') !== -1) {
17209 data = data.slice(0, data.indexOf(' ')) + '>';
17210 }
17211
17212 var message =
17213 'unparsable content ' + (data ? data + ' ' : '') + 'detected\n\t' +
17214 'line: ' + line + '\n\t' +
17215 'column: ' + column + '\n\t' +
17216 'nested error: ' + err.message;
17217
17218 if (lax) {
17219 context.addWarning({
17220 message: message,
17221 error: err
17222 });
17223
17224 return true;
17225 } else {
17226 throw error(message);
17227 }
17228 }
17229
17230 function handleWarning(err, getContext) {
17231
17232 // just like handling errors in <lax=true> mode
17233 return handleError(err, getContext, true);
17234 }
17235
17236 /**
17237 * Resolve collected references on parse end.
17238 */
17239 function resolveReferences() {
17240
17241 var elementsById = context.elementsById;
17242 var references = context.references;
17243
17244 var i, r;
17245
17246 for (i = 0; (r = references[i]); i++) {
17247 var element = r.element;
17248 var reference = elementsById[r.id];
17249 var property = getModdleDescriptor(element).propertiesByName[r.property];
17250
17251 if (!reference) {
17252 context.addWarning({
17253 message: 'unresolved reference <' + r.id + '>',
17254 element: r.element,
17255 property: r.property,
17256 value: r.id
17257 });
17258 }
17259
17260 if (property.isMany) {
17261 var collection = element.get(property.name),
17262 idx = collection.indexOf(r);
17263
17264 // we replace an existing place holder (idx != -1) or
17265 // append to the collection instead
17266 if (idx === -1) {
17267 idx = collection.length;
17268 }
17269
17270 if (!reference) {
17271
17272 // remove unresolvable reference
17273 collection.splice(idx, 1);
17274 } else {
17275
17276 // add or update reference in collection
17277 collection[idx] = reference;
17278 }
17279 } else {
17280 element.set(property.name, reference);
17281 }
17282 }
17283 }
17284
17285 function handleClose() {
17286 stack.pop().handleEnd();
17287 }
17288
17289 var PREAMBLE_START_PATTERN = /^<\?xml /i;
17290
17291 var ENCODING_PATTERN = / encoding="([^"]+)"/i;
17292
17293 var UTF_8_PATTERN = /^utf-8$/i;
17294
17295 function handleQuestion(question) {
17296
17297 if (!PREAMBLE_START_PATTERN.test(question)) {
17298 return;
17299 }
17300
17301 var match = ENCODING_PATTERN.exec(question);
17302 var encoding = match && match[1];
17303
17304 if (!encoding || UTF_8_PATTERN.test(encoding)) {
17305 return;
17306 }
17307
17308 context.addWarning({
17309 message:
17310 'unsupported document encoding <' + encoding + '>, ' +
17311 'falling back to UTF-8'
17312 });
17313 }
17314
17315 function handleOpen(node, getContext) {
17316 var handler = stack.peek();
17317
17318 try {
17319 stack.push(handler.handleNode(node));
17320 } catch (err) {
17321
17322 if (handleError(err, getContext, lax)) {
17323 stack.push(new NoopHandler());
17324 }
17325 }
17326 }
17327
17328 function handleCData(text, getContext) {
17329
17330 try {
17331 stack.peek().handleText(text);
17332 } catch (err) {
17333 handleWarning(err, getContext);
17334 }
17335 }
17336
17337 function handleText(text, getContext) {
17338
17339 // strip whitespace only nodes, i.e. before
17340 // <!CDATA[ ... ]> sections and in between tags
17341
17342 if (!text.trim()) {
17343 return;
17344 }
17345
17346 handleCData(text, getContext);
17347 }
17348
17349 var uriMap = model.getPackages().reduce(function(uriMap, p) {
17350 uriMap[p.uri] = p.prefix;
17351
17352 return uriMap;
17353 }, {
17354 'http://www.w3.org/XML/1998/namespace': 'xml' // add default xml ns
17355 });
17356 parser
17357 .ns(uriMap)
17358 .on('openTag', function(obj, decodeStr, selfClosing, getContext) {
17359
17360 // gracefully handle unparsable attributes (attrs=false)
17361 var attrs = obj.attrs || {};
17362
17363 var decodedAttrs = Object.keys(attrs).reduce(function(d, key) {
17364 var value = decodeStr(attrs[key]);
17365
17366 d[key] = value;
17367
17368 return d;
17369 }, {});
17370
17371 var node = {
17372 name: obj.name,
17373 originalName: obj.originalName,
17374 attributes: decodedAttrs,
17375 ns: obj.ns
17376 };
17377
17378 handleOpen(node, getContext);
17379 })
17380 .on('question', handleQuestion)
17381 .on('closeTag', handleClose)
17382 .on('cdata', handleCData)
17383 .on('text', function(text, decodeEntities, getContext) {
17384 handleText(decodeEntities(text), getContext);
17385 })
17386 .on('error', handleError)
17387 .on('warn', handleWarning);
17388
17389 // async XML parsing to make sure the execution environment
17390 // (node or brower) is kept responsive and that certain optimization
17391 // strategies can kick in.
17392 return new Promise(function(resolve, reject) {
17393
17394 var err;
17395
17396 try {
17397 parser.parse(xml);
17398
17399 resolveReferences();
17400 } catch (e) {
17401 err = e;
17402 }
17403
17404 var rootElement = rootHandler.element;
17405
17406 if (!err && !rootElement) {
17407 err = error('failed to parse document as <' + rootHandler.type.$descriptor.name + '>');
17408 }
17409
17410 var warnings = context.warnings;
17411 var references = context.references;
17412 var elementsById = context.elementsById;
17413
17414 if (err) {
17415 err.warnings = warnings;
17416
17417 return reject(err);
17418 } else {
17419 return resolve({
17420 rootElement: rootElement,
17421 elementsById: elementsById,
17422 references: references,
17423 warnings: warnings
17424 });
17425 }
17426 });
17427 };
17428
17429 Reader.prototype.handler = function(name) {
17430 return new RootElementHandler(this.model, name);
17431 };
17432
17433
17434 // helpers //////////////////////////
17435
17436 function createStack() {
17437 var stack = [];
17438
17439 Object.defineProperty(stack, 'peek', {
17440 value: function() {
17441 return this[this.length - 1];
17442 }
17443 });
17444
17445 return stack;
17446 }
17447
17448 var XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>\n';
17449
17450 var ESCAPE_ATTR_CHARS = /<|>|'|"|&|\n\r|\n/g;
17451 var ESCAPE_CHARS = /<|>|&/g;
17452
17453
17454 function Namespaces(parent) {
17455
17456 var prefixMap = {};
17457 var uriMap = {};
17458 var used = {};
17459
17460 var wellknown = [];
17461 var custom = [];
17462
17463 // API
17464
17465 this.byUri = function(uri) {
17466 return uriMap[uri] || (
17467 parent && parent.byUri(uri)
17468 );
17469 };
17470
17471 this.add = function(ns, isWellknown) {
17472
17473 uriMap[ns.uri] = ns;
17474
17475 if (isWellknown) {
17476 wellknown.push(ns);
17477 } else {
17478 custom.push(ns);
17479 }
17480
17481 this.mapPrefix(ns.prefix, ns.uri);
17482 };
17483
17484 this.uriByPrefix = function(prefix) {
17485 return prefixMap[prefix || 'xmlns'];
17486 };
17487
17488 this.mapPrefix = function(prefix, uri) {
17489 prefixMap[prefix || 'xmlns'] = uri;
17490 };
17491
17492 this.getNSKey = function(ns) {
17493 return (ns.prefix !== undefined) ? (ns.uri + '|' + ns.prefix) : ns.uri;
17494 };
17495
17496 this.logUsed = function(ns) {
17497
17498 var uri = ns.uri;
17499 var nsKey = this.getNSKey(ns);
17500
17501 used[nsKey] = this.byUri(uri);
17502
17503 // Inform parent recursively about the usage of this NS
17504 if (parent) {
17505 parent.logUsed(ns);
17506 }
17507 };
17508
17509 this.getUsed = function(ns) {
17510
17511 function isUsed(ns) {
17512 var nsKey = self.getNSKey(ns);
17513
17514 return used[nsKey];
17515 }
17516
17517 var self = this;
17518
17519 var allNs = [].concat(wellknown, custom);
17520
17521 return allNs.filter(isUsed);
17522 };
17523
17524 }
17525
17526 function lower(string) {
17527 return string.charAt(0).toLowerCase() + string.slice(1);
17528 }
17529
17530 function nameToAlias(name, pkg) {
17531 if (hasLowerCaseAlias(pkg)) {
17532 return lower(name);
17533 } else {
17534 return name;
17535 }
17536 }
17537
17538 function inherits(ctor, superCtor) {
17539 ctor.super_ = superCtor;
17540 ctor.prototype = Object.create(superCtor.prototype, {
17541 constructor: {
17542 value: ctor,
17543 enumerable: false,
17544 writable: true,
17545 configurable: true
17546 }
17547 });
17548 }
17549
17550 function nsName(ns) {
17551 if (isString(ns)) {
17552 return ns;
17553 } else {
17554 return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
17555 }
17556 }
17557
17558 function getNsAttrs(namespaces) {
17559
17560 return namespaces.getUsed().filter(function(ns) {
17561
17562 // do not serialize built in <xml> namespace
17563 return ns.prefix !== 'xml';
17564 }).map(function(ns) {
17565 var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
17566 return { name: name, value: ns.uri };
17567 });
17568
17569 }
17570
17571 function getElementNs(ns, descriptor) {
17572 if (descriptor.isGeneric) {
17573 return assign$1({ localName: descriptor.ns.localName }, ns);
17574 } else {
17575 return assign$1({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
17576 }
17577 }
17578
17579 function getPropertyNs(ns, descriptor) {
17580 return assign$1({ localName: descriptor.ns.localName }, ns);
17581 }
17582
17583 function getSerializableProperties(element) {
17584 var descriptor = element.$descriptor;
17585
17586 return filter(descriptor.properties, function(p) {
17587 var name = p.name;
17588
17589 if (p.isVirtual) {
17590 return false;
17591 }
17592
17593 // do not serialize defaults
17594 if (!has$1(element, name)) {
17595 return false;
17596 }
17597
17598 var value = element[name];
17599
17600 // do not serialize default equals
17601 if (value === p.default) {
17602 return false;
17603 }
17604
17605 // do not serialize null properties
17606 if (value === null) {
17607 return false;
17608 }
17609
17610 return p.isMany ? value.length : true;
17611 });
17612 }
17613
17614 var ESCAPE_ATTR_MAP = {
17615 '\n': '#10',
17616 '\n\r': '#10',
17617 '"': '#34',
17618 '\'': '#39',
17619 '<': '#60',
17620 '>': '#62',
17621 '&': '#38'
17622 };
17623
17624 var ESCAPE_MAP = {
17625 '<': 'lt',
17626 '>': 'gt',
17627 '&': 'amp'
17628 };
17629
17630 function escape(str, charPattern, replaceMap) {
17631
17632 // ensure we are handling strings here
17633 str = isString(str) ? str : '' + str;
17634
17635 return str.replace(charPattern, function(s) {
17636 return '&' + replaceMap[s] + ';';
17637 });
17638 }
17639
17640 /**
17641 * Escape a string attribute to not contain any bad values (line breaks, '"', ...)
17642 *
17643 * @param {String} str the string to escape
17644 * @return {String} the escaped string
17645 */
17646 function escapeAttr(str) {
17647 return escape(str, ESCAPE_ATTR_CHARS, ESCAPE_ATTR_MAP);
17648 }
17649
17650 function escapeBody(str) {
17651 return escape(str, ESCAPE_CHARS, ESCAPE_MAP);
17652 }
17653
17654 function filterAttributes(props) {
17655 return filter(props, function(p) { return p.isAttr; });
17656 }
17657
17658 function filterContained(props) {
17659 return filter(props, function(p) { return !p.isAttr; });
17660 }
17661
17662
17663 function ReferenceSerializer(tagName) {
17664 this.tagName = tagName;
17665 }
17666
17667 ReferenceSerializer.prototype.build = function(element) {
17668 this.element = element;
17669 return this;
17670 };
17671
17672 ReferenceSerializer.prototype.serializeTo = function(writer) {
17673 writer
17674 .appendIndent()
17675 .append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')
17676 .appendNewLine();
17677 };
17678
17679 function BodySerializer() {}
17680
17681 BodySerializer.prototype.serializeValue =
17682 BodySerializer.prototype.serializeTo = function(writer) {
17683 writer.append(
17684 this.escape
17685 ? escapeBody(this.value)
17686 : this.value
17687 );
17688 };
17689
17690 BodySerializer.prototype.build = function(prop, value) {
17691 this.value = value;
17692
17693 if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {
17694 this.escape = true;
17695 }
17696
17697 return this;
17698 };
17699
17700 function ValueSerializer(tagName) {
17701 this.tagName = tagName;
17702 }
17703
17704 inherits(ValueSerializer, BodySerializer);
17705
17706 ValueSerializer.prototype.serializeTo = function(writer) {
17707
17708 writer
17709 .appendIndent()
17710 .append('<' + this.tagName + '>');
17711
17712 this.serializeValue(writer);
17713
17714 writer
17715 .append('</' + this.tagName + '>')
17716 .appendNewLine();
17717 };
17718
17719 function ElementSerializer(parent, propertyDescriptor) {
17720 this.body = [];
17721 this.attrs = [];
17722
17723 this.parent = parent;
17724 this.propertyDescriptor = propertyDescriptor;
17725 }
17726
17727 ElementSerializer.prototype.build = function(element) {
17728 this.element = element;
17729
17730 var elementDescriptor = element.$descriptor,
17731 propertyDescriptor = this.propertyDescriptor;
17732
17733 var otherAttrs,
17734 properties;
17735
17736 var isGeneric = elementDescriptor.isGeneric;
17737
17738 if (isGeneric) {
17739 otherAttrs = this.parseGeneric(element);
17740 } else {
17741 otherAttrs = this.parseNsAttributes(element);
17742 }
17743
17744 if (propertyDescriptor) {
17745 this.ns = this.nsPropertyTagName(propertyDescriptor);
17746 } else {
17747 this.ns = this.nsTagName(elementDescriptor);
17748 }
17749
17750 // compute tag name
17751 this.tagName = this.addTagName(this.ns);
17752
17753 if (!isGeneric) {
17754 properties = getSerializableProperties(element);
17755
17756 this.parseAttributes(filterAttributes(properties));
17757 this.parseContainments(filterContained(properties));
17758 }
17759
17760 this.parseGenericAttributes(element, otherAttrs);
17761
17762 return this;
17763 };
17764
17765 ElementSerializer.prototype.nsTagName = function(descriptor) {
17766 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
17767 return getElementNs(effectiveNs, descriptor);
17768 };
17769
17770 ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
17771 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
17772 return getPropertyNs(effectiveNs, descriptor);
17773 };
17774
17775 ElementSerializer.prototype.isLocalNs = function(ns) {
17776 return ns.uri === this.ns.uri;
17777 };
17778
17779 /**
17780 * Get the actual ns attribute name for the given element.
17781 *
17782 * @param {Object} element
17783 * @param {Boolean} [element.inherited=false]
17784 *
17785 * @return {Object} nsName
17786 */
17787 ElementSerializer.prototype.nsAttributeName = function(element) {
17788
17789 var ns;
17790
17791 if (isString(element)) {
17792 ns = parseName(element);
17793 } else {
17794 ns = element.ns;
17795 }
17796
17797 // return just local name for inherited attributes
17798 if (element.inherited) {
17799 return { localName: ns.localName };
17800 }
17801
17802 // parse + log effective ns
17803 var effectiveNs = this.logNamespaceUsed(ns);
17804
17805 // LOG ACTUAL namespace use
17806 this.getNamespaces().logUsed(effectiveNs);
17807
17808 // strip prefix if same namespace like parent
17809 if (this.isLocalNs(effectiveNs)) {
17810 return { localName: ns.localName };
17811 } else {
17812 return assign$1({ localName: ns.localName }, effectiveNs);
17813 }
17814 };
17815
17816 ElementSerializer.prototype.parseGeneric = function(element) {
17817
17818 var self = this,
17819 body = this.body;
17820
17821 var attributes = [];
17822
17823 forEach$1(element, function(val, key) {
17824
17825 var nonNsAttr;
17826
17827 if (key === '$body') {
17828 body.push(new BodySerializer().build({ type: 'String' }, val));
17829 } else
17830 if (key === '$children') {
17831 forEach$1(val, function(child) {
17832 body.push(new ElementSerializer(self).build(child));
17833 });
17834 } else
17835 if (key.indexOf('$') !== 0) {
17836 nonNsAttr = self.parseNsAttribute(element, key, val);
17837
17838 if (nonNsAttr) {
17839 attributes.push({ name: key, value: val });
17840 }
17841 }
17842 });
17843
17844 return attributes;
17845 };
17846
17847 ElementSerializer.prototype.parseNsAttribute = function(element, name, value) {
17848 var model = element.$model;
17849
17850 var nameNs = parseName(name);
17851
17852 var ns;
17853
17854 // parse xmlns:foo="http://foo.bar"
17855 if (nameNs.prefix === 'xmlns') {
17856 ns = { prefix: nameNs.localName, uri: value };
17857 }
17858
17859 // parse xmlns="http://foo.bar"
17860 if (!nameNs.prefix && nameNs.localName === 'xmlns') {
17861 ns = { uri: value };
17862 }
17863
17864 if (!ns) {
17865 return {
17866 name: name,
17867 value: value
17868 };
17869 }
17870
17871 if (model && model.getPackage(value)) {
17872
17873 // register well known namespace
17874 this.logNamespace(ns, true, true);
17875 } else {
17876
17877 // log custom namespace directly as used
17878 var actualNs = this.logNamespaceUsed(ns, true);
17879
17880 this.getNamespaces().logUsed(actualNs);
17881 }
17882 };
17883
17884
17885 /**
17886 * Parse namespaces and return a list of left over generic attributes
17887 *
17888 * @param {Object} element
17889 * @return {Array<Object>}
17890 */
17891 ElementSerializer.prototype.parseNsAttributes = function(element, attrs) {
17892 var self = this;
17893
17894 var genericAttrs = element.$attrs;
17895
17896 var attributes = [];
17897
17898 // parse namespace attributes first
17899 // and log them. push non namespace attributes to a list
17900 // and process them later
17901 forEach$1(genericAttrs, function(value, name) {
17902
17903 var nonNsAttr = self.parseNsAttribute(element, name, value);
17904
17905 if (nonNsAttr) {
17906 attributes.push(nonNsAttr);
17907 }
17908 });
17909
17910 return attributes;
17911 };
17912
17913 ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
17914
17915 var self = this;
17916
17917 forEach$1(attributes, function(attr) {
17918
17919 // do not serialize xsi:type attribute
17920 // it is set manually based on the actual implementation type
17921 if (attr.name === XSI_TYPE) {
17922 return;
17923 }
17924
17925 try {
17926 self.addAttribute(self.nsAttributeName(attr.name), attr.value);
17927 } catch (e) {
17928 /* global console */
17929
17930 console.warn(
17931 'missing namespace information for ',
17932 attr.name, '=', attr.value, 'on', element,
17933 e);
17934 }
17935 });
17936 };
17937
17938 ElementSerializer.prototype.parseContainments = function(properties) {
17939
17940 var self = this,
17941 body = this.body,
17942 element = this.element;
17943
17944 forEach$1(properties, function(p) {
17945 var value = element.get(p.name),
17946 isReference = p.isReference,
17947 isMany = p.isMany;
17948
17949 if (!isMany) {
17950 value = [ value ];
17951 }
17952
17953 if (p.isBody) {
17954 body.push(new BodySerializer().build(p, value[0]));
17955 } else
17956 if (isSimple(p.type)) {
17957 forEach$1(value, function(v) {
17958 body.push(new ValueSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));
17959 });
17960 } else
17961 if (isReference) {
17962 forEach$1(value, function(v) {
17963 body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));
17964 });
17965 } else {
17966
17967 // allow serialization via type
17968 // rather than element name
17969 var asType = serializeAsType(p),
17970 asProperty = serializeAsProperty(p);
17971
17972 forEach$1(value, function(v) {
17973 var serializer;
17974
17975 if (asType) {
17976 serializer = new TypeSerializer(self, p);
17977 } else
17978 if (asProperty) {
17979 serializer = new ElementSerializer(self, p);
17980 } else {
17981 serializer = new ElementSerializer(self);
17982 }
17983
17984 body.push(serializer.build(v));
17985 });
17986 }
17987 });
17988 };
17989
17990 ElementSerializer.prototype.getNamespaces = function(local) {
17991
17992 var namespaces = this.namespaces,
17993 parent = this.parent,
17994 parentNamespaces;
17995
17996 if (!namespaces) {
17997 parentNamespaces = parent && parent.getNamespaces();
17998
17999 if (local || !parentNamespaces) {
18000 this.namespaces = namespaces = new Namespaces(parentNamespaces);
18001 } else {
18002 namespaces = parentNamespaces;
18003 }
18004 }
18005
18006 return namespaces;
18007 };
18008
18009 ElementSerializer.prototype.logNamespace = function(ns, wellknown, local) {
18010 var namespaces = this.getNamespaces(local);
18011
18012 var nsUri = ns.uri,
18013 nsPrefix = ns.prefix;
18014
18015 var existing = namespaces.byUri(nsUri);
18016
18017 if (!existing || local) {
18018 namespaces.add(ns, wellknown);
18019 }
18020
18021 namespaces.mapPrefix(nsPrefix, nsUri);
18022
18023 return ns;
18024 };
18025
18026 ElementSerializer.prototype.logNamespaceUsed = function(ns, local) {
18027 var element = this.element,
18028 model = element.$model,
18029 namespaces = this.getNamespaces(local);
18030
18031 // ns may be
18032 //
18033 // * prefix only
18034 // * prefix:uri
18035 // * localName only
18036
18037 var prefix = ns.prefix,
18038 uri = ns.uri,
18039 newPrefix, idx,
18040 wellknownUri;
18041
18042 // handle anonymous namespaces (elementForm=unqualified), cf. #23
18043 if (!prefix && !uri) {
18044 return { localName: ns.localName };
18045 }
18046
18047 wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri;
18048
18049 uri = uri || wellknownUri || namespaces.uriByPrefix(prefix);
18050
18051 if (!uri) {
18052 throw new Error('no namespace uri given for prefix <' + prefix + '>');
18053 }
18054
18055 ns = namespaces.byUri(uri);
18056
18057 if (!ns) {
18058 newPrefix = prefix;
18059 idx = 1;
18060
18061 // find a prefix that is not mapped yet
18062 while (namespaces.uriByPrefix(newPrefix)) {
18063 newPrefix = prefix + '_' + idx++;
18064 }
18065
18066 ns = this.logNamespace({ prefix: newPrefix, uri: uri }, wellknownUri === uri);
18067 }
18068
18069 if (prefix) {
18070 namespaces.mapPrefix(prefix, uri);
18071 }
18072
18073 return ns;
18074 };
18075
18076 ElementSerializer.prototype.parseAttributes = function(properties) {
18077 var self = this,
18078 element = this.element;
18079
18080 forEach$1(properties, function(p) {
18081
18082 var value = element.get(p.name);
18083
18084 if (p.isReference) {
18085
18086 if (!p.isMany) {
18087 value = value.id;
18088 }
18089 else {
18090 var values = [];
18091 forEach$1(value, function(v) {
18092 values.push(v.id);
18093 });
18094
18095 // IDREFS is a whitespace-separated list of references.
18096 value = values.join(' ');
18097 }
18098
18099 }
18100
18101 self.addAttribute(self.nsAttributeName(p), value);
18102 });
18103 };
18104
18105 ElementSerializer.prototype.addTagName = function(nsTagName) {
18106 var actualNs = this.logNamespaceUsed(nsTagName);
18107
18108 this.getNamespaces().logUsed(actualNs);
18109
18110 return nsName(nsTagName);
18111 };
18112
18113 ElementSerializer.prototype.addAttribute = function(name, value) {
18114 var attrs = this.attrs;
18115
18116 if (isString(value)) {
18117 value = escapeAttr(value);
18118 }
18119
18120 // de-duplicate attributes
18121 // https://github.com/bpmn-io/moddle-xml/issues/66
18122 var idx = findIndex(attrs, function(element) {
18123 return (
18124 element.name.localName === name.localName &&
18125 element.name.uri === name.uri &&
18126 element.name.prefix === name.prefix
18127 );
18128 });
18129
18130 var attr = { name: name, value: value };
18131
18132 if (idx !== -1) {
18133 attrs.splice(idx, 1, attr);
18134 } else {
18135 attrs.push(attr);
18136 }
18137 };
18138
18139 ElementSerializer.prototype.serializeAttributes = function(writer) {
18140 var attrs = this.attrs,
18141 namespaces = this.namespaces;
18142
18143 if (namespaces) {
18144 attrs = getNsAttrs(namespaces).concat(attrs);
18145 }
18146
18147 forEach$1(attrs, function(a) {
18148 writer
18149 .append(' ')
18150 .append(nsName(a.name)).append('="').append(a.value).append('"');
18151 });
18152 };
18153
18154 ElementSerializer.prototype.serializeTo = function(writer) {
18155 var firstBody = this.body[0],
18156 indent = firstBody && firstBody.constructor !== BodySerializer;
18157
18158 writer
18159 .appendIndent()
18160 .append('<' + this.tagName);
18161
18162 this.serializeAttributes(writer);
18163
18164 writer.append(firstBody ? '>' : ' />');
18165
18166 if (firstBody) {
18167
18168 if (indent) {
18169 writer
18170 .appendNewLine()
18171 .indent();
18172 }
18173
18174 forEach$1(this.body, function(b) {
18175 b.serializeTo(writer);
18176 });
18177
18178 if (indent) {
18179 writer
18180 .unindent()
18181 .appendIndent();
18182 }
18183
18184 writer.append('</' + this.tagName + '>');
18185 }
18186
18187 writer.appendNewLine();
18188 };
18189
18190 /**
18191 * A serializer for types that handles serialization of data types
18192 */
18193 function TypeSerializer(parent, propertyDescriptor) {
18194 ElementSerializer.call(this, parent, propertyDescriptor);
18195 }
18196
18197 inherits(TypeSerializer, ElementSerializer);
18198
18199 TypeSerializer.prototype.parseNsAttributes = function(element) {
18200
18201 // extracted attributes
18202 var attributes = ElementSerializer.prototype.parseNsAttributes.call(this, element);
18203
18204 var descriptor = element.$descriptor;
18205
18206 // only serialize xsi:type if necessary
18207 if (descriptor.name === this.propertyDescriptor.type) {
18208 return attributes;
18209 }
18210
18211 var typeNs = this.typeNs = this.nsTagName(descriptor);
18212 this.getNamespaces().logUsed(this.typeNs);
18213
18214 // add xsi:type attribute to represent the elements
18215 // actual type
18216
18217 var pkg = element.$model.getPackage(typeNs.uri),
18218 typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';
18219
18220 this.addAttribute(
18221 this.nsAttributeName(XSI_TYPE),
18222 (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName
18223 );
18224
18225 return attributes;
18226 };
18227
18228 TypeSerializer.prototype.isLocalNs = function(ns) {
18229 return ns.uri === (this.typeNs || this.ns).uri;
18230 };
18231
18232 function SavingWriter() {
18233 this.value = '';
18234
18235 this.write = function(str) {
18236 this.value += str;
18237 };
18238 }
18239
18240 function FormatingWriter(out, format) {
18241
18242 var indent = [ '' ];
18243
18244 this.append = function(str) {
18245 out.write(str);
18246
18247 return this;
18248 };
18249
18250 this.appendNewLine = function() {
18251 if (format) {
18252 out.write('\n');
18253 }
18254
18255 return this;
18256 };
18257
18258 this.appendIndent = function() {
18259 if (format) {
18260 out.write(indent.join(' '));
18261 }
18262
18263 return this;
18264 };
18265
18266 this.indent = function() {
18267 indent.push('');
18268 return this;
18269 };
18270
18271 this.unindent = function() {
18272 indent.pop();
18273 return this;
18274 };
18275 }
18276
18277 /**
18278 * A writer for meta-model backed document trees
18279 *
18280 * @param {Object} options output options to pass into the writer
18281 */
18282 function Writer(options) {
18283
18284 options = assign$1({ format: false, preamble: true }, options || {});
18285
18286 function toXML(tree, writer) {
18287 var internalWriter = writer || new SavingWriter();
18288 var formatingWriter = new FormatingWriter(internalWriter, options.format);
18289
18290 if (options.preamble) {
18291 formatingWriter.append(XML_PREAMBLE);
18292 }
18293
18294 new ElementSerializer().build(tree).serializeTo(formatingWriter);
18295
18296 if (!writer) {
18297 return internalWriter.value;
18298 }
18299 }
18300
18301 return {
18302 toXML: toXML
18303 };
18304 }
18305
18306 /**
18307 * A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
18308 *
18309 * @class BpmnModdle
18310 * @extends Moddle
18311 *
18312 * @param {Object|Array} packages to use for instantiating the model
18313 * @param {Object} [options] additional options to pass over
18314 */
18315 function BpmnModdle(packages, options) {
18316 Moddle.call(this, packages, options);
18317 }
18318
18319 BpmnModdle.prototype = Object.create(Moddle.prototype);
18320
18321 /**
18322 * The fromXML result.
18323 *
18324 * @typedef {Object} ParseResult
18325 *
18326 * @property {ModdleElement} rootElement
18327 * @property {Array<Object>} references
18328 * @property {Array<Error>} warnings
18329 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
18330 */
18331
18332 /**
18333 * The fromXML error.
18334 *
18335 * @typedef {Error} ParseError
18336 *
18337 * @property {Array<Error>} warnings
18338 */
18339
18340 /**
18341 * Instantiates a BPMN model tree from a given xml string.
18342 *
18343 * @param {String} xmlStr
18344 * @param {String} [typeName='bpmn:Definitions'] name of the root element
18345 * @param {Object} [options] options to pass to the underlying reader
18346 *
18347 * @returns {Promise<ParseResult, ParseError>}
18348 */
18349 BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options) {
18350
18351 if (!isString(typeName)) {
18352 options = typeName;
18353 typeName = 'bpmn:Definitions';
18354 }
18355
18356 var reader = new Reader(assign$1({ model: this, lax: true }, options));
18357 var rootHandler = reader.handler(typeName);
18358
18359 return reader.fromXML(xmlStr, rootHandler);
18360 };
18361
18362
18363 /**
18364 * The toXML result.
18365 *
18366 * @typedef {Object} SerializationResult
18367 *
18368 * @property {String} xml
18369 */
18370
18371 /**
18372 * Serializes a BPMN 2.0 object tree to XML.
18373 *
18374 * @param {String} element the root element, typically an instance of `bpmn:Definitions`
18375 * @param {Object} [options] to pass to the underlying writer
18376 *
18377 * @returns {Promise<SerializationResult, Error>}
18378 */
18379 BpmnModdle.prototype.toXML = function(element, options) {
18380
18381 var writer = new Writer(options);
18382
18383 return new Promise(function(resolve, reject) {
18384 try {
18385 var result = writer.toXML(element);
18386
18387 return resolve({
18388 xml: result
18389 });
18390 } catch (err) {
18391 return reject(err);
18392 }
18393 });
18394 };
18395
18396 var name$5 = "BPMN20";
18397 var uri$5 = "http://www.omg.org/spec/BPMN/20100524/MODEL";
18398 var prefix$5 = "bpmn";
18399 var associations$5 = [
18400 ];
18401 var types$5 = [
18402 {
18403 name: "Interface",
18404 superClass: [
18405 "RootElement"
18406 ],
18407 properties: [
18408 {
18409 name: "name",
18410 isAttr: true,
18411 type: "String"
18412 },
18413 {
18414 name: "operations",
18415 type: "Operation",
18416 isMany: true
18417 },
18418 {
18419 name: "implementationRef",
18420 isAttr: true,
18421 type: "String"
18422 }
18423 ]
18424 },
18425 {
18426 name: "Operation",
18427 superClass: [
18428 "BaseElement"
18429 ],
18430 properties: [
18431 {
18432 name: "name",
18433 isAttr: true,
18434 type: "String"
18435 },
18436 {
18437 name: "inMessageRef",
18438 type: "Message",
18439 isReference: true
18440 },
18441 {
18442 name: "outMessageRef",
18443 type: "Message",
18444 isReference: true
18445 },
18446 {
18447 name: "errorRef",
18448 type: "Error",
18449 isMany: true,
18450 isReference: true
18451 },
18452 {
18453 name: "implementationRef",
18454 isAttr: true,
18455 type: "String"
18456 }
18457 ]
18458 },
18459 {
18460 name: "EndPoint",
18461 superClass: [
18462 "RootElement"
18463 ]
18464 },
18465 {
18466 name: "Auditing",
18467 superClass: [
18468 "BaseElement"
18469 ]
18470 },
18471 {
18472 name: "GlobalTask",
18473 superClass: [
18474 "CallableElement"
18475 ],
18476 properties: [
18477 {
18478 name: "resources",
18479 type: "ResourceRole",
18480 isMany: true
18481 }
18482 ]
18483 },
18484 {
18485 name: "Monitoring",
18486 superClass: [
18487 "BaseElement"
18488 ]
18489 },
18490 {
18491 name: "Performer",
18492 superClass: [
18493 "ResourceRole"
18494 ]
18495 },
18496 {
18497 name: "Process",
18498 superClass: [
18499 "FlowElementsContainer",
18500 "CallableElement"
18501 ],
18502 properties: [
18503 {
18504 name: "processType",
18505 type: "ProcessType",
18506 isAttr: true
18507 },
18508 {
18509 name: "isClosed",
18510 isAttr: true,
18511 type: "Boolean"
18512 },
18513 {
18514 name: "auditing",
18515 type: "Auditing"
18516 },
18517 {
18518 name: "monitoring",
18519 type: "Monitoring"
18520 },
18521 {
18522 name: "properties",
18523 type: "Property",
18524 isMany: true
18525 },
18526 {
18527 name: "laneSets",
18528 isMany: true,
18529 replaces: "FlowElementsContainer#laneSets",
18530 type: "LaneSet"
18531 },
18532 {
18533 name: "flowElements",
18534 isMany: true,
18535 replaces: "FlowElementsContainer#flowElements",
18536 type: "FlowElement"
18537 },
18538 {
18539 name: "artifacts",
18540 type: "Artifact",
18541 isMany: true
18542 },
18543 {
18544 name: "resources",
18545 type: "ResourceRole",
18546 isMany: true
18547 },
18548 {
18549 name: "correlationSubscriptions",
18550 type: "CorrelationSubscription",
18551 isMany: true
18552 },
18553 {
18554 name: "supports",
18555 type: "Process",
18556 isMany: true,
18557 isReference: true
18558 },
18559 {
18560 name: "definitionalCollaborationRef",
18561 type: "Collaboration",
18562 isAttr: true,
18563 isReference: true
18564 },
18565 {
18566 name: "isExecutable",
18567 isAttr: true,
18568 type: "Boolean"
18569 }
18570 ]
18571 },
18572 {
18573 name: "LaneSet",
18574 superClass: [
18575 "BaseElement"
18576 ],
18577 properties: [
18578 {
18579 name: "lanes",
18580 type: "Lane",
18581 isMany: true
18582 },
18583 {
18584 name: "name",
18585 isAttr: true,
18586 type: "String"
18587 }
18588 ]
18589 },
18590 {
18591 name: "Lane",
18592 superClass: [
18593 "BaseElement"
18594 ],
18595 properties: [
18596 {
18597 name: "name",
18598 isAttr: true,
18599 type: "String"
18600 },
18601 {
18602 name: "partitionElementRef",
18603 type: "BaseElement",
18604 isAttr: true,
18605 isReference: true
18606 },
18607 {
18608 name: "partitionElement",
18609 type: "BaseElement"
18610 },
18611 {
18612 name: "flowNodeRef",
18613 type: "FlowNode",
18614 isMany: true,
18615 isReference: true
18616 },
18617 {
18618 name: "childLaneSet",
18619 type: "LaneSet",
18620 xml: {
18621 serialize: "xsi:type"
18622 }
18623 }
18624 ]
18625 },
18626 {
18627 name: "GlobalManualTask",
18628 superClass: [
18629 "GlobalTask"
18630 ]
18631 },
18632 {
18633 name: "ManualTask",
18634 superClass: [
18635 "Task"
18636 ]
18637 },
18638 {
18639 name: "UserTask",
18640 superClass: [
18641 "Task"
18642 ],
18643 properties: [
18644 {
18645 name: "renderings",
18646 type: "Rendering",
18647 isMany: true
18648 },
18649 {
18650 name: "implementation",
18651 isAttr: true,
18652 type: "String"
18653 }
18654 ]
18655 },
18656 {
18657 name: "Rendering",
18658 superClass: [
18659 "BaseElement"
18660 ]
18661 },
18662 {
18663 name: "HumanPerformer",
18664 superClass: [
18665 "Performer"
18666 ]
18667 },
18668 {
18669 name: "PotentialOwner",
18670 superClass: [
18671 "HumanPerformer"
18672 ]
18673 },
18674 {
18675 name: "GlobalUserTask",
18676 superClass: [
18677 "GlobalTask"
18678 ],
18679 properties: [
18680 {
18681 name: "implementation",
18682 isAttr: true,
18683 type: "String"
18684 },
18685 {
18686 name: "renderings",
18687 type: "Rendering",
18688 isMany: true
18689 }
18690 ]
18691 },
18692 {
18693 name: "Gateway",
18694 isAbstract: true,
18695 superClass: [
18696 "FlowNode"
18697 ],
18698 properties: [
18699 {
18700 name: "gatewayDirection",
18701 type: "GatewayDirection",
18702 "default": "Unspecified",
18703 isAttr: true
18704 }
18705 ]
18706 },
18707 {
18708 name: "EventBasedGateway",
18709 superClass: [
18710 "Gateway"
18711 ],
18712 properties: [
18713 {
18714 name: "instantiate",
18715 "default": false,
18716 isAttr: true,
18717 type: "Boolean"
18718 },
18719 {
18720 name: "eventGatewayType",
18721 type: "EventBasedGatewayType",
18722 isAttr: true,
18723 "default": "Exclusive"
18724 }
18725 ]
18726 },
18727 {
18728 name: "ComplexGateway",
18729 superClass: [
18730 "Gateway"
18731 ],
18732 properties: [
18733 {
18734 name: "activationCondition",
18735 type: "Expression",
18736 xml: {
18737 serialize: "xsi:type"
18738 }
18739 },
18740 {
18741 name: "default",
18742 type: "SequenceFlow",
18743 isAttr: true,
18744 isReference: true
18745 }
18746 ]
18747 },
18748 {
18749 name: "ExclusiveGateway",
18750 superClass: [
18751 "Gateway"
18752 ],
18753 properties: [
18754 {
18755 name: "default",
18756 type: "SequenceFlow",
18757 isAttr: true,
18758 isReference: true
18759 }
18760 ]
18761 },
18762 {
18763 name: "InclusiveGateway",
18764 superClass: [
18765 "Gateway"
18766 ],
18767 properties: [
18768 {
18769 name: "default",
18770 type: "SequenceFlow",
18771 isAttr: true,
18772 isReference: true
18773 }
18774 ]
18775 },
18776 {
18777 name: "ParallelGateway",
18778 superClass: [
18779 "Gateway"
18780 ]
18781 },
18782 {
18783 name: "RootElement",
18784 isAbstract: true,
18785 superClass: [
18786 "BaseElement"
18787 ]
18788 },
18789 {
18790 name: "Relationship",
18791 superClass: [
18792 "BaseElement"
18793 ],
18794 properties: [
18795 {
18796 name: "type",
18797 isAttr: true,
18798 type: "String"
18799 },
18800 {
18801 name: "direction",
18802 type: "RelationshipDirection",
18803 isAttr: true
18804 },
18805 {
18806 name: "source",
18807 isMany: true,
18808 isReference: true,
18809 type: "Element"
18810 },
18811 {
18812 name: "target",
18813 isMany: true,
18814 isReference: true,
18815 type: "Element"
18816 }
18817 ]
18818 },
18819 {
18820 name: "BaseElement",
18821 isAbstract: true,
18822 properties: [
18823 {
18824 name: "id",
18825 isAttr: true,
18826 type: "String",
18827 isId: true
18828 },
18829 {
18830 name: "documentation",
18831 type: "Documentation",
18832 isMany: true
18833 },
18834 {
18835 name: "extensionDefinitions",
18836 type: "ExtensionDefinition",
18837 isMany: true,
18838 isReference: true
18839 },
18840 {
18841 name: "extensionElements",
18842 type: "ExtensionElements"
18843 }
18844 ]
18845 },
18846 {
18847 name: "Extension",
18848 properties: [
18849 {
18850 name: "mustUnderstand",
18851 "default": false,
18852 isAttr: true,
18853 type: "Boolean"
18854 },
18855 {
18856 name: "definition",
18857 type: "ExtensionDefinition",
18858 isAttr: true,
18859 isReference: true
18860 }
18861 ]
18862 },
18863 {
18864 name: "ExtensionDefinition",
18865 properties: [
18866 {
18867 name: "name",
18868 isAttr: true,
18869 type: "String"
18870 },
18871 {
18872 name: "extensionAttributeDefinitions",
18873 type: "ExtensionAttributeDefinition",
18874 isMany: true
18875 }
18876 ]
18877 },
18878 {
18879 name: "ExtensionAttributeDefinition",
18880 properties: [
18881 {
18882 name: "name",
18883 isAttr: true,
18884 type: "String"
18885 },
18886 {
18887 name: "type",
18888 isAttr: true,
18889 type: "String"
18890 },
18891 {
18892 name: "isReference",
18893 "default": false,
18894 isAttr: true,
18895 type: "Boolean"
18896 },
18897 {
18898 name: "extensionDefinition",
18899 type: "ExtensionDefinition",
18900 isAttr: true,
18901 isReference: true
18902 }
18903 ]
18904 },
18905 {
18906 name: "ExtensionElements",
18907 properties: [
18908 {
18909 name: "valueRef",
18910 isAttr: true,
18911 isReference: true,
18912 type: "Element"
18913 },
18914 {
18915 name: "values",
18916 type: "Element",
18917 isMany: true
18918 },
18919 {
18920 name: "extensionAttributeDefinition",
18921 type: "ExtensionAttributeDefinition",
18922 isAttr: true,
18923 isReference: true
18924 }
18925 ]
18926 },
18927 {
18928 name: "Documentation",
18929 superClass: [
18930 "BaseElement"
18931 ],
18932 properties: [
18933 {
18934 name: "text",
18935 type: "String",
18936 isBody: true
18937 },
18938 {
18939 name: "textFormat",
18940 "default": "text/plain",
18941 isAttr: true,
18942 type: "String"
18943 }
18944 ]
18945 },
18946 {
18947 name: "Event",
18948 isAbstract: true,
18949 superClass: [
18950 "FlowNode",
18951 "InteractionNode"
18952 ],
18953 properties: [
18954 {
18955 name: "properties",
18956 type: "Property",
18957 isMany: true
18958 }
18959 ]
18960 },
18961 {
18962 name: "IntermediateCatchEvent",
18963 superClass: [
18964 "CatchEvent"
18965 ]
18966 },
18967 {
18968 name: "IntermediateThrowEvent",
18969 superClass: [
18970 "ThrowEvent"
18971 ]
18972 },
18973 {
18974 name: "EndEvent",
18975 superClass: [
18976 "ThrowEvent"
18977 ]
18978 },
18979 {
18980 name: "StartEvent",
18981 superClass: [
18982 "CatchEvent"
18983 ],
18984 properties: [
18985 {
18986 name: "isInterrupting",
18987 "default": true,
18988 isAttr: true,
18989 type: "Boolean"
18990 }
18991 ]
18992 },
18993 {
18994 name: "ThrowEvent",
18995 isAbstract: true,
18996 superClass: [
18997 "Event"
18998 ],
18999 properties: [
19000 {
19001 name: "dataInputs",
19002 type: "DataInput",
19003 isMany: true
19004 },
19005 {
19006 name: "dataInputAssociations",
19007 type: "DataInputAssociation",
19008 isMany: true
19009 },
19010 {
19011 name: "inputSet",
19012 type: "InputSet"
19013 },
19014 {
19015 name: "eventDefinitions",
19016 type: "EventDefinition",
19017 isMany: true
19018 },
19019 {
19020 name: "eventDefinitionRef",
19021 type: "EventDefinition",
19022 isMany: true,
19023 isReference: true
19024 }
19025 ]
19026 },
19027 {
19028 name: "CatchEvent",
19029 isAbstract: true,
19030 superClass: [
19031 "Event"
19032 ],
19033 properties: [
19034 {
19035 name: "parallelMultiple",
19036 isAttr: true,
19037 type: "Boolean",
19038 "default": false
19039 },
19040 {
19041 name: "dataOutputs",
19042 type: "DataOutput",
19043 isMany: true
19044 },
19045 {
19046 name: "dataOutputAssociations",
19047 type: "DataOutputAssociation",
19048 isMany: true
19049 },
19050 {
19051 name: "outputSet",
19052 type: "OutputSet"
19053 },
19054 {
19055 name: "eventDefinitions",
19056 type: "EventDefinition",
19057 isMany: true
19058 },
19059 {
19060 name: "eventDefinitionRef",
19061 type: "EventDefinition",
19062 isMany: true,
19063 isReference: true
19064 }
19065 ]
19066 },
19067 {
19068 name: "BoundaryEvent",
19069 superClass: [
19070 "CatchEvent"
19071 ],
19072 properties: [
19073 {
19074 name: "cancelActivity",
19075 "default": true,
19076 isAttr: true,
19077 type: "Boolean"
19078 },
19079 {
19080 name: "attachedToRef",
19081 type: "Activity",
19082 isAttr: true,
19083 isReference: true
19084 }
19085 ]
19086 },
19087 {
19088 name: "EventDefinition",
19089 isAbstract: true,
19090 superClass: [
19091 "RootElement"
19092 ]
19093 },
19094 {
19095 name: "CancelEventDefinition",
19096 superClass: [
19097 "EventDefinition"
19098 ]
19099 },
19100 {
19101 name: "ErrorEventDefinition",
19102 superClass: [
19103 "EventDefinition"
19104 ],
19105 properties: [
19106 {
19107 name: "errorRef",
19108 type: "Error",
19109 isAttr: true,
19110 isReference: true
19111 }
19112 ]
19113 },
19114 {
19115 name: "TerminateEventDefinition",
19116 superClass: [
19117 "EventDefinition"
19118 ]
19119 },
19120 {
19121 name: "EscalationEventDefinition",
19122 superClass: [
19123 "EventDefinition"
19124 ],
19125 properties: [
19126 {
19127 name: "escalationRef",
19128 type: "Escalation",
19129 isAttr: true,
19130 isReference: true
19131 }
19132 ]
19133 },
19134 {
19135 name: "Escalation",
19136 properties: [
19137 {
19138 name: "structureRef",
19139 type: "ItemDefinition",
19140 isAttr: true,
19141 isReference: true
19142 },
19143 {
19144 name: "name",
19145 isAttr: true,
19146 type: "String"
19147 },
19148 {
19149 name: "escalationCode",
19150 isAttr: true,
19151 type: "String"
19152 }
19153 ],
19154 superClass: [
19155 "RootElement"
19156 ]
19157 },
19158 {
19159 name: "CompensateEventDefinition",
19160 superClass: [
19161 "EventDefinition"
19162 ],
19163 properties: [
19164 {
19165 name: "waitForCompletion",
19166 isAttr: true,
19167 type: "Boolean",
19168 "default": true
19169 },
19170 {
19171 name: "activityRef",
19172 type: "Activity",
19173 isAttr: true,
19174 isReference: true
19175 }
19176 ]
19177 },
19178 {
19179 name: "TimerEventDefinition",
19180 superClass: [
19181 "EventDefinition"
19182 ],
19183 properties: [
19184 {
19185 name: "timeDate",
19186 type: "Expression",
19187 xml: {
19188 serialize: "xsi:type"
19189 }
19190 },
19191 {
19192 name: "timeCycle",
19193 type: "Expression",
19194 xml: {
19195 serialize: "xsi:type"
19196 }
19197 },
19198 {
19199 name: "timeDuration",
19200 type: "Expression",
19201 xml: {
19202 serialize: "xsi:type"
19203 }
19204 }
19205 ]
19206 },
19207 {
19208 name: "LinkEventDefinition",
19209 superClass: [
19210 "EventDefinition"
19211 ],
19212 properties: [
19213 {
19214 name: "name",
19215 isAttr: true,
19216 type: "String"
19217 },
19218 {
19219 name: "target",
19220 type: "LinkEventDefinition",
19221 isReference: true
19222 },
19223 {
19224 name: "source",
19225 type: "LinkEventDefinition",
19226 isMany: true,
19227 isReference: true
19228 }
19229 ]
19230 },
19231 {
19232 name: "MessageEventDefinition",
19233 superClass: [
19234 "EventDefinition"
19235 ],
19236 properties: [
19237 {
19238 name: "messageRef",
19239 type: "Message",
19240 isAttr: true,
19241 isReference: true
19242 },
19243 {
19244 name: "operationRef",
19245 type: "Operation",
19246 isAttr: true,
19247 isReference: true
19248 }
19249 ]
19250 },
19251 {
19252 name: "ConditionalEventDefinition",
19253 superClass: [
19254 "EventDefinition"
19255 ],
19256 properties: [
19257 {
19258 name: "condition",
19259 type: "Expression",
19260 xml: {
19261 serialize: "xsi:type"
19262 }
19263 }
19264 ]
19265 },
19266 {
19267 name: "SignalEventDefinition",
19268 superClass: [
19269 "EventDefinition"
19270 ],
19271 properties: [
19272 {
19273 name: "signalRef",
19274 type: "Signal",
19275 isAttr: true,
19276 isReference: true
19277 }
19278 ]
19279 },
19280 {
19281 name: "Signal",
19282 superClass: [
19283 "RootElement"
19284 ],
19285 properties: [
19286 {
19287 name: "structureRef",
19288 type: "ItemDefinition",
19289 isAttr: true,
19290 isReference: true
19291 },
19292 {
19293 name: "name",
19294 isAttr: true,
19295 type: "String"
19296 }
19297 ]
19298 },
19299 {
19300 name: "ImplicitThrowEvent",
19301 superClass: [
19302 "ThrowEvent"
19303 ]
19304 },
19305 {
19306 name: "DataState",
19307 superClass: [
19308 "BaseElement"
19309 ],
19310 properties: [
19311 {
19312 name: "name",
19313 isAttr: true,
19314 type: "String"
19315 }
19316 ]
19317 },
19318 {
19319 name: "ItemAwareElement",
19320 superClass: [
19321 "BaseElement"
19322 ],
19323 properties: [
19324 {
19325 name: "itemSubjectRef",
19326 type: "ItemDefinition",
19327 isAttr: true,
19328 isReference: true
19329 },
19330 {
19331 name: "dataState",
19332 type: "DataState"
19333 }
19334 ]
19335 },
19336 {
19337 name: "DataAssociation",
19338 superClass: [
19339 "BaseElement"
19340 ],
19341 properties: [
19342 {
19343 name: "sourceRef",
19344 type: "ItemAwareElement",
19345 isMany: true,
19346 isReference: true
19347 },
19348 {
19349 name: "targetRef",
19350 type: "ItemAwareElement",
19351 isReference: true
19352 },
19353 {
19354 name: "transformation",
19355 type: "FormalExpression",
19356 xml: {
19357 serialize: "property"
19358 }
19359 },
19360 {
19361 name: "assignment",
19362 type: "Assignment",
19363 isMany: true
19364 }
19365 ]
19366 },
19367 {
19368 name: "DataInput",
19369 superClass: [
19370 "ItemAwareElement"
19371 ],
19372 properties: [
19373 {
19374 name: "name",
19375 isAttr: true,
19376 type: "String"
19377 },
19378 {
19379 name: "isCollection",
19380 "default": false,
19381 isAttr: true,
19382 type: "Boolean"
19383 },
19384 {
19385 name: "inputSetRef",
19386 type: "InputSet",
19387 isMany: true,
19388 isVirtual: true,
19389 isReference: true
19390 },
19391 {
19392 name: "inputSetWithOptional",
19393 type: "InputSet",
19394 isMany: true,
19395 isVirtual: true,
19396 isReference: true
19397 },
19398 {
19399 name: "inputSetWithWhileExecuting",
19400 type: "InputSet",
19401 isMany: true,
19402 isVirtual: true,
19403 isReference: true
19404 }
19405 ]
19406 },
19407 {
19408 name: "DataOutput",
19409 superClass: [
19410 "ItemAwareElement"
19411 ],
19412 properties: [
19413 {
19414 name: "name",
19415 isAttr: true,
19416 type: "String"
19417 },
19418 {
19419 name: "isCollection",
19420 "default": false,
19421 isAttr: true,
19422 type: "Boolean"
19423 },
19424 {
19425 name: "outputSetRef",
19426 type: "OutputSet",
19427 isMany: true,
19428 isVirtual: true,
19429 isReference: true
19430 },
19431 {
19432 name: "outputSetWithOptional",
19433 type: "OutputSet",
19434 isMany: true,
19435 isVirtual: true,
19436 isReference: true
19437 },
19438 {
19439 name: "outputSetWithWhileExecuting",
19440 type: "OutputSet",
19441 isMany: true,
19442 isVirtual: true,
19443 isReference: true
19444 }
19445 ]
19446 },
19447 {
19448 name: "InputSet",
19449 superClass: [
19450 "BaseElement"
19451 ],
19452 properties: [
19453 {
19454 name: "name",
19455 isAttr: true,
19456 type: "String"
19457 },
19458 {
19459 name: "dataInputRefs",
19460 type: "DataInput",
19461 isMany: true,
19462 isReference: true
19463 },
19464 {
19465 name: "optionalInputRefs",
19466 type: "DataInput",
19467 isMany: true,
19468 isReference: true
19469 },
19470 {
19471 name: "whileExecutingInputRefs",
19472 type: "DataInput",
19473 isMany: true,
19474 isReference: true
19475 },
19476 {
19477 name: "outputSetRefs",
19478 type: "OutputSet",
19479 isMany: true,
19480 isReference: true
19481 }
19482 ]
19483 },
19484 {
19485 name: "OutputSet",
19486 superClass: [
19487 "BaseElement"
19488 ],
19489 properties: [
19490 {
19491 name: "dataOutputRefs",
19492 type: "DataOutput",
19493 isMany: true,
19494 isReference: true
19495 },
19496 {
19497 name: "name",
19498 isAttr: true,
19499 type: "String"
19500 },
19501 {
19502 name: "inputSetRefs",
19503 type: "InputSet",
19504 isMany: true,
19505 isReference: true
19506 },
19507 {
19508 name: "optionalOutputRefs",
19509 type: "DataOutput",
19510 isMany: true,
19511 isReference: true
19512 },
19513 {
19514 name: "whileExecutingOutputRefs",
19515 type: "DataOutput",
19516 isMany: true,
19517 isReference: true
19518 }
19519 ]
19520 },
19521 {
19522 name: "Property",
19523 superClass: [
19524 "ItemAwareElement"
19525 ],
19526 properties: [
19527 {
19528 name: "name",
19529 isAttr: true,
19530 type: "String"
19531 }
19532 ]
19533 },
19534 {
19535 name: "DataInputAssociation",
19536 superClass: [
19537 "DataAssociation"
19538 ]
19539 },
19540 {
19541 name: "DataOutputAssociation",
19542 superClass: [
19543 "DataAssociation"
19544 ]
19545 },
19546 {
19547 name: "InputOutputSpecification",
19548 superClass: [
19549 "BaseElement"
19550 ],
19551 properties: [
19552 {
19553 name: "dataInputs",
19554 type: "DataInput",
19555 isMany: true
19556 },
19557 {
19558 name: "dataOutputs",
19559 type: "DataOutput",
19560 isMany: true
19561 },
19562 {
19563 name: "inputSets",
19564 type: "InputSet",
19565 isMany: true
19566 },
19567 {
19568 name: "outputSets",
19569 type: "OutputSet",
19570 isMany: true
19571 }
19572 ]
19573 },
19574 {
19575 name: "DataObject",
19576 superClass: [
19577 "FlowElement",
19578 "ItemAwareElement"
19579 ],
19580 properties: [
19581 {
19582 name: "isCollection",
19583 "default": false,
19584 isAttr: true,
19585 type: "Boolean"
19586 }
19587 ]
19588 },
19589 {
19590 name: "InputOutputBinding",
19591 properties: [
19592 {
19593 name: "inputDataRef",
19594 type: "InputSet",
19595 isAttr: true,
19596 isReference: true
19597 },
19598 {
19599 name: "outputDataRef",
19600 type: "OutputSet",
19601 isAttr: true,
19602 isReference: true
19603 },
19604 {
19605 name: "operationRef",
19606 type: "Operation",
19607 isAttr: true,
19608 isReference: true
19609 }
19610 ]
19611 },
19612 {
19613 name: "Assignment",
19614 superClass: [
19615 "BaseElement"
19616 ],
19617 properties: [
19618 {
19619 name: "from",
19620 type: "Expression",
19621 xml: {
19622 serialize: "xsi:type"
19623 }
19624 },
19625 {
19626 name: "to",
19627 type: "Expression",
19628 xml: {
19629 serialize: "xsi:type"
19630 }
19631 }
19632 ]
19633 },
19634 {
19635 name: "DataStore",
19636 superClass: [
19637 "RootElement",
19638 "ItemAwareElement"
19639 ],
19640 properties: [
19641 {
19642 name: "name",
19643 isAttr: true,
19644 type: "String"
19645 },
19646 {
19647 name: "capacity",
19648 isAttr: true,
19649 type: "Integer"
19650 },
19651 {
19652 name: "isUnlimited",
19653 "default": true,
19654 isAttr: true,
19655 type: "Boolean"
19656 }
19657 ]
19658 },
19659 {
19660 name: "DataStoreReference",
19661 superClass: [
19662 "ItemAwareElement",
19663 "FlowElement"
19664 ],
19665 properties: [
19666 {
19667 name: "dataStoreRef",
19668 type: "DataStore",
19669 isAttr: true,
19670 isReference: true
19671 }
19672 ]
19673 },
19674 {
19675 name: "DataObjectReference",
19676 superClass: [
19677 "ItemAwareElement",
19678 "FlowElement"
19679 ],
19680 properties: [
19681 {
19682 name: "dataObjectRef",
19683 type: "DataObject",
19684 isAttr: true,
19685 isReference: true
19686 }
19687 ]
19688 },
19689 {
19690 name: "ConversationLink",
19691 superClass: [
19692 "BaseElement"
19693 ],
19694 properties: [
19695 {
19696 name: "sourceRef",
19697 type: "InteractionNode",
19698 isAttr: true,
19699 isReference: true
19700 },
19701 {
19702 name: "targetRef",
19703 type: "InteractionNode",
19704 isAttr: true,
19705 isReference: true
19706 },
19707 {
19708 name: "name",
19709 isAttr: true,
19710 type: "String"
19711 }
19712 ]
19713 },
19714 {
19715 name: "ConversationAssociation",
19716 superClass: [
19717 "BaseElement"
19718 ],
19719 properties: [
19720 {
19721 name: "innerConversationNodeRef",
19722 type: "ConversationNode",
19723 isAttr: true,
19724 isReference: true
19725 },
19726 {
19727 name: "outerConversationNodeRef",
19728 type: "ConversationNode",
19729 isAttr: true,
19730 isReference: true
19731 }
19732 ]
19733 },
19734 {
19735 name: "CallConversation",
19736 superClass: [
19737 "ConversationNode"
19738 ],
19739 properties: [
19740 {
19741 name: "calledCollaborationRef",
19742 type: "Collaboration",
19743 isAttr: true,
19744 isReference: true
19745 },
19746 {
19747 name: "participantAssociations",
19748 type: "ParticipantAssociation",
19749 isMany: true
19750 }
19751 ]
19752 },
19753 {
19754 name: "Conversation",
19755 superClass: [
19756 "ConversationNode"
19757 ]
19758 },
19759 {
19760 name: "SubConversation",
19761 superClass: [
19762 "ConversationNode"
19763 ],
19764 properties: [
19765 {
19766 name: "conversationNodes",
19767 type: "ConversationNode",
19768 isMany: true
19769 }
19770 ]
19771 },
19772 {
19773 name: "ConversationNode",
19774 isAbstract: true,
19775 superClass: [
19776 "InteractionNode",
19777 "BaseElement"
19778 ],
19779 properties: [
19780 {
19781 name: "name",
19782 isAttr: true,
19783 type: "String"
19784 },
19785 {
19786 name: "participantRef",
19787 type: "Participant",
19788 isMany: true,
19789 isReference: true
19790 },
19791 {
19792 name: "messageFlowRefs",
19793 type: "MessageFlow",
19794 isMany: true,
19795 isReference: true
19796 },
19797 {
19798 name: "correlationKeys",
19799 type: "CorrelationKey",
19800 isMany: true
19801 }
19802 ]
19803 },
19804 {
19805 name: "GlobalConversation",
19806 superClass: [
19807 "Collaboration"
19808 ]
19809 },
19810 {
19811 name: "PartnerEntity",
19812 superClass: [
19813 "RootElement"
19814 ],
19815 properties: [
19816 {
19817 name: "name",
19818 isAttr: true,
19819 type: "String"
19820 },
19821 {
19822 name: "participantRef",
19823 type: "Participant",
19824 isMany: true,
19825 isReference: true
19826 }
19827 ]
19828 },
19829 {
19830 name: "PartnerRole",
19831 superClass: [
19832 "RootElement"
19833 ],
19834 properties: [
19835 {
19836 name: "name",
19837 isAttr: true,
19838 type: "String"
19839 },
19840 {
19841 name: "participantRef",
19842 type: "Participant",
19843 isMany: true,
19844 isReference: true
19845 }
19846 ]
19847 },
19848 {
19849 name: "CorrelationProperty",
19850 superClass: [
19851 "RootElement"
19852 ],
19853 properties: [
19854 {
19855 name: "correlationPropertyRetrievalExpression",
19856 type: "CorrelationPropertyRetrievalExpression",
19857 isMany: true
19858 },
19859 {
19860 name: "name",
19861 isAttr: true,
19862 type: "String"
19863 },
19864 {
19865 name: "type",
19866 type: "ItemDefinition",
19867 isAttr: true,
19868 isReference: true
19869 }
19870 ]
19871 },
19872 {
19873 name: "Error",
19874 superClass: [
19875 "RootElement"
19876 ],
19877 properties: [
19878 {
19879 name: "structureRef",
19880 type: "ItemDefinition",
19881 isAttr: true,
19882 isReference: true
19883 },
19884 {
19885 name: "name",
19886 isAttr: true,
19887 type: "String"
19888 },
19889 {
19890 name: "errorCode",
19891 isAttr: true,
19892 type: "String"
19893 }
19894 ]
19895 },
19896 {
19897 name: "CorrelationKey",
19898 superClass: [
19899 "BaseElement"
19900 ],
19901 properties: [
19902 {
19903 name: "correlationPropertyRef",
19904 type: "CorrelationProperty",
19905 isMany: true,
19906 isReference: true
19907 },
19908 {
19909 name: "name",
19910 isAttr: true,
19911 type: "String"
19912 }
19913 ]
19914 },
19915 {
19916 name: "Expression",
19917 superClass: [
19918 "BaseElement"
19919 ],
19920 isAbstract: false,
19921 properties: [
19922 {
19923 name: "body",
19924 isBody: true,
19925 type: "String"
19926 }
19927 ]
19928 },
19929 {
19930 name: "FormalExpression",
19931 superClass: [
19932 "Expression"
19933 ],
19934 properties: [
19935 {
19936 name: "language",
19937 isAttr: true,
19938 type: "String"
19939 },
19940 {
19941 name: "evaluatesToTypeRef",
19942 type: "ItemDefinition",
19943 isAttr: true,
19944 isReference: true
19945 }
19946 ]
19947 },
19948 {
19949 name: "Message",
19950 superClass: [
19951 "RootElement"
19952 ],
19953 properties: [
19954 {
19955 name: "name",
19956 isAttr: true,
19957 type: "String"
19958 },
19959 {
19960 name: "itemRef",
19961 type: "ItemDefinition",
19962 isAttr: true,
19963 isReference: true
19964 }
19965 ]
19966 },
19967 {
19968 name: "ItemDefinition",
19969 superClass: [
19970 "RootElement"
19971 ],
19972 properties: [
19973 {
19974 name: "itemKind",
19975 type: "ItemKind",
19976 isAttr: true
19977 },
19978 {
19979 name: "structureRef",
19980 isAttr: true,
19981 type: "String"
19982 },
19983 {
19984 name: "isCollection",
19985 "default": false,
19986 isAttr: true,
19987 type: "Boolean"
19988 },
19989 {
19990 name: "import",
19991 type: "Import",
19992 isAttr: true,
19993 isReference: true
19994 }
19995 ]
19996 },
19997 {
19998 name: "FlowElement",
19999 isAbstract: true,
20000 superClass: [
20001 "BaseElement"
20002 ],
20003 properties: [
20004 {
20005 name: "name",
20006 isAttr: true,
20007 type: "String"
20008 },
20009 {
20010 name: "auditing",
20011 type: "Auditing"
20012 },
20013 {
20014 name: "monitoring",
20015 type: "Monitoring"
20016 },
20017 {
20018 name: "categoryValueRef",
20019 type: "CategoryValue",
20020 isMany: true,
20021 isReference: true
20022 }
20023 ]
20024 },
20025 {
20026 name: "SequenceFlow",
20027 superClass: [
20028 "FlowElement"
20029 ],
20030 properties: [
20031 {
20032 name: "isImmediate",
20033 isAttr: true,
20034 type: "Boolean"
20035 },
20036 {
20037 name: "conditionExpression",
20038 type: "Expression",
20039 xml: {
20040 serialize: "xsi:type"
20041 }
20042 },
20043 {
20044 name: "sourceRef",
20045 type: "FlowNode",
20046 isAttr: true,
20047 isReference: true
20048 },
20049 {
20050 name: "targetRef",
20051 type: "FlowNode",
20052 isAttr: true,
20053 isReference: true
20054 }
20055 ]
20056 },
20057 {
20058 name: "FlowElementsContainer",
20059 isAbstract: true,
20060 superClass: [
20061 "BaseElement"
20062 ],
20063 properties: [
20064 {
20065 name: "laneSets",
20066 type: "LaneSet",
20067 isMany: true
20068 },
20069 {
20070 name: "flowElements",
20071 type: "FlowElement",
20072 isMany: true
20073 }
20074 ]
20075 },
20076 {
20077 name: "CallableElement",
20078 isAbstract: true,
20079 superClass: [
20080 "RootElement"
20081 ],
20082 properties: [
20083 {
20084 name: "name",
20085 isAttr: true,
20086 type: "String"
20087 },
20088 {
20089 name: "ioSpecification",
20090 type: "InputOutputSpecification",
20091 xml: {
20092 serialize: "property"
20093 }
20094 },
20095 {
20096 name: "supportedInterfaceRef",
20097 type: "Interface",
20098 isMany: true,
20099 isReference: true
20100 },
20101 {
20102 name: "ioBinding",
20103 type: "InputOutputBinding",
20104 isMany: true,
20105 xml: {
20106 serialize: "property"
20107 }
20108 }
20109 ]
20110 },
20111 {
20112 name: "FlowNode",
20113 isAbstract: true,
20114 superClass: [
20115 "FlowElement"
20116 ],
20117 properties: [
20118 {
20119 name: "incoming",
20120 type: "SequenceFlow",
20121 isMany: true,
20122 isReference: true
20123 },
20124 {
20125 name: "outgoing",
20126 type: "SequenceFlow",
20127 isMany: true,
20128 isReference: true
20129 },
20130 {
20131 name: "lanes",
20132 type: "Lane",
20133 isMany: true,
20134 isVirtual: true,
20135 isReference: true
20136 }
20137 ]
20138 },
20139 {
20140 name: "CorrelationPropertyRetrievalExpression",
20141 superClass: [
20142 "BaseElement"
20143 ],
20144 properties: [
20145 {
20146 name: "messagePath",
20147 type: "FormalExpression"
20148 },
20149 {
20150 name: "messageRef",
20151 type: "Message",
20152 isAttr: true,
20153 isReference: true
20154 }
20155 ]
20156 },
20157 {
20158 name: "CorrelationPropertyBinding",
20159 superClass: [
20160 "BaseElement"
20161 ],
20162 properties: [
20163 {
20164 name: "dataPath",
20165 type: "FormalExpression"
20166 },
20167 {
20168 name: "correlationPropertyRef",
20169 type: "CorrelationProperty",
20170 isAttr: true,
20171 isReference: true
20172 }
20173 ]
20174 },
20175 {
20176 name: "Resource",
20177 superClass: [
20178 "RootElement"
20179 ],
20180 properties: [
20181 {
20182 name: "name",
20183 isAttr: true,
20184 type: "String"
20185 },
20186 {
20187 name: "resourceParameters",
20188 type: "ResourceParameter",
20189 isMany: true
20190 }
20191 ]
20192 },
20193 {
20194 name: "ResourceParameter",
20195 superClass: [
20196 "BaseElement"
20197 ],
20198 properties: [
20199 {
20200 name: "name",
20201 isAttr: true,
20202 type: "String"
20203 },
20204 {
20205 name: "isRequired",
20206 isAttr: true,
20207 type: "Boolean"
20208 },
20209 {
20210 name: "type",
20211 type: "ItemDefinition",
20212 isAttr: true,
20213 isReference: true
20214 }
20215 ]
20216 },
20217 {
20218 name: "CorrelationSubscription",
20219 superClass: [
20220 "BaseElement"
20221 ],
20222 properties: [
20223 {
20224 name: "correlationKeyRef",
20225 type: "CorrelationKey",
20226 isAttr: true,
20227 isReference: true
20228 },
20229 {
20230 name: "correlationPropertyBinding",
20231 type: "CorrelationPropertyBinding",
20232 isMany: true
20233 }
20234 ]
20235 },
20236 {
20237 name: "MessageFlow",
20238 superClass: [
20239 "BaseElement"
20240 ],
20241 properties: [
20242 {
20243 name: "name",
20244 isAttr: true,
20245 type: "String"
20246 },
20247 {
20248 name: "sourceRef",
20249 type: "InteractionNode",
20250 isAttr: true,
20251 isReference: true
20252 },
20253 {
20254 name: "targetRef",
20255 type: "InteractionNode",
20256 isAttr: true,
20257 isReference: true
20258 },
20259 {
20260 name: "messageRef",
20261 type: "Message",
20262 isAttr: true,
20263 isReference: true
20264 }
20265 ]
20266 },
20267 {
20268 name: "MessageFlowAssociation",
20269 superClass: [
20270 "BaseElement"
20271 ],
20272 properties: [
20273 {
20274 name: "innerMessageFlowRef",
20275 type: "MessageFlow",
20276 isAttr: true,
20277 isReference: true
20278 },
20279 {
20280 name: "outerMessageFlowRef",
20281 type: "MessageFlow",
20282 isAttr: true,
20283 isReference: true
20284 }
20285 ]
20286 },
20287 {
20288 name: "InteractionNode",
20289 isAbstract: true,
20290 properties: [
20291 {
20292 name: "incomingConversationLinks",
20293 type: "ConversationLink",
20294 isMany: true,
20295 isVirtual: true,
20296 isReference: true
20297 },
20298 {
20299 name: "outgoingConversationLinks",
20300 type: "ConversationLink",
20301 isMany: true,
20302 isVirtual: true,
20303 isReference: true
20304 }
20305 ]
20306 },
20307 {
20308 name: "Participant",
20309 superClass: [
20310 "InteractionNode",
20311 "BaseElement"
20312 ],
20313 properties: [
20314 {
20315 name: "name",
20316 isAttr: true,
20317 type: "String"
20318 },
20319 {
20320 name: "interfaceRef",
20321 type: "Interface",
20322 isMany: true,
20323 isReference: true
20324 },
20325 {
20326 name: "participantMultiplicity",
20327 type: "ParticipantMultiplicity"
20328 },
20329 {
20330 name: "endPointRefs",
20331 type: "EndPoint",
20332 isMany: true,
20333 isReference: true
20334 },
20335 {
20336 name: "processRef",
20337 type: "Process",
20338 isAttr: true,
20339 isReference: true
20340 }
20341 ]
20342 },
20343 {
20344 name: "ParticipantAssociation",
20345 superClass: [
20346 "BaseElement"
20347 ],
20348 properties: [
20349 {
20350 name: "innerParticipantRef",
20351 type: "Participant",
20352 isAttr: true,
20353 isReference: true
20354 },
20355 {
20356 name: "outerParticipantRef",
20357 type: "Participant",
20358 isAttr: true,
20359 isReference: true
20360 }
20361 ]
20362 },
20363 {
20364 name: "ParticipantMultiplicity",
20365 properties: [
20366 {
20367 name: "minimum",
20368 "default": 0,
20369 isAttr: true,
20370 type: "Integer"
20371 },
20372 {
20373 name: "maximum",
20374 "default": 1,
20375 isAttr: true,
20376 type: "Integer"
20377 }
20378 ],
20379 superClass: [
20380 "BaseElement"
20381 ]
20382 },
20383 {
20384 name: "Collaboration",
20385 superClass: [
20386 "RootElement"
20387 ],
20388 properties: [
20389 {
20390 name: "name",
20391 isAttr: true,
20392 type: "String"
20393 },
20394 {
20395 name: "isClosed",
20396 isAttr: true,
20397 type: "Boolean"
20398 },
20399 {
20400 name: "participants",
20401 type: "Participant",
20402 isMany: true
20403 },
20404 {
20405 name: "messageFlows",
20406 type: "MessageFlow",
20407 isMany: true
20408 },
20409 {
20410 name: "artifacts",
20411 type: "Artifact",
20412 isMany: true
20413 },
20414 {
20415 name: "conversations",
20416 type: "ConversationNode",
20417 isMany: true
20418 },
20419 {
20420 name: "conversationAssociations",
20421 type: "ConversationAssociation"
20422 },
20423 {
20424 name: "participantAssociations",
20425 type: "ParticipantAssociation",
20426 isMany: true
20427 },
20428 {
20429 name: "messageFlowAssociations",
20430 type: "MessageFlowAssociation",
20431 isMany: true
20432 },
20433 {
20434 name: "correlationKeys",
20435 type: "CorrelationKey",
20436 isMany: true
20437 },
20438 {
20439 name: "choreographyRef",
20440 type: "Choreography",
20441 isMany: true,
20442 isReference: true
20443 },
20444 {
20445 name: "conversationLinks",
20446 type: "ConversationLink",
20447 isMany: true
20448 }
20449 ]
20450 },
20451 {
20452 name: "ChoreographyActivity",
20453 isAbstract: true,
20454 superClass: [
20455 "FlowNode"
20456 ],
20457 properties: [
20458 {
20459 name: "participantRef",
20460 type: "Participant",
20461 isMany: true,
20462 isReference: true
20463 },
20464 {
20465 name: "initiatingParticipantRef",
20466 type: "Participant",
20467 isAttr: true,
20468 isReference: true
20469 },
20470 {
20471 name: "correlationKeys",
20472 type: "CorrelationKey",
20473 isMany: true
20474 },
20475 {
20476 name: "loopType",
20477 type: "ChoreographyLoopType",
20478 "default": "None",
20479 isAttr: true
20480 }
20481 ]
20482 },
20483 {
20484 name: "CallChoreography",
20485 superClass: [
20486 "ChoreographyActivity"
20487 ],
20488 properties: [
20489 {
20490 name: "calledChoreographyRef",
20491 type: "Choreography",
20492 isAttr: true,
20493 isReference: true
20494 },
20495 {
20496 name: "participantAssociations",
20497 type: "ParticipantAssociation",
20498 isMany: true
20499 }
20500 ]
20501 },
20502 {
20503 name: "SubChoreography",
20504 superClass: [
20505 "ChoreographyActivity",
20506 "FlowElementsContainer"
20507 ],
20508 properties: [
20509 {
20510 name: "artifacts",
20511 type: "Artifact",
20512 isMany: true
20513 }
20514 ]
20515 },
20516 {
20517 name: "ChoreographyTask",
20518 superClass: [
20519 "ChoreographyActivity"
20520 ],
20521 properties: [
20522 {
20523 name: "messageFlowRef",
20524 type: "MessageFlow",
20525 isMany: true,
20526 isReference: true
20527 }
20528 ]
20529 },
20530 {
20531 name: "Choreography",
20532 superClass: [
20533 "Collaboration",
20534 "FlowElementsContainer"
20535 ]
20536 },
20537 {
20538 name: "GlobalChoreographyTask",
20539 superClass: [
20540 "Choreography"
20541 ],
20542 properties: [
20543 {
20544 name: "initiatingParticipantRef",
20545 type: "Participant",
20546 isAttr: true,
20547 isReference: true
20548 }
20549 ]
20550 },
20551 {
20552 name: "TextAnnotation",
20553 superClass: [
20554 "Artifact"
20555 ],
20556 properties: [
20557 {
20558 name: "text",
20559 type: "String"
20560 },
20561 {
20562 name: "textFormat",
20563 "default": "text/plain",
20564 isAttr: true,
20565 type: "String"
20566 }
20567 ]
20568 },
20569 {
20570 name: "Group",
20571 superClass: [
20572 "Artifact"
20573 ],
20574 properties: [
20575 {
20576 name: "categoryValueRef",
20577 type: "CategoryValue",
20578 isAttr: true,
20579 isReference: true
20580 }
20581 ]
20582 },
20583 {
20584 name: "Association",
20585 superClass: [
20586 "Artifact"
20587 ],
20588 properties: [
20589 {
20590 name: "associationDirection",
20591 type: "AssociationDirection",
20592 isAttr: true
20593 },
20594 {
20595 name: "sourceRef",
20596 type: "BaseElement",
20597 isAttr: true,
20598 isReference: true
20599 },
20600 {
20601 name: "targetRef",
20602 type: "BaseElement",
20603 isAttr: true,
20604 isReference: true
20605 }
20606 ]
20607 },
20608 {
20609 name: "Category",
20610 superClass: [
20611 "RootElement"
20612 ],
20613 properties: [
20614 {
20615 name: "categoryValue",
20616 type: "CategoryValue",
20617 isMany: true
20618 },
20619 {
20620 name: "name",
20621 isAttr: true,
20622 type: "String"
20623 }
20624 ]
20625 },
20626 {
20627 name: "Artifact",
20628 isAbstract: true,
20629 superClass: [
20630 "BaseElement"
20631 ]
20632 },
20633 {
20634 name: "CategoryValue",
20635 superClass: [
20636 "BaseElement"
20637 ],
20638 properties: [
20639 {
20640 name: "categorizedFlowElements",
20641 type: "FlowElement",
20642 isMany: true,
20643 isVirtual: true,
20644 isReference: true
20645 },
20646 {
20647 name: "value",
20648 isAttr: true,
20649 type: "String"
20650 }
20651 ]
20652 },
20653 {
20654 name: "Activity",
20655 isAbstract: true,
20656 superClass: [
20657 "FlowNode"
20658 ],
20659 properties: [
20660 {
20661 name: "isForCompensation",
20662 "default": false,
20663 isAttr: true,
20664 type: "Boolean"
20665 },
20666 {
20667 name: "default",
20668 type: "SequenceFlow",
20669 isAttr: true,
20670 isReference: true
20671 },
20672 {
20673 name: "ioSpecification",
20674 type: "InputOutputSpecification",
20675 xml: {
20676 serialize: "property"
20677 }
20678 },
20679 {
20680 name: "boundaryEventRefs",
20681 type: "BoundaryEvent",
20682 isMany: true,
20683 isReference: true
20684 },
20685 {
20686 name: "properties",
20687 type: "Property",
20688 isMany: true
20689 },
20690 {
20691 name: "dataInputAssociations",
20692 type: "DataInputAssociation",
20693 isMany: true
20694 },
20695 {
20696 name: "dataOutputAssociations",
20697 type: "DataOutputAssociation",
20698 isMany: true
20699 },
20700 {
20701 name: "startQuantity",
20702 "default": 1,
20703 isAttr: true,
20704 type: "Integer"
20705 },
20706 {
20707 name: "resources",
20708 type: "ResourceRole",
20709 isMany: true
20710 },
20711 {
20712 name: "completionQuantity",
20713 "default": 1,
20714 isAttr: true,
20715 type: "Integer"
20716 },
20717 {
20718 name: "loopCharacteristics",
20719 type: "LoopCharacteristics"
20720 }
20721 ]
20722 },
20723 {
20724 name: "ServiceTask",
20725 superClass: [
20726 "Task"
20727 ],
20728 properties: [
20729 {
20730 name: "implementation",
20731 isAttr: true,
20732 type: "String"
20733 },
20734 {
20735 name: "operationRef",
20736 type: "Operation",
20737 isAttr: true,
20738 isReference: true
20739 }
20740 ]
20741 },
20742 {
20743 name: "SubProcess",
20744 superClass: [
20745 "Activity",
20746 "FlowElementsContainer",
20747 "InteractionNode"
20748 ],
20749 properties: [
20750 {
20751 name: "triggeredByEvent",
20752 "default": false,
20753 isAttr: true,
20754 type: "Boolean"
20755 },
20756 {
20757 name: "artifacts",
20758 type: "Artifact",
20759 isMany: true
20760 }
20761 ]
20762 },
20763 {
20764 name: "LoopCharacteristics",
20765 isAbstract: true,
20766 superClass: [
20767 "BaseElement"
20768 ]
20769 },
20770 {
20771 name: "MultiInstanceLoopCharacteristics",
20772 superClass: [
20773 "LoopCharacteristics"
20774 ],
20775 properties: [
20776 {
20777 name: "isSequential",
20778 "default": false,
20779 isAttr: true,
20780 type: "Boolean"
20781 },
20782 {
20783 name: "behavior",
20784 type: "MultiInstanceBehavior",
20785 "default": "All",
20786 isAttr: true
20787 },
20788 {
20789 name: "loopCardinality",
20790 type: "Expression",
20791 xml: {
20792 serialize: "xsi:type"
20793 }
20794 },
20795 {
20796 name: "loopDataInputRef",
20797 type: "ItemAwareElement",
20798 isReference: true
20799 },
20800 {
20801 name: "loopDataOutputRef",
20802 type: "ItemAwareElement",
20803 isReference: true
20804 },
20805 {
20806 name: "inputDataItem",
20807 type: "DataInput",
20808 xml: {
20809 serialize: "property"
20810 }
20811 },
20812 {
20813 name: "outputDataItem",
20814 type: "DataOutput",
20815 xml: {
20816 serialize: "property"
20817 }
20818 },
20819 {
20820 name: "complexBehaviorDefinition",
20821 type: "ComplexBehaviorDefinition",
20822 isMany: true
20823 },
20824 {
20825 name: "completionCondition",
20826 type: "Expression",
20827 xml: {
20828 serialize: "xsi:type"
20829 }
20830 },
20831 {
20832 name: "oneBehaviorEventRef",
20833 type: "EventDefinition",
20834 isAttr: true,
20835 isReference: true
20836 },
20837 {
20838 name: "noneBehaviorEventRef",
20839 type: "EventDefinition",
20840 isAttr: true,
20841 isReference: true
20842 }
20843 ]
20844 },
20845 {
20846 name: "StandardLoopCharacteristics",
20847 superClass: [
20848 "LoopCharacteristics"
20849 ],
20850 properties: [
20851 {
20852 name: "testBefore",
20853 "default": false,
20854 isAttr: true,
20855 type: "Boolean"
20856 },
20857 {
20858 name: "loopCondition",
20859 type: "Expression",
20860 xml: {
20861 serialize: "xsi:type"
20862 }
20863 },
20864 {
20865 name: "loopMaximum",
20866 type: "Integer",
20867 isAttr: true
20868 }
20869 ]
20870 },
20871 {
20872 name: "CallActivity",
20873 superClass: [
20874 "Activity",
20875 "InteractionNode"
20876 ],
20877 properties: [
20878 {
20879 name: "calledElement",
20880 type: "String",
20881 isAttr: true
20882 }
20883 ]
20884 },
20885 {
20886 name: "Task",
20887 superClass: [
20888 "Activity",
20889 "InteractionNode"
20890 ]
20891 },
20892 {
20893 name: "SendTask",
20894 superClass: [
20895 "Task"
20896 ],
20897 properties: [
20898 {
20899 name: "implementation",
20900 isAttr: true,
20901 type: "String"
20902 },
20903 {
20904 name: "operationRef",
20905 type: "Operation",
20906 isAttr: true,
20907 isReference: true
20908 },
20909 {
20910 name: "messageRef",
20911 type: "Message",
20912 isAttr: true,
20913 isReference: true
20914 }
20915 ]
20916 },
20917 {
20918 name: "ReceiveTask",
20919 superClass: [
20920 "Task"
20921 ],
20922 properties: [
20923 {
20924 name: "implementation",
20925 isAttr: true,
20926 type: "String"
20927 },
20928 {
20929 name: "instantiate",
20930 "default": false,
20931 isAttr: true,
20932 type: "Boolean"
20933 },
20934 {
20935 name: "operationRef",
20936 type: "Operation",
20937 isAttr: true,
20938 isReference: true
20939 },
20940 {
20941 name: "messageRef",
20942 type: "Message",
20943 isAttr: true,
20944 isReference: true
20945 }
20946 ]
20947 },
20948 {
20949 name: "ScriptTask",
20950 superClass: [
20951 "Task"
20952 ],
20953 properties: [
20954 {
20955 name: "scriptFormat",
20956 isAttr: true,
20957 type: "String"
20958 },
20959 {
20960 name: "script",
20961 type: "String"
20962 }
20963 ]
20964 },
20965 {
20966 name: "BusinessRuleTask",
20967 superClass: [
20968 "Task"
20969 ],
20970 properties: [
20971 {
20972 name: "implementation",
20973 isAttr: true,
20974 type: "String"
20975 }
20976 ]
20977 },
20978 {
20979 name: "AdHocSubProcess",
20980 superClass: [
20981 "SubProcess"
20982 ],
20983 properties: [
20984 {
20985 name: "completionCondition",
20986 type: "Expression",
20987 xml: {
20988 serialize: "xsi:type"
20989 }
20990 },
20991 {
20992 name: "ordering",
20993 type: "AdHocOrdering",
20994 isAttr: true
20995 },
20996 {
20997 name: "cancelRemainingInstances",
20998 "default": true,
20999 isAttr: true,
21000 type: "Boolean"
21001 }
21002 ]
21003 },
21004 {
21005 name: "Transaction",
21006 superClass: [
21007 "SubProcess"
21008 ],
21009 properties: [
21010 {
21011 name: "protocol",
21012 isAttr: true,
21013 type: "String"
21014 },
21015 {
21016 name: "method",
21017 isAttr: true,
21018 type: "String"
21019 }
21020 ]
21021 },
21022 {
21023 name: "GlobalScriptTask",
21024 superClass: [
21025 "GlobalTask"
21026 ],
21027 properties: [
21028 {
21029 name: "scriptLanguage",
21030 isAttr: true,
21031 type: "String"
21032 },
21033 {
21034 name: "script",
21035 isAttr: true,
21036 type: "String"
21037 }
21038 ]
21039 },
21040 {
21041 name: "GlobalBusinessRuleTask",
21042 superClass: [
21043 "GlobalTask"
21044 ],
21045 properties: [
21046 {
21047 name: "implementation",
21048 isAttr: true,
21049 type: "String"
21050 }
21051 ]
21052 },
21053 {
21054 name: "ComplexBehaviorDefinition",
21055 superClass: [
21056 "BaseElement"
21057 ],
21058 properties: [
21059 {
21060 name: "condition",
21061 type: "FormalExpression"
21062 },
21063 {
21064 name: "event",
21065 type: "ImplicitThrowEvent"
21066 }
21067 ]
21068 },
21069 {
21070 name: "ResourceRole",
21071 superClass: [
21072 "BaseElement"
21073 ],
21074 properties: [
21075 {
21076 name: "resourceRef",
21077 type: "Resource",
21078 isReference: true
21079 },
21080 {
21081 name: "resourceParameterBindings",
21082 type: "ResourceParameterBinding",
21083 isMany: true
21084 },
21085 {
21086 name: "resourceAssignmentExpression",
21087 type: "ResourceAssignmentExpression"
21088 },
21089 {
21090 name: "name",
21091 isAttr: true,
21092 type: "String"
21093 }
21094 ]
21095 },
21096 {
21097 name: "ResourceParameterBinding",
21098 properties: [
21099 {
21100 name: "expression",
21101 type: "Expression",
21102 xml: {
21103 serialize: "xsi:type"
21104 }
21105 },
21106 {
21107 name: "parameterRef",
21108 type: "ResourceParameter",
21109 isAttr: true,
21110 isReference: true
21111 }
21112 ],
21113 superClass: [
21114 "BaseElement"
21115 ]
21116 },
21117 {
21118 name: "ResourceAssignmentExpression",
21119 properties: [
21120 {
21121 name: "expression",
21122 type: "Expression",
21123 xml: {
21124 serialize: "xsi:type"
21125 }
21126 }
21127 ],
21128 superClass: [
21129 "BaseElement"
21130 ]
21131 },
21132 {
21133 name: "Import",
21134 properties: [
21135 {
21136 name: "importType",
21137 isAttr: true,
21138 type: "String"
21139 },
21140 {
21141 name: "location",
21142 isAttr: true,
21143 type: "String"
21144 },
21145 {
21146 name: "namespace",
21147 isAttr: true,
21148 type: "String"
21149 }
21150 ]
21151 },
21152 {
21153 name: "Definitions",
21154 superClass: [
21155 "BaseElement"
21156 ],
21157 properties: [
21158 {
21159 name: "name",
21160 isAttr: true,
21161 type: "String"
21162 },
21163 {
21164 name: "targetNamespace",
21165 isAttr: true,
21166 type: "String"
21167 },
21168 {
21169 name: "expressionLanguage",
21170 "default": "http://www.w3.org/1999/XPath",
21171 isAttr: true,
21172 type: "String"
21173 },
21174 {
21175 name: "typeLanguage",
21176 "default": "http://www.w3.org/2001/XMLSchema",
21177 isAttr: true,
21178 type: "String"
21179 },
21180 {
21181 name: "imports",
21182 type: "Import",
21183 isMany: true
21184 },
21185 {
21186 name: "extensions",
21187 type: "Extension",
21188 isMany: true
21189 },
21190 {
21191 name: "rootElements",
21192 type: "RootElement",
21193 isMany: true
21194 },
21195 {
21196 name: "diagrams",
21197 isMany: true,
21198 type: "bpmndi:BPMNDiagram"
21199 },
21200 {
21201 name: "exporter",
21202 isAttr: true,
21203 type: "String"
21204 },
21205 {
21206 name: "relationships",
21207 type: "Relationship",
21208 isMany: true
21209 },
21210 {
21211 name: "exporterVersion",
21212 isAttr: true,
21213 type: "String"
21214 }
21215 ]
21216 }
21217 ];
21218 var enumerations$3 = [
21219 {
21220 name: "ProcessType",
21221 literalValues: [
21222 {
21223 name: "None"
21224 },
21225 {
21226 name: "Public"
21227 },
21228 {
21229 name: "Private"
21230 }
21231 ]
21232 },
21233 {
21234 name: "GatewayDirection",
21235 literalValues: [
21236 {
21237 name: "Unspecified"
21238 },
21239 {
21240 name: "Converging"
21241 },
21242 {
21243 name: "Diverging"
21244 },
21245 {
21246 name: "Mixed"
21247 }
21248 ]
21249 },
21250 {
21251 name: "EventBasedGatewayType",
21252 literalValues: [
21253 {
21254 name: "Parallel"
21255 },
21256 {
21257 name: "Exclusive"
21258 }
21259 ]
21260 },
21261 {
21262 name: "RelationshipDirection",
21263 literalValues: [
21264 {
21265 name: "None"
21266 },
21267 {
21268 name: "Forward"
21269 },
21270 {
21271 name: "Backward"
21272 },
21273 {
21274 name: "Both"
21275 }
21276 ]
21277 },
21278 {
21279 name: "ItemKind",
21280 literalValues: [
21281 {
21282 name: "Physical"
21283 },
21284 {
21285 name: "Information"
21286 }
21287 ]
21288 },
21289 {
21290 name: "ChoreographyLoopType",
21291 literalValues: [
21292 {
21293 name: "None"
21294 },
21295 {
21296 name: "Standard"
21297 },
21298 {
21299 name: "MultiInstanceSequential"
21300 },
21301 {
21302 name: "MultiInstanceParallel"
21303 }
21304 ]
21305 },
21306 {
21307 name: "AssociationDirection",
21308 literalValues: [
21309 {
21310 name: "None"
21311 },
21312 {
21313 name: "One"
21314 },
21315 {
21316 name: "Both"
21317 }
21318 ]
21319 },
21320 {
21321 name: "MultiInstanceBehavior",
21322 literalValues: [
21323 {
21324 name: "None"
21325 },
21326 {
21327 name: "One"
21328 },
21329 {
21330 name: "All"
21331 },
21332 {
21333 name: "Complex"
21334 }
21335 ]
21336 },
21337 {
21338 name: "AdHocOrdering",
21339 literalValues: [
21340 {
21341 name: "Parallel"
21342 },
21343 {
21344 name: "Sequential"
21345 }
21346 ]
21347 }
21348 ];
21349 var xml$1 = {
21350 tagAlias: "lowerCase",
21351 typePrefix: "t"
21352 };
21353 var BpmnPackage = {
21354 name: name$5,
21355 uri: uri$5,
21356 prefix: prefix$5,
21357 associations: associations$5,
21358 types: types$5,
21359 enumerations: enumerations$3,
21360 xml: xml$1
21361 };
21362
21363 var name$4 = "BPMNDI";
21364 var uri$4 = "http://www.omg.org/spec/BPMN/20100524/DI";
21365 var prefix$4 = "bpmndi";
21366 var types$4 = [
21367 {
21368 name: "BPMNDiagram",
21369 properties: [
21370 {
21371 name: "plane",
21372 type: "BPMNPlane",
21373 redefines: "di:Diagram#rootElement"
21374 },
21375 {
21376 name: "labelStyle",
21377 type: "BPMNLabelStyle",
21378 isMany: true
21379 }
21380 ],
21381 superClass: [
21382 "di:Diagram"
21383 ]
21384 },
21385 {
21386 name: "BPMNPlane",
21387 properties: [
21388 {
21389 name: "bpmnElement",
21390 isAttr: true,
21391 isReference: true,
21392 type: "bpmn:BaseElement",
21393 redefines: "di:DiagramElement#modelElement"
21394 }
21395 ],
21396 superClass: [
21397 "di:Plane"
21398 ]
21399 },
21400 {
21401 name: "BPMNShape",
21402 properties: [
21403 {
21404 name: "bpmnElement",
21405 isAttr: true,
21406 isReference: true,
21407 type: "bpmn:BaseElement",
21408 redefines: "di:DiagramElement#modelElement"
21409 },
21410 {
21411 name: "isHorizontal",
21412 isAttr: true,
21413 type: "Boolean"
21414 },
21415 {
21416 name: "isExpanded",
21417 isAttr: true,
21418 type: "Boolean"
21419 },
21420 {
21421 name: "isMarkerVisible",
21422 isAttr: true,
21423 type: "Boolean"
21424 },
21425 {
21426 name: "label",
21427 type: "BPMNLabel"
21428 },
21429 {
21430 name: "isMessageVisible",
21431 isAttr: true,
21432 type: "Boolean"
21433 },
21434 {
21435 name: "participantBandKind",
21436 type: "ParticipantBandKind",
21437 isAttr: true
21438 },
21439 {
21440 name: "choreographyActivityShape",
21441 type: "BPMNShape",
21442 isAttr: true,
21443 isReference: true
21444 }
21445 ],
21446 superClass: [
21447 "di:LabeledShape"
21448 ]
21449 },
21450 {
21451 name: "BPMNEdge",
21452 properties: [
21453 {
21454 name: "label",
21455 type: "BPMNLabel"
21456 },
21457 {
21458 name: "bpmnElement",
21459 isAttr: true,
21460 isReference: true,
21461 type: "bpmn:BaseElement",
21462 redefines: "di:DiagramElement#modelElement"
21463 },
21464 {
21465 name: "sourceElement",
21466 isAttr: true,
21467 isReference: true,
21468 type: "di:DiagramElement",
21469 redefines: "di:Edge#source"
21470 },
21471 {
21472 name: "targetElement",
21473 isAttr: true,
21474 isReference: true,
21475 type: "di:DiagramElement",
21476 redefines: "di:Edge#target"
21477 },
21478 {
21479 name: "messageVisibleKind",
21480 type: "MessageVisibleKind",
21481 isAttr: true,
21482 "default": "initiating"
21483 }
21484 ],
21485 superClass: [
21486 "di:LabeledEdge"
21487 ]
21488 },
21489 {
21490 name: "BPMNLabel",
21491 properties: [
21492 {
21493 name: "labelStyle",
21494 type: "BPMNLabelStyle",
21495 isAttr: true,
21496 isReference: true,
21497 redefines: "di:DiagramElement#style"
21498 }
21499 ],
21500 superClass: [
21501 "di:Label"
21502 ]
21503 },
21504 {
21505 name: "BPMNLabelStyle",
21506 properties: [
21507 {
21508 name: "font",
21509 type: "dc:Font"
21510 }
21511 ],
21512 superClass: [
21513 "di:Style"
21514 ]
21515 }
21516 ];
21517 var enumerations$2 = [
21518 {
21519 name: "ParticipantBandKind",
21520 literalValues: [
21521 {
21522 name: "top_initiating"
21523 },
21524 {
21525 name: "middle_initiating"
21526 },
21527 {
21528 name: "bottom_initiating"
21529 },
21530 {
21531 name: "top_non_initiating"
21532 },
21533 {
21534 name: "middle_non_initiating"
21535 },
21536 {
21537 name: "bottom_non_initiating"
21538 }
21539 ]
21540 },
21541 {
21542 name: "MessageVisibleKind",
21543 literalValues: [
21544 {
21545 name: "initiating"
21546 },
21547 {
21548 name: "non_initiating"
21549 }
21550 ]
21551 }
21552 ];
21553 var associations$4 = [
21554 ];
21555 var BpmnDiPackage = {
21556 name: name$4,
21557 uri: uri$4,
21558 prefix: prefix$4,
21559 types: types$4,
21560 enumerations: enumerations$2,
21561 associations: associations$4
21562 };
21563
21564 var name$3 = "DC";
21565 var uri$3 = "http://www.omg.org/spec/DD/20100524/DC";
21566 var prefix$3 = "dc";
21567 var types$3 = [
21568 {
21569 name: "Boolean"
21570 },
21571 {
21572 name: "Integer"
21573 },
21574 {
21575 name: "Real"
21576 },
21577 {
21578 name: "String"
21579 },
21580 {
21581 name: "Font",
21582 properties: [
21583 {
21584 name: "name",
21585 type: "String",
21586 isAttr: true
21587 },
21588 {
21589 name: "size",
21590 type: "Real",
21591 isAttr: true
21592 },
21593 {
21594 name: "isBold",
21595 type: "Boolean",
21596 isAttr: true
21597 },
21598 {
21599 name: "isItalic",
21600 type: "Boolean",
21601 isAttr: true
21602 },
21603 {
21604 name: "isUnderline",
21605 type: "Boolean",
21606 isAttr: true
21607 },
21608 {
21609 name: "isStrikeThrough",
21610 type: "Boolean",
21611 isAttr: true
21612 }
21613 ]
21614 },
21615 {
21616 name: "Point",
21617 properties: [
21618 {
21619 name: "x",
21620 type: "Real",
21621 "default": "0",
21622 isAttr: true
21623 },
21624 {
21625 name: "y",
21626 type: "Real",
21627 "default": "0",
21628 isAttr: true
21629 }
21630 ]
21631 },
21632 {
21633 name: "Bounds",
21634 properties: [
21635 {
21636 name: "x",
21637 type: "Real",
21638 "default": "0",
21639 isAttr: true
21640 },
21641 {
21642 name: "y",
21643 type: "Real",
21644 "default": "0",
21645 isAttr: true
21646 },
21647 {
21648 name: "width",
21649 type: "Real",
21650 isAttr: true
21651 },
21652 {
21653 name: "height",
21654 type: "Real",
21655 isAttr: true
21656 }
21657 ]
21658 }
21659 ];
21660 var associations$3 = [
21661 ];
21662 var DcPackage = {
21663 name: name$3,
21664 uri: uri$3,
21665 prefix: prefix$3,
21666 types: types$3,
21667 associations: associations$3
21668 };
21669
21670 var name$2 = "DI";
21671 var uri$2 = "http://www.omg.org/spec/DD/20100524/DI";
21672 var prefix$2 = "di";
21673 var types$2 = [
21674 {
21675 name: "DiagramElement",
21676 isAbstract: true,
21677 properties: [
21678 {
21679 name: "id",
21680 isAttr: true,
21681 isId: true,
21682 type: "String"
21683 },
21684 {
21685 name: "extension",
21686 type: "Extension"
21687 },
21688 {
21689 name: "owningDiagram",
21690 type: "Diagram",
21691 isReadOnly: true,
21692 isVirtual: true,
21693 isReference: true
21694 },
21695 {
21696 name: "owningElement",
21697 type: "DiagramElement",
21698 isReadOnly: true,
21699 isVirtual: true,
21700 isReference: true
21701 },
21702 {
21703 name: "modelElement",
21704 isReadOnly: true,
21705 isVirtual: true,
21706 isReference: true,
21707 type: "Element"
21708 },
21709 {
21710 name: "style",
21711 type: "Style",
21712 isReadOnly: true,
21713 isVirtual: true,
21714 isReference: true
21715 },
21716 {
21717 name: "ownedElement",
21718 type: "DiagramElement",
21719 isReadOnly: true,
21720 isMany: true,
21721 isVirtual: true
21722 }
21723 ]
21724 },
21725 {
21726 name: "Node",
21727 isAbstract: true,
21728 superClass: [
21729 "DiagramElement"
21730 ]
21731 },
21732 {
21733 name: "Edge",
21734 isAbstract: true,
21735 superClass: [
21736 "DiagramElement"
21737 ],
21738 properties: [
21739 {
21740 name: "source",
21741 type: "DiagramElement",
21742 isReadOnly: true,
21743 isVirtual: true,
21744 isReference: true
21745 },
21746 {
21747 name: "target",
21748 type: "DiagramElement",
21749 isReadOnly: true,
21750 isVirtual: true,
21751 isReference: true
21752 },
21753 {
21754 name: "waypoint",
21755 isUnique: false,
21756 isMany: true,
21757 type: "dc:Point",
21758 xml: {
21759 serialize: "xsi:type"
21760 }
21761 }
21762 ]
21763 },
21764 {
21765 name: "Diagram",
21766 isAbstract: true,
21767 properties: [
21768 {
21769 name: "id",
21770 isAttr: true,
21771 isId: true,
21772 type: "String"
21773 },
21774 {
21775 name: "rootElement",
21776 type: "DiagramElement",
21777 isReadOnly: true,
21778 isVirtual: true
21779 },
21780 {
21781 name: "name",
21782 isAttr: true,
21783 type: "String"
21784 },
21785 {
21786 name: "documentation",
21787 isAttr: true,
21788 type: "String"
21789 },
21790 {
21791 name: "resolution",
21792 isAttr: true,
21793 type: "Real"
21794 },
21795 {
21796 name: "ownedStyle",
21797 type: "Style",
21798 isReadOnly: true,
21799 isMany: true,
21800 isVirtual: true
21801 }
21802 ]
21803 },
21804 {
21805 name: "Shape",
21806 isAbstract: true,
21807 superClass: [
21808 "Node"
21809 ],
21810 properties: [
21811 {
21812 name: "bounds",
21813 type: "dc:Bounds"
21814 }
21815 ]
21816 },
21817 {
21818 name: "Plane",
21819 isAbstract: true,
21820 superClass: [
21821 "Node"
21822 ],
21823 properties: [
21824 {
21825 name: "planeElement",
21826 type: "DiagramElement",
21827 subsettedProperty: "DiagramElement-ownedElement",
21828 isMany: true
21829 }
21830 ]
21831 },
21832 {
21833 name: "LabeledEdge",
21834 isAbstract: true,
21835 superClass: [
21836 "Edge"
21837 ],
21838 properties: [
21839 {
21840 name: "ownedLabel",
21841 type: "Label",
21842 isReadOnly: true,
21843 subsettedProperty: "DiagramElement-ownedElement",
21844 isMany: true,
21845 isVirtual: true
21846 }
21847 ]
21848 },
21849 {
21850 name: "LabeledShape",
21851 isAbstract: true,
21852 superClass: [
21853 "Shape"
21854 ],
21855 properties: [
21856 {
21857 name: "ownedLabel",
21858 type: "Label",
21859 isReadOnly: true,
21860 subsettedProperty: "DiagramElement-ownedElement",
21861 isMany: true,
21862 isVirtual: true
21863 }
21864 ]
21865 },
21866 {
21867 name: "Label",
21868 isAbstract: true,
21869 superClass: [
21870 "Node"
21871 ],
21872 properties: [
21873 {
21874 name: "bounds",
21875 type: "dc:Bounds"
21876 }
21877 ]
21878 },
21879 {
21880 name: "Style",
21881 isAbstract: true,
21882 properties: [
21883 {
21884 name: "id",
21885 isAttr: true,
21886 isId: true,
21887 type: "String"
21888 }
21889 ]
21890 },
21891 {
21892 name: "Extension",
21893 properties: [
21894 {
21895 name: "values",
21896 isMany: true,
21897 type: "Element"
21898 }
21899 ]
21900 }
21901 ];
21902 var associations$2 = [
21903 ];
21904 var xml = {
21905 tagAlias: "lowerCase"
21906 };
21907 var DiPackage = {
21908 name: name$2,
21909 uri: uri$2,
21910 prefix: prefix$2,
21911 types: types$2,
21912 associations: associations$2,
21913 xml: xml
21914 };
21915
21916 var name$1 = "bpmn.io colors for BPMN";
21917 var uri$1 = "http://bpmn.io/schema/bpmn/biocolor/1.0";
21918 var prefix$1 = "bioc";
21919 var types$1 = [
21920 {
21921 name: "ColoredShape",
21922 "extends": [
21923 "bpmndi:BPMNShape"
21924 ],
21925 properties: [
21926 {
21927 name: "stroke",
21928 isAttr: true,
21929 type: "String"
21930 },
21931 {
21932 name: "fill",
21933 isAttr: true,
21934 type: "String"
21935 }
21936 ]
21937 },
21938 {
21939 name: "ColoredEdge",
21940 "extends": [
21941 "bpmndi:BPMNEdge"
21942 ],
21943 properties: [
21944 {
21945 name: "stroke",
21946 isAttr: true,
21947 type: "String"
21948 },
21949 {
21950 name: "fill",
21951 isAttr: true,
21952 type: "String"
21953 }
21954 ]
21955 }
21956 ];
21957 var enumerations$1 = [
21958 ];
21959 var associations$1 = [
21960 ];
21961 var BiocPackage = {
21962 name: name$1,
21963 uri: uri$1,
21964 prefix: prefix$1,
21965 types: types$1,
21966 enumerations: enumerations$1,
21967 associations: associations$1
21968 };
21969
21970 var name = "BPMN in Color";
21971 var uri = "http://www.omg.org/spec/BPMN/non-normative/color/1.0";
21972 var prefix = "color";
21973 var types = [
21974 {
21975 name: "ColoredLabel",
21976 "extends": [
21977 "bpmndi:BPMNLabel"
21978 ],
21979 properties: [
21980 {
21981 name: "color",
21982 isAttr: true,
21983 type: "String"
21984 }
21985 ]
21986 },
21987 {
21988 name: "ColoredShape",
21989 "extends": [
21990 "bpmndi:BPMNShape"
21991 ],
21992 properties: [
21993 {
21994 name: "background-color",
21995 isAttr: true,
21996 type: "String"
21997 },
21998 {
21999 name: "border-color",
22000 isAttr: true,
22001 type: "String"
22002 }
22003 ]
22004 },
22005 {
22006 name: "ColoredEdge",
22007 "extends": [
22008 "bpmndi:BPMNEdge"
22009 ],
22010 properties: [
22011 {
22012 name: "border-color",
22013 isAttr: true,
22014 type: "String"
22015 }
22016 ]
22017 }
22018 ];
22019 var enumerations = [
22020 ];
22021 var associations = [
22022 ];
22023 var BpmnInColorPackage = {
22024 name: name,
22025 uri: uri,
22026 prefix: prefix,
22027 types: types,
22028 enumerations: enumerations,
22029 associations: associations
22030 };
22031
22032 var packages = {
22033 bpmn: BpmnPackage,
22034 bpmndi: BpmnDiPackage,
22035 dc: DcPackage,
22036 di: DiPackage,
22037 bioc: BiocPackage,
22038 color: BpmnInColorPackage
22039 };
22040
22041 function simple(additionalPackages, options) {
22042 var pks = assign$1({}, packages, additionalPackages);
22043
22044 return new BpmnModdle(pks, options);
22045 }
22046
22047 /**
22048 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22049 */
22050
22051
22052 // TODO(nikku): remove with future bpmn-js version
22053
22054 var DI_ERROR_MESSAGE = 'Tried to access di from the businessObject. The di is available through the diagram element only. For more information, see https://github.com/bpmn-io/bpmn-js/issues/1472';
22055
22056 /**
22057 * @private
22058 *
22059 * @param {ModdleElement} businessObject
22060 */
22061 function ensureCompatDiRef(businessObject) {
22062
22063 // bpmnElement can have multiple independent DIs
22064 if (!has$1(businessObject, 'di')) {
22065 Object.defineProperty(businessObject, 'di', {
22066 enumerable: false,
22067 get: function() {
22068 throw new Error(DI_ERROR_MESSAGE);
22069 }
22070 });
22071 }
22072 }
22073
22074 /**
22075 * @typedef {import('diagram-js/lib/i18n/translate/translate').default} Translate
22076 *
22077 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22078 */
22079
22080 /**
22081 * Returns true if an element is of the given meta-model type.
22082 *
22083 * @param {ModdleElement} element
22084 * @param {string} type
22085 *
22086 * @return {boolean}
22087 */
22088 function is(element, type) {
22089 return element.$instanceOf(type);
22090 }
22091
22092
22093 /**
22094 * Find a suitable display candidate for definitions where the DI does not
22095 * correctly specify one.
22096 *
22097 * @param {ModdleElement} definitions
22098 *
22099 * @return {ModdleElement}
22100 */
22101 function findDisplayCandidate(definitions) {
22102 return find(definitions.rootElements, function(e) {
22103 return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration');
22104 });
22105 }
22106
22107 /**
22108 * @param {Record<'element' | 'root' | 'error', Function>} handler
22109 * @param {Translate} translate
22110 */
22111 function BpmnTreeWalker(handler, translate) {
22112
22113 // list of containers already walked
22114 var handledElements = {};
22115
22116 // list of elements to handle deferred to ensure
22117 // prerequisites are drawn
22118 var deferred = [];
22119
22120 var diMap = {};
22121
22122 // Helpers //////////////////////
22123
22124 function contextual(fn, ctx) {
22125 return function(e) {
22126 fn(e, ctx);
22127 };
22128 }
22129
22130 function handled(element) {
22131 handledElements[element.id] = element;
22132 }
22133
22134 function isHandled(element) {
22135 return handledElements[element.id];
22136 }
22137
22138 function visit(element, ctx) {
22139
22140 var gfx = element.gfx;
22141
22142 // avoid multiple rendering of elements
22143 if (gfx) {
22144 throw new Error(
22145 translate('already rendered {element}', { element: elementToString(element) })
22146 );
22147 }
22148
22149 // call handler
22150 return handler.element(element, diMap[element.id], ctx);
22151 }
22152
22153 function visitRoot(element, diagram) {
22154 return handler.root(element, diMap[element.id], diagram);
22155 }
22156
22157 function visitIfDi(element, ctx) {
22158
22159 try {
22160 var gfx = diMap[element.id] && visit(element, ctx);
22161
22162 handled(element);
22163
22164 return gfx;
22165 } catch (e) {
22166 logError(e.message, { element: element, error: e });
22167
22168 console.error(translate('failed to import {element}', { element: elementToString(element) }));
22169 console.error(e);
22170 }
22171 }
22172
22173 function logError(message, context) {
22174 handler.error(message, context);
22175 }
22176
22177 // DI handling //////////////////////
22178
22179 var registerDi = this.registerDi = function registerDi(di) {
22180 var bpmnElement = di.bpmnElement;
22181
22182 if (bpmnElement) {
22183 if (diMap[bpmnElement.id]) {
22184 logError(
22185 translate('multiple DI elements defined for {element}', {
22186 element: elementToString(bpmnElement)
22187 }),
22188 { element: bpmnElement }
22189 );
22190 } else {
22191 diMap[bpmnElement.id] = di;
22192
22193 ensureCompatDiRef(bpmnElement);
22194 }
22195 } else {
22196 logError(
22197 translate('no bpmnElement referenced in {element}', {
22198 element: elementToString(di)
22199 }),
22200 { element: di }
22201 );
22202 }
22203 };
22204
22205 function handleDiagram(diagram) {
22206 handlePlane(diagram.plane);
22207 }
22208
22209 function handlePlane(plane) {
22210 registerDi(plane);
22211
22212 forEach$1(plane.planeElement, handlePlaneElement);
22213 }
22214
22215 function handlePlaneElement(planeElement) {
22216 registerDi(planeElement);
22217 }
22218
22219
22220 // Semantic handling //////////////////////
22221
22222 /**
22223 * Handle definitions and return the rendered diagram (if any).
22224 *
22225 * @param {ModdleElement} definitions to walk and import
22226 * @param {ModdleElement} [diagram] specific diagram to import and display
22227 *
22228 * @throws {Error} if no diagram to display could be found
22229 */
22230 this.handleDefinitions = function handleDefinitions(definitions, diagram) {
22231
22232 // make sure we walk the correct bpmnElement
22233
22234 var diagrams = definitions.diagrams;
22235
22236 if (diagram && diagrams.indexOf(diagram) === -1) {
22237 throw new Error(translate('diagram not part of bpmn:Definitions'));
22238 }
22239
22240 if (!diagram && diagrams && diagrams.length) {
22241 diagram = diagrams[0];
22242 }
22243
22244 // no diagram -> nothing to import
22245 if (!diagram) {
22246 throw new Error(translate('no diagram to display'));
22247 }
22248
22249 // load DI from selected diagram only
22250 diMap = {};
22251 handleDiagram(diagram);
22252
22253
22254 var plane = diagram.plane;
22255
22256 if (!plane) {
22257 throw new Error(translate(
22258 'no plane for {element}',
22259 { element: elementToString(diagram) }
22260 ));
22261 }
22262
22263 var rootElement = plane.bpmnElement;
22264
22265 // ensure we default to a suitable display candidate (process or collaboration),
22266 // even if non is specified in DI
22267 if (!rootElement) {
22268 rootElement = findDisplayCandidate(definitions);
22269
22270 if (!rootElement) {
22271 throw new Error(translate('no process or collaboration to display'));
22272 } else {
22273
22274 logError(
22275 translate('correcting missing bpmnElement on {plane} to {rootElement}', {
22276 plane: elementToString(plane),
22277 rootElement: elementToString(rootElement)
22278 })
22279 );
22280
22281 // correct DI on the fly
22282 plane.bpmnElement = rootElement;
22283 registerDi(plane);
22284 }
22285 }
22286
22287
22288 var ctx = visitRoot(rootElement, plane);
22289
22290 if (is(rootElement, 'bpmn:Process') || is(rootElement, 'bpmn:SubProcess')) {
22291 handleProcess(rootElement, ctx);
22292 } else if (is(rootElement, 'bpmn:Collaboration')) {
22293 handleCollaboration(rootElement, ctx);
22294
22295 // force drawing of everything not yet drawn that is part of the target DI
22296 handleUnhandledProcesses(definitions.rootElements, ctx);
22297 } else {
22298 throw new Error(
22299 translate('unsupported bpmnElement for {plane}: {rootElement}', {
22300 plane: elementToString(plane),
22301 rootElement: elementToString(rootElement)
22302 })
22303 );
22304 }
22305
22306 // handle all deferred elements
22307 handleDeferred(deferred);
22308 };
22309
22310 var handleDeferred = this.handleDeferred = function handleDeferred() {
22311
22312 var fn;
22313
22314 // drain deferred until empty
22315 while (deferred.length) {
22316 fn = deferred.shift();
22317
22318 fn();
22319 }
22320 };
22321
22322 function handleProcess(process, context) {
22323 handleFlowElementsContainer(process, context);
22324 handleIoSpecification(process.ioSpecification, context);
22325
22326 handleArtifacts(process.artifacts, context);
22327
22328 // log process handled
22329 handled(process);
22330 }
22331
22332 function handleUnhandledProcesses(rootElements, ctx) {
22333
22334 // walk through all processes that have not yet been drawn and draw them
22335 // if they contain lanes with DI information.
22336 // we do this to pass the free-floating lane test cases in the MIWG test suite
22337 var processes = filter(rootElements, function(e) {
22338 return !isHandled(e) && is(e, 'bpmn:Process') && e.laneSets;
22339 });
22340
22341 processes.forEach(contextual(handleProcess, ctx));
22342 }
22343
22344 function handleMessageFlow(messageFlow, context) {
22345 visitIfDi(messageFlow, context);
22346 }
22347
22348 function handleMessageFlows(messageFlows, context) {
22349 forEach$1(messageFlows, contextual(handleMessageFlow, context));
22350 }
22351
22352 function handleDataAssociation(association, context) {
22353 visitIfDi(association, context);
22354 }
22355
22356 function handleDataInput(dataInput, context) {
22357 visitIfDi(dataInput, context);
22358 }
22359
22360 function handleDataOutput(dataOutput, context) {
22361 visitIfDi(dataOutput, context);
22362 }
22363
22364 function handleArtifact(artifact, context) {
22365
22366 // bpmn:TextAnnotation
22367 // bpmn:Group
22368 // bpmn:Association
22369
22370 visitIfDi(artifact, context);
22371 }
22372
22373 function handleArtifacts(artifacts, context) {
22374
22375 forEach$1(artifacts, function(e) {
22376 if (is(e, 'bpmn:Association')) {
22377 deferred.push(function() {
22378 handleArtifact(e, context);
22379 });
22380 } else {
22381 handleArtifact(e, context);
22382 }
22383 });
22384 }
22385
22386 function handleIoSpecification(ioSpecification, context) {
22387
22388 if (!ioSpecification) {
22389 return;
22390 }
22391
22392 forEach$1(ioSpecification.dataInputs, contextual(handleDataInput, context));
22393 forEach$1(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
22394 }
22395
22396 var handleSubProcess = this.handleSubProcess = function handleSubProcess(subProcess, context) {
22397 handleFlowElementsContainer(subProcess, context);
22398 handleArtifacts(subProcess.artifacts, context);
22399 };
22400
22401 function handleFlowNode(flowNode, context) {
22402 var childCtx = visitIfDi(flowNode, context);
22403
22404 if (is(flowNode, 'bpmn:SubProcess')) {
22405 handleSubProcess(flowNode, childCtx || context);
22406 }
22407
22408 if (is(flowNode, 'bpmn:Activity')) {
22409 handleIoSpecification(flowNode.ioSpecification, context);
22410 }
22411
22412 // defer handling of associations
22413 // affected types:
22414 //
22415 // * bpmn:Activity
22416 // * bpmn:ThrowEvent
22417 // * bpmn:CatchEvent
22418 //
22419 deferred.push(function() {
22420 forEach$1(flowNode.dataInputAssociations, contextual(handleDataAssociation, context));
22421 forEach$1(flowNode.dataOutputAssociations, contextual(handleDataAssociation, context));
22422 });
22423 }
22424
22425 function handleSequenceFlow(sequenceFlow, context) {
22426 visitIfDi(sequenceFlow, context);
22427 }
22428
22429 function handleDataElement(dataObject, context) {
22430 visitIfDi(dataObject, context);
22431 }
22432
22433 function handleLane(lane, context) {
22434
22435 deferred.push(function() {
22436
22437 var newContext = visitIfDi(lane, context);
22438
22439 if (lane.childLaneSet) {
22440 handleLaneSet(lane.childLaneSet, newContext || context);
22441 }
22442
22443 wireFlowNodeRefs(lane);
22444 });
22445 }
22446
22447 function handleLaneSet(laneSet, context) {
22448 forEach$1(laneSet.lanes, contextual(handleLane, context));
22449 }
22450
22451 function handleLaneSets(laneSets, context) {
22452 forEach$1(laneSets, contextual(handleLaneSet, context));
22453 }
22454
22455 function handleFlowElementsContainer(container, context) {
22456 handleFlowElements(container.flowElements, context);
22457
22458 if (container.laneSets) {
22459 handleLaneSets(container.laneSets, context);
22460 }
22461 }
22462
22463 function handleFlowElements(flowElements, context) {
22464 forEach$1(flowElements, function(e) {
22465 if (is(e, 'bpmn:SequenceFlow')) {
22466 deferred.push(function() {
22467 handleSequenceFlow(e, context);
22468 });
22469 } else if (is(e, 'bpmn:BoundaryEvent')) {
22470 deferred.unshift(function() {
22471 handleFlowNode(e, context);
22472 });
22473 } else if (is(e, 'bpmn:FlowNode')) {
22474 handleFlowNode(e, context);
22475 } else if (is(e, 'bpmn:DataObject')) ; else if (is(e, 'bpmn:DataStoreReference')) {
22476 handleDataElement(e, context);
22477 } else if (is(e, 'bpmn:DataObjectReference')) {
22478 handleDataElement(e, context);
22479 } else {
22480 logError(
22481 translate('unrecognized flowElement {element} in context {context}', {
22482 element: elementToString(e),
22483 context: (context ? elementToString(context.businessObject) : 'null')
22484 }),
22485 { element: e, context: context }
22486 );
22487 }
22488 });
22489 }
22490
22491 function handleParticipant(participant, context) {
22492 var newCtx = visitIfDi(participant, context);
22493
22494 var process = participant.processRef;
22495 if (process) {
22496 handleProcess(process, newCtx || context);
22497 }
22498 }
22499
22500 function handleCollaboration(collaboration, context) {
22501
22502 forEach$1(collaboration.participants, contextual(handleParticipant, context));
22503
22504 handleArtifacts(collaboration.artifacts, context);
22505
22506 // handle message flows latest in the process
22507 deferred.push(function() {
22508 handleMessageFlows(collaboration.messageFlows, context);
22509 });
22510 }
22511
22512
22513 function wireFlowNodeRefs(lane) {
22514
22515 // wire the virtual flowNodeRefs <-> relationship
22516 forEach$1(lane.flowNodeRef, function(flowNode) {
22517 var lanes = flowNode.get('lanes');
22518
22519 if (lanes) {
22520 lanes.push(lane);
22521 }
22522 });
22523 }
22524 }
22525
22526 /**
22527 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22528 *
22529 * @typedef { {
22530 * warnings: string[];
22531 * } } ImportBPMNDiagramResult
22532 *
22533 * @typedef {ImportBPMNDiagramResult & Error} ImportBPMNDiagramError
22534 */
22535
22536 /**
22537 * Import the definitions into a diagram.
22538 *
22539 * Errors and warnings are reported through the specified callback.
22540 *
22541 * @param {ModdleElement} diagram
22542 * @param {ModdleElement} definitions
22543 * @param {ModdleElement} [bpmnDiagram] The diagram to be rendered (if not
22544 * provided, the first one will be rendered).
22545 *
22546 * @return {Promise<ImportBPMNDiagramResult>}
22547 */
22548 function importBpmnDiagram(diagram, definitions, bpmnDiagram) {
22549
22550 var importer,
22551 eventBus,
22552 translate,
22553 canvas;
22554
22555 var error,
22556 warnings = [];
22557
22558 /**
22559 * Walk the diagram semantically, importing (=drawing)
22560 * all elements you encounter.
22561 *
22562 * @param {ModdleElement} definitions
22563 * @param {ModdleElement} bpmnDiagram
22564 */
22565 function render(definitions, bpmnDiagram) {
22566
22567 var visitor = {
22568
22569 root: function(element, di) {
22570 return importer.add(element, di);
22571 },
22572
22573 element: function(element, di, parentShape) {
22574 return importer.add(element, di, parentShape);
22575 },
22576
22577 error: function(message, context) {
22578 warnings.push({ message: message, context: context });
22579 }
22580 };
22581
22582 var walker = new BpmnTreeWalker(visitor, translate);
22583
22584
22585 bpmnDiagram = bpmnDiagram || (definitions.diagrams && definitions.diagrams[0]);
22586
22587 var diagramsToImport = getDiagramsToImport(definitions, bpmnDiagram);
22588
22589 if (!diagramsToImport) {
22590 throw new Error(translate('no diagram to display'));
22591 }
22592
22593 // traverse BPMN 2.0 document model,
22594 // starting at definitions
22595 forEach$1(diagramsToImport, function(diagram) {
22596 walker.handleDefinitions(definitions, diagram);
22597 });
22598
22599 var rootId = bpmnDiagram.plane.bpmnElement.id;
22600
22601 // we do need to account for different ways we create root elements
22602 // each nested imported <root> do have the `_plane` suffix, while
22603 // the root <root> is found under the business object ID
22604 canvas.setRootElement(
22605 canvas.findRoot(rootId + '_plane') || canvas.findRoot(rootId)
22606 );
22607 }
22608
22609 return new Promise(function(resolve, reject) {
22610 try {
22611 importer = diagram.get('bpmnImporter');
22612 eventBus = diagram.get('eventBus');
22613 translate = diagram.get('translate');
22614 canvas = diagram.get('canvas');
22615
22616 eventBus.fire('import.render.start', { definitions: definitions });
22617
22618 render(definitions, bpmnDiagram);
22619
22620 eventBus.fire('import.render.complete', {
22621 error: error,
22622 warnings: warnings
22623 });
22624
22625 return resolve({ warnings: warnings });
22626 } catch (e) {
22627
22628 e.warnings = warnings;
22629 return reject(e);
22630 }
22631 });
22632 }
22633
22634 /**
22635 * Returns all diagrams in the same hierarchy as the requested diagram.
22636 * Includes all parent and sub process diagrams.
22637 *
22638 * @param {ModdleElement} definitions
22639 * @param {ModdleElement} bpmnDiagram
22640 *
22641 * @return {ModdleElement[]}
22642 */
22643 function getDiagramsToImport(definitions, bpmnDiagram) {
22644 if (!bpmnDiagram) {
22645 return;
22646 }
22647
22648 var bpmnElement = bpmnDiagram.plane.bpmnElement,
22649 rootElement = bpmnElement;
22650
22651 if (!is$1(bpmnElement, 'bpmn:Process') && !is$1(bpmnElement, 'bpmn:Collaboration')) {
22652 rootElement = findRootProcess(bpmnElement);
22653 }
22654
22655 // in case the process is part of a collaboration, the plane references the
22656 // collaboration, not the process
22657 var collaboration;
22658
22659 if (is$1(rootElement, 'bpmn:Collaboration')) {
22660 collaboration = rootElement;
22661 } else {
22662 collaboration = find(definitions.rootElements, function(element) {
22663 if (!is$1(element, 'bpmn:Collaboration')) {
22664 return;
22665 }
22666
22667 return find(element.participants, function(participant) {
22668 return participant.processRef === rootElement;
22669 });
22670 });
22671 }
22672
22673 var rootElements = [ rootElement ];
22674
22675 // all collaboration processes can contain sub-diagrams
22676 if (collaboration) {
22677 rootElements = map$1(collaboration.participants, function(participant) {
22678 return participant.processRef;
22679 });
22680
22681 rootElements.push(collaboration);
22682 }
22683
22684 var allChildren = selfAndAllFlowElements(rootElements);
22685
22686 // if we have multiple diagrams referencing the same element, we
22687 // use the first in the file
22688 var diagramsToImport = [ bpmnDiagram ];
22689 var handledElements = [ bpmnElement ];
22690
22691 forEach$1(definitions.diagrams, function(diagram) {
22692 var businessObject = diagram.plane.bpmnElement;
22693
22694 if (
22695 allChildren.indexOf(businessObject) !== -1 &&
22696 handledElements.indexOf(businessObject) === -1
22697 ) {
22698 diagramsToImport.push(diagram);
22699 handledElements.push(businessObject);
22700 }
22701 });
22702
22703
22704 return diagramsToImport;
22705 }
22706
22707 function selfAndAllFlowElements(elements) {
22708 var result = [];
22709
22710 forEach$1(elements, function(element) {
22711 if (!element) {
22712 return;
22713 }
22714
22715 result.push(element);
22716
22717 result = result.concat(selfAndAllFlowElements(element.flowElements));
22718 });
22719
22720 return result;
22721 }
22722
22723 function findRootProcess(element) {
22724 var parent = element;
22725
22726 while (parent) {
22727 if (is$1(parent, 'bpmn:Process')) {
22728 return parent;
22729 }
22730
22731 parent = parent.$parent;
22732 }
22733 }
22734
22735 /**
22736 * This file must not be changed or exchanged.
22737 *
22738 * @see http://bpmn.io/license for more information.
22739 */
22740
22741
22742 // inlined ../../resources/logo.svg
22743 var BPMNIO_LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14.02 5.57" width="53" height="21"><path fill="currentColor" d="M1.88.92v.14c0 .41-.13.68-.4.8.33.14.46.44.46.86v.33c0 .61-.33.95-.95.95H0V0h.95c.65 0 .93.3.93.92zM.63.57v1.06h.24c.24 0 .38-.1.38-.43V.98c0-.28-.1-.4-.32-.4zm0 1.63v1.22h.36c.2 0 .32-.1.32-.39v-.35c0-.37-.12-.48-.4-.48H.63zM4.18.99v.52c0 .64-.31.98-.94.98h-.3V4h-.62V0h.92c.63 0 .94.35.94.99zM2.94.57v1.35h.3c.2 0 .3-.09.3-.37v-.6c0-.29-.1-.38-.3-.38h-.3zm2.89 2.27L6.25 0h.88v4h-.6V1.12L6.1 3.99h-.6l-.46-2.82v2.82h-.55V0h.87zM8.14 1.1V4h-.56V0h.79L9 2.4V0h.56v4h-.64zm2.49 2.29v.6h-.6v-.6zM12.12 1c0-.63.33-1 .95-1 .61 0 .95.37.95 1v2.04c0 .64-.34 1-.95 1-.62 0-.95-.37-.95-1zm.62 2.08c0 .28.13.39.33.39s.32-.1.32-.4V.98c0-.29-.12-.4-.32-.4s-.33.11-.33.4z"/><path fill="currentColor" d="M0 4.53h14.02v1.04H0zM11.08 0h.63v.62h-.63zm.63 4V1h-.63v2.98z"/></svg>';
22744
22745 var BPMNIO_IMG = BPMNIO_LOGO_SVG;
22746
22747 var LOGO_STYLES = {
22748 verticalAlign: 'middle'
22749 };
22750
22751 var LINK_STYLES = {
22752 'color': '#404040'
22753 };
22754
22755 var LIGHTBOX_STYLES = {
22756 'zIndex': '1001',
22757 'position': 'fixed',
22758 'top': '0',
22759 'left': '0',
22760 'right': '0',
22761 'bottom': '0'
22762 };
22763
22764 var BACKDROP_STYLES = {
22765 'width': '100%',
22766 'height': '100%',
22767 'background': 'rgba(40,40,40,0.2)'
22768 };
22769
22770 var NOTICE_STYLES = {
22771 'position': 'absolute',
22772 'left': '50%',
22773 'top': '40%',
22774 'transform': 'translate(-50%)',
22775 'width': '260px',
22776 'padding': '10px',
22777 'background': 'white',
22778 'boxShadow': '0 1px 4px rgba(0,0,0,0.3)',
22779 'fontFamily': 'Helvetica, Arial, sans-serif',
22780 'fontSize': '14px',
22781 'display': 'flex',
22782 'lineHeight': '1.3'
22783 };
22784
22785 var LIGHTBOX_MARKUP =
22786 '<div class="bjs-powered-by-lightbox">' +
22787 '<div class="backdrop"></div>' +
22788 '<div class="notice">' +
22789 '<a href="https://bpmn.io" target="_blank" rel="noopener" class="link">' +
22790 BPMNIO_IMG +
22791 '</a>' +
22792 '<span>' +
22793 'Web-based tooling for BPMN, DMN and forms ' +
22794 'powered by <a href="https://bpmn.io" target="_blank" rel="noopener">bpmn.io</a>.' +
22795 '</span>' +
22796 '</div>' +
22797 '</div>';
22798
22799
22800 var lightbox;
22801
22802 function createLightbox() {
22803 lightbox = domify$1(LIGHTBOX_MARKUP);
22804
22805 assign(lightbox, LIGHTBOX_STYLES);
22806 assign(query('svg', lightbox), LOGO_STYLES);
22807 assign(query('.backdrop', lightbox), BACKDROP_STYLES);
22808 assign(query('.notice', lightbox), NOTICE_STYLES);
22809 assign(query('.link', lightbox), LINK_STYLES, {
22810 'margin': '15px 20px 15px 10px',
22811 'alignSelf': 'center'
22812 });
22813 }
22814
22815 function open() {
22816
22817 if (!lightbox) {
22818 createLightbox();
22819
22820 delegate.bind(lightbox, '.backdrop', 'click', function(event) {
22821 document.body.removeChild(lightbox);
22822 });
22823 }
22824
22825 document.body.appendChild(lightbox);
22826 }
22827
22828 /**
22829 * The code in the <project-logo></project-logo> area
22830 * must not be changed.
22831 *
22832 * @see http://bpmn.io/license for more information.
22833 */
22834
22835 /**
22836 * @template T
22837 *
22838 * @typedef {import('diagram-js/lib/core/EventBus').EventBusEventCallback<T>} EventBusEventCallback
22839 */
22840
22841 /**
22842 * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration
22843 *
22844 * @typedef {import('./model/Types').Moddle} Moddle
22845 * @typedef {import('./model/Types').ModdleElement} ModdleElement
22846 * @typedef {import('./model/Types').ModdleExtension} ModdleExtension
22847 *
22848 * @typedef { {
22849 * width?: number|string;
22850 * height?: number|string;
22851 * position?: string;
22852 * container?: string|HTMLElement;
22853 * moddleExtensions?: ModdleExtensions;
22854 * additionalModules?: ModuleDeclaration[];
22855 * } & Record<string, any> } BaseViewerOptions
22856 *
22857 * @typedef {Record<string, ModdleElement>} ModdleElementsById
22858 *
22859 * @typedef { {
22860 * [key: string]: ModdleExtension;
22861 * } } ModdleExtensions
22862 *
22863 * @typedef { {
22864 * warnings: string[];
22865 * } } ImportXMLResult
22866 *
22867 * @typedef {ImportXMLResult & Error} ImportXMLError
22868 *
22869 * @typedef {ImportXMLResult} ImportDefinitionsResult
22870 *
22871 * @typedef {ImportXMLError} ImportDefinitionsError
22872 *
22873 * @typedef {ImportXMLResult} OpenResult
22874 *
22875 * @typedef {ImportXMLError} OpenError
22876 *
22877 * @typedef { {
22878 * format?: boolean;
22879 * preamble?: boolean;
22880 * } } SaveXMLOptions
22881 *
22882 * @typedef { {
22883 * xml?: string;
22884 * error?: Error;
22885 * } } SaveXMLResult
22886 *
22887 * @typedef { {
22888 * svg: string;
22889 * } } SaveSVGResult
22890 *
22891 * @typedef { {
22892 * xml: string;
22893 * } } ImportParseStartEvent
22894 *
22895 * @typedef { {
22896 * error?: ImportXMLError;
22897 * definitions?: ModdleElement;
22898 * elementsById?: ModdleElementsById;
22899 * references?: ModdleElement[];
22900 * warnings: string[];
22901 * } } ImportParseCompleteEvent
22902 *
22903 * @typedef { {
22904 * error?: ImportXMLError;
22905 * warnings: string[];
22906 * } } ImportDoneEvent
22907 *
22908 * @typedef { {
22909 * definitions: ModdleElement;
22910 * } } SaveXMLStartEvent
22911 *
22912 * @typedef {SaveXMLResult} SaveXMLDoneEvent
22913 *
22914 * @typedef { {
22915 * error?: Error;
22916 * svg: string;
22917 * } } SaveSVGDoneEvent
22918 */
22919
22920 /**
22921 * A base viewer for BPMN 2.0 diagrams.
22922 *
22923 * Have a look at {@link Viewer}, {@link NavigatedViewer} or {@link Modeler} for
22924 * bundles that include actual features.
22925 *
22926 * @param {BaseViewerOptions} [options] The options to configure the viewer.
22927 */
22928 function BaseViewer(options) {
22929
22930 /**
22931 * @type {BaseViewerOptions}
22932 */
22933 options = assign$1({}, DEFAULT_OPTIONS, options);
22934
22935 /**
22936 * @type {Moddle}
22937 */
22938 this._moddle = this._createModdle(options);
22939
22940 /**
22941 * @type {HTMLElement}
22942 */
22943 this._container = this._createContainer(options);
22944
22945 /* <project-logo> */
22946
22947 addProjectLogo(this._container);
22948
22949 /* </project-logo> */
22950
22951 this._init(this._container, this._moddle, options);
22952 }
22953
22954 e(BaseViewer, Diagram);
22955
22956 /**
22957 * Parse and render a BPMN 2.0 diagram.
22958 *
22959 * Once finished the viewer reports back the result to the
22960 * provided callback function with (err, warnings).
22961 *
22962 * ## Life-Cycle Events
22963 *
22964 * During import the viewer will fire life-cycle events:
22965 *
22966 * * import.parse.start (about to read model from XML)
22967 * * import.parse.complete (model read; may have worked or not)
22968 * * import.render.start (graphical import start)
22969 * * import.render.complete (graphical import finished)
22970 * * import.done (everything done)
22971 *
22972 * You can use these events to hook into the life-cycle.
22973 *
22974 * @throws {ImportXMLError} An error thrown during the import of the XML.
22975 *
22976 * @fires BaseViewer#ImportParseStartEvent
22977 * @fires BaseViewer#ImportParseCompleteEvent
22978 * @fires Importer#ImportRenderStartEvent
22979 * @fires Importer#ImportRenderCompleteEvent
22980 * @fires BaseViewer#ImportDoneEvent
22981 *
22982 * @param {string} xml The BPMN 2.0 XML to be imported.
22983 * @param {ModdleElement|string} [bpmnDiagram] The optional diagram or Id of the BPMN diagram to open.
22984 *
22985 * @return {Promise<ImportXMLResult>} A promise resolving with warnings that were produced during the import.
22986 */
22987 BaseViewer.prototype.importXML = async function importXML(xml, bpmnDiagram) {
22988
22989 const self = this;
22990
22991 function ParseCompleteEvent(data) {
22992 return self.get('eventBus').createEvent(data);
22993 }
22994
22995 let aggregatedWarnings = [];
22996 try {
22997
22998 // hook in pre-parse listeners +
22999 // allow xml manipulation
23000
23001 /**
23002 * A `import.parse.start` event.
23003 *
23004 * @event BaseViewer#ImportParseStartEvent
23005 * @type {ImportParseStartEvent}
23006 */
23007 xml = this._emit('import.parse.start', { xml: xml }) || xml;
23008
23009 let parseResult;
23010 try {
23011 parseResult = await this._moddle.fromXML(xml, 'bpmn:Definitions');
23012 } catch (error) {
23013 this._emit('import.parse.complete', {
23014 error
23015 });
23016
23017 throw error;
23018 }
23019
23020 let definitions = parseResult.rootElement;
23021 const references = parseResult.references;
23022 const parseWarnings = parseResult.warnings;
23023 const elementsById = parseResult.elementsById;
23024
23025 aggregatedWarnings = aggregatedWarnings.concat(parseWarnings);
23026
23027 // hook in post parse listeners +
23028 // allow definitions manipulation
23029
23030 /**
23031 * A `import.parse.complete` event.
23032 *
23033 * @event BaseViewer#ImportParseCompleteEvent
23034 * @type {ImportParseCompleteEvent}
23035 */
23036 definitions = this._emit('import.parse.complete', ParseCompleteEvent({
23037 error: null,
23038 definitions: definitions,
23039 elementsById: elementsById,
23040 references: references,
23041 warnings: aggregatedWarnings
23042 })) || definitions;
23043
23044 const importResult = await this.importDefinitions(definitions, bpmnDiagram);
23045
23046 aggregatedWarnings = aggregatedWarnings.concat(importResult.warnings);
23047
23048 /**
23049 * A `import.parse.complete` event.
23050 *
23051 * @event BaseViewer#ImportDoneEvent
23052 * @type {ImportDoneEvent}
23053 */
23054 this._emit('import.done', { error: null, warnings: aggregatedWarnings });
23055
23056 return { warnings: aggregatedWarnings };
23057 } catch (err) {
23058 let error = err;
23059 aggregatedWarnings = aggregatedWarnings.concat(error.warnings || []);
23060 addWarningsToError(error, aggregatedWarnings);
23061
23062 error = checkValidationError(error);
23063
23064 this._emit('import.done', { error, warnings: error.warnings });
23065
23066 throw error;
23067 }
23068 };
23069
23070
23071 /**
23072 * Import parsed definitions and render a BPMN 2.0 diagram.
23073 *
23074 * Once finished the viewer reports back the result to the
23075 * provided callback function with (err, warnings).
23076 *
23077 * ## Life-Cycle Events
23078 *
23079 * During import the viewer will fire life-cycle events:
23080 *
23081 * * import.render.start (graphical import start)
23082 * * import.render.complete (graphical import finished)
23083 *
23084 * You can use these events to hook into the life-cycle.
23085 *
23086 * @throws {ImportDefinitionsError} An error thrown during the import of the definitions.
23087 *
23088 * @param {ModdleElement} definitions The definitions.
23089 * @param {ModdleElement|string} [bpmnDiagram] The optional diagram or ID of the BPMN diagram to open.
23090 *
23091 * @return {Promise<ImportDefinitionsResult>} A promise resolving with warnings that were produced during the import.
23092 */
23093 BaseViewer.prototype.importDefinitions = async function importDefinitions(definitions, bpmnDiagram) {
23094 this._setDefinitions(definitions);
23095 const result = await this.open(bpmnDiagram);
23096
23097 return { warnings: result.warnings };
23098 };
23099
23100
23101 /**
23102 * Open diagram of previously imported XML.
23103 *
23104 * Once finished the viewer reports back the result to the
23105 * provided callback function with (err, warnings).
23106 *
23107 * ## Life-Cycle Events
23108 *
23109 * During switch the viewer will fire life-cycle events:
23110 *
23111 * * import.render.start (graphical import start)
23112 * * import.render.complete (graphical import finished)
23113 *
23114 * You can use these events to hook into the life-cycle.
23115 *
23116 * @throws {OpenError} An error thrown during opening.
23117 *
23118 * @param {ModdleElement|string} bpmnDiagramOrId The diagram or Id of the BPMN diagram to open.
23119 *
23120 * @return {Promise<OpenResult>} A promise resolving with warnings that were produced during opening.
23121 */
23122 BaseViewer.prototype.open = async function open(bpmnDiagramOrId) {
23123
23124 const definitions = this._definitions;
23125 let bpmnDiagram = bpmnDiagramOrId;
23126
23127 if (!definitions) {
23128 const error = new Error('no XML imported');
23129 addWarningsToError(error, []);
23130
23131 throw error;
23132 }
23133
23134 if (typeof bpmnDiagramOrId === 'string') {
23135 bpmnDiagram = findBPMNDiagram(definitions, bpmnDiagramOrId);
23136
23137 if (!bpmnDiagram) {
23138 const error = new Error('BPMNDiagram <' + bpmnDiagramOrId + '> not found');
23139 addWarningsToError(error, []);
23140
23141 throw error;
23142 }
23143 }
23144
23145 // clear existing rendered diagram
23146 // catch synchronous exceptions during #clear()
23147 try {
23148 this.clear();
23149 } catch (error) {
23150 addWarningsToError(error, []);
23151
23152 throw error;
23153 }
23154
23155 // perform graphical import
23156 const { warnings } = await importBpmnDiagram(this, definitions, bpmnDiagram);
23157
23158 return { warnings };
23159 };
23160
23161 /**
23162 * Export the currently displayed BPMN 2.0 diagram as
23163 * a BPMN 2.0 XML document.
23164 *
23165 * ## Life-Cycle Events
23166 *
23167 * During XML saving the viewer will fire life-cycle events:
23168 *
23169 * * saveXML.start (before serialization)
23170 * * saveXML.serialized (after xml generation)
23171 * * saveXML.done (everything done)
23172 *
23173 * You can use these events to hook into the life-cycle.
23174 *
23175 * @throws {Error} An error thrown during export.
23176 *
23177 * @fires BaseViewer#SaveXMLStart
23178 * @fires BaseViewer#SaveXMLDone
23179 *
23180 * @param {SaveXMLOptions} [options] The options.
23181 *
23182 * @return {Promise<SaveXMLResult>} A promise resolving with the XML.
23183 */
23184 BaseViewer.prototype.saveXML = async function saveXML(options) {
23185
23186 options = options || {};
23187
23188 let definitions = this._definitions,
23189 error, xml;
23190
23191 try {
23192 if (!definitions) {
23193 throw new Error('no definitions loaded');
23194 }
23195
23196 // allow to fiddle around with definitions
23197
23198 /**
23199 * A `saveXML.start` event.
23200 *
23201 * @event BaseViewer#SaveXMLStartEvent
23202 * @type {SaveXMLStartEvent}
23203 */
23204 definitions = this._emit('saveXML.start', {
23205 definitions
23206 }) || definitions;
23207
23208 const result = await this._moddle.toXML(definitions, options);
23209 xml = result.xml;
23210
23211 xml = this._emit('saveXML.serialized', {
23212 xml
23213 }) || xml;
23214 } catch (err) {
23215 error = err;
23216 }
23217
23218 const result = error ? { error } : { xml };
23219
23220 /**
23221 * A `saveXML.done` event.
23222 *
23223 * @event BaseViewer#SaveXMLDoneEvent
23224 * @type {SaveXMLDoneEvent}
23225 */
23226 this._emit('saveXML.done', result);
23227
23228 if (error) {
23229 throw error;
23230 }
23231
23232 return result;
23233 };
23234
23235
23236 /**
23237 * Export the currently displayed BPMN 2.0 diagram as
23238 * an SVG image.
23239 *
23240 * ## Life-Cycle Events
23241 *
23242 * During SVG saving the viewer will fire life-cycle events:
23243 *
23244 * * saveSVG.start (before serialization)
23245 * * saveSVG.done (everything done)
23246 *
23247 * You can use these events to hook into the life-cycle.
23248 *
23249 * @throws {Error} An error thrown during export.
23250 *
23251 * @fires BaseViewer#SaveSVGDone
23252 *
23253 * @return {Promise<SaveSVGResult>} A promise resolving with the SVG.
23254 */
23255 BaseViewer.prototype.saveSVG = async function saveSVG() {
23256 this._emit('saveSVG.start');
23257
23258 let svg, err;
23259
23260 try {
23261 const canvas = this.get('canvas');
23262
23263 const contentNode = canvas.getActiveLayer(),
23264 defsNode = query('defs', canvas._svg);
23265
23266 const contents = innerSVG(contentNode),
23267 defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
23268
23269 const bbox = contentNode.getBBox();
23270
23271 svg =
23272 '<?xml version="1.0" encoding="utf-8"?>\n' +
23273 '<!-- created with bpmn-js / http://bpmn.io -->\n' +
23274 '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
23275 '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
23276 'width="' + bbox.width + '" height="' + bbox.height + '" ' +
23277 'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
23278 defs + contents +
23279 '</svg>';
23280 } catch (e) {
23281 err = e;
23282 }
23283
23284 /**
23285 * A `saveSVG.done` event.
23286 *
23287 * @event BaseViewer#SaveSVGDoneEvent
23288 * @type {SaveSVGDoneEvent}
23289 */
23290 this._emit('saveSVG.done', {
23291 error: err,
23292 svg: svg
23293 });
23294
23295 if (err) {
23296 throw err;
23297 }
23298
23299 return { svg };
23300 };
23301
23302 BaseViewer.prototype._setDefinitions = function(definitions) {
23303 this._definitions = definitions;
23304 };
23305
23306 /**
23307 * Return modules to instantiate with.
23308 *
23309 * @return {ModuleDeclaration[]} The modules.
23310 */
23311 BaseViewer.prototype.getModules = function() {
23312 return this._modules;
23313 };
23314
23315 /**
23316 * Remove all drawn elements from the viewer.
23317 *
23318 * After calling this method the viewer can still be reused for opening another
23319 * diagram.
23320 */
23321 BaseViewer.prototype.clear = function() {
23322 if (!this.getDefinitions()) {
23323
23324 // no diagram to clear
23325 return;
23326 }
23327
23328 // remove drawn elements
23329 Diagram.prototype.clear.call(this);
23330 };
23331
23332 /**
23333 * Destroy the viewer instance and remove all its remainders from the document
23334 * tree.
23335 */
23336 BaseViewer.prototype.destroy = function() {
23337
23338 // diagram destroy
23339 Diagram.prototype.destroy.call(this);
23340
23341 // dom detach
23342 remove$1(this._container);
23343 };
23344
23345 /**
23346 * Register an event listener.
23347 *
23348 * Remove an event listener via {@link BaseViewer#off}.
23349 *
23350 * @template T
23351 *
23352 * @param {string|string[]} events The event(s) to listen to.
23353 * @param {number} [priority] The priority with which to listen.
23354 * @param {EventBusEventCallback<T>} callback The callback.
23355 * @param {any} [that] Value of `this` the callback will be called with.
23356 */
23357 BaseViewer.prototype.on = function(events, priority, callback, that) {
23358 return this.get('eventBus').on(events, priority, callback, that);
23359 };
23360
23361 /**
23362 * Remove an event listener.
23363 *
23364 * @param {string|string[]} events The event(s).
23365 * @param {Function} [callback] The callback.
23366 */
23367 BaseViewer.prototype.off = function(events, callback) {
23368 this.get('eventBus').off(events, callback);
23369 };
23370
23371 /**
23372 * Attach the viewer to an HTML element.
23373 *
23374 * @param {HTMLElement} parentNode The parent node to attach to.
23375 */
23376 BaseViewer.prototype.attachTo = function(parentNode) {
23377
23378 if (!parentNode) {
23379 throw new Error('parentNode required');
23380 }
23381
23382 // ensure we detach from the
23383 // previous, old parent
23384 this.detach();
23385
23386 // unwrap jQuery if provided
23387 if (parentNode.get && parentNode.constructor.prototype.jquery) {
23388 parentNode = parentNode.get(0);
23389 }
23390
23391 if (typeof parentNode === 'string') {
23392 parentNode = query(parentNode);
23393 }
23394
23395 parentNode.appendChild(this._container);
23396
23397 this._emit('attach', {});
23398
23399 this.get('canvas').resized();
23400 };
23401
23402 /**
23403 * Get the definitions model element.
23404 *
23405 * @return {ModdleElement} The definitions model element.
23406 */
23407 BaseViewer.prototype.getDefinitions = function() {
23408 return this._definitions;
23409 };
23410
23411 /**
23412 * Detach the viewer.
23413 *
23414 * @fires BaseViewer#DetachEvent
23415 */
23416 BaseViewer.prototype.detach = function() {
23417
23418 const container = this._container,
23419 parentNode = container.parentNode;
23420
23421 if (!parentNode) {
23422 return;
23423 }
23424
23425 /**
23426 * A `detach` event.
23427 *
23428 * @event BaseViewer#DetachEvent
23429 * @type {Object}
23430 */
23431 this._emit('detach', {});
23432
23433 parentNode.removeChild(container);
23434 };
23435
23436 BaseViewer.prototype._init = function(container, moddle, options) {
23437
23438 const baseModules = options.modules || this.getModules(options),
23439 additionalModules = options.additionalModules || [],
23440 staticModules = [
23441 {
23442 bpmnjs: [ 'value', this ],
23443 moddle: [ 'value', moddle ]
23444 }
23445 ];
23446
23447 const diagramModules = [].concat(staticModules, baseModules, additionalModules);
23448
23449 const diagramOptions = assign$1(omit(options, [ 'additionalModules' ]), {
23450 canvas: assign$1({}, options.canvas, { container: container }),
23451 modules: diagramModules
23452 });
23453
23454 // invoke diagram constructor
23455 Diagram.call(this, diagramOptions);
23456
23457 if (options && options.container) {
23458 this.attachTo(options.container);
23459 }
23460 };
23461
23462 /**
23463 * Emit an event on the underlying {@link EventBus}
23464 *
23465 * @param {string} type
23466 * @param {Object} event
23467 *
23468 * @return {Object} The return value after calling all event listeners.
23469 */
23470 BaseViewer.prototype._emit = function(type, event) {
23471 return this.get('eventBus').fire(type, event);
23472 };
23473
23474 /**
23475 * @param {BaseViewerOptions} options
23476 *
23477 * @return {HTMLElement}
23478 */
23479 BaseViewer.prototype._createContainer = function(options) {
23480
23481 const container = domify$1('<div class="bjs-container"></div>');
23482
23483 assign(container, {
23484 width: ensureUnit(options.width),
23485 height: ensureUnit(options.height),
23486 position: options.position
23487 });
23488
23489 return container;
23490 };
23491
23492 /**
23493 * @param {BaseViewerOptions} options
23494 *
23495 * @return {Moddle}
23496 */
23497 BaseViewer.prototype._createModdle = function(options) {
23498 const moddleOptions = assign$1({}, this._moddleExtensions, options.moddleExtensions);
23499
23500 return new simple(moddleOptions);
23501 };
23502
23503 BaseViewer.prototype._modules = [];
23504
23505 // helpers ///////////////
23506
23507 function addWarningsToError(err, warningsAry) {
23508 err.warnings = warningsAry;
23509 return err;
23510 }
23511
23512 function checkValidationError(err) {
23513
23514 // check if we can help the user by indicating wrong BPMN 2.0 xml
23515 // (in case he or the exporting tool did not get that right)
23516
23517 const pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/;
23518 const match = pattern.exec(err.message);
23519
23520 if (match) {
23521 err.message =
23522 'unparsable content <' + match[1] + '> detected; ' +
23523 'this may indicate an invalid BPMN 2.0 diagram file' + match[2];
23524 }
23525
23526 return err;
23527 }
23528
23529 const DEFAULT_OPTIONS = {
23530 width: '100%',
23531 height: '100%',
23532 position: 'relative'
23533 };
23534
23535
23536 /**
23537 * Ensure the passed argument is a proper unit (defaulting to px)
23538 */
23539 function ensureUnit(val) {
23540 return val + (isNumber(val) ? 'px' : '');
23541 }
23542
23543
23544 /**
23545 * Find BPMNDiagram in definitions by ID
23546 *
23547 * @param {ModdleElement<Definitions>} definitions
23548 * @param {string} diagramId
23549 *
23550 * @return {ModdleElement<BPMNDiagram>|null}
23551 */
23552 function findBPMNDiagram(definitions, diagramId) {
23553 if (!diagramId) {
23554 return null;
23555 }
23556
23557 return find(definitions.diagrams, function(element) {
23558 return element.id === diagramId;
23559 }) || null;
23560 }
23561
23562 /**
23563 * Adds the project logo to the diagram container as
23564 * required by the bpmn.io license.
23565 *
23566 * @see http://bpmn.io/license
23567 *
23568 * @param {Element} container
23569 */
23570 function addProjectLogo(container) {
23571 const img = BPMNIO_IMG;
23572
23573 const linkMarkup =
23574 '<a href="http://bpmn.io" ' +
23575 'target="_blank" ' +
23576 'class="bjs-powered-by" ' +
23577 'title="Powered by bpmn.io" ' +
23578 '>' +
23579 img +
23580 '</a>';
23581
23582 const linkElement = domify$1(linkMarkup);
23583
23584 assign(query('svg', linkElement), LOGO_STYLES);
23585 assign(linkElement, LINK_STYLES, {
23586 position: 'absolute',
23587 bottom: '15px',
23588 right: '15px',
23589 zIndex: '100'
23590 });
23591
23592 container.appendChild(linkElement);
23593
23594 event.bind(linkElement, 'click', function(event) {
23595 open();
23596
23597 event.preventDefault();
23598 });
23599 }
23600
23601 /* </project-logo> */
23602
23603 /**
23604 * @typedef { import('./BaseViewer').BaseViewerOptions } BaseViewerOptions
23605 */
23606
23607 /**
23608 * A viewer for BPMN 2.0 diagrams.
23609 *
23610 * Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include
23611 * additional features.
23612 *
23613 *
23614 * ## Extending the Viewer
23615 *
23616 * In order to extend the viewer pass extension modules to bootstrap via the
23617 * `additionalModules` option. An extension module is an object that exposes
23618 * named services.
23619 *
23620 * The following example depicts the integration of a simple
23621 * logging component that integrates with interaction events:
23622 *
23623 *
23624 * ```javascript
23625 *
23626 * // logging component
23627 * function InteractionLogger(eventBus) {
23628 * eventBus.on('element.hover', function(event) {
23629 * console.log()
23630 * })
23631 * }
23632 *
23633 * InteractionLogger.$inject = [ 'eventBus' ]; // minification save
23634 *
23635 * // extension module
23636 * var extensionModule = {
23637 * __init__: [ 'interactionLogger' ],
23638 * interactionLogger: [ 'type', InteractionLogger ]
23639 * };
23640 *
23641 * // extend the viewer
23642 * var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] });
23643 * bpmnViewer.importXML(...);
23644 * ```
23645 *
23646 * @param {BaseViewerOptions} [options] The options to configure the viewer.
23647 */
23648 function Viewer(options) {
23649 BaseViewer.call(this, options);
23650 }
23651
23652 e(Viewer, BaseViewer);
23653
23654 // modules the viewer is composed of
23655 Viewer.prototype._modules = [
23656 CoreModule$1,
23657 DrilldownModdule,
23658 OutlineModule,
23659 OverlaysModule,
23660 SelectionModule,
23661 TranslateModule
23662 ];
23663
23664 // default moddle extensions the viewer is composed of
23665 Viewer.prototype._moddleExtensions = {};
23666
23667 return Viewer;
23668
23669}));