UNPKG

585 kBJavaScriptView Raw
1/*!
2 * bpmn-js - bpmn-navigated-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$2(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$1(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$1(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$4 = 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$4, 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$3 = 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$3;
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$3 = 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$3, 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$3, 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$3,
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$3,
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$2 = 500;
8743
8744 var DEFAULT_PRIORITY$2 = 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$2, 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$2;
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 {Event} event
9146 *
9147 * @return {Point|null}
9148 */
9149 function toPoint(event) {
9150
9151 if (event.pointers && event.pointers.length) {
9152 event = event.pointers[0];
9153 }
9154
9155 if (event.touches && event.touches.length) {
9156 event = event.touches[0];
9157 }
9158
9159 return event ? {
9160 x: event.clientX,
9161 y: event.clientY
9162 } : null;
9163 }
9164
9165 function isMac() {
9166 return (/mac/i).test(navigator.platform);
9167 }
9168
9169 /**
9170 * @param {MouseEvent} event
9171 * @param {string} button
9172 *
9173 * @return {boolean}
9174 */
9175 function isButton$1(event, button) {
9176 return (getOriginal(event) || event).button === button;
9177 }
9178
9179 /**
9180 * @param {MouseEvent} event
9181 *
9182 * @return {boolean}
9183 */
9184 function isPrimaryButton(event) {
9185
9186 // button === 0 -> left áka primary mouse button
9187 return isButton$1(event, 0);
9188 }
9189
9190 /**
9191 * @param {MouseEvent} event
9192 *
9193 * @return {boolean}
9194 */
9195 function isAuxiliaryButton(event) {
9196
9197 // button === 1 -> auxiliary áka wheel button
9198 return isButton$1(event, 1);
9199 }
9200
9201 /**
9202 * @param {MouseEvent} event
9203 *
9204 * @return {boolean}
9205 */
9206 function hasSecondaryModifier(event) {
9207 var originalEvent = getOriginal(event) || event;
9208
9209 return isPrimaryButton(event) && originalEvent.shiftKey;
9210 }
9211
9212 /**
9213 * @typedef {import('../../model/Types').Element} Element
9214 *
9215 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
9216 * @typedef {import('../../core/EventBus').default} EventBus
9217 * @typedef {import('../../draw/Styles').default} Styles
9218 *
9219 * @typedef {import('../../util/Types').Point} Point
9220 */
9221
9222 function allowAll(event) { return true; }
9223
9224 function allowPrimaryAndAuxiliary(event) {
9225 return isPrimaryButton(event) || isAuxiliaryButton(event);
9226 }
9227
9228 var LOW_PRIORITY$1 = 500;
9229
9230
9231 /**
9232 * A plugin that provides interaction events for diagram elements.
9233 *
9234 * It emits the following events:
9235 *
9236 * * element.click
9237 * * element.contextmenu
9238 * * element.dblclick
9239 * * element.hover
9240 * * element.mousedown
9241 * * element.mousemove
9242 * * element.mouseup
9243 * * element.out
9244 *
9245 * Each event is a tuple { element, gfx, originalEvent }.
9246 *
9247 * Canceling the event via Event#preventDefault()
9248 * prevents the original DOM operation.
9249 *
9250 * @param {EventBus} eventBus
9251 * @param {ElementRegistry} elementRegistry
9252 * @param {Styles} styles
9253 */
9254 function InteractionEvents(eventBus, elementRegistry, styles) {
9255
9256 var self = this;
9257
9258 /**
9259 * Fire an interaction event.
9260 *
9261 * @param {string} type local event name, e.g. element.click.
9262 * @param {MouseEvent|TouchEvent} event native event
9263 * @param {Element} [element] the diagram element to emit the event on;
9264 * defaults to the event target
9265 */
9266 function fire(type, event, element) {
9267
9268 if (isIgnored(type, event)) {
9269 return;
9270 }
9271
9272 var target, gfx, returnValue;
9273
9274 if (!element) {
9275 target = event.delegateTarget || event.target;
9276
9277 if (target) {
9278 gfx = target;
9279 element = elementRegistry.get(gfx);
9280 }
9281 } else {
9282 gfx = elementRegistry.getGraphics(element);
9283 }
9284
9285 if (!gfx || !element) {
9286 return;
9287 }
9288
9289 returnValue = eventBus.fire(type, {
9290 element: element,
9291 gfx: gfx,
9292 originalEvent: event
9293 });
9294
9295 if (returnValue === false) {
9296 event.stopPropagation();
9297 event.preventDefault();
9298 }
9299 }
9300
9301 // TODO(nikku): document this
9302 var handlers = {};
9303
9304 function mouseHandler(localEventName) {
9305 return handlers[localEventName];
9306 }
9307
9308 function isIgnored(localEventName, event) {
9309
9310 var filter = ignoredFilters[localEventName] || isPrimaryButton;
9311
9312 // only react on left mouse button interactions
9313 // except for interaction events that are enabled
9314 // for secundary mouse button
9315 return !filter(event);
9316 }
9317
9318 var bindings = {
9319 click: 'element.click',
9320 contextmenu: 'element.contextmenu',
9321 dblclick: 'element.dblclick',
9322 mousedown: 'element.mousedown',
9323 mousemove: 'element.mousemove',
9324 mouseover: 'element.hover',
9325 mouseout: 'element.out',
9326 mouseup: 'element.mouseup',
9327 };
9328
9329 var ignoredFilters = {
9330 'element.contextmenu': allowAll,
9331 'element.mousedown': allowPrimaryAndAuxiliary,
9332 'element.mouseup': allowPrimaryAndAuxiliary,
9333 'element.click': allowPrimaryAndAuxiliary,
9334 'element.dblclick': allowPrimaryAndAuxiliary
9335 };
9336
9337
9338 // manual event trigger //////////
9339
9340 /**
9341 * Trigger an interaction event (based on a native dom event)
9342 * on the target shape or connection.
9343 *
9344 * @param {string} eventName the name of the triggered DOM event
9345 * @param {MouseEvent|TouchEvent} event
9346 * @param {Element} targetElement
9347 */
9348 function triggerMouseEvent(eventName, event, targetElement) {
9349
9350 // i.e. element.mousedown...
9351 var localEventName = bindings[eventName];
9352
9353 if (!localEventName) {
9354 throw new Error('unmapped DOM event name <' + eventName + '>');
9355 }
9356
9357 return fire(localEventName, event, targetElement);
9358 }
9359
9360
9361 var ELEMENT_SELECTOR = 'svg, .djs-element';
9362
9363 // event handling ///////
9364
9365 function registerEvent(node, event, localEvent, ignoredFilter) {
9366
9367 var handler = handlers[localEvent] = function(event) {
9368 fire(localEvent, event);
9369 };
9370
9371 if (ignoredFilter) {
9372 ignoredFilters[localEvent] = ignoredFilter;
9373 }
9374
9375 handler.$delegate = delegate.bind(node, ELEMENT_SELECTOR, event, handler);
9376 }
9377
9378 function unregisterEvent(node, event, localEvent) {
9379
9380 var handler = mouseHandler(localEvent);
9381
9382 if (!handler) {
9383 return;
9384 }
9385
9386 delegate.unbind(node, event, handler.$delegate);
9387 }
9388
9389 function registerEvents(svg) {
9390 forEach$1(bindings, function(val, key) {
9391 registerEvent(svg, key, val);
9392 });
9393 }
9394
9395 function unregisterEvents(svg) {
9396 forEach$1(bindings, function(val, key) {
9397 unregisterEvent(svg, key, val);
9398 });
9399 }
9400
9401 eventBus.on('canvas.destroy', function(event) {
9402 unregisterEvents(event.svg);
9403 });
9404
9405 eventBus.on('canvas.init', function(event) {
9406 registerEvents(event.svg);
9407 });
9408
9409
9410 // hit box updating ////////////////
9411
9412 eventBus.on([ 'shape.added', 'connection.added' ], function(event) {
9413 var element = event.element,
9414 gfx = event.gfx;
9415
9416 eventBus.fire('interactionEvents.createHit', { element: element, gfx: gfx });
9417 });
9418
9419 // Update djs-hit on change.
9420 // A low priortity is necessary, because djs-hit of labels has to be updated
9421 // after the label bounds have been updated in the renderer.
9422 eventBus.on([
9423 'shape.changed',
9424 'connection.changed'
9425 ], LOW_PRIORITY$1, function(event) {
9426
9427 var element = event.element,
9428 gfx = event.gfx;
9429
9430 eventBus.fire('interactionEvents.updateHit', { element: element, gfx: gfx });
9431 });
9432
9433 eventBus.on('interactionEvents.createHit', LOW_PRIORITY$1, function(event) {
9434 var element = event.element,
9435 gfx = event.gfx;
9436
9437 self.createDefaultHit(element, gfx);
9438 });
9439
9440 eventBus.on('interactionEvents.updateHit', function(event) {
9441 var element = event.element,
9442 gfx = event.gfx;
9443
9444 self.updateDefaultHit(element, gfx);
9445 });
9446
9447
9448 // hit styles ////////////
9449
9450 var STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-stroke');
9451
9452 var CLICK_STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-click-stroke');
9453
9454 var ALL_HIT_STYLE = createHitStyle('djs-hit djs-hit-all');
9455
9456 var NO_MOVE_HIT_STYLE = createHitStyle('djs-hit djs-hit-no-move');
9457
9458 var HIT_TYPES = {
9459 'all': ALL_HIT_STYLE,
9460 'click-stroke': CLICK_STROKE_HIT_STYLE,
9461 'stroke': STROKE_HIT_STYLE,
9462 'no-move': NO_MOVE_HIT_STYLE
9463 };
9464
9465 function createHitStyle(classNames, attrs) {
9466
9467 attrs = assign$1({
9468 stroke: 'white',
9469 strokeWidth: 15
9470 }, attrs || {});
9471
9472 return styles.cls(classNames, [ 'no-fill', 'no-border' ], attrs);
9473 }
9474
9475
9476 // style helpers ///////////////
9477
9478 function applyStyle(hit, type) {
9479
9480 var attrs = HIT_TYPES[type];
9481
9482 if (!attrs) {
9483 throw new Error('invalid hit type <' + type + '>');
9484 }
9485
9486 attr$1(hit, attrs);
9487
9488 return hit;
9489 }
9490
9491 function appendHit(gfx, hit) {
9492 append(gfx, hit);
9493 }
9494
9495
9496 // API
9497
9498 /**
9499 * Remove hints on the given graphics.
9500 *
9501 * @param {SVGElement} gfx
9502 */
9503 this.removeHits = function(gfx) {
9504 var hits = all('.djs-hit', gfx);
9505
9506 forEach$1(hits, remove$2);
9507 };
9508
9509 /**
9510 * Create default hit for the given element.
9511 *
9512 * @param {Element} element
9513 * @param {SVGElement} gfx
9514 *
9515 * @return {SVGElement} created hit
9516 */
9517 this.createDefaultHit = function(element, gfx) {
9518 var waypoints = element.waypoints,
9519 isFrame = element.isFrame,
9520 boxType;
9521
9522 if (waypoints) {
9523 return this.createWaypointsHit(gfx, waypoints);
9524 } else {
9525
9526 boxType = isFrame ? 'stroke' : 'all';
9527
9528 return this.createBoxHit(gfx, boxType, {
9529 width: element.width,
9530 height: element.height
9531 });
9532 }
9533 };
9534
9535 /**
9536 * Create hits for the given waypoints.
9537 *
9538 * @param {SVGElement} gfx
9539 * @param {Point[]} waypoints
9540 *
9541 * @return {SVGElement}
9542 */
9543 this.createWaypointsHit = function(gfx, waypoints) {
9544
9545 var hit = createLine(waypoints);
9546
9547 applyStyle(hit, 'stroke');
9548
9549 appendHit(gfx, hit);
9550
9551 return hit;
9552 };
9553
9554 /**
9555 * Create hits for a box.
9556 *
9557 * @param {SVGElement} gfx
9558 * @param {string} type
9559 * @param {Object} attrs
9560 *
9561 * @return {SVGElement}
9562 */
9563 this.createBoxHit = function(gfx, type, attrs) {
9564
9565 attrs = assign$1({
9566 x: 0,
9567 y: 0
9568 }, attrs);
9569
9570 var hit = create$1('rect');
9571
9572 applyStyle(hit, type);
9573
9574 attr$1(hit, attrs);
9575
9576 appendHit(gfx, hit);
9577
9578 return hit;
9579 };
9580
9581 /**
9582 * Update default hit of the element.
9583 *
9584 * @param {Element} element
9585 * @param {SVGElement} gfx
9586 *
9587 * @return {SVGElement} updated hit
9588 */
9589 this.updateDefaultHit = function(element, gfx) {
9590
9591 var hit = query('.djs-hit', gfx);
9592
9593 if (!hit) {
9594 return;
9595 }
9596
9597 if (element.waypoints) {
9598 updateLine(hit, element.waypoints);
9599 } else {
9600 attr$1(hit, {
9601 width: element.width,
9602 height: element.height
9603 });
9604 }
9605
9606 return hit;
9607 };
9608
9609 this.fire = fire;
9610
9611 this.triggerMouseEvent = triggerMouseEvent;
9612
9613 this.mouseHandler = mouseHandler;
9614
9615 this.registerEvent = registerEvent;
9616 this.unregisterEvent = unregisterEvent;
9617 }
9618
9619
9620 InteractionEvents.$inject = [
9621 'eventBus',
9622 'elementRegistry',
9623 'styles'
9624 ];
9625
9626
9627 /**
9628 * An event indicating that the mouse hovered over an element
9629 *
9630 * @event element.hover
9631 *
9632 * @type {Object}
9633 * @property {Element} element
9634 * @property {SVGElement} gfx
9635 * @property {Event} originalEvent
9636 */
9637
9638 /**
9639 * An event indicating that the mouse has left an element
9640 *
9641 * @event element.out
9642 *
9643 * @type {Object}
9644 * @property {Element} element
9645 * @property {SVGElement} gfx
9646 * @property {Event} originalEvent
9647 */
9648
9649 /**
9650 * An event indicating that the mouse has clicked an element
9651 *
9652 * @event element.click
9653 *
9654 * @type {Object}
9655 * @property {Element} element
9656 * @property {SVGElement} gfx
9657 * @property {Event} originalEvent
9658 */
9659
9660 /**
9661 * An event indicating that the mouse has double clicked an element
9662 *
9663 * @event element.dblclick
9664 *
9665 * @type {Object}
9666 * @property {Element} element
9667 * @property {SVGElement} gfx
9668 * @property {Event} originalEvent
9669 */
9670
9671 /**
9672 * An event indicating that the mouse has gone down on an element.
9673 *
9674 * @event element.mousedown
9675 *
9676 * @type {Object}
9677 * @property {Element} element
9678 * @property {SVGElement} gfx
9679 * @property {Event} originalEvent
9680 */
9681
9682 /**
9683 * An event indicating that the mouse has gone up on an element.
9684 *
9685 * @event element.mouseup
9686 *
9687 * @type {Object}
9688 * @property {Element} element
9689 * @property {SVGElement} gfx
9690 * @property {Event} originalEvent
9691 */
9692
9693 /**
9694 * An event indicating that the context menu action is triggered
9695 * via mouse or touch controls.
9696 *
9697 * @event element.contextmenu
9698 *
9699 * @type {Object}
9700 * @property {Element} element
9701 * @property {SVGElement} gfx
9702 * @property {Event} originalEvent
9703 */
9704
9705 /**
9706 * @type { import('didi').ModuleDeclaration }
9707 */
9708 var InteractionEventsModule = {
9709 __init__: [ 'interactionEvents' ],
9710 interactionEvents: [ 'type', InteractionEvents ]
9711 };
9712
9713 /**
9714 * @typedef {import('../../core/Canvas').default} Canvas
9715 * @typedef {import('../../core/EventBus').default} EventBus
9716 */
9717
9718 /**
9719 * A service that offers the current selection in a diagram.
9720 * Offers the api to control the selection, too.
9721 *
9722 * @param {EventBus} eventBus
9723 * @param {Canvas} canvas
9724 */
9725 function Selection(eventBus, canvas) {
9726
9727 this._eventBus = eventBus;
9728 this._canvas = canvas;
9729
9730 /**
9731 * @type {Object[]}
9732 */
9733 this._selectedElements = [];
9734
9735 var self = this;
9736
9737 eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
9738 var element = e.element;
9739 self.deselect(element);
9740 });
9741
9742 eventBus.on([ 'diagram.clear', 'root.set' ], function(e) {
9743 self.select(null);
9744 });
9745 }
9746
9747 Selection.$inject = [ 'eventBus', 'canvas' ];
9748
9749 /**
9750 * Deselect an element.
9751 *
9752 * @param {Object} element The element to deselect.
9753 */
9754 Selection.prototype.deselect = function(element) {
9755 var selectedElements = this._selectedElements;
9756
9757 var idx = selectedElements.indexOf(element);
9758
9759 if (idx !== -1) {
9760 var oldSelection = selectedElements.slice();
9761
9762 selectedElements.splice(idx, 1);
9763
9764 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
9765 }
9766 };
9767
9768 /**
9769 * Get the selected elements.
9770 *
9771 * @return {Object[]} The selected elements.
9772 */
9773 Selection.prototype.get = function() {
9774 return this._selectedElements;
9775 };
9776
9777 /**
9778 * Check whether an element is selected.
9779 *
9780 * @param {Object} element The element.
9781 *
9782 * @return {boolean} Whether the element is selected.
9783 */
9784 Selection.prototype.isSelected = function(element) {
9785 return this._selectedElements.indexOf(element) !== -1;
9786 };
9787
9788
9789 /**
9790 * Select one or many elements.
9791 *
9792 * @param {Object|Object[]} elements The element(s) to select.
9793 * @param {boolean} [add] Whether to add the element(s) to the selected elements.
9794 * Defaults to `false`.
9795 */
9796 Selection.prototype.select = function(elements, add) {
9797 var selectedElements = this._selectedElements,
9798 oldSelection = selectedElements.slice();
9799
9800 if (!isArray$2(elements)) {
9801 elements = elements ? [ elements ] : [];
9802 }
9803
9804 var canvas = this._canvas;
9805
9806 var rootElement = canvas.getRootElement();
9807
9808 elements = elements.filter(function(element) {
9809 var elementRoot = canvas.findRoot(element);
9810
9811 return rootElement === elementRoot;
9812 });
9813
9814 // selection may be cleared by passing an empty array or null
9815 // to the method
9816 if (add) {
9817 forEach$1(elements, function(element) {
9818 if (selectedElements.indexOf(element) !== -1) {
9819
9820 // already selected
9821 return;
9822 } else {
9823 selectedElements.push(element);
9824 }
9825 });
9826 } else {
9827 this._selectedElements = selectedElements = elements.slice();
9828 }
9829
9830 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
9831 };
9832
9833 /**
9834 * @typedef {import('../../core/Canvas').default} Canvas
9835 * @typedef {import('../../core/EventBus').default} EventBus
9836 * @typedef {import('./Selection').default} Selection
9837 */
9838
9839 var MARKER_HOVER = 'hover',
9840 MARKER_SELECTED = 'selected';
9841
9842 var SELECTION_OUTLINE_PADDING = 6;
9843
9844
9845 /**
9846 * A plugin that adds a visible selection UI to shapes and connections
9847 * by appending the <code>hover</code> and <code>selected</code> classes to them.
9848 *
9849 * @class
9850 *
9851 * Makes elements selectable, too.
9852 *
9853 * @param {Canvas} canvas
9854 * @param {EventBus} eventBus
9855 * @param {Selection} selection
9856 */
9857 function SelectionVisuals(canvas, eventBus, selection) {
9858 this._canvas = canvas;
9859
9860 var self = this;
9861
9862 this._multiSelectionBox = null;
9863
9864 function addMarker(e, cls) {
9865 canvas.addMarker(e, cls);
9866 }
9867
9868 function removeMarker(e, cls) {
9869 canvas.removeMarker(e, cls);
9870 }
9871
9872 eventBus.on('element.hover', function(event) {
9873 addMarker(event.element, MARKER_HOVER);
9874 });
9875
9876 eventBus.on('element.out', function(event) {
9877 removeMarker(event.element, MARKER_HOVER);
9878 });
9879
9880 eventBus.on('selection.changed', function(event) {
9881
9882 function deselect(s) {
9883 removeMarker(s, MARKER_SELECTED);
9884 }
9885
9886 function select(s) {
9887 addMarker(s, MARKER_SELECTED);
9888 }
9889
9890 var oldSelection = event.oldSelection,
9891 newSelection = event.newSelection;
9892
9893 forEach$1(oldSelection, function(e) {
9894 if (newSelection.indexOf(e) === -1) {
9895 deselect(e);
9896 }
9897 });
9898
9899 forEach$1(newSelection, function(e) {
9900 if (oldSelection.indexOf(e) === -1) {
9901 select(e);
9902 }
9903 });
9904
9905 self._updateSelectionOutline(newSelection);
9906 });
9907
9908
9909 eventBus.on('element.changed', function(event) {
9910 if (selection.isSelected(event.element)) {
9911 self._updateSelectionOutline(selection.get());
9912 }
9913 });
9914 }
9915
9916 SelectionVisuals.$inject = [
9917 'canvas',
9918 'eventBus',
9919 'selection'
9920 ];
9921
9922 SelectionVisuals.prototype._updateSelectionOutline = function(selection) {
9923 var layer = this._canvas.getLayer('selectionOutline');
9924
9925 clear$1(layer);
9926
9927 var enabled = selection.length > 1;
9928
9929 var container = this._canvas.getContainer();
9930
9931 classes$1(container)[enabled ? 'add' : 'remove']('djs-multi-select');
9932
9933 if (!enabled) {
9934 return;
9935 }
9936
9937 var bBox = addSelectionOutlinePadding(getBBox(selection));
9938
9939 var rect = create$1('rect');
9940
9941 attr$1(rect, assign$1({
9942 rx: 3
9943 }, bBox));
9944
9945 classes$1(rect).add('djs-selection-outline');
9946
9947 append(layer, rect);
9948 };
9949
9950 // helpers //////////
9951
9952 function addSelectionOutlinePadding(bBox) {
9953 return {
9954 x: bBox.x - SELECTION_OUTLINE_PADDING,
9955 y: bBox.y - SELECTION_OUTLINE_PADDING,
9956 width: bBox.width + SELECTION_OUTLINE_PADDING * 2,
9957 height: bBox.height + SELECTION_OUTLINE_PADDING * 2
9958 };
9959 }
9960
9961 /**
9962 * @typedef {import('../../core/Canvas').default} Canvas
9963 * @typedef {import('../../core/ElementRegistry').default} ElementRegistry
9964 * @typedef {import('../../core/EventBus').default} EventBus
9965 * @typedef {import('./Selection').default} Selection
9966 */
9967
9968 /**
9969 * @param {EventBus} eventBus
9970 * @param {Selection} selection
9971 * @param {Canvas} canvas
9972 * @param {ElementRegistry} elementRegistry
9973 */
9974 function SelectionBehavior(eventBus, selection, canvas, elementRegistry) {
9975
9976 // Select elements on create
9977 eventBus.on('create.end', 500, function(event) {
9978 var context = event.context,
9979 canExecute = context.canExecute,
9980 elements = context.elements,
9981 hints = context.hints || {},
9982 autoSelect = hints.autoSelect;
9983
9984 if (canExecute) {
9985 if (autoSelect === false) {
9986
9987 // Select no elements
9988 return;
9989 }
9990
9991 if (isArray$2(autoSelect)) {
9992 selection.select(autoSelect);
9993 } else {
9994
9995 // Select all elements by default
9996 selection.select(elements.filter(isShown));
9997 }
9998 }
9999 });
10000
10001 // Select connection targets on connect
10002 eventBus.on('connect.end', 500, function(event) {
10003 var context = event.context,
10004 connection = context.connection;
10005
10006 if (connection) {
10007 selection.select(connection);
10008 }
10009 });
10010
10011 // Select shapes on move
10012 eventBus.on('shape.move.end', 500, function(event) {
10013 var previousSelection = event.previousSelection || [];
10014
10015 var shape = elementRegistry.get(event.context.shape.id);
10016
10017 // Always select main shape on move
10018 var isSelected = find(previousSelection, function(selectedShape) {
10019 return shape.id === selectedShape.id;
10020 });
10021
10022 if (!isSelected) {
10023 selection.select(shape);
10024 }
10025 });
10026
10027 // Select elements on click
10028 eventBus.on('element.click', function(event) {
10029
10030 if (!isPrimaryButton(event)) {
10031 return;
10032 }
10033
10034 var element = event.element;
10035
10036 if (element === canvas.getRootElement()) {
10037 element = null;
10038 }
10039
10040 var isSelected = selection.isSelected(element),
10041 isMultiSelect = selection.get().length > 1;
10042
10043 // Add to selection if SHIFT pressed
10044 var add = hasSecondaryModifier(event);
10045
10046 if (isSelected && isMultiSelect) {
10047 if (add) {
10048
10049 // Deselect element
10050 return selection.deselect(element);
10051 } else {
10052
10053 // Select element only
10054 return selection.select(element);
10055 }
10056 } else if (!isSelected) {
10057
10058 // Select element
10059 selection.select(element, add);
10060 } else {
10061
10062 // Deselect element
10063 selection.deselect(element);
10064 }
10065 });
10066 }
10067
10068 SelectionBehavior.$inject = [
10069 'eventBus',
10070 'selection',
10071 'canvas',
10072 'elementRegistry'
10073 ];
10074
10075
10076 function isShown(element) {
10077 return !element.hidden;
10078 }
10079
10080 /**
10081 * @type { import('didi').ModuleDeclaration }
10082 */
10083 var SelectionModule = {
10084 __init__: [ 'selectionVisuals', 'selectionBehavior' ],
10085 __depends__: [
10086 InteractionEventsModule,
10087 OutlineModule$1
10088 ],
10089 selection: [ 'type', Selection ],
10090 selectionVisuals: [ 'type', SelectionVisuals ],
10091 selectionBehavior: [ 'type', SelectionBehavior ]
10092 };
10093
10094 const CLASS_PATTERN = /^class[ {]/;
10095
10096
10097 /**
10098 * @param {function} fn
10099 *
10100 * @return {boolean}
10101 */
10102 function isClass(fn) {
10103 return CLASS_PATTERN.test(fn.toString());
10104 }
10105
10106 /**
10107 * @param {any} obj
10108 *
10109 * @return {boolean}
10110 */
10111 function isArray(obj) {
10112 return Array.isArray(obj);
10113 }
10114
10115 /**
10116 * @param {any} obj
10117 * @param {string} prop
10118 *
10119 * @return {boolean}
10120 */
10121 function hasOwnProp(obj, prop) {
10122 return Object.prototype.hasOwnProperty.call(obj, prop);
10123 }
10124
10125 /**
10126 * @typedef {import('./index.js').InjectAnnotated } InjectAnnotated
10127 */
10128
10129 /**
10130 * @template T
10131 *
10132 * @params {[...string[], T] | ...string[], T} args
10133 *
10134 * @return {T & InjectAnnotated}
10135 */
10136 function annotate(...args) {
10137
10138 if (args.length === 1 && isArray(args[0])) {
10139 args = args[0];
10140 }
10141
10142 args = [ ...args ];
10143
10144 const fn = args.pop();
10145
10146 fn.$inject = args;
10147
10148 return fn;
10149 }
10150
10151
10152 // Current limitations:
10153 // - can't put into "function arg" comments
10154 // function /* (no parenthesis like this) */ (){}
10155 // function abc( /* xx (no parenthesis like this) */ a, b) {}
10156 //
10157 // Just put the comment before function or inside:
10158 // /* (((this is fine))) */ function(a, b) {}
10159 // function abc(a) { /* (((this is fine))) */}
10160 //
10161 // - can't reliably auto-annotate constructor; we'll match the
10162 // first constructor(...) pattern found which may be the one
10163 // of a nested class, too.
10164
10165 const CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
10166 const FN_ARGS = /^(?:async\s+)?(?:function\s*[^(]*)?(?:\(\s*([^)]*)\)|(\w+))/m;
10167 const FN_ARG = /\/\*([^*]*)\*\//m;
10168
10169 /**
10170 * @param {unknown} fn
10171 *
10172 * @return {string[]}
10173 */
10174 function parseAnnotations(fn) {
10175
10176 if (typeof fn !== 'function') {
10177 throw new Error(`Cannot annotate "${fn}". Expected a function!`);
10178 }
10179
10180 const match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
10181
10182 // may parse class without constructor
10183 if (!match) {
10184 return [];
10185 }
10186
10187 const args = match[1] || match[2];
10188
10189 return args && args.split(',').map(arg => {
10190 const argMatch = arg.match(FN_ARG);
10191 return (argMatch && argMatch[1] || arg).trim();
10192 }) || [];
10193 }
10194
10195 /**
10196 * @typedef { import('./index.js').ModuleDeclaration } ModuleDeclaration
10197 * @typedef { import('./index.js').ModuleDefinition } ModuleDefinition
10198 * @typedef { import('./index.js').InjectorContext } InjectorContext
10199 *
10200 * @typedef { import('./index.js').TypedDeclaration<any, any> } TypedDeclaration
10201 */
10202
10203 /**
10204 * Create a new injector with the given modules.
10205 *
10206 * @param {ModuleDefinition[]} modules
10207 * @param {InjectorContext} [_parent]
10208 */
10209 function Injector(modules, _parent) {
10210
10211 const parent = _parent || /** @type InjectorContext */ ({
10212 get: function(name, strict) {
10213 currentlyResolving.push(name);
10214
10215 if (strict === false) {
10216 return null;
10217 } else {
10218 throw error(`No provider for "${ name }"!`);
10219 }
10220 }
10221 });
10222
10223 const currentlyResolving = [];
10224 const providers = this._providers = Object.create(parent._providers || null);
10225 const instances = this._instances = Object.create(null);
10226
10227 const self = instances.injector = this;
10228
10229 const error = function(msg) {
10230 const stack = currentlyResolving.join(' -> ');
10231 currentlyResolving.length = 0;
10232 return new Error(stack ? `${ msg } (Resolving: ${ stack })` : msg);
10233 };
10234
10235 /**
10236 * Return a named service.
10237 *
10238 * @param {string} name
10239 * @param {boolean} [strict=true] if false, resolve missing services to null
10240 *
10241 * @return {any}
10242 */
10243 function get(name, strict) {
10244 if (!providers[name] && name.includes('.')) {
10245
10246 const parts = name.split('.');
10247 let pivot = get(/** @type { string } */ (parts.shift()));
10248
10249 while (parts.length) {
10250 pivot = pivot[/** @type { string } */ (parts.shift())];
10251 }
10252
10253 return pivot;
10254 }
10255
10256 if (hasOwnProp(instances, name)) {
10257 return instances[name];
10258 }
10259
10260 if (hasOwnProp(providers, name)) {
10261 if (currentlyResolving.indexOf(name) !== -1) {
10262 currentlyResolving.push(name);
10263 throw error('Cannot resolve circular dependency!');
10264 }
10265
10266 currentlyResolving.push(name);
10267 instances[name] = providers[name][0](providers[name][1]);
10268 currentlyResolving.pop();
10269
10270 return instances[name];
10271 }
10272
10273 return parent.get(name, strict);
10274 }
10275
10276 function fnDef(fn, locals) {
10277
10278 if (typeof locals === 'undefined') {
10279 locals = {};
10280 }
10281
10282 if (typeof fn !== 'function') {
10283 if (isArray(fn)) {
10284 fn = annotate(fn.slice());
10285 } else {
10286 throw error(`Cannot invoke "${ fn }". Expected a function!`);
10287 }
10288 }
10289
10290 /**
10291 * @type {string[]}
10292 */
10293 const inject = fn.$inject || parseAnnotations(fn);
10294 const dependencies = inject.map(dep => {
10295 if (hasOwnProp(locals, dep)) {
10296 return locals[dep];
10297 } else {
10298 return get(dep);
10299 }
10300 });
10301
10302 return {
10303 fn: fn,
10304 dependencies
10305 };
10306 }
10307
10308 /**
10309 * Instantiate the given type, injecting dependencies.
10310 *
10311 * @template T
10312 *
10313 * @param { Function | [...string[], Function ]} type
10314 *
10315 * @return T
10316 */
10317 function instantiate(type) {
10318 const {
10319 fn,
10320 dependencies
10321 } = fnDef(type);
10322
10323 // instantiate var args constructor
10324 const Constructor = Function.prototype.bind.call(fn, null, ...dependencies);
10325
10326 return new Constructor();
10327 }
10328
10329 /**
10330 * Invoke the given function, injecting dependencies. Return the result.
10331 *
10332 * @template T
10333 *
10334 * @param { Function | [...string[], Function ]} func
10335 * @param { Object } [context]
10336 * @param { Object } [locals]
10337 *
10338 * @return {T} invocation result
10339 */
10340 function invoke(func, context, locals) {
10341 const {
10342 fn,
10343 dependencies
10344 } = fnDef(func, locals);
10345
10346 return fn.apply(context, dependencies);
10347 }
10348
10349 /**
10350 * @param {Injector} childInjector
10351 *
10352 * @return {Function}
10353 */
10354 function createPrivateInjectorFactory(childInjector) {
10355 return annotate(key => childInjector.get(key));
10356 }
10357
10358 /**
10359 * @param {ModuleDefinition[]} modules
10360 * @param {string[]} [forceNewInstances]
10361 *
10362 * @return {Injector}
10363 */
10364 function createChild(modules, forceNewInstances) {
10365 if (forceNewInstances && forceNewInstances.length) {
10366 const fromParentModule = Object.create(null);
10367 const matchedScopes = Object.create(null);
10368
10369 const privateInjectorsCache = [];
10370 const privateChildInjectors = [];
10371 const privateChildFactories = [];
10372
10373 let provider;
10374 let cacheIdx;
10375 let privateChildInjector;
10376 let privateChildInjectorFactory;
10377
10378 for (let name in providers) {
10379 provider = providers[name];
10380
10381 if (forceNewInstances.indexOf(name) !== -1) {
10382 if (provider[2] === 'private') {
10383 cacheIdx = privateInjectorsCache.indexOf(provider[3]);
10384 if (cacheIdx === -1) {
10385 privateChildInjector = provider[3].createChild([], forceNewInstances);
10386 privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
10387 privateInjectorsCache.push(provider[3]);
10388 privateChildInjectors.push(privateChildInjector);
10389 privateChildFactories.push(privateChildInjectorFactory);
10390 fromParentModule[name] = [ privateChildInjectorFactory, name, 'private', privateChildInjector ];
10391 } else {
10392 fromParentModule[name] = [ privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx] ];
10393 }
10394 } else {
10395 fromParentModule[name] = [ provider[2], provider[1] ];
10396 }
10397 matchedScopes[name] = true;
10398 }
10399
10400 if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
10401 /* jshint -W083 */
10402 forceNewInstances.forEach(scope => {
10403 if (provider[1].$scope.indexOf(scope) !== -1) {
10404 fromParentModule[name] = [ provider[2], provider[1] ];
10405 matchedScopes[scope] = true;
10406 }
10407 });
10408 }
10409 }
10410
10411 forceNewInstances.forEach(scope => {
10412 if (!matchedScopes[scope]) {
10413 throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
10414 }
10415 });
10416
10417 modules.unshift(fromParentModule);
10418 }
10419
10420 return new Injector(modules, self);
10421 }
10422
10423 const factoryMap = {
10424 factory: invoke,
10425 type: instantiate,
10426 value: function(value) {
10427 return value;
10428 }
10429 };
10430
10431 /**
10432 * @param {ModuleDefinition} moduleDefinition
10433 * @param {Injector} injector
10434 */
10435 function createInitializer(moduleDefinition, injector) {
10436
10437 const initializers = moduleDefinition.__init__ || [];
10438
10439 return function() {
10440 initializers.forEach(initializer => {
10441
10442 // eagerly resolve component (fn or string)
10443 if (typeof initializer === 'string') {
10444 injector.get(initializer);
10445 } else {
10446 injector.invoke(initializer);
10447 }
10448 });
10449 };
10450 }
10451
10452 /**
10453 * @param {ModuleDefinition} moduleDefinition
10454 */
10455 function loadModule(moduleDefinition) {
10456
10457 const moduleExports = moduleDefinition.__exports__;
10458
10459 // private module
10460 if (moduleExports) {
10461 const nestedModules = moduleDefinition.__modules__;
10462
10463 const clonedModule = Object.keys(moduleDefinition).reduce((clonedModule, key) => {
10464
10465 if (key !== '__exports__' && key !== '__modules__' && key !== '__init__' && key !== '__depends__') {
10466 clonedModule[key] = moduleDefinition[key];
10467 }
10468
10469 return clonedModule;
10470 }, Object.create(null));
10471
10472 const childModules = (nestedModules || []).concat(clonedModule);
10473
10474 const privateInjector = createChild(childModules);
10475 const getFromPrivateInjector = annotate(function(key) {
10476 return privateInjector.get(key);
10477 });
10478
10479 moduleExports.forEach(function(key) {
10480 providers[key] = [ getFromPrivateInjector, key, 'private', privateInjector ];
10481 });
10482
10483 // ensure child injector initializes
10484 const initializers = (moduleDefinition.__init__ || []).slice();
10485
10486 initializers.unshift(function() {
10487 privateInjector.init();
10488 });
10489
10490 moduleDefinition = Object.assign({}, moduleDefinition, {
10491 __init__: initializers
10492 });
10493
10494 return createInitializer(moduleDefinition, privateInjector);
10495 }
10496
10497 // normal module
10498 Object.keys(moduleDefinition).forEach(function(key) {
10499
10500 if (key === '__init__' || key === '__depends__') {
10501 return;
10502 }
10503
10504 const typeDeclaration = /** @type { TypedDeclaration } */ (
10505 moduleDefinition[key]
10506 );
10507
10508 if (typeDeclaration[2] === 'private') {
10509 providers[key] = typeDeclaration;
10510 return;
10511 }
10512
10513 const type = typeDeclaration[0];
10514 const value = typeDeclaration[1];
10515
10516 providers[key] = [ factoryMap[type], arrayUnwrap(type, value), type ];
10517 });
10518
10519 return createInitializer(moduleDefinition, self);
10520 }
10521
10522 /**
10523 * @param {ModuleDefinition[]} moduleDefinitions
10524 * @param {ModuleDefinition} moduleDefinition
10525 *
10526 * @return {ModuleDefinition[]}
10527 */
10528 function resolveDependencies(moduleDefinitions, moduleDefinition) {
10529
10530 if (moduleDefinitions.indexOf(moduleDefinition) !== -1) {
10531 return moduleDefinitions;
10532 }
10533
10534 moduleDefinitions = (moduleDefinition.__depends__ || []).reduce(resolveDependencies, moduleDefinitions);
10535
10536 if (moduleDefinitions.indexOf(moduleDefinition) !== -1) {
10537 return moduleDefinitions;
10538 }
10539
10540 return moduleDefinitions.concat(moduleDefinition);
10541 }
10542
10543 /**
10544 * @param {ModuleDefinition[]} moduleDefinitions
10545 *
10546 * @return { () => void } initializerFn
10547 */
10548 function bootstrap(moduleDefinitions) {
10549
10550 const initializers = moduleDefinitions
10551 .reduce(resolveDependencies, [])
10552 .map(loadModule);
10553
10554 let initialized = false;
10555
10556 return function() {
10557
10558 if (initialized) {
10559 return;
10560 }
10561
10562 initialized = true;
10563
10564 initializers.forEach(initializer => initializer());
10565 };
10566 }
10567
10568 // public API
10569 this.get = get;
10570 this.invoke = invoke;
10571 this.instantiate = instantiate;
10572 this.createChild = createChild;
10573
10574 // setup
10575 this.init = bootstrap(modules);
10576 }
10577
10578
10579 // helpers ///////////////
10580
10581 function arrayUnwrap(type, value) {
10582 if (type !== 'value' && isArray(value)) {
10583 value = annotate(value.slice());
10584 }
10585
10586 return value;
10587 }
10588
10589 /**
10590 * @typedef {import('../core/EventBus').default} EventBus
10591 * @typedef {import('./Styles').default} Styles
10592 */
10593
10594 // apply default renderer with lowest possible priority
10595 // so that it only kicks in if noone else could render
10596 var DEFAULT_RENDER_PRIORITY = 1;
10597
10598 /**
10599 * The default renderer used for shapes and connections.
10600 *
10601 * @param {EventBus} eventBus
10602 * @param {Styles} styles
10603 */
10604 function DefaultRenderer(eventBus, styles) {
10605
10606 BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY);
10607
10608 this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
10609 this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
10610 this.FRAME_STYLE = styles.style([ 'no-fill' ], { stroke: 'fuchsia', strokeDasharray: 4, strokeWidth: 2 });
10611 }
10612
10613 e(DefaultRenderer, BaseRenderer);
10614
10615
10616 /**
10617 * @private
10618 */
10619 DefaultRenderer.prototype.canRender = function() {
10620 return true;
10621 };
10622
10623 /**
10624 * @private
10625 */
10626 DefaultRenderer.prototype.drawShape = function drawShape(visuals, element, attrs) {
10627 var rect = create$1('rect');
10628
10629 attr$1(rect, {
10630 x: 0,
10631 y: 0,
10632 width: element.width || 0,
10633 height: element.height || 0
10634 });
10635
10636 if (isFrameElement(element)) {
10637 attr$1(rect, assign$1({}, this.FRAME_STYLE, attrs || {}));
10638 } else {
10639 attr$1(rect, assign$1({}, this.SHAPE_STYLE, attrs || {}));
10640 }
10641
10642 append(visuals, rect);
10643
10644 return rect;
10645 };
10646
10647 /**
10648 * @private
10649 */
10650 DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection, attrs) {
10651
10652 var line = createLine(connection.waypoints, assign$1({}, this.CONNECTION_STYLE, attrs || {}));
10653 append(visuals, line);
10654
10655 return line;
10656 };
10657
10658 /**
10659 * @private
10660 */
10661 DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {
10662
10663 var x = shape.x,
10664 y = shape.y,
10665 width = shape.width,
10666 height = shape.height;
10667
10668 var shapePath = [
10669 [ 'M', x, y ],
10670 [ 'l', width, 0 ],
10671 [ 'l', 0, height ],
10672 [ 'l', -width, 0 ],
10673 [ 'z' ]
10674 ];
10675
10676 return componentsToPath(shapePath);
10677 };
10678
10679 /**
10680 * @private
10681 */
10682 DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
10683 var waypoints = connection.waypoints;
10684
10685 var idx, point, connectionPath = [];
10686
10687 for (idx = 0; (point = waypoints[idx]); idx++) {
10688
10689 // take invisible docking into account
10690 // when creating the path
10691 point = point.original || point;
10692
10693 connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
10694 }
10695
10696 return componentsToPath(connectionPath);
10697 };
10698
10699 DefaultRenderer.$inject = [ 'eventBus', 'styles' ];
10700
10701 /**
10702 * A component that manages shape styles
10703 */
10704 function Styles() {
10705
10706 var defaultTraits = {
10707
10708 'no-fill': {
10709 fill: 'none'
10710 },
10711 'no-border': {
10712 strokeOpacity: 0.0
10713 },
10714 'no-events': {
10715 pointerEvents: 'none'
10716 }
10717 };
10718
10719 var self = this;
10720
10721 /**
10722 * Builds a style definition from a className, a list of traits and an object
10723 * of additional attributes.
10724 *
10725 * @param {string} className
10726 * @param {string[]} [traits]
10727 * @param {Object} [additionalAttrs]
10728 *
10729 * @return {Object} the style definition
10730 */
10731 this.cls = function(className, traits, additionalAttrs) {
10732 var attrs = this.style(traits, additionalAttrs);
10733
10734 return assign$1(attrs, { 'class': className });
10735 };
10736
10737 /**
10738 * Builds a style definition from a list of traits and an object of additional
10739 * attributes.
10740 *
10741 * @param {string[]} [traits]
10742 * @param {Object} additionalAttrs
10743 *
10744 * @return {Object} the style definition
10745 */
10746 this.style = function(traits, additionalAttrs) {
10747
10748 if (!isArray$2(traits) && !additionalAttrs) {
10749 additionalAttrs = traits;
10750 traits = [];
10751 }
10752
10753 var attrs = reduce(traits, function(attrs, t) {
10754 return assign$1(attrs, defaultTraits[t] || {});
10755 }, {});
10756
10757 return additionalAttrs ? assign$1(attrs, additionalAttrs) : attrs;
10758 };
10759
10760
10761 /**
10762 * Computes a style definition from a list of traits and an object of
10763 * additional attributes, with custom style definition object.
10764 *
10765 * @param {Object} custom
10766 * @param {string[]} [traits]
10767 * @param {Object} defaultStyles
10768 *
10769 * @return {Object} the style definition
10770 */
10771 this.computeStyle = function(custom, traits, defaultStyles) {
10772 if (!isArray$2(traits)) {
10773 defaultStyles = traits;
10774 traits = [];
10775 }
10776
10777 return self.style(traits || [], assign$1({}, defaultStyles, custom || {}));
10778 };
10779 }
10780
10781 /**
10782 * @type { import('didi').ModuleDeclaration }
10783 */
10784 var DrawModule = {
10785 __init__: [ 'defaultRenderer' ],
10786 defaultRenderer: [ 'type', DefaultRenderer ],
10787 styles: [ 'type', Styles ]
10788 };
10789
10790 /**
10791 * Failsafe remove an element from a collection
10792 *
10793 * @param {Array<Object>} [collection]
10794 * @param {Object} [element]
10795 *
10796 * @return {number} the previous index of the element
10797 */
10798 function remove(collection, element) {
10799
10800 if (!collection || !element) {
10801 return -1;
10802 }
10803
10804 var idx = collection.indexOf(element);
10805
10806 if (idx !== -1) {
10807 collection.splice(idx, 1);
10808 }
10809
10810 return idx;
10811 }
10812
10813 /**
10814 * Fail save add an element to the given connection, ensuring
10815 * it does not yet exist.
10816 *
10817 * @param {Array<Object>} collection
10818 * @param {Object} element
10819 * @param {number} [idx]
10820 */
10821 function add(collection, element, idx) {
10822
10823 if (!collection || !element) {
10824 return;
10825 }
10826
10827 if (typeof idx !== 'number') {
10828 idx = -1;
10829 }
10830
10831 var currentIdx = collection.indexOf(element);
10832
10833 if (currentIdx !== -1) {
10834
10835 if (currentIdx === idx) {
10836
10837 // nothing to do, position has not changed
10838 return;
10839 } else {
10840
10841 if (idx !== -1) {
10842
10843 // remove from current position
10844 collection.splice(currentIdx, 1);
10845 } else {
10846
10847 // already exists in collection
10848 return;
10849 }
10850 }
10851 }
10852
10853 if (idx !== -1) {
10854
10855 // insert at specified position
10856 collection.splice(idx, 0, element);
10857 } else {
10858
10859 // push to end
10860 collection.push(element);
10861 }
10862 }
10863
10864 /**
10865 * @typedef {import('./Types').ConnectionLike} ConnectionLike
10866 * @typedef {import('./Types').RootLike} RootLike
10867 * @typedef {import('./Types').ParentLike } ParentLike
10868 * @typedef {import('./Types').ShapeLike} ShapeLike
10869 *
10870 * @typedef { {
10871 * container?: HTMLElement;
10872 * deferUpdate?: boolean;
10873 * width?: number;
10874 * height?: number;
10875 * } } CanvasConfig
10876 * @typedef { {
10877 * group: SVGElement;
10878 * index: number;
10879 * visible: boolean;
10880 * } } CanvasLayer
10881 * @typedef { {
10882 * [key: string]: CanvasLayer;
10883 * } } CanvasLayers
10884 * @typedef { {
10885 * rootElement: ShapeLike;
10886 * layer: CanvasLayer;
10887 * } } CanvasPlane
10888 * @typedef { {
10889 * scale: number;
10890 * inner: Rect;
10891 * outer: Dimensions;
10892 * } & Rect } CanvasViewbox
10893 *
10894 * @typedef {import('./ElementRegistry').default} ElementRegistry
10895 * @typedef {import('./EventBus').default} EventBus
10896 * @typedef {import('./GraphicsFactory').default} GraphicsFactory
10897 *
10898 * @typedef {import('../util/Types').Dimensions} Dimensions
10899 * @typedef {import('../util/Types').Point} Point
10900 * @typedef {import('../util/Types').Rect} Rect
10901 * @typedef {import('../util/Types').RectTRBL} RectTRBL
10902 * @typedef {import('../util/Types').ScrollDelta} ScrollDelta
10903 */
10904
10905 function round(number, resolution) {
10906 return Math.round(number * resolution) / resolution;
10907 }
10908
10909 function ensurePx(number) {
10910 return isNumber(number) ? number + 'px' : number;
10911 }
10912
10913 function findRoot(element) {
10914 while (element.parent) {
10915 element = element.parent;
10916 }
10917
10918 return element;
10919 }
10920
10921 /**
10922 * Creates a HTML container element for a SVG element with
10923 * the given configuration
10924 *
10925 * @param {CanvasConfig} options
10926 *
10927 * @return {HTMLElement} the container element
10928 */
10929 function createContainer(options) {
10930
10931 options = assign$1({}, { width: '100%', height: '100%' }, options);
10932
10933 const container = options.container || document.body;
10934
10935 // create a <div> around the svg element with the respective size
10936 // this way we can always get the correct container size
10937 // (this is impossible for <svg> elements at the moment)
10938 const parent = document.createElement('div');
10939 parent.setAttribute('class', 'djs-container djs-parent');
10940
10941 assign(parent, {
10942 position: 'relative',
10943 overflow: 'hidden',
10944 width: ensurePx(options.width),
10945 height: ensurePx(options.height)
10946 });
10947
10948 container.appendChild(parent);
10949
10950 return parent;
10951 }
10952
10953 function createGroup(parent, cls, childIndex) {
10954 const group = create$1('g');
10955 classes$1(group).add(cls);
10956
10957 const index = childIndex !== undefined ? childIndex : parent.childNodes.length - 1;
10958
10959 // must ensure second argument is node or _null_
10960 // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
10961 parent.insertBefore(group, parent.childNodes[index] || null);
10962
10963 return group;
10964 }
10965
10966 const BASE_LAYER = 'base';
10967
10968 // render plane contents behind utility layers
10969 const PLANE_LAYER_INDEX = 0;
10970 const UTILITY_LAYER_INDEX = 1;
10971
10972
10973 const REQUIRED_MODEL_ATTRS = {
10974 shape: [ 'x', 'y', 'width', 'height' ],
10975 connection: [ 'waypoints' ]
10976 };
10977
10978 /**
10979 * The main drawing canvas.
10980 *
10981 * @class
10982 * @constructor
10983 *
10984 * @emits Canvas#canvas.init
10985 *
10986 * @param {CanvasConfig|null} config
10987 * @param {EventBus} eventBus
10988 * @param {GraphicsFactory} graphicsFactory
10989 * @param {ElementRegistry} elementRegistry
10990 */
10991 function Canvas(config, eventBus, graphicsFactory, elementRegistry) {
10992 this._eventBus = eventBus;
10993 this._elementRegistry = elementRegistry;
10994 this._graphicsFactory = graphicsFactory;
10995
10996 /**
10997 * @type {number}
10998 */
10999 this._rootsIdx = 0;
11000
11001 /**
11002 * @type {CanvasLayers}
11003 */
11004 this._layers = {};
11005
11006 /**
11007 * @type {CanvasPlane[]}
11008 */
11009 this._planes = [];
11010
11011 /**
11012 * @type {RootLike|null}
11013 */
11014 this._rootElement = null;
11015
11016 this._init(config || {});
11017 }
11018
11019 Canvas.$inject = [
11020 'config.canvas',
11021 'eventBus',
11022 'graphicsFactory',
11023 'elementRegistry'
11024 ];
11025
11026 /**
11027 * Creates a <svg> element that is wrapped into a <div>.
11028 * This way we are always able to correctly figure out the size of the svg element
11029 * by querying the parent node.
11030
11031 * (It is not possible to get the size of a svg element cross browser @ 2014-04-01)
11032
11033 * <div class="djs-container" style="width: {desired-width}, height: {desired-height}">
11034 * <svg width="100%" height="100%">
11035 * ...
11036 * </svg>
11037 * </div>
11038 *
11039 * @param {CanvasConfig} config
11040 */
11041 Canvas.prototype._init = function(config) {
11042
11043 const eventBus = this._eventBus;
11044
11045 // html container
11046 const container = this._container = createContainer(config);
11047
11048 const svg = this._svg = create$1('svg');
11049 attr$1(svg, { width: '100%', height: '100%' });
11050
11051 append(container, svg);
11052
11053 const viewport = this._viewport = createGroup(svg, 'viewport');
11054
11055 // debounce canvas.viewbox.changed events when deferUpdate is set
11056 // to help with potential performance issues
11057 if (config.deferUpdate) {
11058 this._viewboxChanged = debounce(bind$2(this._viewboxChanged, this), 300);
11059 }
11060
11061 eventBus.on('diagram.init', () => {
11062
11063 /**
11064 * An event indicating that the canvas is ready to be drawn on.
11065 *
11066 * @memberOf Canvas
11067 *
11068 * @event canvas.init
11069 *
11070 * @type {Object}
11071 * @property {SVGElement} svg the created svg element
11072 * @property {SVGElement} viewport the direct parent of diagram elements and shapes
11073 */
11074 eventBus.fire('canvas.init', {
11075 svg: svg,
11076 viewport: viewport
11077 });
11078
11079 });
11080
11081 // reset viewbox on shape changes to
11082 // recompute the viewbox
11083 eventBus.on([
11084 'shape.added',
11085 'connection.added',
11086 'shape.removed',
11087 'connection.removed',
11088 'elements.changed',
11089 'root.set'
11090 ], () => {
11091 delete this._cachedViewbox;
11092 });
11093
11094 eventBus.on('diagram.destroy', 500, this._destroy, this);
11095 eventBus.on('diagram.clear', 500, this._clear, this);
11096 };
11097
11098 Canvas.prototype._destroy = function() {
11099 this._eventBus.fire('canvas.destroy', {
11100 svg: this._svg,
11101 viewport: this._viewport
11102 });
11103
11104 const parent = this._container.parentNode;
11105
11106 if (parent) {
11107 parent.removeChild(this._container);
11108 }
11109
11110 delete this._svg;
11111 delete this._container;
11112 delete this._layers;
11113 delete this._planes;
11114 delete this._rootElement;
11115 delete this._viewport;
11116 };
11117
11118 Canvas.prototype._clear = function() {
11119
11120 const allElements = this._elementRegistry.getAll();
11121
11122 // remove all elements
11123 allElements.forEach(element => {
11124 const type = getType(element);
11125
11126 if (type === 'root') {
11127 this.removeRootElement(element);
11128 } else {
11129 this._removeElement(element, type);
11130 }
11131 });
11132
11133 // remove all planes
11134 this._planes = [];
11135 this._rootElement = null;
11136
11137 // force recomputation of view box
11138 delete this._cachedViewbox;
11139 };
11140
11141 /**
11142 * Returns the default layer on which
11143 * all elements are drawn.
11144 *
11145 * @return {SVGElement} The SVG element of the layer.
11146 */
11147 Canvas.prototype.getDefaultLayer = function() {
11148 return this.getLayer(BASE_LAYER, PLANE_LAYER_INDEX);
11149 };
11150
11151 /**
11152 * Returns a layer that is used to draw elements
11153 * or annotations on it.
11154 *
11155 * Non-existing layers retrieved through this method
11156 * will be created. During creation, the optional index
11157 * may be used to create layers below or above existing layers.
11158 * A layer with a certain index is always created above all
11159 * existing layers with the same index.
11160 *
11161 * @param {string} name The name of the layer.
11162 * @param {number} [index] The index of the layer.
11163 *
11164 * @return {SVGElement} The SVG element of the layer.
11165 */
11166 Canvas.prototype.getLayer = function(name, index) {
11167
11168 if (!name) {
11169 throw new Error('must specify a name');
11170 }
11171
11172 let layer = this._layers[name];
11173
11174 if (!layer) {
11175 layer = this._layers[name] = this._createLayer(name, index);
11176 }
11177
11178 // throw an error if layer creation / retrival is
11179 // requested on different index
11180 if (typeof index !== 'undefined' && layer.index !== index) {
11181 throw new Error('layer <' + name + '> already created at index <' + index + '>');
11182 }
11183
11184 return layer.group;
11185 };
11186
11187 /**
11188 * For a given index, return the number of layers that have a higher index and
11189 * are visible.
11190 *
11191 * This is used to determine the node a layer should be inserted at.
11192 *
11193 * @param {number} index
11194 *
11195 * @return {number}
11196 */
11197 Canvas.prototype._getChildIndex = function(index) {
11198 return reduce(this._layers, function(childIndex, layer) {
11199 if (layer.visible && index >= layer.index) {
11200 childIndex++;
11201 }
11202
11203 return childIndex;
11204 }, 0);
11205 };
11206
11207 /**
11208 * Creates a given layer and returns it.
11209 *
11210 * @param {string} name
11211 * @param {number} [index=0]
11212 *
11213 * @return {CanvasLayer}
11214 */
11215 Canvas.prototype._createLayer = function(name, index) {
11216
11217 if (typeof index === 'undefined') {
11218 index = UTILITY_LAYER_INDEX;
11219 }
11220
11221 const childIndex = this._getChildIndex(index);
11222
11223 return {
11224 group: createGroup(this._viewport, 'layer-' + name, childIndex),
11225 index: index,
11226 visible: true
11227 };
11228 };
11229
11230
11231 /**
11232 * Shows a given layer.
11233 *
11234 * @param {string} name The name of the layer.
11235 *
11236 * @return {SVGElement} The SVG element of the layer.
11237 */
11238 Canvas.prototype.showLayer = function(name) {
11239
11240 if (!name) {
11241 throw new Error('must specify a name');
11242 }
11243
11244 const layer = this._layers[name];
11245
11246 if (!layer) {
11247 throw new Error('layer <' + name + '> does not exist');
11248 }
11249
11250 const viewport = this._viewport;
11251 const group = layer.group;
11252 const index = layer.index;
11253
11254 if (layer.visible) {
11255 return group;
11256 }
11257
11258 const childIndex = this._getChildIndex(index);
11259
11260 viewport.insertBefore(group, viewport.childNodes[childIndex] || null);
11261
11262 layer.visible = true;
11263
11264 return group;
11265 };
11266
11267 /**
11268 * Hides a given layer.
11269 *
11270 * @param {string} name The name of the layer.
11271 *
11272 * @return {SVGElement} The SVG element of the layer.
11273 */
11274 Canvas.prototype.hideLayer = function(name) {
11275
11276 if (!name) {
11277 throw new Error('must specify a name');
11278 }
11279
11280 const layer = this._layers[name];
11281
11282 if (!layer) {
11283 throw new Error('layer <' + name + '> does not exist');
11284 }
11285
11286 const group = layer.group;
11287
11288 if (!layer.visible) {
11289 return group;
11290 }
11291
11292 remove$2(group);
11293
11294 layer.visible = false;
11295
11296 return group;
11297 };
11298
11299
11300 Canvas.prototype._removeLayer = function(name) {
11301
11302 const layer = this._layers[name];
11303
11304 if (layer) {
11305 delete this._layers[name];
11306
11307 remove$2(layer.group);
11308 }
11309 };
11310
11311 /**
11312 * Returns the currently active layer. Can be null.
11313 *
11314 * @return {CanvasLayer|null} The active layer of `null`.
11315 */
11316 Canvas.prototype.getActiveLayer = function() {
11317 const plane = this._findPlaneForRoot(this.getRootElement());
11318
11319 if (!plane) {
11320 return null;
11321 }
11322
11323 return plane.layer;
11324 };
11325
11326
11327 /**
11328 * Returns the plane which contains the given element.
11329 *
11330 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11331 *
11332 * @return {RootLike|undefined} The root of the element.
11333 */
11334 Canvas.prototype.findRoot = function(element) {
11335 if (typeof element === 'string') {
11336 element = this._elementRegistry.get(element);
11337 }
11338
11339 if (!element) {
11340 return;
11341 }
11342
11343 const plane = this._findPlaneForRoot(
11344 findRoot(element)
11345 ) || {};
11346
11347 return plane.rootElement;
11348 };
11349
11350 /**
11351 * Return a list of all root elements on the diagram.
11352 *
11353 * @return {(RootLike)[]} The list of root elements.
11354 */
11355 Canvas.prototype.getRootElements = function() {
11356 return this._planes.map(function(plane) {
11357 return plane.rootElement;
11358 });
11359 };
11360
11361 Canvas.prototype._findPlaneForRoot = function(rootElement) {
11362 return find(this._planes, function(plane) {
11363 return plane.rootElement === rootElement;
11364 });
11365 };
11366
11367
11368 /**
11369 * Returns the html element that encloses the
11370 * drawing canvas.
11371 *
11372 * @return {HTMLElement} The HTML element of the container.
11373 */
11374 Canvas.prototype.getContainer = function() {
11375 return this._container;
11376 };
11377
11378
11379 // markers //////////////////////
11380
11381 Canvas.prototype._updateMarker = function(element, marker, add) {
11382 let container;
11383
11384 if (!element.id) {
11385 element = this._elementRegistry.get(element);
11386 }
11387
11388 // we need to access all
11389 container = this._elementRegistry._elements[element.id];
11390
11391 if (!container) {
11392 return;
11393 }
11394
11395 forEach$1([ container.gfx, container.secondaryGfx ], function(gfx) {
11396 if (gfx) {
11397
11398 // invoke either addClass or removeClass based on mode
11399 if (add) {
11400 classes$1(gfx).add(marker);
11401 } else {
11402 classes$1(gfx).remove(marker);
11403 }
11404 }
11405 });
11406
11407 /**
11408 * An event indicating that a marker has been updated for an element
11409 *
11410 * @event element.marker.update
11411 * @type {Object}
11412 * @property {Element} element the shape
11413 * @property {SVGElement} gfx the graphical representation of the shape
11414 * @property {string} marker
11415 * @property {boolean} add true if the marker was added, false if it got removed
11416 */
11417 this._eventBus.fire('element.marker.update', { element: element, gfx: container.gfx, marker: marker, add: !!add });
11418 };
11419
11420
11421 /**
11422 * Adds a marker to an element (basically a css class).
11423 *
11424 * Fires the element.marker.update event, making it possible to
11425 * integrate extension into the marker life-cycle, too.
11426 *
11427 * @example
11428 *
11429 * ```javascript
11430 * canvas.addMarker('foo', 'some-marker');
11431 *
11432 * const fooGfx = canvas.getGraphics('foo');
11433 *
11434 * fooGfx; // <g class="... some-marker"> ... </g>
11435 * ```
11436 *
11437 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11438 * @param {string} marker The marker.
11439 */
11440 Canvas.prototype.addMarker = function(element, marker) {
11441 this._updateMarker(element, marker, true);
11442 };
11443
11444
11445 /**
11446 * Remove a marker from an element.
11447 *
11448 * Fires the element.marker.update event, making it possible to
11449 * integrate extension into the marker life-cycle, too.
11450 *
11451 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11452 * @param {string} marker The marker.
11453 */
11454 Canvas.prototype.removeMarker = function(element, marker) {
11455 this._updateMarker(element, marker, false);
11456 };
11457
11458 /**
11459 * Check whether an element has a given marker.
11460 *
11461 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11462 * @param {string} marker The marker.
11463 */
11464 Canvas.prototype.hasMarker = function(element, marker) {
11465 if (!element.id) {
11466 element = this._elementRegistry.get(element);
11467 }
11468
11469 const gfx = this.getGraphics(element);
11470
11471 return classes$1(gfx).has(marker);
11472 };
11473
11474 /**
11475 * Toggles a marker on an element.
11476 *
11477 * Fires the element.marker.update event, making it possible to
11478 * integrate extension into the marker life-cycle, too.
11479 *
11480 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11481 * @param {string} marker The marker.
11482 */
11483 Canvas.prototype.toggleMarker = function(element, marker) {
11484 if (this.hasMarker(element, marker)) {
11485 this.removeMarker(element, marker);
11486 } else {
11487 this.addMarker(element, marker);
11488 }
11489 };
11490
11491 /**
11492 * Returns the current root element.
11493 *
11494 * Supports two different modes for handling root elements:
11495 *
11496 * 1. if no root element has been added before, an implicit root will be added
11497 * and returned. This is used in applications that don't require explicit
11498 * root elements.
11499 *
11500 * 2. when root elements have been added before calling `getRootElement`,
11501 * root elements can be null. This is used for applications that want to manage
11502 * root elements themselves.
11503 *
11504 * @return {RootLike} The current root element.
11505 */
11506 Canvas.prototype.getRootElement = function() {
11507 const rootElement = this._rootElement;
11508
11509 // can return null if root elements are present but none was set yet
11510 if (rootElement || this._planes.length) {
11511 return rootElement;
11512 }
11513
11514 return this.setRootElement(this.addRootElement(null));
11515 };
11516
11517 /**
11518 * Adds a given root element and returns it.
11519 *
11520 * @param {RootLike} [rootElement] The root element to be added.
11521 *
11522 * @return {RootLike} The added root element or an implicit root element.
11523 */
11524 Canvas.prototype.addRootElement = function(rootElement) {
11525 const idx = this._rootsIdx++;
11526
11527 if (!rootElement) {
11528 rootElement = {
11529 id: '__implicitroot_' + idx,
11530 children: [],
11531 isImplicit: true
11532 };
11533 }
11534
11535 const layerName = rootElement.layer = 'root-' + idx;
11536
11537 this._ensureValid('root', rootElement);
11538
11539 const layer = this.getLayer(layerName, PLANE_LAYER_INDEX);
11540
11541 this.hideLayer(layerName);
11542
11543 this._addRoot(rootElement, layer);
11544
11545 this._planes.push({
11546 rootElement: rootElement,
11547 layer: layer
11548 });
11549
11550 return rootElement;
11551 };
11552
11553 /**
11554 * Removes a given root element and returns it.
11555 *
11556 * @param {RootLike|string} rootElement element or element ID
11557 *
11558 * @return {RootLike|undefined} removed element
11559 */
11560 Canvas.prototype.removeRootElement = function(rootElement) {
11561
11562 if (typeof rootElement === 'string') {
11563 rootElement = this._elementRegistry.get(rootElement);
11564 }
11565
11566 const plane = this._findPlaneForRoot(rootElement);
11567
11568 if (!plane) {
11569 return;
11570 }
11571
11572 // hook up life-cycle events
11573 this._removeRoot(rootElement);
11574
11575 // clean up layer
11576 this._removeLayer(rootElement.layer);
11577
11578 // clean up plane
11579 this._planes = this._planes.filter(function(plane) {
11580 return plane.rootElement !== rootElement;
11581 });
11582
11583 // clean up active root
11584 if (this._rootElement === rootElement) {
11585 this._rootElement = null;
11586 }
11587
11588 return rootElement;
11589 };
11590
11591
11592 /**
11593 * Sets a given element as the new root element for the canvas
11594 * and returns the new root element.
11595 *
11596 * @param {RootLike} rootElement The root element to be set.
11597 *
11598 * @return {RootLike} The set root element.
11599 */
11600 Canvas.prototype.setRootElement = function(rootElement) {
11601
11602 if (rootElement === this._rootElement) {
11603 return rootElement;
11604 }
11605
11606 let plane;
11607
11608 if (!rootElement) {
11609 throw new Error('rootElement required');
11610 }
11611
11612 plane = this._findPlaneForRoot(rootElement);
11613
11614 // give set add semantics for backwards compatibility
11615 if (!plane) {
11616 rootElement = this.addRootElement(rootElement);
11617 }
11618
11619 this._setRoot(rootElement);
11620
11621 return rootElement;
11622 };
11623
11624
11625 Canvas.prototype._removeRoot = function(element) {
11626 const elementRegistry = this._elementRegistry,
11627 eventBus = this._eventBus;
11628
11629 // simulate element remove event sequence
11630 eventBus.fire('root.remove', { element: element });
11631 eventBus.fire('root.removed', { element: element });
11632
11633 elementRegistry.remove(element);
11634 };
11635
11636
11637 Canvas.prototype._addRoot = function(element, gfx) {
11638 const elementRegistry = this._elementRegistry,
11639 eventBus = this._eventBus;
11640
11641 // resemble element add event sequence
11642 eventBus.fire('root.add', { element: element });
11643
11644 elementRegistry.add(element, gfx);
11645
11646 eventBus.fire('root.added', { element: element, gfx: gfx });
11647 };
11648
11649
11650 Canvas.prototype._setRoot = function(rootElement, layer) {
11651
11652 const currentRoot = this._rootElement;
11653
11654 if (currentRoot) {
11655
11656 // un-associate previous root element <svg>
11657 this._elementRegistry.updateGraphics(currentRoot, null, true);
11658
11659 // hide previous layer
11660 this.hideLayer(currentRoot.layer);
11661 }
11662
11663 if (rootElement) {
11664
11665 if (!layer) {
11666 layer = this._findPlaneForRoot(rootElement).layer;
11667 }
11668
11669 // associate element with <svg>
11670 this._elementRegistry.updateGraphics(rootElement, this._svg, true);
11671
11672 // show root layer
11673 this.showLayer(rootElement.layer);
11674 }
11675
11676 this._rootElement = rootElement;
11677
11678 this._eventBus.fire('root.set', { element: rootElement });
11679 };
11680
11681 Canvas.prototype._ensureValid = function(type, element) {
11682 if (!element.id) {
11683 throw new Error('element must have an id');
11684 }
11685
11686 if (this._elementRegistry.get(element.id)) {
11687 throw new Error('element <' + element.id + '> already exists');
11688 }
11689
11690 const requiredAttrs = REQUIRED_MODEL_ATTRS[type];
11691
11692 const valid = every(requiredAttrs, function(attr) {
11693 return typeof element[attr] !== 'undefined';
11694 });
11695
11696 if (!valid) {
11697 throw new Error(
11698 'must supply { ' + requiredAttrs.join(', ') + ' } with ' + type);
11699 }
11700 };
11701
11702 Canvas.prototype._setParent = function(element, parent, parentIndex) {
11703 add(parent.children, element, parentIndex);
11704 element.parent = parent;
11705 };
11706
11707 /**
11708 * Adds an element to the canvas.
11709 *
11710 * This wires the parent <-> child relationship between the element and
11711 * a explicitly specified parent or an implicit root element.
11712 *
11713 * During add it emits the events
11714 *
11715 * * <{type}.add> (element, parent)
11716 * * <{type}.added> (element, gfx)
11717 *
11718 * Extensions may hook into these events to perform their magic.
11719 *
11720 * @param {string} type
11721 * @param {ConnectionLike|ShapeLike} element
11722 * @param {ShapeLike} [parent]
11723 * @param {number} [parentIndex]
11724 *
11725 * @return {ConnectionLike|ShapeLike} The added element.
11726 */
11727 Canvas.prototype._addElement = function(type, element, parent, parentIndex) {
11728
11729 parent = parent || this.getRootElement();
11730
11731 const eventBus = this._eventBus,
11732 graphicsFactory = this._graphicsFactory;
11733
11734 this._ensureValid(type, element);
11735
11736 eventBus.fire(type + '.add', { element: element, parent: parent });
11737
11738 this._setParent(element, parent, parentIndex);
11739
11740 // create graphics
11741 const gfx = graphicsFactory.create(type, element, parentIndex);
11742
11743 this._elementRegistry.add(element, gfx);
11744
11745 // update its visual
11746 graphicsFactory.update(type, element, gfx);
11747
11748 eventBus.fire(type + '.added', { element: element, gfx: gfx });
11749
11750 return element;
11751 };
11752
11753 /**
11754 * Adds a shape to the canvas.
11755 *
11756 * @param {ShapeLike} shape The shape to be added
11757 * @param {ParentLike} [parent] The shape's parent.
11758 * @param {number} [parentIndex] The index at which to add the shape to the parent's children.
11759 *
11760 * @return {ShapeLike} The added shape.
11761 */
11762 Canvas.prototype.addShape = function(shape, parent, parentIndex) {
11763 return this._addElement('shape', shape, parent, parentIndex);
11764 };
11765
11766 /**
11767 * Adds a connection to the canvas.
11768 *
11769 * @param {ConnectionLike} connection The connection to be added.
11770 * @param {ParentLike} [parent] The connection's parent.
11771 * @param {number} [parentIndex] The index at which to add the connection to the parent's children.
11772 *
11773 * @return {ConnectionLike} The added connection.
11774 */
11775 Canvas.prototype.addConnection = function(connection, parent, parentIndex) {
11776 return this._addElement('connection', connection, parent, parentIndex);
11777 };
11778
11779
11780 /**
11781 * Internal remove element
11782 */
11783 Canvas.prototype._removeElement = function(element, type) {
11784
11785 const elementRegistry = this._elementRegistry,
11786 graphicsFactory = this._graphicsFactory,
11787 eventBus = this._eventBus;
11788
11789 element = elementRegistry.get(element.id || element);
11790
11791 if (!element) {
11792
11793 // element was removed already
11794 return;
11795 }
11796
11797 eventBus.fire(type + '.remove', { element: element });
11798
11799 graphicsFactory.remove(element);
11800
11801 // unset parent <-> child relationship
11802 remove(element.parent && element.parent.children, element);
11803 element.parent = null;
11804
11805 eventBus.fire(type + '.removed', { element: element });
11806
11807 elementRegistry.remove(element);
11808
11809 return element;
11810 };
11811
11812
11813 /**
11814 * Removes a shape from the canvas.
11815 *
11816 * @fires ShapeRemoveEvent
11817 * @fires ShapeRemovedEvent
11818 *
11819 * @param {ShapeLike|string} shape The shape or its ID.
11820 *
11821 * @return {ShapeLike} The removed shape.
11822 */
11823 Canvas.prototype.removeShape = function(shape) {
11824
11825 /**
11826 * An event indicating that a shape is about to be removed from the canvas.
11827 *
11828 * @memberOf Canvas
11829 *
11830 * @event ShapeRemoveEvent
11831 * @type {Object}
11832 * @property {ShapeLike} element The shape.
11833 * @property {SVGElement} gfx The graphical element.
11834 */
11835
11836 /**
11837 * An event indicating that a shape has been removed from the canvas.
11838 *
11839 * @memberOf Canvas
11840 *
11841 * @event ShapeRemovedEvent
11842 * @type {Object}
11843 * @property {ShapeLike} element The shape.
11844 * @property {SVGElement} gfx The graphical element.
11845 */
11846 return this._removeElement(shape, 'shape');
11847 };
11848
11849
11850 /**
11851 * Removes a connection from the canvas.
11852 *
11853 * @fires ConnectionRemoveEvent
11854 * @fires ConnectionRemovedEvent
11855 *
11856 * @param {ConnectionLike|string} connection The connection or its ID.
11857 *
11858 * @return {ConnectionLike} The removed connection.
11859 */
11860 Canvas.prototype.removeConnection = function(connection) {
11861
11862 /**
11863 * An event indicating that a connection is about to be removed from the canvas.
11864 *
11865 * @memberOf Canvas
11866 *
11867 * @event ConnectionRemoveEvent
11868 * @type {Object}
11869 * @property {ConnectionLike} element The connection.
11870 * @property {SVGElement} gfx The graphical element.
11871 */
11872
11873 /**
11874 * An event indicating that a connection has been removed from the canvas.
11875 *
11876 * @memberOf Canvas
11877 *
11878 * @event ConnectionRemovedEvent
11879 * @type {Object}
11880 * @property {ConnectionLike} element The connection.
11881 * @property {SVGElement} gfx The graphical element.
11882 */
11883 return this._removeElement(connection, 'connection');
11884 };
11885
11886
11887 /**
11888 * Returns the graphical element of an element.
11889 *
11890 * @param {ShapeLike|ConnectionLike|string} element The element or its ID.
11891 * @param {boolean} [secondary=false] Whether to return the secondary graphical element.
11892 *
11893 * @return {SVGElement} The graphical element.
11894 */
11895 Canvas.prototype.getGraphics = function(element, secondary) {
11896 return this._elementRegistry.getGraphics(element, secondary);
11897 };
11898
11899
11900 /**
11901 * Perform a viewbox update via a given change function.
11902 *
11903 * @param {Function} changeFn
11904 */
11905 Canvas.prototype._changeViewbox = function(changeFn) {
11906
11907 // notify others of the upcoming viewbox change
11908 this._eventBus.fire('canvas.viewbox.changing');
11909
11910 // perform actual change
11911 changeFn.apply(this);
11912
11913 // reset the cached viewbox so that
11914 // a new get operation on viewbox or zoom
11915 // triggers a viewbox re-computation
11916 this._cachedViewbox = null;
11917
11918 // notify others of the change; this step
11919 // may or may not be debounced
11920 this._viewboxChanged();
11921 };
11922
11923 Canvas.prototype._viewboxChanged = function() {
11924 this._eventBus.fire('canvas.viewbox.changed', { viewbox: this.viewbox() });
11925 };
11926
11927
11928 /**
11929 * Gets or sets the view box of the canvas, i.e. the
11930 * area that is currently displayed.
11931 *
11932 * The getter may return a cached viewbox (if it is currently
11933 * changing). To force a recomputation, pass `false` as the first argument.
11934 *
11935 * @example
11936 *
11937 * ```javascript
11938 * canvas.viewbox({ x: 100, y: 100, width: 500, height: 500 })
11939 *
11940 * // sets the visible area of the diagram to (100|100) -> (600|100)
11941 * // and and scales it according to the diagram width
11942 *
11943 * const viewbox = canvas.viewbox(); // pass `false` to force recomputing the box.
11944 *
11945 * console.log(viewbox);
11946 * // {
11947 * // inner: Dimensions,
11948 * // outer: Dimensions,
11949 * // scale,
11950 * // x, y,
11951 * // width, height
11952 * // }
11953 *
11954 * // if the current diagram is zoomed and scrolled, you may reset it to the
11955 * // default zoom via this method, too:
11956 *
11957 * const zoomedAndScrolledViewbox = canvas.viewbox();
11958 *
11959 * canvas.viewbox({
11960 * x: 0,
11961 * y: 0,
11962 * width: zoomedAndScrolledViewbox.outer.width,
11963 * height: zoomedAndScrolledViewbox.outer.height
11964 * });
11965 * ```
11966 *
11967 * @param {Rect} [box] The viewbox to be set.
11968 *
11969 * @return {CanvasViewbox} The set viewbox.
11970 */
11971 Canvas.prototype.viewbox = function(box) {
11972
11973 if (box === undefined && this._cachedViewbox) {
11974 return this._cachedViewbox;
11975 }
11976
11977 const viewport = this._viewport,
11978 outerBox = this.getSize();
11979 let innerBox,
11980 matrix,
11981 activeLayer,
11982 transform,
11983 scale,
11984 x, y;
11985
11986 if (!box) {
11987
11988 // compute the inner box based on the
11989 // diagrams active layer. This allows us to exclude
11990 // external components, such as overlays
11991
11992 activeLayer = this._rootElement ? this.getActiveLayer() : null;
11993 innerBox = activeLayer && activeLayer.getBBox() || {};
11994
11995 transform = transform$1(viewport);
11996 matrix = transform ? transform.matrix : createMatrix();
11997 scale = round(matrix.a, 1000);
11998
11999 x = round(-matrix.e || 0, 1000);
12000 y = round(-matrix.f || 0, 1000);
12001
12002 box = this._cachedViewbox = {
12003 x: x ? x / scale : 0,
12004 y: y ? y / scale : 0,
12005 width: outerBox.width / scale,
12006 height: outerBox.height / scale,
12007 scale: scale,
12008 inner: {
12009 width: innerBox.width || 0,
12010 height: innerBox.height || 0,
12011 x: innerBox.x || 0,
12012 y: innerBox.y || 0
12013 },
12014 outer: outerBox
12015 };
12016
12017 return box;
12018 } else {
12019
12020 this._changeViewbox(function() {
12021 scale = Math.min(outerBox.width / box.width, outerBox.height / box.height);
12022
12023 const matrix = this._svg.createSVGMatrix()
12024 .scale(scale)
12025 .translate(-box.x, -box.y);
12026
12027 transform$1(viewport, matrix);
12028 });
12029 }
12030
12031 return box;
12032 };
12033
12034
12035 /**
12036 * Gets or sets the scroll of the canvas.
12037 *
12038 * @param {ScrollDelta} [delta] The scroll to be set.
12039 *
12040 * @return {Point}
12041 */
12042 Canvas.prototype.scroll = function(delta) {
12043
12044 const node = this._viewport;
12045 let matrix = node.getCTM();
12046
12047 if (delta) {
12048 this._changeViewbox(function() {
12049 delta = assign$1({ dx: 0, dy: 0 }, delta || {});
12050
12051 matrix = this._svg.createSVGMatrix().translate(delta.dx, delta.dy).multiply(matrix);
12052
12053 setCTM(node, matrix);
12054 });
12055 }
12056
12057 return { x: matrix.e, y: matrix.f };
12058 };
12059
12060 /**
12061 * Scrolls the viewbox to contain the given element.
12062 * Optionally specify a padding to be applied to the edges.
12063 *
12064 * @param {ShapeLike|ConnectionLike|string} element The element to scroll to or its ID.
12065 * @param {RectTRBL|number} [padding=100] The padding to be applied. Can also specify top, bottom, left and right.
12066 */
12067 Canvas.prototype.scrollToElement = function(element, padding) {
12068 let defaultPadding = 100;
12069
12070 if (typeof element === 'string') {
12071 element = this._elementRegistry.get(element);
12072 }
12073
12074 // set to correct rootElement
12075 const rootElement = this.findRoot(element);
12076
12077 if (rootElement !== this.getRootElement()) {
12078 this.setRootElement(rootElement);
12079 }
12080
12081 // element is rootElement, do not change viewport
12082 if (rootElement === element) {
12083 return;
12084 }
12085
12086 if (!padding) {
12087 padding = {};
12088 }
12089 if (typeof padding === 'number') {
12090 defaultPadding = padding;
12091 }
12092
12093 padding = {
12094 top: padding.top || defaultPadding,
12095 right: padding.right || defaultPadding,
12096 bottom: padding.bottom || defaultPadding,
12097 left: padding.left || defaultPadding
12098 };
12099
12100 const elementBounds = getBBox(element),
12101 elementTrbl = asTRBL(elementBounds),
12102 viewboxBounds = this.viewbox(),
12103 zoom = this.zoom();
12104 let dx, dy;
12105
12106 // shrink viewboxBounds with padding
12107 viewboxBounds.y += padding.top / zoom;
12108 viewboxBounds.x += padding.left / zoom;
12109 viewboxBounds.width -= (padding.right + padding.left) / zoom;
12110 viewboxBounds.height -= (padding.bottom + padding.top) / zoom;
12111
12112 const viewboxTrbl = asTRBL(viewboxBounds);
12113
12114 const canFit = elementBounds.width < viewboxBounds.width && elementBounds.height < viewboxBounds.height;
12115
12116 if (!canFit) {
12117
12118 // top-left when element can't fit
12119 dx = elementBounds.x - viewboxBounds.x;
12120 dy = elementBounds.y - viewboxBounds.y;
12121
12122 } else {
12123
12124 const dRight = Math.max(0, elementTrbl.right - viewboxTrbl.right),
12125 dLeft = Math.min(0, elementTrbl.left - viewboxTrbl.left),
12126 dBottom = Math.max(0, elementTrbl.bottom - viewboxTrbl.bottom),
12127 dTop = Math.min(0, elementTrbl.top - viewboxTrbl.top);
12128
12129 dx = dRight || dLeft;
12130 dy = dBottom || dTop;
12131
12132 }
12133
12134 this.scroll({ dx: -dx * zoom, dy: -dy * zoom });
12135 };
12136
12137 /**
12138 * Gets or sets the current zoom of the canvas, optionally zooming to the
12139 * specified position.
12140 *
12141 * The getter may return a cached zoom level. Call it with `false` as the first
12142 * argument to force recomputation of the current level.
12143 *
12144 * @param {number|'fit-viewport'} [newScale] The new zoom level, either a number,
12145 * i.e. 0.9, or `fit-viewport` to adjust the size to fit the current viewport.
12146 * @param {Point} [center] The reference point { x: ..., y: ...} to zoom to.
12147 *
12148 * @return {number} The set zoom level.
12149 */
12150 Canvas.prototype.zoom = function(newScale, center) {
12151
12152 if (!newScale) {
12153 return this.viewbox(newScale).scale;
12154 }
12155
12156 if (newScale === 'fit-viewport') {
12157 return this._fitViewport(center);
12158 }
12159
12160 let outer,
12161 matrix;
12162
12163 this._changeViewbox(function() {
12164
12165 if (typeof center !== 'object') {
12166 outer = this.viewbox().outer;
12167
12168 center = {
12169 x: outer.width / 2,
12170 y: outer.height / 2
12171 };
12172 }
12173
12174 matrix = this._setZoom(newScale, center);
12175 });
12176
12177 return round(matrix.a, 1000);
12178 };
12179
12180 function setCTM(node, m) {
12181 const mstr = 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.e + ',' + m.f + ')';
12182 node.setAttribute('transform', mstr);
12183 }
12184
12185 Canvas.prototype._fitViewport = function(center) {
12186
12187 const vbox = this.viewbox(),
12188 outer = vbox.outer,
12189 inner = vbox.inner;
12190 let newScale,
12191 newViewbox;
12192
12193 // display the complete diagram without zooming in.
12194 // instead of relying on internal zoom, we perform a
12195 // hard reset on the canvas viewbox to realize this
12196 //
12197 // if diagram does not need to be zoomed in, we focus it around
12198 // the diagram origin instead
12199
12200 if (inner.x >= 0 &&
12201 inner.y >= 0 &&
12202 inner.x + inner.width <= outer.width &&
12203 inner.y + inner.height <= outer.height &&
12204 !center) {
12205
12206 newViewbox = {
12207 x: 0,
12208 y: 0,
12209 width: Math.max(inner.width + inner.x, outer.width),
12210 height: Math.max(inner.height + inner.y, outer.height)
12211 };
12212 } else {
12213
12214 newScale = Math.min(1, outer.width / inner.width, outer.height / inner.height);
12215 newViewbox = {
12216 x: inner.x + (center ? inner.width / 2 - outer.width / newScale / 2 : 0),
12217 y: inner.y + (center ? inner.height / 2 - outer.height / newScale / 2 : 0),
12218 width: outer.width / newScale,
12219 height: outer.height / newScale
12220 };
12221 }
12222
12223 this.viewbox(newViewbox);
12224
12225 return this.viewbox(false).scale;
12226 };
12227
12228
12229 Canvas.prototype._setZoom = function(scale, center) {
12230
12231 const svg = this._svg,
12232 viewport = this._viewport;
12233
12234 const matrix = svg.createSVGMatrix();
12235 const point = svg.createSVGPoint();
12236
12237 let centerPoint,
12238 originalPoint,
12239 currentMatrix,
12240 scaleMatrix,
12241 newMatrix;
12242
12243 currentMatrix = viewport.getCTM();
12244
12245 const currentScale = currentMatrix.a;
12246
12247 if (center) {
12248 centerPoint = assign$1(point, center);
12249
12250 // revert applied viewport transformations
12251 originalPoint = centerPoint.matrixTransform(currentMatrix.inverse());
12252
12253 // create scale matrix
12254 scaleMatrix = matrix
12255 .translate(originalPoint.x, originalPoint.y)
12256 .scale(1 / currentScale * scale)
12257 .translate(-originalPoint.x, -originalPoint.y);
12258
12259 newMatrix = currentMatrix.multiply(scaleMatrix);
12260 } else {
12261 newMatrix = matrix.scale(scale);
12262 }
12263
12264 setCTM(this._viewport, newMatrix);
12265
12266 return newMatrix;
12267 };
12268
12269
12270 /**
12271 * Returns the size of the canvas.
12272 *
12273 * @return {Dimensions} The size of the canvas.
12274 */
12275 Canvas.prototype.getSize = function() {
12276 return {
12277 width: this._container.clientWidth,
12278 height: this._container.clientHeight
12279 };
12280 };
12281
12282
12283 /**
12284 * Returns the absolute bounding box of an element.
12285 *
12286 * The absolute bounding box may be used to display overlays in the callers
12287 * (browser) coordinate system rather than the zoomed in/out canvas coordinates.
12288 *
12289 * @param {ShapeLike|ConnectionLike} element The element.
12290 *
12291 * @return {Rect} The element's absolute bounding box.
12292 */
12293 Canvas.prototype.getAbsoluteBBox = function(element) {
12294 const vbox = this.viewbox();
12295 let bbox;
12296
12297 // connection
12298 // use svg bbox
12299 if (element.waypoints) {
12300 const gfx = this.getGraphics(element);
12301
12302 bbox = gfx.getBBox();
12303 }
12304
12305 // shapes
12306 // use data
12307 else {
12308 bbox = element;
12309 }
12310
12311 const x = bbox.x * vbox.scale - vbox.x * vbox.scale;
12312 const y = bbox.y * vbox.scale - vbox.y * vbox.scale;
12313
12314 const width = bbox.width * vbox.scale;
12315 const height = bbox.height * vbox.scale;
12316
12317 return {
12318 x: x,
12319 y: y,
12320 width: width,
12321 height: height
12322 };
12323 };
12324
12325 /**
12326 * Fires an event so other modules can react to the canvas resizing.
12327 */
12328 Canvas.prototype.resized = function() {
12329
12330 // force recomputation of view box
12331 delete this._cachedViewbox;
12332
12333 this._eventBus.fire('canvas.resized');
12334 };
12335
12336 var ELEMENT_ID = 'data-element-id';
12337
12338 /**
12339 * @typedef {import('./Types').ElementLike} ElementLike
12340 *
12341 * @typedef {import('./EventBus').default} EventBus
12342 *
12343 * @typedef { (element: ElementLike, gfx: SVGElement) => boolean|any } ElementRegistryFilterCallback
12344 * @typedef { (element: ElementLike, gfx: SVGElement) => any } ElementRegistryForEachCallback
12345 */
12346
12347 /**
12348 * A registry that keeps track of all shapes in the diagram.
12349 *
12350 * @class
12351 * @constructor
12352 *
12353 * @param {EventBus} eventBus
12354 */
12355 function ElementRegistry(eventBus) {
12356
12357 /**
12358 * @type { {
12359 * [id: string]: {
12360 * element: ElementLike;
12361 * gfx?: SVGElement;
12362 * secondaryGfx?: SVGElement;
12363 * }
12364 * } }
12365 */
12366 this._elements = {};
12367
12368 this._eventBus = eventBus;
12369 }
12370
12371 ElementRegistry.$inject = [ 'eventBus' ];
12372
12373 /**
12374 * Add an element and its graphical representation(s) to the registry.
12375 *
12376 * @param {ElementLike} element The element to be added.
12377 * @param {SVGElement} gfx The primary graphical representation.
12378 * @param {SVGElement} [secondaryGfx] The secondary graphical representation.
12379 */
12380 ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) {
12381
12382 var id = element.id;
12383
12384 this._validateId(id);
12385
12386 // associate dom node with element
12387 attr$1(gfx, ELEMENT_ID, id);
12388
12389 if (secondaryGfx) {
12390 attr$1(secondaryGfx, ELEMENT_ID, id);
12391 }
12392
12393 this._elements[id] = { element: element, gfx: gfx, secondaryGfx: secondaryGfx };
12394 };
12395
12396 /**
12397 * Remove an element from the registry.
12398 *
12399 * @param {ElementLike|string} element
12400 */
12401 ElementRegistry.prototype.remove = function(element) {
12402 var elements = this._elements,
12403 id = element.id || element,
12404 container = id && elements[id];
12405
12406 if (container) {
12407
12408 // unset element id on gfx
12409 attr$1(container.gfx, ELEMENT_ID, '');
12410
12411 if (container.secondaryGfx) {
12412 attr$1(container.secondaryGfx, ELEMENT_ID, '');
12413 }
12414
12415 delete elements[id];
12416 }
12417 };
12418
12419 /**
12420 * Update an elements ID.
12421 *
12422 * @param {ElementLike|string} element The element or its ID.
12423 * @param {string} newId The new ID.
12424 */
12425 ElementRegistry.prototype.updateId = function(element, newId) {
12426
12427 this._validateId(newId);
12428
12429 if (typeof element === 'string') {
12430 element = this.get(element);
12431 }
12432
12433 this._eventBus.fire('element.updateId', {
12434 element: element,
12435 newId: newId
12436 });
12437
12438 var gfx = this.getGraphics(element),
12439 secondaryGfx = this.getGraphics(element, true);
12440
12441 this.remove(element);
12442
12443 element.id = newId;
12444
12445 this.add(element, gfx, secondaryGfx);
12446 };
12447
12448 /**
12449 * Update the graphical representation of an element.
12450 *
12451 * @param {ElementLike|string} filter The element or its ID.
12452 * @param {SVGElement} gfx The new graphical representation.
12453 * @param {boolean} [secondary=false] Whether to update the secondary graphical representation.
12454 */
12455 ElementRegistry.prototype.updateGraphics = function(filter, gfx, secondary) {
12456 var id = filter.id || filter;
12457
12458 var container = this._elements[id];
12459
12460 if (secondary) {
12461 container.secondaryGfx = gfx;
12462 } else {
12463 container.gfx = gfx;
12464 }
12465
12466 if (gfx) {
12467 attr$1(gfx, ELEMENT_ID, id);
12468 }
12469
12470 return gfx;
12471 };
12472
12473 /**
12474 * Get the element with the given ID or graphical representation.
12475 *
12476 * @example
12477 *
12478 * ```javascript
12479 * elementRegistry.get('SomeElementId_1');
12480 *
12481 * elementRegistry.get(gfx);
12482 * ```
12483 *
12484 * @param {string|SVGElement} filter The elements ID or graphical representation.
12485 *
12486 * @return {ElementLike|undefined} The element.
12487 */
12488 ElementRegistry.prototype.get = function(filter) {
12489 var id;
12490
12491 if (typeof filter === 'string') {
12492 id = filter;
12493 } else {
12494 id = filter && attr$1(filter, ELEMENT_ID);
12495 }
12496
12497 var container = this._elements[id];
12498 return container && container.element;
12499 };
12500
12501 /**
12502 * Return all elements that match a given filter function.
12503 *
12504 * @param {ElementRegistryFilterCallback} fn The filter function.
12505 *
12506 * @return {ElementLike[]} The matching elements.
12507 */
12508 ElementRegistry.prototype.filter = function(fn) {
12509
12510 var filtered = [];
12511
12512 this.forEach(function(element, gfx) {
12513 if (fn(element, gfx)) {
12514 filtered.push(element);
12515 }
12516 });
12517
12518 return filtered;
12519 };
12520
12521 /**
12522 * Return the first element that matches the given filter function.
12523 *
12524 * @param {ElementRegistryFilterCallback} fn The filter function.
12525 *
12526 * @return {ElementLike|undefined} The matching element.
12527 */
12528 ElementRegistry.prototype.find = function(fn) {
12529 var map = this._elements,
12530 keys = Object.keys(map);
12531
12532 for (var i = 0; i < keys.length; i++) {
12533 var id = keys[i],
12534 container = map[id],
12535 element = container.element,
12536 gfx = container.gfx;
12537
12538 if (fn(element, gfx)) {
12539 return element;
12540 }
12541 }
12542 };
12543
12544 /**
12545 * Get all elements.
12546 *
12547 * @return {ElementLike[]} All elements.
12548 */
12549 ElementRegistry.prototype.getAll = function() {
12550 return this.filter(function(e) { return e; });
12551 };
12552
12553 /**
12554 * Execute a given function for each element.
12555 *
12556 * @param {ElementRegistryForEachCallback} fn The function to execute.
12557 */
12558 ElementRegistry.prototype.forEach = function(fn) {
12559
12560 var map = this._elements;
12561
12562 Object.keys(map).forEach(function(id) {
12563 var container = map[id],
12564 element = container.element,
12565 gfx = container.gfx;
12566
12567 return fn(element, gfx);
12568 });
12569 };
12570
12571 /**
12572 * Return the graphical representation of an element.
12573 *
12574 * @example
12575 *
12576 * ```javascript
12577 * elementRegistry.getGraphics('SomeElementId_1');
12578 *
12579 * elementRegistry.getGraphics(rootElement); // <g ...>
12580 *
12581 * elementRegistry.getGraphics(rootElement, true); // <svg ...>
12582 * ```
12583 *
12584 * @param {ElementLike|string} filter The element or its ID.
12585 * @param {boolean} [secondary=false] Whether to return the secondary graphical representation.
12586 *
12587 * @return {SVGElement} The graphical representation.
12588 */
12589 ElementRegistry.prototype.getGraphics = function(filter, secondary) {
12590 var id = filter.id || filter;
12591
12592 var container = this._elements[id];
12593 return container && (secondary ? container.secondaryGfx : container.gfx);
12594 };
12595
12596 /**
12597 * Validate an ID and throw an error if invalid.
12598 *
12599 * @param {string} id
12600 *
12601 * @throws {Error} Error indicating that the ID is invalid or already assigned.
12602 */
12603 ElementRegistry.prototype._validateId = function(id) {
12604 if (!id) {
12605 throw new Error('element must have an id');
12606 }
12607
12608 if (this._elements[id]) {
12609 throw new Error('element with id ' + id + ' already added');
12610 }
12611 };
12612
12613 /**
12614 * Extends a collection with {@link Refs} aware methods
12615 *
12616 * @param {Array<Object>} collection
12617 * @param {Refs} refs instance
12618 * @param {Object} property represented by the collection
12619 * @param {Object} target object the collection is attached to
12620 *
12621 * @return {RefsCollection<Object>} the extended array
12622 */
12623 function extend(collection, refs, property, target) {
12624 var inverseProperty = property.inverse;
12625
12626 /**
12627 * Removes the given element from the array and returns it.
12628 *
12629 * @method RefsCollection#remove
12630 *
12631 * @param {Object} element the element to remove
12632 */
12633 Object.defineProperty(collection, 'remove', {
12634 value: function (element) {
12635 var idx = this.indexOf(element);
12636 if (idx !== -1) {
12637 this.splice(idx, 1);
12638
12639 // unset inverse
12640 refs.unset(element, inverseProperty, target);
12641 }
12642 return element;
12643 }
12644 });
12645
12646 /**
12647 * Returns true if the collection contains the given element
12648 *
12649 * @method RefsCollection#contains
12650 *
12651 * @param {Object} element the element to check for
12652 */
12653 Object.defineProperty(collection, 'contains', {
12654 value: function (element) {
12655 return this.indexOf(element) !== -1;
12656 }
12657 });
12658
12659 /**
12660 * Adds an element to the array, unless it exists already (set semantics).
12661 *
12662 * @method RefsCollection#add
12663 *
12664 * @param {Object} element the element to add
12665 * @param {Number} optional index to add element to
12666 * (possibly moving other elements around)
12667 */
12668 Object.defineProperty(collection, 'add', {
12669 value: function (element, idx) {
12670 var currentIdx = this.indexOf(element);
12671 if (typeof idx === 'undefined') {
12672 if (currentIdx !== -1) {
12673 // element already in collection (!)
12674 return;
12675 }
12676
12677 // add to end of array, as no idx is specified
12678 idx = this.length;
12679 }
12680
12681 // handle already in collection
12682 if (currentIdx !== -1) {
12683 // remove element from currentIdx
12684 this.splice(currentIdx, 1);
12685 }
12686
12687 // add element at idx
12688 this.splice(idx, 0, element);
12689 if (currentIdx === -1) {
12690 // set inverse, unless element was
12691 // in collection already
12692 refs.set(element, inverseProperty, target);
12693 }
12694 }
12695 });
12696
12697 // a simple marker, identifying this element
12698 // as being a refs collection
12699 Object.defineProperty(collection, '__refs_collection', {
12700 value: true
12701 });
12702 return collection;
12703 }
12704
12705 /**
12706 * Checks if a given collection is extended
12707 *
12708 * @param {Array<Object>} collection
12709 *
12710 * @return {boolean}
12711 */
12712 function isExtended(collection) {
12713 return collection.__refs_collection === true;
12714 }
12715
12716 function hasOwnProperty$1(e, property) {
12717 return Object.prototype.hasOwnProperty.call(e, property.name || property);
12718 }
12719 function defineCollectionProperty(ref, property, target) {
12720 var collection = extend(target[property.name] || [], ref, property, target);
12721 Object.defineProperty(target, property.name, {
12722 enumerable: property.enumerable,
12723 value: collection
12724 });
12725 if (collection.length) {
12726 collection.forEach(function (o) {
12727 ref.set(o, property.inverse, target);
12728 });
12729 }
12730 }
12731 function defineProperty$1(ref, property, target) {
12732 var inverseProperty = property.inverse;
12733 var _value = target[property.name];
12734 Object.defineProperty(target, property.name, {
12735 configurable: property.configurable,
12736 enumerable: property.enumerable,
12737 get: function () {
12738 return _value;
12739 },
12740 set: function (value) {
12741 // return if we already performed all changes
12742 if (value === _value) {
12743 return;
12744 }
12745 var old = _value;
12746
12747 // temporary set null
12748 _value = null;
12749 if (old) {
12750 ref.unset(old, inverseProperty, target);
12751 }
12752
12753 // set new value
12754 _value = value;
12755
12756 // set inverse value
12757 ref.set(_value, inverseProperty, target);
12758 }
12759 });
12760 }
12761
12762 /**
12763 * Creates a new references object defining two inversly related
12764 * attribute descriptors a and b.
12765 *
12766 * <p>
12767 * When bound to an object using {@link Refs#bind} the references
12768 * get activated and ensure that add and remove operations are applied
12769 * reversely, too.
12770 * </p>
12771 *
12772 * <p>
12773 * For attributes represented as collections {@link Refs} provides the
12774 * {@link RefsCollection#add}, {@link RefsCollection#remove} and {@link RefsCollection#contains} extensions
12775 * that must be used to properly hook into the inverse change mechanism.
12776 * </p>
12777 *
12778 * @class Refs
12779 *
12780 * @classdesc A bi-directional reference between two attributes.
12781 *
12782 * @param {Refs.AttributeDescriptor} a property descriptor
12783 * @param {Refs.AttributeDescriptor} b property descriptor
12784 *
12785 * @example
12786 *
12787 * var refs = Refs({ name: 'wheels', collection: true, enumerable: true }, { name: 'car' });
12788 *
12789 * var car = { name: 'toyota' };
12790 * var wheels = [{ pos: 'front-left' }, { pos: 'front-right' }];
12791 *
12792 * refs.bind(car, 'wheels');
12793 *
12794 * car.wheels // []
12795 * car.wheels.add(wheels[0]);
12796 * car.wheels.add(wheels[1]);
12797 *
12798 * car.wheels // [{ pos: 'front-left' }, { pos: 'front-right' }]
12799 *
12800 * wheels[0].car // { name: 'toyota' };
12801 * car.wheels.remove(wheels[0]);
12802 *
12803 * wheels[0].car // undefined
12804 */
12805 function Refs(a, b) {
12806 if (!(this instanceof Refs)) {
12807 return new Refs(a, b);
12808 }
12809
12810 // link
12811 a.inverse = b;
12812 b.inverse = a;
12813 this.props = {};
12814 this.props[a.name] = a;
12815 this.props[b.name] = b;
12816 }
12817
12818 /**
12819 * Binds one side of a bi-directional reference to a
12820 * target object.
12821 *
12822 * @memberOf Refs
12823 *
12824 * @param {Object} target
12825 * @param {String} property
12826 */
12827 Refs.prototype.bind = function (target, property) {
12828 if (typeof property === 'string') {
12829 if (!this.props[property]) {
12830 throw new Error('no property <' + property + '> in ref');
12831 }
12832 property = this.props[property];
12833 }
12834 if (property.collection) {
12835 defineCollectionProperty(this, property, target);
12836 } else {
12837 defineProperty$1(this, property, target);
12838 }
12839 };
12840 Refs.prototype.ensureRefsCollection = function (target, property) {
12841 var collection = target[property.name];
12842 if (!isExtended(collection)) {
12843 defineCollectionProperty(this, property, target);
12844 }
12845 return collection;
12846 };
12847 Refs.prototype.ensureBound = function (target, property) {
12848 if (!hasOwnProperty$1(target, property)) {
12849 this.bind(target, property);
12850 }
12851 };
12852 Refs.prototype.unset = function (target, property, value) {
12853 if (target) {
12854 this.ensureBound(target, property);
12855 if (property.collection) {
12856 this.ensureRefsCollection(target, property).remove(value);
12857 } else {
12858 target[property.name] = undefined;
12859 }
12860 }
12861 };
12862 Refs.prototype.set = function (target, property, value) {
12863 if (target) {
12864 this.ensureBound(target, property);
12865 if (property.collection) {
12866 this.ensureRefsCollection(target, property).add(value);
12867 } else {
12868 target[property.name] = value;
12869 }
12870 }
12871 };
12872
12873 var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
12874 labelRefs = new Refs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
12875 attacherRefs = new Refs({ name: 'attachers', collection: true }, { name: 'host' }),
12876 outgoingRefs = new Refs({ name: 'outgoing', collection: true }, { name: 'source' }),
12877 incomingRefs = new Refs({ name: 'incoming', collection: true }, { name: 'target' });
12878
12879 /**
12880 * @typedef {import('./Types').Element} Element
12881 * @typedef {import('./Types').Shape} Shape
12882 * @typedef {import('./Types').Root} Root
12883 * @typedef {import('./Types').Label} Label
12884 * @typedef {import('./Types').Connection} Connection
12885 */
12886
12887 /**
12888 * The basic graphical representation
12889 *
12890 * @class
12891 * @constructor
12892 */
12893 function ElementImpl() {
12894
12895 /**
12896 * The object that backs up the shape
12897 *
12898 * @name Element#businessObject
12899 * @type Object
12900 */
12901 Object.defineProperty(this, 'businessObject', {
12902 writable: true
12903 });
12904
12905
12906 /**
12907 * Single label support, will mapped to multi label array
12908 *
12909 * @name Element#label
12910 * @type Object
12911 */
12912 Object.defineProperty(this, 'label', {
12913 get: function() {
12914 return this.labels[0];
12915 },
12916 set: function(newLabel) {
12917
12918 var label = this.label,
12919 labels = this.labels;
12920
12921 if (!newLabel && label) {
12922 labels.remove(label);
12923 } else {
12924 labels.add(newLabel, 0);
12925 }
12926 }
12927 });
12928
12929 /**
12930 * The parent shape
12931 *
12932 * @name Element#parent
12933 * @type Shape
12934 */
12935 parentRefs.bind(this, 'parent');
12936
12937 /**
12938 * The list of labels
12939 *
12940 * @name Element#labels
12941 * @type Label
12942 */
12943 labelRefs.bind(this, 'labels');
12944
12945 /**
12946 * The list of outgoing connections
12947 *
12948 * @name Element#outgoing
12949 * @type Array<Connection>
12950 */
12951 outgoingRefs.bind(this, 'outgoing');
12952
12953 /**
12954 * The list of incoming connections
12955 *
12956 * @name Element#incoming
12957 * @type Array<Connection>
12958 */
12959 incomingRefs.bind(this, 'incoming');
12960 }
12961
12962
12963 /**
12964 * A graphical object
12965 *
12966 * @class
12967 * @constructor
12968 *
12969 * @extends ElementImpl
12970 */
12971 function ShapeImpl() {
12972 ElementImpl.call(this);
12973
12974 /**
12975 * Indicates frame shapes
12976 *
12977 * @name ShapeImpl#isFrame
12978 * @type boolean
12979 */
12980
12981 /**
12982 * The list of children
12983 *
12984 * @name ShapeImpl#children
12985 * @type Element[]
12986 */
12987 parentRefs.bind(this, 'children');
12988
12989 /**
12990 * @name ShapeImpl#host
12991 * @type Shape
12992 */
12993 attacherRefs.bind(this, 'host');
12994
12995 /**
12996 * @name ShapeImpl#attachers
12997 * @type Shape
12998 */
12999 attacherRefs.bind(this, 'attachers');
13000 }
13001
13002 e(ShapeImpl, ElementImpl);
13003
13004
13005 /**
13006 * A root graphical object
13007 *
13008 * @class
13009 * @constructor
13010 *
13011 * @extends ElementImpl
13012 */
13013 function RootImpl() {
13014 ElementImpl.call(this);
13015
13016 /**
13017 * The list of children
13018 *
13019 * @name RootImpl#children
13020 * @type Element[]
13021 */
13022 parentRefs.bind(this, 'children');
13023 }
13024
13025 e(RootImpl, ShapeImpl);
13026
13027
13028 /**
13029 * A label for an element
13030 *
13031 * @class
13032 * @constructor
13033 *
13034 * @extends ShapeImpl
13035 */
13036 function LabelImpl() {
13037 ShapeImpl.call(this);
13038
13039 /**
13040 * The labeled element
13041 *
13042 * @name LabelImpl#labelTarget
13043 * @type Element
13044 */
13045 labelRefs.bind(this, 'labelTarget');
13046 }
13047
13048 e(LabelImpl, ShapeImpl);
13049
13050
13051 /**
13052 * A connection between two elements
13053 *
13054 * @class
13055 * @constructor
13056 *
13057 * @extends ElementImpl
13058 */
13059 function ConnectionImpl() {
13060 ElementImpl.call(this);
13061
13062 /**
13063 * The element this connection originates from
13064 *
13065 * @name ConnectionImpl#source
13066 * @type Element
13067 */
13068 outgoingRefs.bind(this, 'source');
13069
13070 /**
13071 * The element this connection points to
13072 *
13073 * @name ConnectionImpl#target
13074 * @type Element
13075 */
13076 incomingRefs.bind(this, 'target');
13077 }
13078
13079 e(ConnectionImpl, ElementImpl);
13080
13081
13082 var types$6 = {
13083 connection: ConnectionImpl,
13084 shape: ShapeImpl,
13085 label: LabelImpl,
13086 root: RootImpl
13087 };
13088
13089 /**
13090 * Creates a root element.
13091 *
13092 * @overlord
13093 *
13094 * @example
13095 *
13096 * ```javascript
13097 * import * as Model from 'diagram-js/lib/model';
13098 *
13099 * const root = Model.create('root', {
13100 * x: 100,
13101 * y: 100,
13102 * width: 100,
13103 * height: 100
13104 * });
13105 * ```
13106 *
13107 * @param {'root'} type
13108 * @param {any} [attrs]
13109 *
13110 * @return {Root}
13111 */
13112
13113 /**
13114 * Creates a connection.
13115 *
13116 * @overlord
13117 *
13118 * @example
13119 *
13120 * ```javascript
13121 * import * as Model from 'diagram-js/lib/model';
13122 *
13123 * const connection = Model.create('connection', {
13124 * waypoints: [
13125 * { x: 100, y: 100 },
13126 * { x: 200, y: 100 }
13127 * ]
13128 * });
13129 * ```
13130 *
13131 * @param {'connection'} type
13132 * @param {any} [attrs]
13133 *
13134 * @return {Connection}
13135 */
13136
13137 /**
13138 * Creates a shape.
13139 *
13140 * @overlord
13141 *
13142 * @example
13143 *
13144 * ```javascript
13145 * import * as Model from 'diagram-js/lib/model';
13146 *
13147 * const shape = Model.create('shape', {
13148 * x: 100,
13149 * y: 100,
13150 * width: 100,
13151 * height: 100
13152 * });
13153 * ```
13154 *
13155 * @param {'shape'} type
13156 * @param {any} [attrs]
13157 *
13158 * @return {Shape}
13159 */
13160
13161 /**
13162 * Creates a label.
13163 *
13164 * @example
13165 *
13166 * ```javascript
13167 * import * as Model from 'diagram-js/lib/model';
13168 *
13169 * const label = Model.create('label', {
13170 * x: 100,
13171 * y: 100,
13172 * width: 100,
13173 * height: 100,
13174 * labelTarget: shape
13175 * });
13176 * ```
13177 *
13178 * @param {'label'} type
13179 * @param {Object} [attrs]
13180 *
13181 * @return {Label}
13182 */
13183 function create(type, attrs) {
13184 var Type = types$6[type];
13185 if (!Type) {
13186 throw new Error('unknown type: <' + type + '>');
13187 }
13188 return assign$1(new Type(), attrs);
13189 }
13190
13191 /**
13192 * @typedef {import('../model/Types').Element} Element
13193 * @typedef {import('../model/Types').Connection} Connection
13194 * @typedef {import('../model/Types').Label} Label
13195 * @typedef {import('../model/Types').Root} Root
13196 * @typedef {import('../model/Types').Shape} Shape
13197 */
13198
13199 /**
13200 * A factory for model elements.
13201 *
13202 * @template {Connection} [T=Connection]
13203 * @template {Label} [U=Label]
13204 * @template {Root} [V=Root]
13205 * @template {Shape} [W=Shape]
13206 */
13207 function ElementFactory() {
13208 this._uid = 12;
13209 }
13210
13211 /**
13212 * Create a root element.
13213 *
13214 * @param {Partial<Root>} [attrs]
13215 *
13216 * @return {V} The created root element.
13217 */
13218 ElementFactory.prototype.createRoot = function(attrs) {
13219 return this.create('root', attrs);
13220 };
13221
13222 /**
13223 * Create a label.
13224 *
13225 * @param {Partial<Label>} [attrs]
13226 *
13227 * @return {U} The created label.
13228 */
13229 ElementFactory.prototype.createLabel = function(attrs) {
13230 return this.create('label', attrs);
13231 };
13232
13233 /**
13234 * Create a shape.
13235 *
13236 * @param {Partial<Shape>} [attrs]
13237 *
13238 * @return {W} The created shape.
13239 */
13240 ElementFactory.prototype.createShape = function(attrs) {
13241 return this.create('shape', attrs);
13242 };
13243
13244 /**
13245 * Create a connection.
13246 *
13247 * @param {Partial<Connection>} [attrs]
13248 *
13249 * @return {T} The created connection.
13250 */
13251 ElementFactory.prototype.createConnection = function(attrs) {
13252 return this.create('connection', attrs);
13253 };
13254
13255 /**
13256 * Create a root element.
13257 *
13258 * @overlord
13259 * @param {'root'} type
13260 * @param {Partial<Root>} [attrs]
13261 * @return {V}
13262 */
13263 /**
13264 * Create a shape.
13265 *
13266 * @overlord
13267 * @param {'shape'} type
13268 * @param {Partial<Shape>} [attrs]
13269 * @return {W}
13270 */
13271 /**
13272 * Create a connection.
13273 *
13274 * @overlord
13275 * @param {'connection'} type
13276 * @param {Partial<Connection>} [attrs]
13277 * @return {T}
13278 */
13279 /**
13280 * Create a label.
13281 *
13282 * @param {'label'} type
13283 * @param {Partial<Label>} [attrs]
13284 * @return {U}
13285 */
13286 ElementFactory.prototype.create = function(type, attrs) {
13287
13288 attrs = assign$1({}, attrs || {});
13289
13290 if (!attrs.id) {
13291 attrs.id = type + '_' + (this._uid++);
13292 }
13293
13294 return create(type, attrs);
13295 };
13296
13297 var FN_REF = '__fn';
13298
13299 var DEFAULT_PRIORITY$1 = 1000;
13300
13301 var slice = Array.prototype.slice;
13302
13303 /**
13304 * @typedef { {
13305 * stopPropagation(): void;
13306 * preventDefault(): void;
13307 * cancelBubble: boolean;
13308 * defaultPrevented: boolean;
13309 * returnValue: any;
13310 * } } Event
13311 */
13312
13313 /**
13314 * @template E
13315 *
13316 * @typedef { (event: E & Event, ...any) => any } EventBusEventCallback
13317 */
13318
13319 /**
13320 * @typedef { {
13321 * priority: number;
13322 * next: EventBusListener | null;
13323 * callback: EventBusEventCallback<any>;
13324 * } } EventBusListener
13325 */
13326
13327 /**
13328 * A general purpose event bus.
13329 *
13330 * This component is used to communicate across a diagram instance.
13331 * Other parts of a diagram can use it to listen to and broadcast events.
13332 *
13333 *
13334 * ## Registering for Events
13335 *
13336 * The event bus provides the {@link EventBus#on} and {@link EventBus#once}
13337 * methods to register for events. {@link EventBus#off} can be used to
13338 * remove event registrations. Listeners receive an instance of {@link Event}
13339 * as the first argument. It allows them to hook into the event execution.
13340 *
13341 * ```javascript
13342 *
13343 * // listen for event
13344 * eventBus.on('foo', function(event) {
13345 *
13346 * // access event type
13347 * event.type; // 'foo'
13348 *
13349 * // stop propagation to other listeners
13350 * event.stopPropagation();
13351 *
13352 * // prevent event default
13353 * event.preventDefault();
13354 * });
13355 *
13356 * // listen for event with custom payload
13357 * eventBus.on('bar', function(event, payload) {
13358 * console.log(payload);
13359 * });
13360 *
13361 * // listen for event returning value
13362 * eventBus.on('foobar', function(event) {
13363 *
13364 * // stop event propagation + prevent default
13365 * return false;
13366 *
13367 * // stop event propagation + return custom result
13368 * return {
13369 * complex: 'listening result'
13370 * };
13371 * });
13372 *
13373 *
13374 * // listen with custom priority (default=1000, higher is better)
13375 * eventBus.on('priorityfoo', 1500, function(event) {
13376 * console.log('invoked first!');
13377 * });
13378 *
13379 *
13380 * // listen for event and pass the context (`this`)
13381 * eventBus.on('foobar', function(event) {
13382 * this.foo();
13383 * }, this);
13384 * ```
13385 *
13386 *
13387 * ## Emitting Events
13388 *
13389 * Events can be emitted via the event bus using {@link EventBus#fire}.
13390 *
13391 * ```javascript
13392 *
13393 * // false indicates that the default action
13394 * // was prevented by listeners
13395 * if (eventBus.fire('foo') === false) {
13396 * console.log('default has been prevented!');
13397 * };
13398 *
13399 *
13400 * // custom args + return value listener
13401 * eventBus.on('sum', function(event, a, b) {
13402 * return a + b;
13403 * });
13404 *
13405 * // you can pass custom arguments + retrieve result values.
13406 * var sum = eventBus.fire('sum', 1, 2);
13407 * console.log(sum); // 3
13408 * ```
13409 *
13410 * @template [EventMap=null]
13411 */
13412 function EventBus() {
13413
13414 /**
13415 * @type { Record<string, EventBusListener> }
13416 */
13417 this._listeners = {};
13418
13419 // cleanup on destroy on lowest priority to allow
13420 // message passing until the bitter end
13421 this.on('diagram.destroy', 1, this._destroy, this);
13422 }
13423
13424 /**
13425 * @overlord
13426 *
13427 * Register an event listener for events with the given name.
13428 *
13429 * The callback will be invoked with `event, ...additionalArguments`
13430 * that have been passed to {@link EventBus#fire}.
13431 *
13432 * Returning false from a listener will prevent the events default action
13433 * (if any is specified). To stop an event from being processed further in
13434 * other listeners execute {@link Event#stopPropagation}.
13435 *
13436 * Returning anything but `undefined` from a listener will stop the listener propagation.
13437 *
13438 * @template T
13439 *
13440 * @param {string|string[]} events to subscribe to
13441 * @param {number} [priority=1000] listen priority
13442 * @param {EventBusEventCallback<T>} callback
13443 * @param {any} [that] callback context
13444 */
13445 /**
13446 * Register an event listener for events with the given name.
13447 *
13448 * The callback will be invoked with `event, ...additionalArguments`
13449 * that have been passed to {@link EventBus#fire}.
13450 *
13451 * Returning false from a listener will prevent the events default action
13452 * (if any is specified). To stop an event from being processed further in
13453 * other listeners execute {@link Event#stopPropagation}.
13454 *
13455 * Returning anything but `undefined` from a listener will stop the listener propagation.
13456 *
13457 * @template {keyof EventMap} EventName
13458 *
13459 * @param {EventName} events to subscribe to
13460 * @param {number} [priority=1000] listen priority
13461 * @param {EventBusEventCallback<EventMap[EventName]>} callback
13462 * @param {any} [that] callback context
13463 */
13464 EventBus.prototype.on = function(events, priority, callback, that) {
13465
13466 events = isArray$2(events) ? events : [ events ];
13467
13468 if (isFunction(priority)) {
13469 that = callback;
13470 callback = priority;
13471 priority = DEFAULT_PRIORITY$1;
13472 }
13473
13474 if (!isNumber(priority)) {
13475 throw new Error('priority must be a number');
13476 }
13477
13478 var actualCallback = callback;
13479
13480 if (that) {
13481 actualCallback = bind$2(callback, that);
13482
13483 // make sure we remember and are able to remove
13484 // bound callbacks via {@link #off} using the original
13485 // callback
13486 actualCallback[FN_REF] = callback[FN_REF] || callback;
13487 }
13488
13489 var self = this;
13490
13491 events.forEach(function(e) {
13492 self._addListener(e, {
13493 priority: priority,
13494 callback: actualCallback,
13495 next: null
13496 });
13497 });
13498 };
13499
13500 /**
13501 * @overlord
13502 *
13503 * Register an event listener that is called only once.
13504 *
13505 * @template T
13506 *
13507 * @param {string|string[]} events to subscribe to
13508 * @param {number} [priority=1000] the listen priority
13509 * @param {EventBusEventCallback<T>} callback
13510 * @param {any} [that] callback context
13511 */
13512 /**
13513 * Register an event listener that is called only once.
13514 *
13515 * @template {keyof EventMap} EventName
13516 *
13517 * @param {EventName} events to subscribe to
13518 * @param {number} [priority=1000] listen priority
13519 * @param {EventBusEventCallback<EventMap[EventName]>} callback
13520 * @param {any} [that] callback context
13521 */
13522 EventBus.prototype.once = function(events, priority, callback, that) {
13523 var self = this;
13524
13525 if (isFunction(priority)) {
13526 that = callback;
13527 callback = priority;
13528 priority = DEFAULT_PRIORITY$1;
13529 }
13530
13531 if (!isNumber(priority)) {
13532 throw new Error('priority must be a number');
13533 }
13534
13535 function wrappedCallback() {
13536 wrappedCallback.__isTomb = true;
13537
13538 var result = callback.apply(that, arguments);
13539
13540 self.off(events, wrappedCallback);
13541
13542 return result;
13543 }
13544
13545 // make sure we remember and are able to remove
13546 // bound callbacks via {@link #off} using the original
13547 // callback
13548 wrappedCallback[FN_REF] = callback;
13549
13550 this.on(events, priority, wrappedCallback);
13551 };
13552
13553
13554 /**
13555 * Removes event listeners by event and callback.
13556 *
13557 * If no callback is given, all listeners for a given event name are being removed.
13558 *
13559 * @param {string|string[]} events
13560 * @param {EventBusEventCallback} [callback]
13561 */
13562 EventBus.prototype.off = function(events, callback) {
13563
13564 events = isArray$2(events) ? events : [ events ];
13565
13566 var self = this;
13567
13568 events.forEach(function(event) {
13569 self._removeListener(event, callback);
13570 });
13571
13572 };
13573
13574
13575 /**
13576 * Create an event recognized be the event bus.
13577 *
13578 * @param {Object} data Event data.
13579 *
13580 * @return {Event} An event that will be recognized by the event bus.
13581 */
13582 EventBus.prototype.createEvent = function(data) {
13583 var event = new InternalEvent();
13584
13585 event.init(data);
13586
13587 return event;
13588 };
13589
13590
13591 /**
13592 * Fires an event.
13593 *
13594 * @example
13595 *
13596 * ```javascript
13597 * // fire event by name
13598 * events.fire('foo');
13599 *
13600 * // fire event object with nested type
13601 * var event = { type: 'foo' };
13602 * events.fire(event);
13603 *
13604 * // fire event with explicit type
13605 * var event = { x: 10, y: 20 };
13606 * events.fire('element.moved', event);
13607 *
13608 * // pass additional arguments to the event
13609 * events.on('foo', function(event, bar) {
13610 * alert(bar);
13611 * });
13612 *
13613 * events.fire({ type: 'foo' }, 'I am bar!');
13614 * ```
13615 *
13616 * @param {string} [type] event type
13617 * @param {Object} [data] event or event data
13618 * @param {...any} [args] additional arguments the callback will be called with.
13619 *
13620 * @return {any} The return value. Will be set to `false` if the default was prevented.
13621 */
13622 EventBus.prototype.fire = function(type, data) {
13623 var event,
13624 firstListener,
13625 returnValue,
13626 args;
13627
13628 args = slice.call(arguments);
13629
13630 if (typeof type === 'object') {
13631 data = type;
13632 type = data.type;
13633 }
13634
13635 if (!type) {
13636 throw new Error('no event type specified');
13637 }
13638
13639 firstListener = this._listeners[type];
13640
13641 if (!firstListener) {
13642 return;
13643 }
13644
13645 // we make sure we fire instances of our home made
13646 // events here. We wrap them only once, though
13647 if (data instanceof InternalEvent) {
13648
13649 // we are fine, we alread have an event
13650 event = data;
13651 } else {
13652 event = this.createEvent(data);
13653 }
13654
13655 // ensure we pass the event as the first parameter
13656 args[0] = event;
13657
13658 // original event type (in case we delegate)
13659 var originalType = event.type;
13660
13661 // update event type before delegation
13662 if (type !== originalType) {
13663 event.type = type;
13664 }
13665
13666 try {
13667 returnValue = this._invokeListeners(event, args, firstListener);
13668 } finally {
13669
13670 // reset event type after delegation
13671 if (type !== originalType) {
13672 event.type = originalType;
13673 }
13674 }
13675
13676 // set the return value to false if the event default
13677 // got prevented and no other return value exists
13678 if (returnValue === undefined && event.defaultPrevented) {
13679 returnValue = false;
13680 }
13681
13682 return returnValue;
13683 };
13684
13685 /**
13686 * Handle an error by firing an event.
13687 *
13688 * @param {Error} error The error to be handled.
13689 *
13690 * @return {boolean} Whether the error was handled.
13691 */
13692 EventBus.prototype.handleError = function(error) {
13693 return this.fire('error', { error: error }) === false;
13694 };
13695
13696
13697 EventBus.prototype._destroy = function() {
13698 this._listeners = {};
13699 };
13700
13701 /**
13702 * @param {Event} event
13703 * @param {any[]} args
13704 * @param {EventBusListener} listener
13705 *
13706 * @return {any}
13707 */
13708 EventBus.prototype._invokeListeners = function(event, args, listener) {
13709
13710 var returnValue;
13711
13712 while (listener) {
13713
13714 // handle stopped propagation
13715 if (event.cancelBubble) {
13716 break;
13717 }
13718
13719 returnValue = this._invokeListener(event, args, listener);
13720
13721 listener = listener.next;
13722 }
13723
13724 return returnValue;
13725 };
13726
13727 /**
13728 * @param {Event} event
13729 * @param {any[]} args
13730 * @param {EventBusListener} listener
13731 *
13732 * @return {any}
13733 */
13734 EventBus.prototype._invokeListener = function(event, args, listener) {
13735
13736 var returnValue;
13737
13738 if (listener.callback.__isTomb) {
13739 return returnValue;
13740 }
13741
13742 try {
13743
13744 // returning false prevents the default action
13745 returnValue = invokeFunction(listener.callback, args);
13746
13747 // stop propagation on return value
13748 if (returnValue !== undefined) {
13749 event.returnValue = returnValue;
13750 event.stopPropagation();
13751 }
13752
13753 // prevent default on return false
13754 if (returnValue === false) {
13755 event.preventDefault();
13756 }
13757 } catch (error) {
13758 if (!this.handleError(error)) {
13759 console.error('unhandled error in event listener', error);
13760
13761 throw error;
13762 }
13763 }
13764
13765 return returnValue;
13766 };
13767
13768 /**
13769 * Add new listener with a certain priority to the list
13770 * of listeners (for the given event).
13771 *
13772 * The semantics of listener registration / listener execution are
13773 * first register, first serve: New listeners will always be inserted
13774 * after existing listeners with the same priority.
13775 *
13776 * Example: Inserting two listeners with priority 1000 and 1300
13777 *
13778 * * before: [ 1500, 1500, 1000, 1000 ]
13779 * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
13780 *
13781 * @param {string} event
13782 * @param {EventBusListener} newListener
13783 */
13784 EventBus.prototype._addListener = function(event, newListener) {
13785
13786 var listener = this._getListeners(event),
13787 previousListener;
13788
13789 // no prior listeners
13790 if (!listener) {
13791 this._setListeners(event, newListener);
13792
13793 return;
13794 }
13795
13796 // ensure we order listeners by priority from
13797 // 0 (high) to n > 0 (low)
13798 while (listener) {
13799
13800 if (listener.priority < newListener.priority) {
13801
13802 newListener.next = listener;
13803
13804 if (previousListener) {
13805 previousListener.next = newListener;
13806 } else {
13807 this._setListeners(event, newListener);
13808 }
13809
13810 return;
13811 }
13812
13813 previousListener = listener;
13814 listener = listener.next;
13815 }
13816
13817 // add new listener to back
13818 previousListener.next = newListener;
13819 };
13820
13821
13822 /**
13823 * @param {string} name
13824 *
13825 * @return {EventBusListener}
13826 */
13827 EventBus.prototype._getListeners = function(name) {
13828 return this._listeners[name];
13829 };
13830
13831 /**
13832 * @param {string} name
13833 * @param {EventBusListener} listener
13834 */
13835 EventBus.prototype._setListeners = function(name, listener) {
13836 this._listeners[name] = listener;
13837 };
13838
13839 EventBus.prototype._removeListener = function(event, callback) {
13840
13841 var listener = this._getListeners(event),
13842 nextListener,
13843 previousListener,
13844 listenerCallback;
13845
13846 if (!callback) {
13847
13848 // clear listeners
13849 this._setListeners(event, null);
13850
13851 return;
13852 }
13853
13854 while (listener) {
13855
13856 nextListener = listener.next;
13857
13858 listenerCallback = listener.callback;
13859
13860 if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
13861 if (previousListener) {
13862 previousListener.next = nextListener;
13863 } else {
13864
13865 // new first listener
13866 this._setListeners(event, nextListener);
13867 }
13868 }
13869
13870 previousListener = listener;
13871 listener = nextListener;
13872 }
13873 };
13874
13875 /**
13876 * A event that is emitted via the event bus.
13877 */
13878 function InternalEvent() { }
13879
13880 InternalEvent.prototype.stopPropagation = function() {
13881 this.cancelBubble = true;
13882 };
13883
13884 InternalEvent.prototype.preventDefault = function() {
13885 this.defaultPrevented = true;
13886 };
13887
13888 InternalEvent.prototype.init = function(data) {
13889 assign$1(this, data || {});
13890 };
13891
13892
13893 /**
13894 * Invoke function. Be fast...
13895 *
13896 * @param {Function} fn
13897 * @param {any[]} args
13898 *
13899 * @return {any}
13900 */
13901 function invokeFunction(fn, args) {
13902 return fn.apply(null, args);
13903 }
13904
13905 /**
13906 * SVGs for elements are generated by the {@link GraphicsFactory}.
13907 *
13908 * This utility gives quick access to the important semantic
13909 * parts of an element.
13910 */
13911
13912 /**
13913 * Returns the visual part of a diagram element.
13914 *
13915 * @param {SVGElement} gfx
13916 *
13917 * @return {SVGElement}
13918 */
13919 function getVisual(gfx) {
13920 return gfx.childNodes[0];
13921 }
13922
13923 /**
13924 * Returns the children for a given diagram element.
13925 *
13926 * @param {SVGElement} gfx
13927 * @return {SVGElement}
13928 */
13929 function getChildren(gfx) {
13930 return gfx.parentNode.childNodes[1];
13931 }
13932
13933 /**
13934 * @typedef {import('./Types').ConnectionLike} ConnectionLike
13935 * @typedef {import('./Types').ElementLike} ElementLike
13936 * @typedef {import('./Types').ShapeLike} ShapeLike
13937 *
13938 * @typedef {import('./ElementRegistry').default} ElementRegistry
13939 * @typedef {import('./EventBus').default} EventBus
13940 */
13941
13942 /**
13943 * A factory that creates graphical elements.
13944 *
13945 * @param {EventBus} eventBus
13946 * @param {ElementRegistry} elementRegistry
13947 */
13948 function GraphicsFactory(eventBus, elementRegistry) {
13949 this._eventBus = eventBus;
13950 this._elementRegistry = elementRegistry;
13951 }
13952
13953 GraphicsFactory.$inject = [ 'eventBus' , 'elementRegistry' ];
13954
13955 /**
13956 * @param { { parent?: any } } element
13957 * @return {SVGElement}
13958 */
13959 GraphicsFactory.prototype._getChildrenContainer = function(element) {
13960
13961 var gfx = this._elementRegistry.getGraphics(element);
13962
13963 var childrenGfx;
13964
13965 // root element
13966 if (!element.parent) {
13967 childrenGfx = gfx;
13968 } else {
13969 childrenGfx = getChildren(gfx);
13970 if (!childrenGfx) {
13971 childrenGfx = create$1('g');
13972 classes$1(childrenGfx).add('djs-children');
13973
13974 append(gfx.parentNode, childrenGfx);
13975 }
13976 }
13977
13978 return childrenGfx;
13979 };
13980
13981 /**
13982 * Clears the graphical representation of the element and returns the
13983 * cleared visual (the <g class="djs-visual" /> element).
13984 */
13985 GraphicsFactory.prototype._clear = function(gfx) {
13986 var visual = getVisual(gfx);
13987
13988 clear(visual);
13989
13990 return visual;
13991 };
13992
13993 /**
13994 * Creates a gfx container for shapes and connections
13995 *
13996 * The layout is as follows:
13997 *
13998 * <g class="djs-group">
13999 *
14000 * <!-- the gfx -->
14001 * <g class="djs-element djs-(shape|connection|frame)">
14002 * <g class="djs-visual">
14003 * <!-- the renderer draws in here -->
14004 * </g>
14005 *
14006 * <!-- extensions (overlays, click box, ...) goes here
14007 * </g>
14008 *
14009 * <!-- the gfx child nodes -->
14010 * <g class="djs-children"></g>
14011 * </g>
14012 *
14013 * @param {string} type the type of the element, i.e. shape | connection
14014 * @param {SVGElement} childrenGfx
14015 * @param {number} [parentIndex] position to create container in parent
14016 * @param {boolean} [isFrame] is frame element
14017 *
14018 * @return {SVGElement}
14019 */
14020 GraphicsFactory.prototype._createContainer = function(
14021 type, childrenGfx, parentIndex, isFrame
14022 ) {
14023 var outerGfx = create$1('g');
14024 classes$1(outerGfx).add('djs-group');
14025
14026 // insert node at position
14027 if (typeof parentIndex !== 'undefined') {
14028 prependTo(outerGfx, childrenGfx, childrenGfx.childNodes[parentIndex]);
14029 } else {
14030 append(childrenGfx, outerGfx);
14031 }
14032
14033 var gfx = create$1('g');
14034 classes$1(gfx).add('djs-element');
14035 classes$1(gfx).add('djs-' + type);
14036
14037 if (isFrame) {
14038 classes$1(gfx).add('djs-frame');
14039 }
14040
14041 append(outerGfx, gfx);
14042
14043 // create visual
14044 var visual = create$1('g');
14045 classes$1(visual).add('djs-visual');
14046
14047 append(gfx, visual);
14048
14049 return gfx;
14050 };
14051
14052 /**
14053 * Create a graphical element.
14054 *
14055 * @param { 'shape' | 'connection' | 'label' | 'root' } type The type of the element.
14056 * @param {ElementLike} element The element.
14057 * @param {number} [parentIndex] The index at which to add the graphical element to its parent's children.
14058 *
14059 * @return {SVGElement} The graphical element.
14060 */
14061 GraphicsFactory.prototype.create = function(type, element, parentIndex) {
14062 var childrenGfx = this._getChildrenContainer(element.parent);
14063 return this._createContainer(type, childrenGfx, parentIndex, isFrameElement(element));
14064 };
14065
14066 /**
14067 * Update the containments of the given elements.
14068 *
14069 * @param {ElementLike[]} elements The elements.
14070 */
14071 GraphicsFactory.prototype.updateContainments = function(elements) {
14072
14073 var self = this,
14074 elementRegistry = this._elementRegistry,
14075 parents;
14076
14077 parents = reduce(elements, function(map, e) {
14078
14079 if (e.parent) {
14080 map[e.parent.id] = e.parent;
14081 }
14082
14083 return map;
14084 }, {});
14085
14086 // update all parents of changed and reorganized their children
14087 // in the correct order (as indicated in our model)
14088 forEach$1(parents, function(parent) {
14089
14090 var children = parent.children;
14091
14092 if (!children) {
14093 return;
14094 }
14095
14096 var childrenGfx = self._getChildrenContainer(parent);
14097
14098 forEach$1(children.slice().reverse(), function(child) {
14099 var childGfx = elementRegistry.getGraphics(child);
14100
14101 prependTo(childGfx.parentNode, childrenGfx);
14102 });
14103 });
14104 };
14105
14106 /**
14107 * Draw a shape.
14108 *
14109 * @param {SVGElement} visual The graphical element.
14110 * @param {ShapeLike} element The shape.
14111 * @param {Object} attrs Optional attributes.
14112 *
14113 * @return {SVGElement}
14114 */
14115 GraphicsFactory.prototype.drawShape = function(visual, element, attrs = {}) {
14116 var eventBus = this._eventBus;
14117
14118 return eventBus.fire('render.shape', { gfx: visual, element, attrs });
14119 };
14120
14121 /**
14122 * Get the path of a shape.
14123 *
14124 * @param {ShapeLike} element The shape.
14125 *
14126 * @return {string} The path of the shape.
14127 */
14128 GraphicsFactory.prototype.getShapePath = function(element) {
14129 var eventBus = this._eventBus;
14130
14131 return eventBus.fire('render.getShapePath', element);
14132 };
14133
14134 /**
14135 * Draw a connection.
14136 *
14137 * @param {SVGElement} visual The graphical element.
14138 * @param {ConnectionLike} element The connection.
14139 * @param {Object} attrs Optional attributes.
14140 *
14141 * @return {SVGElement}
14142 */
14143 GraphicsFactory.prototype.drawConnection = function(visual, element, attrs = {}) {
14144 var eventBus = this._eventBus;
14145
14146 return eventBus.fire('render.connection', { gfx: visual, element, attrs });
14147 };
14148
14149 /**
14150 * Get the path of a connection.
14151 *
14152 * @param {ConnectionLike} connection The connection.
14153 *
14154 * @return {string} The path of the connection.
14155 */
14156 GraphicsFactory.prototype.getConnectionPath = function(connection) {
14157 var eventBus = this._eventBus;
14158
14159 return eventBus.fire('render.getConnectionPath', connection);
14160 };
14161
14162 /**
14163 * Update an elements graphical representation.
14164 *
14165 * @param {'shape'|'connection'} type
14166 * @param {ElementLike} element
14167 * @param {SVGElement} gfx
14168 */
14169 GraphicsFactory.prototype.update = function(type, element, gfx) {
14170
14171 // do NOT update root element
14172 if (!element.parent) {
14173 return;
14174 }
14175
14176 var visual = this._clear(gfx);
14177
14178 // redraw
14179 if (type === 'shape') {
14180 this.drawShape(visual, element);
14181
14182 // update positioning
14183 translate$1(gfx, element.x, element.y);
14184 } else if (type === 'connection') {
14185 this.drawConnection(visual, element);
14186 } else {
14187 throw new Error('unknown type: ' + type);
14188 }
14189
14190 if (element.hidden) {
14191 attr$1(gfx, 'display', 'none');
14192 } else {
14193 attr$1(gfx, 'display', 'block');
14194 }
14195 };
14196
14197 /**
14198 * Remove a graphical element.
14199 *
14200 * @param {ElementLike} element The element.
14201 */
14202 GraphicsFactory.prototype.remove = function(element) {
14203 var gfx = this._elementRegistry.getGraphics(element);
14204
14205 // remove
14206 remove$2(gfx.parentNode);
14207 };
14208
14209
14210 // helpers //////////
14211
14212 function prependTo(newNode, parentNode, siblingNode) {
14213 var node = siblingNode || parentNode.firstChild;
14214
14215 // do not prepend node to itself to prevent IE from crashing
14216 // https://github.com/bpmn-io/bpmn-js/issues/746
14217 if (newNode === node) {
14218 return;
14219 }
14220
14221 parentNode.insertBefore(newNode, node);
14222 }
14223
14224 /**
14225 * @type { import('didi').ModuleDeclaration }
14226 */
14227 var CoreModule = {
14228 __depends__: [ DrawModule ],
14229 __init__: [ 'canvas' ],
14230 canvas: [ 'type', Canvas ],
14231 elementRegistry: [ 'type', ElementRegistry ],
14232 elementFactory: [ 'type', ElementFactory ],
14233 eventBus: [ 'type', EventBus ],
14234 graphicsFactory: [ 'type', GraphicsFactory ]
14235 };
14236
14237 /**
14238 * @typedef {import('didi').InjectionContext} InjectionContext
14239 * @typedef {import('didi').LocalsMap} LocalsMap
14240 * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration
14241 *
14242 * @typedef { {
14243 * modules?: ModuleDeclaration[];
14244 * } & Record<string, any> } DiagramOptions
14245 */
14246
14247 /**
14248 * @template T
14249 * @typedef {import('didi').FactoryFunction<T>} FactoryFunction
14250 */
14251
14252 /**
14253 * @template T
14254 * @typedef {import('didi').ArrayFunc<T>} ArrayFunc
14255 */
14256
14257 /**
14258 * Bootstrap an injector from a list of modules, instantiating a number of default components
14259 *
14260 * @param {ModuleDeclaration[]} modules
14261 *
14262 * @return {Injector} a injector to use to access the components
14263 */
14264 function bootstrap(modules) {
14265 var injector = new Injector(modules);
14266
14267 injector.init();
14268
14269 return injector;
14270 }
14271
14272 /**
14273 * Creates an injector from passed options.
14274 *
14275 * @template ServiceMap
14276 * @param {DiagramOptions} [options]
14277 *
14278 * @return {Injector<ServiceMap>}
14279 */
14280 function createInjector(options) {
14281
14282 options = options || {};
14283
14284 /**
14285 * @type { ModuleDeclaration }
14286 */
14287 var configModule = {
14288 'config': [ 'value', options ]
14289 };
14290
14291 var modules = [ configModule, CoreModule ].concat(options.modules || []);
14292
14293 return bootstrap(modules);
14294 }
14295
14296
14297 /**
14298 * The main diagram-js entry point that bootstraps the diagram with the given
14299 * configuration.
14300 *
14301 * To register extensions with the diagram, pass them as Array<Module> to the constructor.
14302 *
14303 * @class
14304 * @constructor
14305 * @template [ServiceMap=null]
14306 *
14307 * @example Creating a plug-in that logs whenever a shape is added to the canvas.
14308 *
14309 * ```javascript
14310 * // plug-in implementation
14311 * function MyLoggingPlugin(eventBus) {
14312 * eventBus.on('shape.added', function(event) {
14313 * console.log('shape ', event.shape, ' was added to the diagram');
14314 * });
14315 * }
14316 *
14317 * // export as module
14318 * export default {
14319 * __init__: [ 'myLoggingPlugin' ],
14320 * myLoggingPlugin: [ 'type', MyLoggingPlugin ]
14321 * };
14322 * ```
14323 *
14324 * Use the plug-in in a Diagram instance:
14325 *
14326 * ```javascript
14327 * import MyLoggingModule from 'path-to-my-logging-plugin';
14328 *
14329 * var diagram = new Diagram({
14330 * modules: [
14331 * MyLoggingModule
14332 * ]
14333 * });
14334 *
14335 * diagram.invoke([ 'canvas', function(canvas) {
14336 * // add shape to drawing canvas
14337 * canvas.addShape({ x: 10, y: 10 });
14338 * });
14339 *
14340 * // 'shape ... was added to the diagram' logged to console
14341 * ```
14342 *
14343 * @param {DiagramOptions} [options]
14344 * @param {Injector<ServiceMap>} [injector] An (optional) injector to bootstrap the diagram with.
14345 */
14346 function Diagram(options, injector) {
14347
14348 /**
14349 * @type {Injector<ServiceMap>}
14350 */
14351 this._injector = injector || createInjector(options);
14352
14353 // init
14354
14355 /**
14356 * An event indicating that all plug-ins are loaded.
14357 *
14358 * Use this event to fire other events to interested plug-ins
14359 *
14360 * @memberOf Diagram
14361 *
14362 * @event diagram.init
14363 *
14364 * @example
14365 *
14366 * ```javascript
14367 * eventBus.on('diagram.init', function() {
14368 * eventBus.fire('my-custom-event', { foo: 'BAR' });
14369 * });
14370 * ```
14371 *
14372 * @type {Object}
14373 */
14374 this.get('eventBus').fire('diagram.init');
14375 }
14376
14377 /**
14378 * @overlord
14379 *
14380 * Resolves a diagram service.
14381 *
14382 * @template T
14383 *
14384 * @param {string} name The name of the service to get.
14385 *
14386 * @return {T}
14387 */
14388 /**
14389 * @overlord
14390 *
14391 * Resolves a diagram service.
14392 *
14393 * @template T
14394 *
14395 * @param {string} name The name of the service to get.
14396 * @param {true} strict If false, resolve missing services to null.
14397 *
14398 * @return {T}
14399 */
14400 /**
14401 * @overlord
14402 *
14403 * Resolves a diagram service.
14404 *
14405 * @template T
14406 *
14407 * @param {string} name The name of the service to get.
14408 * @param {boolean} strict If false, resolve missing services to null.
14409 *
14410 * @return {T|null}
14411 */
14412 /**
14413 * Resolves a diagram service.
14414 *
14415 * @template {keyof ServiceMap} Name
14416 *
14417 * @param {Name} name The name of the service to get.
14418 *
14419 * @return {ServiceMap[Name]}
14420 */
14421 Diagram.prototype.get = function(name, strict) {
14422 return this._injector.get(name, strict);
14423 };
14424
14425 /**
14426 * @overlord
14427 *
14428 * Invoke the given function, injecting dependencies. Return the result.
14429 *
14430 * @template T
14431 *
14432 * @param {FactoryFunction<T>} func
14433 * @param {InjectionContext} [context]
14434 * @param {LocalsMap} [locals]
14435 *
14436 * @return {T}
14437 */
14438 /**
14439 * Invoke the given function, injecting dependencies provided in
14440 * array notation. Return the result.
14441 *
14442 * @template T
14443 *
14444 * @param {ArrayFunc<T>} func function to be invoked
14445 * @param {InjectionContext} [context] context of the invocation
14446 * @param {LocalsMap} [locals] locals provided
14447 *
14448 * @return {T}
14449 */
14450 Diagram.prototype.invoke = function(func, context, locals) {
14451 return this._injector.invoke(func, context, locals);
14452 };
14453
14454 /**
14455 * Destroys the diagram
14456 */
14457 Diagram.prototype.destroy = function() {
14458 this.get('eventBus').fire('diagram.destroy');
14459 };
14460
14461 /**
14462 * Clear the diagram, removing all contents.
14463 */
14464 Diagram.prototype.clear = function() {
14465 this.get('eventBus').fire('diagram.clear');
14466 };
14467
14468 /**
14469 * Moddle base element.
14470 */
14471 function Base() { }
14472
14473 Base.prototype.get = function(name) {
14474 return this.$model.properties.get(this, name);
14475 };
14476
14477 Base.prototype.set = function(name, value) {
14478 this.$model.properties.set(this, name, value);
14479 };
14480
14481 /**
14482 * A model element factory.
14483 *
14484 * @param {Moddle} model
14485 * @param {Properties} properties
14486 */
14487 function Factory(model, properties) {
14488 this.model = model;
14489 this.properties = properties;
14490 }
14491
14492
14493 Factory.prototype.createType = function(descriptor) {
14494
14495 var model = this.model;
14496
14497 var props = this.properties,
14498 prototype = Object.create(Base.prototype);
14499
14500 // initialize default values
14501 forEach$1(descriptor.properties, function(p) {
14502 if (!p.isMany && p.default !== undefined) {
14503 prototype[p.name] = p.default;
14504 }
14505 });
14506
14507 props.defineModel(prototype, model);
14508 props.defineDescriptor(prototype, descriptor);
14509
14510 var name = descriptor.ns.name;
14511
14512 /**
14513 * The new type constructor
14514 */
14515 function ModdleElement(attrs) {
14516 props.define(this, '$type', { value: name, enumerable: true });
14517 props.define(this, '$attrs', { value: {} });
14518 props.define(this, '$parent', { writable: true });
14519
14520 forEach$1(attrs, bind$2(function(val, key) {
14521 this.set(key, val);
14522 }, this));
14523 }
14524
14525 ModdleElement.prototype = prototype;
14526
14527 ModdleElement.hasType = prototype.$instanceOf = this.model.hasType;
14528
14529 // static links
14530 props.defineModel(ModdleElement, model);
14531 props.defineDescriptor(ModdleElement, descriptor);
14532
14533 return ModdleElement;
14534 };
14535
14536 /**
14537 * Built-in moddle types
14538 */
14539 var BUILTINS = {
14540 String: true,
14541 Boolean: true,
14542 Integer: true,
14543 Real: true,
14544 Element: true
14545 };
14546
14547 /**
14548 * Converters for built in types from string representations
14549 */
14550 var TYPE_CONVERTERS = {
14551 String: function(s) { return s; },
14552 Boolean: function(s) { return s === 'true'; },
14553 Integer: function(s) { return parseInt(s, 10); },
14554 Real: function(s) { return parseFloat(s); }
14555 };
14556
14557 /**
14558 * Convert a type to its real representation
14559 */
14560 function coerceType(type, value) {
14561
14562 var converter = TYPE_CONVERTERS[type];
14563
14564 if (converter) {
14565 return converter(value);
14566 } else {
14567 return value;
14568 }
14569 }
14570
14571 /**
14572 * Return whether the given type is built-in
14573 */
14574 function isBuiltIn(type) {
14575 return !!BUILTINS[type];
14576 }
14577
14578 /**
14579 * Return whether the given type is simple
14580 */
14581 function isSimple(type) {
14582 return !!TYPE_CONVERTERS[type];
14583 }
14584
14585 /**
14586 * Parses a namespaced attribute name of the form (ns:)localName to an object,
14587 * given a default prefix to assume in case no explicit namespace is given.
14588 *
14589 * @param {String} name
14590 * @param {String} [defaultPrefix] the default prefix to take, if none is present.
14591 *
14592 * @return {Object} the parsed name
14593 */
14594 function parseName(name, defaultPrefix) {
14595 var parts = name.split(/:/),
14596 localName, prefix;
14597
14598 // no prefix (i.e. only local name)
14599 if (parts.length === 1) {
14600 localName = name;
14601 prefix = defaultPrefix;
14602 } else
14603
14604 // prefix + local name
14605 if (parts.length === 2) {
14606 localName = parts[1];
14607 prefix = parts[0];
14608 } else {
14609 throw new Error('expected <prefix:localName> or <localName>, got ' + name);
14610 }
14611
14612 name = (prefix ? prefix + ':' : '') + localName;
14613
14614 return {
14615 name: name,
14616 prefix: prefix,
14617 localName: localName
14618 };
14619 }
14620
14621 /**
14622 * A utility to build element descriptors.
14623 */
14624 function DescriptorBuilder(nameNs) {
14625 this.ns = nameNs;
14626 this.name = nameNs.name;
14627 this.allTypes = [];
14628 this.allTypesByName = {};
14629 this.properties = [];
14630 this.propertiesByName = {};
14631 }
14632
14633
14634 DescriptorBuilder.prototype.build = function() {
14635 return pick(this, [
14636 'ns',
14637 'name',
14638 'allTypes',
14639 'allTypesByName',
14640 'properties',
14641 'propertiesByName',
14642 'bodyProperty',
14643 'idProperty'
14644 ]);
14645 };
14646
14647 /**
14648 * Add property at given index.
14649 *
14650 * @param {Object} p
14651 * @param {Number} [idx]
14652 * @param {Boolean} [validate=true]
14653 */
14654 DescriptorBuilder.prototype.addProperty = function(p, idx, validate) {
14655
14656 if (typeof idx === 'boolean') {
14657 validate = idx;
14658 idx = undefined;
14659 }
14660
14661 this.addNamedProperty(p, validate !== false);
14662
14663 var properties = this.properties;
14664
14665 if (idx !== undefined) {
14666 properties.splice(idx, 0, p);
14667 } else {
14668 properties.push(p);
14669 }
14670 };
14671
14672
14673 DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty, replace) {
14674 var oldNameNs = oldProperty.ns;
14675
14676 var props = this.properties,
14677 propertiesByName = this.propertiesByName,
14678 rename = oldProperty.name !== newProperty.name;
14679
14680 if (oldProperty.isId) {
14681 if (!newProperty.isId) {
14682 throw new Error(
14683 'property <' + newProperty.ns.name + '> must be id property ' +
14684 'to refine <' + oldProperty.ns.name + '>');
14685 }
14686
14687 this.setIdProperty(newProperty, false);
14688 }
14689
14690 if (oldProperty.isBody) {
14691
14692 if (!newProperty.isBody) {
14693 throw new Error(
14694 'property <' + newProperty.ns.name + '> must be body property ' +
14695 'to refine <' + oldProperty.ns.name + '>');
14696 }
14697
14698 // TODO: Check compatibility
14699 this.setBodyProperty(newProperty, false);
14700 }
14701
14702 // validate existence and get location of old property
14703 var idx = props.indexOf(oldProperty);
14704 if (idx === -1) {
14705 throw new Error('property <' + oldNameNs.name + '> not found in property list');
14706 }
14707
14708 // remove old property
14709 props.splice(idx, 1);
14710
14711 // replacing the named property is intentional
14712 //
14713 // * validate only if this is a "rename" operation
14714 // * add at specific index unless we "replace"
14715 //
14716 this.addProperty(newProperty, replace ? undefined : idx, rename);
14717
14718 // make new property available under old name
14719 propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
14720 };
14721
14722
14723 DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, replace) {
14724
14725 var nsPrefix = p.ns.prefix;
14726 var parts = targetPropertyName.split('#');
14727
14728 var name = parseName(parts[0], nsPrefix);
14729 var attrName = parseName(parts[1], name.prefix).name;
14730
14731 var redefinedProperty = this.propertiesByName[attrName];
14732 if (!redefinedProperty) {
14733 throw new Error('refined property <' + attrName + '> not found');
14734 } else {
14735 this.replaceProperty(redefinedProperty, p, replace);
14736 }
14737
14738 delete p.redefines;
14739 };
14740
14741 DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
14742 var ns = p.ns,
14743 propsByName = this.propertiesByName;
14744
14745 if (validate) {
14746 this.assertNotDefined(p, ns.name);
14747 this.assertNotDefined(p, ns.localName);
14748 }
14749
14750 propsByName[ns.name] = propsByName[ns.localName] = p;
14751 };
14752
14753 DescriptorBuilder.prototype.removeNamedProperty = function(p) {
14754 var ns = p.ns,
14755 propsByName = this.propertiesByName;
14756
14757 delete propsByName[ns.name];
14758 delete propsByName[ns.localName];
14759 };
14760
14761 DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
14762
14763 if (validate && this.bodyProperty) {
14764 throw new Error(
14765 'body property defined multiple times ' +
14766 '(<' + this.bodyProperty.ns.name + '>, <' + p.ns.name + '>)');
14767 }
14768
14769 this.bodyProperty = p;
14770 };
14771
14772 DescriptorBuilder.prototype.setIdProperty = function(p, validate) {
14773
14774 if (validate && this.idProperty) {
14775 throw new Error(
14776 'id property defined multiple times ' +
14777 '(<' + this.idProperty.ns.name + '>, <' + p.ns.name + '>)');
14778 }
14779
14780 this.idProperty = p;
14781 };
14782
14783 DescriptorBuilder.prototype.assertNotTrait = function(typeDescriptor) {
14784
14785 const _extends = typeDescriptor.extends || [];
14786
14787 if (_extends.length) {
14788 throw new Error(
14789 `cannot create <${ typeDescriptor.name }> extending <${ typeDescriptor.extends }>`
14790 );
14791 }
14792 };
14793
14794 DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
14795 var propertyName = p.name,
14796 definedProperty = this.propertiesByName[propertyName];
14797
14798 if (definedProperty) {
14799 throw new Error(
14800 'property <' + propertyName + '> already defined; ' +
14801 'override of <' + definedProperty.definedBy.ns.name + '#' + definedProperty.ns.name + '> by ' +
14802 '<' + p.definedBy.ns.name + '#' + p.ns.name + '> not allowed without redefines');
14803 }
14804 };
14805
14806 DescriptorBuilder.prototype.hasProperty = function(name) {
14807 return this.propertiesByName[name];
14808 };
14809
14810 DescriptorBuilder.prototype.addTrait = function(t, inherited) {
14811
14812 if (inherited) {
14813 this.assertNotTrait(t);
14814 }
14815
14816 var typesByName = this.allTypesByName,
14817 types = this.allTypes;
14818
14819 var typeName = t.name;
14820
14821 if (typeName in typesByName) {
14822 return;
14823 }
14824
14825 forEach$1(t.properties, bind$2(function(p) {
14826
14827 // clone property to allow extensions
14828 p = assign$1({}, p, {
14829 name: p.ns.localName,
14830 inherited: inherited
14831 });
14832
14833 Object.defineProperty(p, 'definedBy', {
14834 value: t
14835 });
14836
14837 var replaces = p.replaces,
14838 redefines = p.redefines;
14839
14840 // add replace/redefine support
14841 if (replaces || redefines) {
14842 this.redefineProperty(p, replaces || redefines, replaces);
14843 } else {
14844 if (p.isBody) {
14845 this.setBodyProperty(p);
14846 }
14847 if (p.isId) {
14848 this.setIdProperty(p);
14849 }
14850 this.addProperty(p);
14851 }
14852 }, this));
14853
14854 types.push(t);
14855 typesByName[typeName] = t;
14856 };
14857
14858 /**
14859 * A registry of Moddle packages.
14860 *
14861 * @param {Array<Package>} packages
14862 * @param {Properties} properties
14863 */
14864 function Registry(packages, properties) {
14865 this.packageMap = {};
14866 this.typeMap = {};
14867
14868 this.packages = [];
14869
14870 this.properties = properties;
14871
14872 forEach$1(packages, bind$2(this.registerPackage, this));
14873 }
14874
14875
14876 Registry.prototype.getPackage = function(uriOrPrefix) {
14877 return this.packageMap[uriOrPrefix];
14878 };
14879
14880 Registry.prototype.getPackages = function() {
14881 return this.packages;
14882 };
14883
14884
14885 Registry.prototype.registerPackage = function(pkg) {
14886
14887 // copy package
14888 pkg = assign$1({}, pkg);
14889
14890 var pkgMap = this.packageMap;
14891
14892 ensureAvailable(pkgMap, pkg, 'prefix');
14893 ensureAvailable(pkgMap, pkg, 'uri');
14894
14895 // register types
14896 forEach$1(pkg.types, bind$2(function(descriptor) {
14897 this.registerType(descriptor, pkg);
14898 }, this));
14899
14900 pkgMap[pkg.uri] = pkgMap[pkg.prefix] = pkg;
14901 this.packages.push(pkg);
14902 };
14903
14904
14905 /**
14906 * Register a type from a specific package with us
14907 */
14908 Registry.prototype.registerType = function(type, pkg) {
14909
14910 type = assign$1({}, type, {
14911 superClass: (type.superClass || []).slice(),
14912 extends: (type.extends || []).slice(),
14913 properties: (type.properties || []).slice(),
14914 meta: assign$1((type.meta || {}))
14915 });
14916
14917 var ns = parseName(type.name, pkg.prefix),
14918 name = ns.name,
14919 propertiesByName = {};
14920
14921 // parse properties
14922 forEach$1(type.properties, bind$2(function(p) {
14923
14924 // namespace property names
14925 var propertyNs = parseName(p.name, ns.prefix),
14926 propertyName = propertyNs.name;
14927
14928 // namespace property types
14929 if (!isBuiltIn(p.type)) {
14930 p.type = parseName(p.type, propertyNs.prefix).name;
14931 }
14932
14933 assign$1(p, {
14934 ns: propertyNs,
14935 name: propertyName
14936 });
14937
14938 propertiesByName[propertyName] = p;
14939 }, this));
14940
14941 // update ns + name
14942 assign$1(type, {
14943 ns: ns,
14944 name: name,
14945 propertiesByName: propertiesByName
14946 });
14947
14948 forEach$1(type.extends, bind$2(function(extendsName) {
14949 var extendsNameNs = parseName(extendsName, ns.prefix);
14950
14951 var extended = this.typeMap[extendsNameNs.name];
14952
14953 extended.traits = extended.traits || [];
14954 extended.traits.push(name);
14955 }, this));
14956
14957 // link to package
14958 this.definePackage(type, pkg);
14959
14960 // register
14961 this.typeMap[name] = type;
14962 };
14963
14964
14965 /**
14966 * Traverse the type hierarchy from bottom to top,
14967 * calling iterator with (type, inherited) for all elements in
14968 * the inheritance chain.
14969 *
14970 * @param {Object} nsName
14971 * @param {Function} iterator
14972 * @param {Boolean} [trait=false]
14973 */
14974 Registry.prototype.mapTypes = function(nsName, iterator, trait) {
14975
14976 var type = isBuiltIn(nsName.name) ? { name: nsName.name } : this.typeMap[nsName.name];
14977
14978 var self = this;
14979
14980 /**
14981 * Traverse the selected super type or trait
14982 *
14983 * @param {String} cls
14984 * @param {Boolean} [trait=false]
14985 */
14986 function traverse(cls, trait) {
14987 var parentNs = parseName(cls, isBuiltIn(cls) ? '' : nsName.prefix);
14988 self.mapTypes(parentNs, iterator, trait);
14989 }
14990
14991 /**
14992 * Traverse the selected trait.
14993 *
14994 * @param {String} cls
14995 */
14996 function traverseTrait(cls) {
14997 return traverse(cls, true);
14998 }
14999
15000 /**
15001 * Traverse the selected super type
15002 *
15003 * @param {String} cls
15004 */
15005 function traverseSuper(cls) {
15006 return traverse(cls, false);
15007 }
15008
15009 if (!type) {
15010 throw new Error('unknown type <' + nsName.name + '>');
15011 }
15012
15013 forEach$1(type.superClass, trait ? traverseTrait : traverseSuper);
15014
15015 // call iterator with (type, inherited=!trait)
15016 iterator(type, !trait);
15017
15018 forEach$1(type.traits, traverseTrait);
15019 };
15020
15021
15022 /**
15023 * Returns the effective descriptor for a type.
15024 *
15025 * @param {String} type the namespaced name (ns:localName) of the type
15026 *
15027 * @return {Descriptor} the resulting effective descriptor
15028 */
15029 Registry.prototype.getEffectiveDescriptor = function(name) {
15030
15031 var nsName = parseName(name);
15032
15033 var builder = new DescriptorBuilder(nsName);
15034
15035 this.mapTypes(nsName, function(type, inherited) {
15036 builder.addTrait(type, inherited);
15037 });
15038
15039 var descriptor = builder.build();
15040
15041 // define package link
15042 this.definePackage(descriptor, descriptor.allTypes[descriptor.allTypes.length - 1].$pkg);
15043
15044 return descriptor;
15045 };
15046
15047
15048 Registry.prototype.definePackage = function(target, pkg) {
15049 this.properties.define(target, '$pkg', { value: pkg });
15050 };
15051
15052
15053
15054 // helpers ////////////////////////////
15055
15056 function ensureAvailable(packageMap, pkg, identifierKey) {
15057
15058 var value = pkg[identifierKey];
15059
15060 if (value in packageMap) {
15061 throw new Error('package with ' + identifierKey + ' <' + value + '> already defined');
15062 }
15063 }
15064
15065 /**
15066 * A utility that gets and sets properties of model elements.
15067 *
15068 * @param {Model} model
15069 */
15070 function Properties(model) {
15071 this.model = model;
15072 }
15073
15074
15075 /**
15076 * Sets a named property on the target element.
15077 * If the value is undefined, the property gets deleted.
15078 *
15079 * @param {Object} target
15080 * @param {String} name
15081 * @param {Object} value
15082 */
15083 Properties.prototype.set = function(target, name, value) {
15084
15085 if (!isString(name) || !name.length) {
15086 throw new TypeError('property name must be a non-empty string');
15087 }
15088
15089 var property = this.getProperty(target, name);
15090
15091 var propertyName = property && property.name;
15092
15093 if (isUndefined(value)) {
15094
15095 // unset the property, if the specified value is undefined;
15096 // delete from $attrs (for extensions) or the target itself
15097 if (property) {
15098 delete target[propertyName];
15099 } else {
15100 delete target.$attrs[stripGlobal(name)];
15101 }
15102 } else {
15103
15104 // set the property, defining well defined properties on the fly
15105 // or simply updating them in target.$attrs (for extensions)
15106 if (property) {
15107 if (propertyName in target) {
15108 target[propertyName] = value;
15109 } else {
15110 defineProperty(target, property, value);
15111 }
15112 } else {
15113 target.$attrs[stripGlobal(name)] = value;
15114 }
15115 }
15116 };
15117
15118 /**
15119 * Returns the named property of the given element
15120 *
15121 * @param {Object} target
15122 * @param {String} name
15123 *
15124 * @return {Object}
15125 */
15126 Properties.prototype.get = function(target, name) {
15127
15128 var property = this.getProperty(target, name);
15129
15130 if (!property) {
15131 return target.$attrs[stripGlobal(name)];
15132 }
15133
15134 var propertyName = property.name;
15135
15136 // check if access to collection property and lazily initialize it
15137 if (!target[propertyName] && property.isMany) {
15138 defineProperty(target, property, []);
15139 }
15140
15141 return target[propertyName];
15142 };
15143
15144
15145 /**
15146 * Define a property on the target element
15147 *
15148 * @param {Object} target
15149 * @param {String} name
15150 * @param {Object} options
15151 */
15152 Properties.prototype.define = function(target, name, options) {
15153
15154 if (!options.writable) {
15155
15156 var value = options.value;
15157
15158 // use getters for read-only variables to support ES6 proxies
15159 // cf. https://github.com/bpmn-io/internal-docs/issues/386
15160 options = assign$1({}, options, {
15161 get: function() { return value; }
15162 });
15163
15164 delete options.value;
15165 }
15166
15167 Object.defineProperty(target, name, options);
15168 };
15169
15170
15171 /**
15172 * Define the descriptor for an element
15173 */
15174 Properties.prototype.defineDescriptor = function(target, descriptor) {
15175 this.define(target, '$descriptor', { value: descriptor });
15176 };
15177
15178 /**
15179 * Define the model for an element
15180 */
15181 Properties.prototype.defineModel = function(target, model) {
15182 this.define(target, '$model', { value: model });
15183 };
15184
15185 /**
15186 * Return property with the given name on the element.
15187 *
15188 * @param {any} target
15189 * @param {string} name
15190 *
15191 * @return {object | null} property
15192 */
15193 Properties.prototype.getProperty = function(target, name) {
15194
15195 var model = this.model;
15196
15197 var property = model.getPropertyDescriptor(target, name);
15198
15199 if (property) {
15200 return property;
15201 }
15202
15203 if (name.includes(':')) {
15204 return null;
15205 }
15206
15207 const strict = model.config.strict;
15208
15209 if (typeof strict !== 'undefined') {
15210 const error = new TypeError(`unknown property <${ name }> on <${ target.$type }>`);
15211
15212 if (strict) {
15213 throw error;
15214 } else {
15215
15216 // eslint-disable-next-line no-undef
15217 typeof console !== 'undefined' && console.warn(error);
15218 }
15219 }
15220
15221 return null;
15222 };
15223
15224 function isUndefined(val) {
15225 return typeof val === 'undefined';
15226 }
15227
15228 function defineProperty(target, property, value) {
15229 Object.defineProperty(target, property.name, {
15230 enumerable: !property.isReference,
15231 writable: true,
15232 value: value,
15233 configurable: true
15234 });
15235 }
15236
15237 function stripGlobal(name) {
15238 return name.replace(/^:/, '');
15239 }
15240
15241 // Moddle implementation /////////////////////////////////////////////////
15242
15243 /**
15244 * @class Moddle
15245 *
15246 * A model that can be used to create elements of a specific type.
15247 *
15248 * @example
15249 *
15250 * var Moddle = require('moddle');
15251 *
15252 * var pkg = {
15253 * name: 'mypackage',
15254 * prefix: 'my',
15255 * types: [
15256 * { name: 'Root' }
15257 * ]
15258 * };
15259 *
15260 * var moddle = new Moddle([pkg]);
15261 *
15262 * @param {Array<Package>} packages the packages to contain
15263 *
15264 * @param { { strict?: boolean } } [config] moddle configuration
15265 */
15266 function Moddle(packages, config = {}) {
15267
15268 this.properties = new Properties(this);
15269
15270 this.factory = new Factory(this, this.properties);
15271 this.registry = new Registry(packages, this.properties);
15272
15273 this.typeCache = {};
15274
15275 this.config = config;
15276 }
15277
15278
15279 /**
15280 * Create an instance of the specified type.
15281 *
15282 * @method Moddle#create
15283 *
15284 * @example
15285 *
15286 * var foo = moddle.create('my:Foo');
15287 * var bar = moddle.create('my:Bar', { id: 'BAR_1' });
15288 *
15289 * @param {String|Object} descriptor the type descriptor or name know to the model
15290 * @param {Object} attrs a number of attributes to initialize the model instance with
15291 * @return {Object} model instance
15292 */
15293 Moddle.prototype.create = function(descriptor, attrs) {
15294 var Type = this.getType(descriptor);
15295
15296 if (!Type) {
15297 throw new Error('unknown type <' + descriptor + '>');
15298 }
15299
15300 return new Type(attrs);
15301 };
15302
15303
15304 /**
15305 * Returns the type representing a given descriptor
15306 *
15307 * @method Moddle#getType
15308 *
15309 * @example
15310 *
15311 * var Foo = moddle.getType('my:Foo');
15312 * var foo = new Foo({ 'id' : 'FOO_1' });
15313 *
15314 * @param {String|Object} descriptor the type descriptor or name know to the model
15315 * @return {Object} the type representing the descriptor
15316 */
15317 Moddle.prototype.getType = function(descriptor) {
15318
15319 var cache = this.typeCache;
15320
15321 var name = isString(descriptor) ? descriptor : descriptor.ns.name;
15322
15323 var type = cache[name];
15324
15325 if (!type) {
15326 descriptor = this.registry.getEffectiveDescriptor(name);
15327 type = cache[name] = this.factory.createType(descriptor);
15328 }
15329
15330 return type;
15331 };
15332
15333
15334 /**
15335 * Creates an any-element type to be used within model instances.
15336 *
15337 * This can be used to create custom elements that lie outside the meta-model.
15338 * The created element contains all the meta-data required to serialize it
15339 * as part of meta-model elements.
15340 *
15341 * @method Moddle#createAny
15342 *
15343 * @example
15344 *
15345 * var foo = moddle.createAny('vendor:Foo', 'http://vendor', {
15346 * value: 'bar'
15347 * });
15348 *
15349 * var container = moddle.create('my:Container', 'http://my', {
15350 * any: [ foo ]
15351 * });
15352 *
15353 * // go ahead and serialize the stuff
15354 *
15355 *
15356 * @param {String} name the name of the element
15357 * @param {String} nsUri the namespace uri of the element
15358 * @param {Object} [properties] a map of properties to initialize the instance with
15359 * @return {Object} the any type instance
15360 */
15361 Moddle.prototype.createAny = function(name, nsUri, properties) {
15362
15363 var nameNs = parseName(name);
15364
15365 var element = {
15366 $type: name,
15367 $instanceOf: function(type) {
15368 return type === this.$type;
15369 },
15370 get: function(key) {
15371 return this[key];
15372 },
15373 set: function(key, value) {
15374 set$2(this, [ key ], value);
15375 }
15376 };
15377
15378 var descriptor = {
15379 name: name,
15380 isGeneric: true,
15381 ns: {
15382 prefix: nameNs.prefix,
15383 localName: nameNs.localName,
15384 uri: nsUri
15385 }
15386 };
15387
15388 this.properties.defineDescriptor(element, descriptor);
15389 this.properties.defineModel(element, this);
15390 this.properties.define(element, 'get', { enumerable: false, writable: true });
15391 this.properties.define(element, 'set', { enumerable: false, writable: true });
15392 this.properties.define(element, '$parent', { enumerable: false, writable: true });
15393 this.properties.define(element, '$instanceOf', { enumerable: false, writable: true });
15394
15395 forEach$1(properties, function(a, key) {
15396 if (isObject(a) && a.value !== undefined) {
15397 element[a.name] = a.value;
15398 } else {
15399 element[key] = a;
15400 }
15401 });
15402
15403 return element;
15404 };
15405
15406 /**
15407 * Returns a registered package by uri or prefix
15408 *
15409 * @return {Object} the package
15410 */
15411 Moddle.prototype.getPackage = function(uriOrPrefix) {
15412 return this.registry.getPackage(uriOrPrefix);
15413 };
15414
15415 /**
15416 * Returns a snapshot of all known packages
15417 *
15418 * @return {Object} the package
15419 */
15420 Moddle.prototype.getPackages = function() {
15421 return this.registry.getPackages();
15422 };
15423
15424 /**
15425 * Returns the descriptor for an element
15426 */
15427 Moddle.prototype.getElementDescriptor = function(element) {
15428 return element.$descriptor;
15429 };
15430
15431 /**
15432 * Returns true if the given descriptor or instance
15433 * represents the given type.
15434 *
15435 * May be applied to this, if element is omitted.
15436 */
15437 Moddle.prototype.hasType = function(element, type) {
15438 if (type === undefined) {
15439 type = element;
15440 element = this;
15441 }
15442
15443 var descriptor = element.$model.getElementDescriptor(element);
15444
15445 return (type in descriptor.allTypesByName);
15446 };
15447
15448 /**
15449 * Returns the descriptor of an elements named property
15450 */
15451 Moddle.prototype.getPropertyDescriptor = function(element, property) {
15452 return this.getElementDescriptor(element).propertiesByName[property];
15453 };
15454
15455 /**
15456 * Returns a mapped type's descriptor
15457 */
15458 Moddle.prototype.getTypeDescriptor = function(type) {
15459 return this.registry.typeMap[type];
15460 };
15461
15462 var fromCharCode = String.fromCharCode;
15463
15464 var hasOwnProperty = Object.prototype.hasOwnProperty;
15465
15466 var ENTITY_PATTERN = /&#(\d+);|&#x([0-9a-f]+);|&(\w+);/ig;
15467
15468 var ENTITY_MAPPING = {
15469 'amp': '&',
15470 'apos': '\'',
15471 'gt': '>',
15472 'lt': '<',
15473 'quot': '"'
15474 };
15475
15476 // map UPPERCASE variants of supported special chars
15477 Object.keys(ENTITY_MAPPING).forEach(function(k) {
15478 ENTITY_MAPPING[k.toUpperCase()] = ENTITY_MAPPING[k];
15479 });
15480
15481
15482 function replaceEntities(_, d, x, z) {
15483
15484 // reserved names, i.e. &nbsp;
15485 if (z) {
15486 if (hasOwnProperty.call(ENTITY_MAPPING, z)) {
15487 return ENTITY_MAPPING[z];
15488 } else {
15489
15490 // fall back to original value
15491 return '&' + z + ';';
15492 }
15493 }
15494
15495 // decimal encoded char
15496 if (d) {
15497 return fromCharCode(d);
15498 }
15499
15500 // hex encoded char
15501 return fromCharCode(parseInt(x, 16));
15502 }
15503
15504
15505 /**
15506 * A basic entity decoder that can decode a minimal
15507 * sub-set of reserved names (&amp;) as well as
15508 * hex (&#xaaf;) and decimal (&#1231;) encoded characters.
15509 *
15510 * @param {string} str
15511 *
15512 * @return {string} decoded string
15513 */
15514 function decodeEntities(s) {
15515 if (s.length > 3 && s.indexOf('&') !== -1) {
15516 return s.replace(ENTITY_PATTERN, replaceEntities);
15517 }
15518
15519 return s;
15520 }
15521
15522 var XSI_URI = 'http://www.w3.org/2001/XMLSchema-instance';
15523 var XSI_PREFIX = 'xsi';
15524 var XSI_TYPE$1 = 'xsi:type';
15525
15526 var NON_WHITESPACE_OUTSIDE_ROOT_NODE = 'non-whitespace outside of root node';
15527
15528 function error$1(msg) {
15529 return new Error(msg);
15530 }
15531
15532 function missingNamespaceForPrefix(prefix) {
15533 return 'missing namespace for prefix <' + prefix + '>';
15534 }
15535
15536 function getter(getFn) {
15537 return {
15538 'get': getFn,
15539 'enumerable': true
15540 };
15541 }
15542
15543 function cloneNsMatrix(nsMatrix) {
15544 var clone = {}, key;
15545 for (key in nsMatrix) {
15546 clone[key] = nsMatrix[key];
15547 }
15548 return clone;
15549 }
15550
15551 function uriPrefix(prefix) {
15552 return prefix + '$uri';
15553 }
15554
15555 function buildNsMatrix(nsUriToPrefix) {
15556 var nsMatrix = {},
15557 uri,
15558 prefix;
15559
15560 for (uri in nsUriToPrefix) {
15561 prefix = nsUriToPrefix[uri];
15562 nsMatrix[prefix] = prefix;
15563 nsMatrix[uriPrefix(prefix)] = uri;
15564 }
15565
15566 return nsMatrix;
15567 }
15568
15569 function noopGetContext() {
15570 return { 'line': 0, 'column': 0 };
15571 }
15572
15573 function throwFunc(err) {
15574 throw err;
15575 }
15576
15577 /**
15578 * Creates a new parser with the given options.
15579 *
15580 * @constructor
15581 *
15582 * @param {!Object<string, ?>=} options
15583 */
15584 function Parser(options) {
15585
15586 if (!this) {
15587 return new Parser(options);
15588 }
15589
15590 var proxy = options && options['proxy'];
15591
15592 var onText,
15593 onOpenTag,
15594 onCloseTag,
15595 onCDATA,
15596 onError = throwFunc,
15597 onWarning,
15598 onComment,
15599 onQuestion,
15600 onAttention;
15601
15602 var getContext = noopGetContext;
15603
15604 /**
15605 * Do we need to parse the current elements attributes for namespaces?
15606 *
15607 * @type {boolean}
15608 */
15609 var maybeNS = false;
15610
15611 /**
15612 * Do we process namespaces at all?
15613 *
15614 * @type {boolean}
15615 */
15616 var isNamespace = false;
15617
15618 /**
15619 * The caught error returned on parse end
15620 *
15621 * @type {Error}
15622 */
15623 var returnError = null;
15624
15625 /**
15626 * Should we stop parsing?
15627 *
15628 * @type {boolean}
15629 */
15630 var parseStop = false;
15631
15632 /**
15633 * A map of { uri: prefix } used by the parser.
15634 *
15635 * This map will ensure we can normalize prefixes during processing;
15636 * for each uri, only one prefix will be exposed to the handlers.
15637 *
15638 * @type {!Object<string, string>}}
15639 */
15640 var nsUriToPrefix;
15641
15642 /**
15643 * Handle parse error.
15644 *
15645 * @param {string|Error} err
15646 */
15647 function handleError(err) {
15648 if (!(err instanceof Error)) {
15649 err = error$1(err);
15650 }
15651
15652 returnError = err;
15653
15654 onError(err, getContext);
15655 }
15656
15657 /**
15658 * Handle parse error.
15659 *
15660 * @param {string|Error} err
15661 */
15662 function handleWarning(err) {
15663
15664 if (!onWarning) {
15665 return;
15666 }
15667
15668 if (!(err instanceof Error)) {
15669 err = error$1(err);
15670 }
15671
15672 onWarning(err, getContext);
15673 }
15674
15675 /**
15676 * Register parse listener.
15677 *
15678 * @param {string} name
15679 * @param {Function} cb
15680 *
15681 * @return {Parser}
15682 */
15683 this['on'] = function(name, cb) {
15684
15685 if (typeof cb !== 'function') {
15686 throw error$1('required args <name, cb>');
15687 }
15688
15689 switch (name) {
15690 case 'openTag': onOpenTag = cb; break;
15691 case 'text': onText = cb; break;
15692 case 'closeTag': onCloseTag = cb; break;
15693 case 'error': onError = cb; break;
15694 case 'warn': onWarning = cb; break;
15695 case 'cdata': onCDATA = cb; break;
15696 case 'attention': onAttention = cb; break; // <!XXXXX zzzz="eeee">
15697 case 'question': onQuestion = cb; break; // <? .... ?>
15698 case 'comment': onComment = cb; break;
15699 default:
15700 throw error$1('unsupported event: ' + name);
15701 }
15702
15703 return this;
15704 };
15705
15706 /**
15707 * Set the namespace to prefix mapping.
15708 *
15709 * @example
15710 *
15711 * parser.ns({
15712 * 'http://foo': 'foo',
15713 * 'http://bar': 'bar'
15714 * });
15715 *
15716 * @param {!Object<string, string>} nsMap
15717 *
15718 * @return {Parser}
15719 */
15720 this['ns'] = function(nsMap) {
15721
15722 if (typeof nsMap === 'undefined') {
15723 nsMap = {};
15724 }
15725
15726 if (typeof nsMap !== 'object') {
15727 throw error$1('required args <nsMap={}>');
15728 }
15729
15730 var _nsUriToPrefix = {}, k;
15731
15732 for (k in nsMap) {
15733 _nsUriToPrefix[k] = nsMap[k];
15734 }
15735
15736 // FORCE default mapping for schema instance
15737 _nsUriToPrefix[XSI_URI] = XSI_PREFIX;
15738
15739 isNamespace = true;
15740 nsUriToPrefix = _nsUriToPrefix;
15741
15742 return this;
15743 };
15744
15745 /**
15746 * Parse xml string.
15747 *
15748 * @param {string} xml
15749 *
15750 * @return {Error} returnError, if not thrown
15751 */
15752 this['parse'] = function(xml) {
15753 if (typeof xml !== 'string') {
15754 throw error$1('required args <xml=string>');
15755 }
15756
15757 returnError = null;
15758
15759 parse(xml);
15760
15761 getContext = noopGetContext;
15762 parseStop = false;
15763
15764 return returnError;
15765 };
15766
15767 /**
15768 * Stop parsing.
15769 */
15770 this['stop'] = function() {
15771 parseStop = true;
15772 };
15773
15774 /**
15775 * Parse string, invoking configured listeners on element.
15776 *
15777 * @param {string} xml
15778 */
15779 function parse(xml) {
15780 var nsMatrixStack = isNamespace ? [] : null,
15781 nsMatrix = isNamespace ? buildNsMatrix(nsUriToPrefix) : null,
15782 _nsMatrix,
15783 nodeStack = [],
15784 anonymousNsCount = 0,
15785 tagStart = false,
15786 tagEnd = false,
15787 i = 0, j = 0,
15788 x, y, q, w, v,
15789 xmlns,
15790 elementName,
15791 _elementName,
15792 elementProxy
15793 ;
15794
15795 var attrsString = '',
15796 attrsStart = 0,
15797 cachedAttrs // false = parsed with errors, null = needs parsing
15798 ;
15799
15800 /**
15801 * Parse attributes on demand and returns the parsed attributes.
15802 *
15803 * Return semantics: (1) `false` on attribute parse error,
15804 * (2) object hash on extracted attrs.
15805 *
15806 * @return {boolean|Object}
15807 */
15808 function getAttrs() {
15809 if (cachedAttrs !== null) {
15810 return cachedAttrs;
15811 }
15812
15813 var nsUri,
15814 nsUriPrefix,
15815 nsName,
15816 defaultAlias = isNamespace && nsMatrix['xmlns'],
15817 attrList = isNamespace && maybeNS ? [] : null,
15818 i = attrsStart,
15819 s = attrsString,
15820 l = s.length,
15821 hasNewMatrix,
15822 newalias,
15823 value,
15824 alias,
15825 name,
15826 attrs = {},
15827 seenAttrs = {},
15828 skipAttr,
15829 w,
15830 j;
15831
15832 parseAttr:
15833 for (; i < l; i++) {
15834 skipAttr = false;
15835 w = s.charCodeAt(i);
15836
15837 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE={ \f\n\r\t\v}
15838 continue;
15839 }
15840
15841 // wait for non whitespace character
15842 if (w < 65 || w > 122 || (w > 90 && w < 97)) {
15843 if (w !== 95 && w !== 58) { // char 95"_" 58":"
15844 handleWarning('illegal first char attribute name');
15845 skipAttr = true;
15846 }
15847 }
15848
15849 // parse attribute name
15850 for (j = i + 1; j < l; j++) {
15851 w = s.charCodeAt(j);
15852
15853 if (
15854 w > 96 && w < 123 ||
15855 w > 64 && w < 91 ||
15856 w > 47 && w < 59 ||
15857 w === 46 || // '.'
15858 w === 45 || // '-'
15859 w === 95 // '_'
15860 ) {
15861 continue;
15862 }
15863
15864 // unexpected whitespace
15865 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15866 handleWarning('missing attribute value');
15867 i = j;
15868
15869 continue parseAttr;
15870 }
15871
15872 // expected "="
15873 if (w === 61) { // "=" == 61
15874 break;
15875 }
15876
15877 handleWarning('illegal attribute name char');
15878 skipAttr = true;
15879 }
15880
15881 name = s.substring(i, j);
15882
15883 if (name === 'xmlns:xmlns') {
15884 handleWarning('illegal declaration of xmlns');
15885 skipAttr = true;
15886 }
15887
15888 w = s.charCodeAt(j + 1);
15889
15890 if (w === 34) { // '"'
15891 j = s.indexOf('"', i = j + 2);
15892
15893 if (j === -1) {
15894 j = s.indexOf('\'', i);
15895
15896 if (j !== -1) {
15897 handleWarning('attribute value quote missmatch');
15898 skipAttr = true;
15899 }
15900 }
15901
15902 } else if (w === 39) { // "'"
15903 j = s.indexOf('\'', i = j + 2);
15904
15905 if (j === -1) {
15906 j = s.indexOf('"', i);
15907
15908 if (j !== -1) {
15909 handleWarning('attribute value quote missmatch');
15910 skipAttr = true;
15911 }
15912 }
15913
15914 } else {
15915 handleWarning('missing attribute value quotes');
15916 skipAttr = true;
15917
15918 // skip to next space
15919 for (j = j + 1; j < l; j++) {
15920 w = s.charCodeAt(j + 1);
15921
15922 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15923 break;
15924 }
15925 }
15926
15927 }
15928
15929 if (j === -1) {
15930 handleWarning('missing closing quotes');
15931
15932 j = l;
15933 skipAttr = true;
15934 }
15935
15936 if (!skipAttr) {
15937 value = s.substring(i, j);
15938 }
15939
15940 i = j;
15941
15942 // ensure SPACE follows attribute
15943 // skip illegal content otherwise
15944 // example a="b"c
15945 for (; j + 1 < l; j++) {
15946 w = s.charCodeAt(j + 1);
15947
15948 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
15949 break;
15950 }
15951
15952 // FIRST ILLEGAL CHAR
15953 if (i === j) {
15954 handleWarning('illegal character after attribute end');
15955 skipAttr = true;
15956 }
15957 }
15958
15959 // advance cursor to next attribute
15960 i = j + 1;
15961
15962 if (skipAttr) {
15963 continue parseAttr;
15964 }
15965
15966 // check attribute re-declaration
15967 if (name in seenAttrs) {
15968 handleWarning('attribute <' + name + '> already defined');
15969 continue;
15970 }
15971
15972 seenAttrs[name] = true;
15973
15974 if (!isNamespace) {
15975 attrs[name] = value;
15976 continue;
15977 }
15978
15979 // try to extract namespace information
15980 if (maybeNS) {
15981 newalias = (
15982 name === 'xmlns'
15983 ? 'xmlns'
15984 : (name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:')
15985 ? name.substr(6)
15986 : null
15987 );
15988
15989 // handle xmlns(:alias) assignment
15990 if (newalias !== null) {
15991 nsUri = decodeEntities(value);
15992 nsUriPrefix = uriPrefix(newalias);
15993
15994 alias = nsUriToPrefix[nsUri];
15995
15996 if (!alias) {
15997
15998 // no prefix defined or prefix collision
15999 if (
16000 (newalias === 'xmlns') ||
16001 (nsUriPrefix in nsMatrix && nsMatrix[nsUriPrefix] !== nsUri)
16002 ) {
16003
16004 // alocate free ns prefix
16005 do {
16006 alias = 'ns' + (anonymousNsCount++);
16007 } while (typeof nsMatrix[alias] !== 'undefined');
16008 } else {
16009 alias = newalias;
16010 }
16011
16012 nsUriToPrefix[nsUri] = alias;
16013 }
16014
16015 if (nsMatrix[newalias] !== alias) {
16016 if (!hasNewMatrix) {
16017 nsMatrix = cloneNsMatrix(nsMatrix);
16018 hasNewMatrix = true;
16019 }
16020
16021 nsMatrix[newalias] = alias;
16022 if (newalias === 'xmlns') {
16023 nsMatrix[uriPrefix(alias)] = nsUri;
16024 defaultAlias = alias;
16025 }
16026
16027 nsMatrix[nsUriPrefix] = nsUri;
16028 }
16029
16030 // expose xmlns(:asd)="..." in attributes
16031 attrs[name] = value;
16032 continue;
16033 }
16034
16035 // collect attributes until all namespace
16036 // declarations are processed
16037 attrList.push(name, value);
16038 continue;
16039
16040 } /** end if (maybeNs) */
16041
16042 // handle attributes on element without
16043 // namespace declarations
16044 w = name.indexOf(':');
16045 if (w === -1) {
16046 attrs[name] = value;
16047 continue;
16048 }
16049
16050 // normalize ns attribute name
16051 if (!(nsName = nsMatrix[name.substring(0, w)])) {
16052 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
16053 continue;
16054 }
16055
16056 name = defaultAlias === nsName
16057 ? name.substr(w + 1)
16058 : nsName + name.substr(w);
16059
16060 // end: normalize ns attribute name
16061
16062 // normalize xsi:type ns attribute value
16063 if (name === XSI_TYPE$1) {
16064 w = value.indexOf(':');
16065
16066 if (w !== -1) {
16067 nsName = value.substring(0, w);
16068
16069 // handle default prefixes, i.e. xs:String gracefully
16070 nsName = nsMatrix[nsName] || nsName;
16071 value = nsName + value.substring(w);
16072 } else {
16073 value = defaultAlias + ':' + value;
16074 }
16075 }
16076
16077 // end: normalize xsi:type ns attribute value
16078
16079 attrs[name] = value;
16080 }
16081
16082
16083 // handle deferred, possibly namespaced attributes
16084 if (maybeNS) {
16085
16086 // normalize captured attributes
16087 for (i = 0, l = attrList.length; i < l; i++) {
16088
16089 name = attrList[i++];
16090 value = attrList[i];
16091
16092 w = name.indexOf(':');
16093
16094 if (w !== -1) {
16095
16096 // normalize ns attribute name
16097 if (!(nsName = nsMatrix[name.substring(0, w)])) {
16098 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
16099 continue;
16100 }
16101
16102 name = defaultAlias === nsName
16103 ? name.substr(w + 1)
16104 : nsName + name.substr(w);
16105
16106 // end: normalize ns attribute name
16107
16108 // normalize xsi:type ns attribute value
16109 if (name === XSI_TYPE$1) {
16110 w = value.indexOf(':');
16111
16112 if (w !== -1) {
16113 nsName = value.substring(0, w);
16114
16115 // handle default prefixes, i.e. xs:String gracefully
16116 nsName = nsMatrix[nsName] || nsName;
16117 value = nsName + value.substring(w);
16118 } else {
16119 value = defaultAlias + ':' + value;
16120 }
16121 }
16122
16123 // end: normalize xsi:type ns attribute value
16124 }
16125
16126 attrs[name] = value;
16127 }
16128
16129 // end: normalize captured attributes
16130 }
16131
16132 return cachedAttrs = attrs;
16133 }
16134
16135 /**
16136 * Extract the parse context { line, column, part }
16137 * from the current parser position.
16138 *
16139 * @return {Object} parse context
16140 */
16141 function getParseContext() {
16142 var splitsRe = /(\r\n|\r|\n)/g;
16143
16144 var line = 0;
16145 var column = 0;
16146 var startOfLine = 0;
16147 var endOfLine = j;
16148 var match;
16149 var data;
16150
16151 while (i >= startOfLine) {
16152
16153 match = splitsRe.exec(xml);
16154
16155 if (!match) {
16156 break;
16157 }
16158
16159 // end of line = (break idx + break chars)
16160 endOfLine = match[0].length + match.index;
16161
16162 if (endOfLine > i) {
16163 break;
16164 }
16165
16166 // advance to next line
16167 line += 1;
16168
16169 startOfLine = endOfLine;
16170 }
16171
16172 // EOF errors
16173 if (i == -1) {
16174 column = endOfLine;
16175 data = xml.substring(j);
16176 } else
16177
16178 // start errors
16179 if (j === 0) {
16180 data = xml.substring(j, i);
16181 }
16182
16183 // other errors
16184 else {
16185 column = i - startOfLine;
16186 data = (j == -1 ? xml.substring(i) : xml.substring(i, j + 1));
16187 }
16188
16189 return {
16190 'data': data,
16191 'line': line,
16192 'column': column
16193 };
16194 }
16195
16196 getContext = getParseContext;
16197
16198
16199 if (proxy) {
16200 elementProxy = Object.create({}, {
16201 'name': getter(function() {
16202 return elementName;
16203 }),
16204 'originalName': getter(function() {
16205 return _elementName;
16206 }),
16207 'attrs': getter(getAttrs),
16208 'ns': getter(function() {
16209 return nsMatrix;
16210 })
16211 });
16212 }
16213
16214 // actual parse logic
16215 while (j !== -1) {
16216
16217 if (xml.charCodeAt(j) === 60) { // "<"
16218 i = j;
16219 } else {
16220 i = xml.indexOf('<', j);
16221 }
16222
16223 // parse end
16224 if (i === -1) {
16225 if (nodeStack.length) {
16226 return handleError('unexpected end of file');
16227 }
16228
16229 if (j === 0) {
16230 return handleError('missing start tag');
16231 }
16232
16233 if (j < xml.length) {
16234 if (xml.substring(j).trim()) {
16235 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
16236 }
16237 }
16238
16239 return;
16240 }
16241
16242 // parse text
16243 if (j !== i) {
16244
16245 if (nodeStack.length) {
16246 if (onText) {
16247 onText(xml.substring(j, i), decodeEntities, getContext);
16248
16249 if (parseStop) {
16250 return;
16251 }
16252 }
16253 } else {
16254 if (xml.substring(j, i).trim()) {
16255 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
16256
16257 if (parseStop) {
16258 return;
16259 }
16260 }
16261 }
16262 }
16263
16264 w = xml.charCodeAt(i+1);
16265
16266 // parse comments + CDATA
16267 if (w === 33) { // "!"
16268 q = xml.charCodeAt(i+2);
16269
16270 // CDATA section
16271 if (q === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
16272 j = xml.indexOf(']]>', i);
16273 if (j === -1) {
16274 return handleError('unclosed cdata');
16275 }
16276
16277 if (onCDATA) {
16278 onCDATA(xml.substring(i + 9, j), getContext);
16279 if (parseStop) {
16280 return;
16281 }
16282 }
16283
16284 j += 3;
16285 continue;
16286 }
16287
16288 // comment
16289 if (q === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
16290 j = xml.indexOf('-->', i);
16291 if (j === -1) {
16292 return handleError('unclosed comment');
16293 }
16294
16295
16296 if (onComment) {
16297 onComment(xml.substring(i + 4, j), decodeEntities, getContext);
16298 if (parseStop) {
16299 return;
16300 }
16301 }
16302
16303 j += 3;
16304 continue;
16305 }
16306 }
16307
16308 // parse question <? ... ?>
16309 if (w === 63) { // "?"
16310 j = xml.indexOf('?>', i);
16311 if (j === -1) {
16312 return handleError('unclosed question');
16313 }
16314
16315 if (onQuestion) {
16316 onQuestion(xml.substring(i, j + 2), getContext);
16317 if (parseStop) {
16318 return;
16319 }
16320 }
16321
16322 j += 2;
16323 continue;
16324 }
16325
16326 // find matching closing tag for attention or standard tags
16327 // for that we must skip through attribute values
16328 // (enclosed in single or double quotes)
16329 for (x = i + 1; ; x++) {
16330 v = xml.charCodeAt(x);
16331 if (isNaN(v)) {
16332 j = -1;
16333 return handleError('unclosed tag');
16334 }
16335
16336 // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
16337 // skips the quoted string
16338 // (double quotes) does not appear in a literal enclosed by (double quotes)
16339 // (single quote) does not appear in a literal enclosed by (single quote)
16340 if (v === 34) { // '"'
16341 q = xml.indexOf('"', x + 1);
16342 x = q !== -1 ? q : x;
16343 } else if (v === 39) { // "'"
16344 q = xml.indexOf("'", x + 1);
16345 x = q !== -1 ? q : x;
16346 } else if (v === 62) { // '>'
16347 j = x;
16348 break;
16349 }
16350 }
16351
16352
16353 // parse attention <! ...>
16354 // previously comment and CDATA have already been parsed
16355 if (w === 33) { // "!"
16356
16357 if (onAttention) {
16358 onAttention(xml.substring(i, j + 1), decodeEntities, getContext);
16359 if (parseStop) {
16360 return;
16361 }
16362 }
16363
16364 j += 1;
16365 continue;
16366 }
16367
16368 // don't process attributes;
16369 // there are none
16370 cachedAttrs = {};
16371
16372 // if (xml.charCodeAt(i+1) === 47) { // </...
16373 if (w === 47) { // </...
16374 tagStart = false;
16375 tagEnd = true;
16376
16377 if (!nodeStack.length) {
16378 return handleError('missing open tag');
16379 }
16380
16381 // verify open <-> close tag match
16382 x = elementName = nodeStack.pop();
16383 q = i + 2 + x.length;
16384
16385 if (xml.substring(i + 2, q) !== x) {
16386 return handleError('closing tag mismatch');
16387 }
16388
16389 // verify chars in close tag
16390 for (; q < j; q++) {
16391 w = xml.charCodeAt(q);
16392
16393 if (w === 32 || (w > 8 && w < 14)) { // \f\n\r\t\v space
16394 continue;
16395 }
16396
16397 return handleError('close tag');
16398 }
16399
16400 } else {
16401 if (xml.charCodeAt(j - 1) === 47) { // .../>
16402 x = elementName = xml.substring(i + 1, j - 1);
16403
16404 tagStart = true;
16405 tagEnd = true;
16406
16407 } else {
16408 x = elementName = xml.substring(i + 1, j);
16409
16410 tagStart = true;
16411 tagEnd = false;
16412 }
16413
16414 if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) { // char 95"_" 58":"
16415 return handleError('illegal first char nodeName');
16416 }
16417
16418 for (q = 1, y = x.length; q < y; q++) {
16419 w = x.charCodeAt(q);
16420
16421 if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w == 46) {
16422 continue;
16423 }
16424
16425 if (w === 32 || (w < 14 && w > 8)) { // \f\n\r\t\v space
16426 elementName = x.substring(0, q);
16427
16428 // maybe there are attributes
16429 cachedAttrs = null;
16430 break;
16431 }
16432
16433 return handleError('invalid nodeName');
16434 }
16435
16436 if (!tagEnd) {
16437 nodeStack.push(elementName);
16438 }
16439 }
16440
16441 if (isNamespace) {
16442
16443 _nsMatrix = nsMatrix;
16444
16445 if (tagStart) {
16446
16447 // remember old namespace
16448 // unless we're self-closing
16449 if (!tagEnd) {
16450 nsMatrixStack.push(_nsMatrix);
16451 }
16452
16453 if (cachedAttrs === null) {
16454
16455 // quick check, whether there may be namespace
16456 // declarations on the node; if that is the case
16457 // we need to eagerly parse the node attributes
16458 if ((maybeNS = x.indexOf('xmlns', q) !== -1)) {
16459 attrsStart = q;
16460 attrsString = x;
16461
16462 getAttrs();
16463
16464 maybeNS = false;
16465 }
16466 }
16467 }
16468
16469 _elementName = elementName;
16470
16471 w = elementName.indexOf(':');
16472 if (w !== -1) {
16473 xmlns = nsMatrix[elementName.substring(0, w)];
16474
16475 // prefix given; namespace must exist
16476 if (!xmlns) {
16477 return handleError('missing namespace on <' + _elementName + '>');
16478 }
16479
16480 elementName = elementName.substr(w + 1);
16481 } else {
16482 xmlns = nsMatrix['xmlns'];
16483
16484 // if no default namespace is defined,
16485 // we'll import the element as anonymous.
16486 //
16487 // it is up to users to correct that to the document defined
16488 // targetNamespace, or whatever their undersanding of the
16489 // XML spec mandates.
16490 }
16491
16492 // adjust namespace prefixs as configured
16493 if (xmlns) {
16494 elementName = xmlns + ':' + elementName;
16495 }
16496
16497 }
16498
16499 if (tagStart) {
16500 attrsStart = q;
16501 attrsString = x;
16502
16503 if (onOpenTag) {
16504 if (proxy) {
16505 onOpenTag(elementProxy, decodeEntities, tagEnd, getContext);
16506 } else {
16507 onOpenTag(elementName, getAttrs, decodeEntities, tagEnd, getContext);
16508 }
16509
16510 if (parseStop) {
16511 return;
16512 }
16513 }
16514
16515 }
16516
16517 if (tagEnd) {
16518
16519 if (onCloseTag) {
16520 onCloseTag(proxy ? elementProxy : elementName, decodeEntities, tagStart, getContext);
16521
16522 if (parseStop) {
16523 return;
16524 }
16525 }
16526
16527 // restore old namespace
16528 if (isNamespace) {
16529 if (!tagStart) {
16530 nsMatrix = nsMatrixStack.pop();
16531 } else {
16532 nsMatrix = _nsMatrix;
16533 }
16534 }
16535 }
16536
16537 j += 1;
16538 }
16539 } /** end parse */
16540
16541 }
16542
16543 function hasLowerCaseAlias(pkg) {
16544 return pkg.xml && pkg.xml.tagAlias === 'lowerCase';
16545 }
16546
16547 var DEFAULT_NS_MAP = {
16548 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
16549 'xml': 'http://www.w3.org/XML/1998/namespace'
16550 };
16551
16552 var XSI_TYPE = 'xsi:type';
16553
16554 function serializeFormat(element) {
16555 return element.xml && element.xml.serialize;
16556 }
16557
16558 function serializeAsType(element) {
16559 return serializeFormat(element) === XSI_TYPE;
16560 }
16561
16562 function serializeAsProperty(element) {
16563 return serializeFormat(element) === 'property';
16564 }
16565
16566 function capitalize(str) {
16567 return str.charAt(0).toUpperCase() + str.slice(1);
16568 }
16569
16570 function aliasToName(aliasNs, pkg) {
16571
16572 if (!hasLowerCaseAlias(pkg)) {
16573 return aliasNs.name;
16574 }
16575
16576 return aliasNs.prefix + ':' + capitalize(aliasNs.localName);
16577 }
16578
16579 function prefixedToName(nameNs, pkg) {
16580
16581 var name = nameNs.name,
16582 localName = nameNs.localName;
16583
16584 var typePrefix = pkg.xml && pkg.xml.typePrefix;
16585
16586 if (typePrefix && localName.indexOf(typePrefix) === 0) {
16587 return nameNs.prefix + ':' + localName.slice(typePrefix.length);
16588 } else {
16589 return name;
16590 }
16591 }
16592
16593 function normalizeXsiTypeName(name, model) {
16594
16595 var nameNs = parseName(name);
16596 var pkg = model.getPackage(nameNs.prefix);
16597
16598 return prefixedToName(nameNs, pkg);
16599 }
16600
16601 function error(message) {
16602 return new Error(message);
16603 }
16604
16605 /**
16606 * Get the moddle descriptor for a given instance or type.
16607 *
16608 * @param {ModdleElement|Function} element
16609 *
16610 * @return {Object} the moddle descriptor
16611 */
16612 function getModdleDescriptor(element) {
16613 return element.$descriptor;
16614 }
16615
16616
16617 /**
16618 * A parse context.
16619 *
16620 * @class
16621 *
16622 * @param {Object} options
16623 * @param {ElementHandler} options.rootHandler the root handler for parsing a document
16624 * @param {boolean} [options.lax=false] whether or not to ignore invalid elements
16625 */
16626 function Context(options) {
16627
16628 /**
16629 * @property {ElementHandler} rootHandler
16630 */
16631
16632 /**
16633 * @property {Boolean} lax
16634 */
16635
16636 assign$1(this, options);
16637
16638 this.elementsById = {};
16639 this.references = [];
16640 this.warnings = [];
16641
16642 /**
16643 * Add an unresolved reference.
16644 *
16645 * @param {Object} reference
16646 */
16647 this.addReference = function(reference) {
16648 this.references.push(reference);
16649 };
16650
16651 /**
16652 * Add a processed element.
16653 *
16654 * @param {ModdleElement} element
16655 */
16656 this.addElement = function(element) {
16657
16658 if (!element) {
16659 throw error('expected element');
16660 }
16661
16662 var elementsById = this.elementsById;
16663
16664 var descriptor = getModdleDescriptor(element);
16665
16666 var idProperty = descriptor.idProperty,
16667 id;
16668
16669 if (idProperty) {
16670 id = element.get(idProperty.name);
16671
16672 if (id) {
16673
16674 // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
16675 if (!/^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i.test(id)) {
16676 throw new Error('illegal ID <' + id + '>');
16677 }
16678
16679 if (elementsById[id]) {
16680 throw error('duplicate ID <' + id + '>');
16681 }
16682
16683 elementsById[id] = element;
16684 }
16685 }
16686 };
16687
16688 /**
16689 * Add an import warning.
16690 *
16691 * @param {Object} warning
16692 * @param {String} warning.message
16693 * @param {Error} [warning.error]
16694 */
16695 this.addWarning = function(warning) {
16696 this.warnings.push(warning);
16697 };
16698 }
16699
16700 function BaseHandler() {}
16701
16702 BaseHandler.prototype.handleEnd = function() {};
16703 BaseHandler.prototype.handleText = function() {};
16704 BaseHandler.prototype.handleNode = function() {};
16705
16706
16707 /**
16708 * A simple pass through handler that does nothing except for
16709 * ignoring all input it receives.
16710 *
16711 * This is used to ignore unknown elements and
16712 * attributes.
16713 */
16714 function NoopHandler() { }
16715
16716 NoopHandler.prototype = Object.create(BaseHandler.prototype);
16717
16718 NoopHandler.prototype.handleNode = function() {
16719 return this;
16720 };
16721
16722 function BodyHandler() {}
16723
16724 BodyHandler.prototype = Object.create(BaseHandler.prototype);
16725
16726 BodyHandler.prototype.handleText = function(text) {
16727 this.body = (this.body || '') + text;
16728 };
16729
16730 function ReferenceHandler(property, context) {
16731 this.property = property;
16732 this.context = context;
16733 }
16734
16735 ReferenceHandler.prototype = Object.create(BodyHandler.prototype);
16736
16737 ReferenceHandler.prototype.handleNode = function(node) {
16738
16739 if (this.element) {
16740 throw error('expected no sub nodes');
16741 } else {
16742 this.element = this.createReference(node);
16743 }
16744
16745 return this;
16746 };
16747
16748 ReferenceHandler.prototype.handleEnd = function() {
16749 this.element.id = this.body;
16750 };
16751
16752 ReferenceHandler.prototype.createReference = function(node) {
16753 return {
16754 property: this.property.ns.name,
16755 id: ''
16756 };
16757 };
16758
16759 function ValueHandler(propertyDesc, element) {
16760 this.element = element;
16761 this.propertyDesc = propertyDesc;
16762 }
16763
16764 ValueHandler.prototype = Object.create(BodyHandler.prototype);
16765
16766 ValueHandler.prototype.handleEnd = function() {
16767
16768 var value = this.body || '',
16769 element = this.element,
16770 propertyDesc = this.propertyDesc;
16771
16772 value = coerceType(propertyDesc.type, value);
16773
16774 if (propertyDesc.isMany) {
16775 element.get(propertyDesc.name).push(value);
16776 } else {
16777 element.set(propertyDesc.name, value);
16778 }
16779 };
16780
16781
16782 function BaseElementHandler() {}
16783
16784 BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
16785
16786 BaseElementHandler.prototype.handleNode = function(node) {
16787 var parser = this,
16788 element = this.element;
16789
16790 if (!element) {
16791 element = this.element = this.createElement(node);
16792
16793 this.context.addElement(element);
16794 } else {
16795 parser = this.handleChild(node);
16796 }
16797
16798 return parser;
16799 };
16800
16801 /**
16802 * @class Reader.ElementHandler
16803 *
16804 */
16805 function ElementHandler(model, typeName, context) {
16806 this.model = model;
16807 this.type = model.getType(typeName);
16808 this.context = context;
16809 }
16810
16811 ElementHandler.prototype = Object.create(BaseElementHandler.prototype);
16812
16813 ElementHandler.prototype.addReference = function(reference) {
16814 this.context.addReference(reference);
16815 };
16816
16817 ElementHandler.prototype.handleText = function(text) {
16818
16819 var element = this.element,
16820 descriptor = getModdleDescriptor(element),
16821 bodyProperty = descriptor.bodyProperty;
16822
16823 if (!bodyProperty) {
16824 throw error('unexpected body text <' + text + '>');
16825 }
16826
16827 BodyHandler.prototype.handleText.call(this, text);
16828 };
16829
16830 ElementHandler.prototype.handleEnd = function() {
16831
16832 var value = this.body,
16833 element = this.element,
16834 descriptor = getModdleDescriptor(element),
16835 bodyProperty = descriptor.bodyProperty;
16836
16837 if (bodyProperty && value !== undefined) {
16838 value = coerceType(bodyProperty.type, value);
16839 element.set(bodyProperty.name, value);
16840 }
16841 };
16842
16843 /**
16844 * Create an instance of the model from the given node.
16845 *
16846 * @param {Element} node the xml node
16847 */
16848 ElementHandler.prototype.createElement = function(node) {
16849 var attributes = node.attributes,
16850 Type = this.type,
16851 descriptor = getModdleDescriptor(Type),
16852 context = this.context,
16853 instance = new Type({}),
16854 model = this.model,
16855 propNameNs;
16856
16857 forEach$1(attributes, function(value, name) {
16858
16859 var prop = descriptor.propertiesByName[name],
16860 values;
16861
16862 if (prop && prop.isReference) {
16863
16864 if (!prop.isMany) {
16865 context.addReference({
16866 element: instance,
16867 property: prop.ns.name,
16868 id: value
16869 });
16870 } else {
16871
16872 // IDREFS: parse references as whitespace-separated list
16873 values = value.split(' ');
16874
16875 forEach$1(values, function(v) {
16876 context.addReference({
16877 element: instance,
16878 property: prop.ns.name,
16879 id: v
16880 });
16881 });
16882 }
16883
16884 } else {
16885 if (prop) {
16886 value = coerceType(prop.type, value);
16887 } else
16888 if (name !== 'xmlns') {
16889 propNameNs = parseName(name, descriptor.ns.prefix);
16890
16891 // check whether attribute is defined in a well-known namespace
16892 // if that is the case we emit a warning to indicate potential misuse
16893 if (model.getPackage(propNameNs.prefix)) {
16894
16895 context.addWarning({
16896 message: 'unknown attribute <' + name + '>',
16897 element: instance,
16898 property: name,
16899 value: value
16900 });
16901 }
16902 }
16903
16904 instance.set(name, value);
16905 }
16906 });
16907
16908 return instance;
16909 };
16910
16911 ElementHandler.prototype.getPropertyForNode = function(node) {
16912
16913 var name = node.name;
16914 var nameNs = parseName(name);
16915
16916 var type = this.type,
16917 model = this.model,
16918 descriptor = getModdleDescriptor(type);
16919
16920 var propertyName = nameNs.name,
16921 property = descriptor.propertiesByName[propertyName],
16922 elementTypeName,
16923 elementType;
16924
16925 // search for properties by name first
16926
16927 if (property && !property.isAttr) {
16928
16929 if (serializeAsType(property)) {
16930 elementTypeName = node.attributes[XSI_TYPE];
16931
16932 // xsi type is optional, if it does not exists the
16933 // default type is assumed
16934 if (elementTypeName) {
16935
16936 // take possible type prefixes from XML
16937 // into account, i.e.: xsi:type="t{ActualType}"
16938 elementTypeName = normalizeXsiTypeName(elementTypeName, model);
16939
16940 elementType = model.getType(elementTypeName);
16941
16942 return assign$1({}, property, {
16943 effectiveType: getModdleDescriptor(elementType).name
16944 });
16945 }
16946 }
16947
16948 // search for properties by name first
16949 return property;
16950 }
16951
16952 var pkg = model.getPackage(nameNs.prefix);
16953
16954 if (pkg) {
16955 elementTypeName = aliasToName(nameNs, pkg);
16956 elementType = model.getType(elementTypeName);
16957
16958 // search for collection members later
16959 property = find(descriptor.properties, function(p) {
16960 return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
16961 });
16962
16963 if (property) {
16964 return assign$1({}, property, {
16965 effectiveType: getModdleDescriptor(elementType).name
16966 });
16967 }
16968 } else {
16969
16970 // parse unknown element (maybe extension)
16971 property = find(descriptor.properties, function(p) {
16972 return !p.isReference && !p.isAttribute && p.type === 'Element';
16973 });
16974
16975 if (property) {
16976 return property;
16977 }
16978 }
16979
16980 throw error('unrecognized element <' + nameNs.name + '>');
16981 };
16982
16983 ElementHandler.prototype.toString = function() {
16984 return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';
16985 };
16986
16987 ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
16988 return new ValueHandler(propertyDesc, element);
16989 };
16990
16991 ElementHandler.prototype.referenceHandler = function(propertyDesc) {
16992 return new ReferenceHandler(propertyDesc, this.context);
16993 };
16994
16995 ElementHandler.prototype.handler = function(type) {
16996 if (type === 'Element') {
16997 return new GenericElementHandler(this.model, type, this.context);
16998 } else {
16999 return new ElementHandler(this.model, type, this.context);
17000 }
17001 };
17002
17003 /**
17004 * Handle the child element parsing
17005 *
17006 * @param {Element} node the xml node
17007 */
17008 ElementHandler.prototype.handleChild = function(node) {
17009 var propertyDesc, type, element, childHandler;
17010
17011 propertyDesc = this.getPropertyForNode(node);
17012 element = this.element;
17013
17014 type = propertyDesc.effectiveType || propertyDesc.type;
17015
17016 if (isSimple(type)) {
17017 return this.valueHandler(propertyDesc, element);
17018 }
17019
17020 if (propertyDesc.isReference) {
17021 childHandler = this.referenceHandler(propertyDesc).handleNode(node);
17022 } else {
17023 childHandler = this.handler(type).handleNode(node);
17024 }
17025
17026 var newElement = childHandler.element;
17027
17028 // child handles may decide to skip elements
17029 // by not returning anything
17030 if (newElement !== undefined) {
17031
17032 if (propertyDesc.isMany) {
17033 element.get(propertyDesc.name).push(newElement);
17034 } else {
17035 element.set(propertyDesc.name, newElement);
17036 }
17037
17038 if (propertyDesc.isReference) {
17039 assign$1(newElement, {
17040 element: element
17041 });
17042
17043 this.context.addReference(newElement);
17044 } else {
17045
17046 // establish child -> parent relationship
17047 newElement.$parent = element;
17048 }
17049 }
17050
17051 return childHandler;
17052 };
17053
17054 /**
17055 * An element handler that performs special validation
17056 * to ensure the node it gets initialized with matches
17057 * the handlers type (namespace wise).
17058 *
17059 * @param {Moddle} model
17060 * @param {String} typeName
17061 * @param {Context} context
17062 */
17063 function RootElementHandler(model, typeName, context) {
17064 ElementHandler.call(this, model, typeName, context);
17065 }
17066
17067 RootElementHandler.prototype = Object.create(ElementHandler.prototype);
17068
17069 RootElementHandler.prototype.createElement = function(node) {
17070
17071 var name = node.name,
17072 nameNs = parseName(name),
17073 model = this.model,
17074 type = this.type,
17075 pkg = model.getPackage(nameNs.prefix),
17076 typeName = pkg && aliasToName(nameNs, pkg) || name;
17077
17078 // verify the correct namespace if we parse
17079 // the first element in the handler tree
17080 //
17081 // this ensures we don't mistakenly import wrong namespace elements
17082 if (!type.hasType(typeName)) {
17083 throw error('unexpected element <' + node.originalName + '>');
17084 }
17085
17086 return ElementHandler.prototype.createElement.call(this, node);
17087 };
17088
17089
17090 function GenericElementHandler(model, typeName, context) {
17091 this.model = model;
17092 this.context = context;
17093 }
17094
17095 GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
17096
17097 GenericElementHandler.prototype.createElement = function(node) {
17098
17099 var name = node.name,
17100 ns = parseName(name),
17101 prefix = ns.prefix,
17102 uri = node.ns[prefix + '$uri'],
17103 attributes = node.attributes;
17104
17105 return this.model.createAny(name, uri, attributes);
17106 };
17107
17108 GenericElementHandler.prototype.handleChild = function(node) {
17109
17110 var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
17111 element = this.element;
17112
17113 var newElement = handler.element,
17114 children;
17115
17116 if (newElement !== undefined) {
17117 children = element.$children = element.$children || [];
17118 children.push(newElement);
17119
17120 // establish child -> parent relationship
17121 newElement.$parent = element;
17122 }
17123
17124 return handler;
17125 };
17126
17127 GenericElementHandler.prototype.handleEnd = function() {
17128 if (this.body) {
17129 this.element.$body = this.body;
17130 }
17131 };
17132
17133 /**
17134 * A reader for a meta-model
17135 *
17136 * @param {Object} options
17137 * @param {Model} options.model used to read xml files
17138 * @param {Boolean} options.lax whether to make parse errors warnings
17139 */
17140 function Reader(options) {
17141
17142 if (options instanceof Moddle) {
17143 options = {
17144 model: options
17145 };
17146 }
17147
17148 assign$1(this, { lax: false }, options);
17149 }
17150
17151 /**
17152 * The fromXML result.
17153 *
17154 * @typedef {Object} ParseResult
17155 *
17156 * @property {ModdleElement} rootElement
17157 * @property {Array<Object>} references
17158 * @property {Array<Error>} warnings
17159 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
17160 */
17161
17162 /**
17163 * The fromXML result.
17164 *
17165 * @typedef {Error} ParseError
17166 *
17167 * @property {Array<Error>} warnings
17168 */
17169
17170 /**
17171 * Parse the given XML into a moddle document tree.
17172 *
17173 * @param {String} xml
17174 * @param {ElementHandler|Object} options or rootHandler
17175 *
17176 * @returns {Promise<ParseResult, ParseError>}
17177 */
17178 Reader.prototype.fromXML = function(xml, options, done) {
17179
17180 var rootHandler = options.rootHandler;
17181
17182 if (options instanceof ElementHandler) {
17183
17184 // root handler passed via (xml, { rootHandler: ElementHandler }, ...)
17185 rootHandler = options;
17186 options = {};
17187 } else {
17188 if (typeof options === 'string') {
17189
17190 // rootHandler passed via (xml, 'someString', ...)
17191 rootHandler = this.handler(options);
17192 options = {};
17193 } else if (typeof rootHandler === 'string') {
17194
17195 // rootHandler passed via (xml, { rootHandler: 'someString' }, ...)
17196 rootHandler = this.handler(rootHandler);
17197 }
17198 }
17199
17200 var model = this.model,
17201 lax = this.lax;
17202
17203 var context = new Context(assign$1({}, options, { rootHandler: rootHandler })),
17204 parser = new Parser({ proxy: true }),
17205 stack = createStack();
17206
17207 rootHandler.context = context;
17208
17209 // push root handler
17210 stack.push(rootHandler);
17211
17212
17213 /**
17214 * Handle error.
17215 *
17216 * @param {Error} err
17217 * @param {Function} getContext
17218 * @param {boolean} lax
17219 *
17220 * @return {boolean} true if handled
17221 */
17222 function handleError(err, getContext, lax) {
17223
17224 var ctx = getContext();
17225
17226 var line = ctx.line,
17227 column = ctx.column,
17228 data = ctx.data;
17229
17230 // we receive the full context data here,
17231 // for elements trim down the information
17232 // to the tag name, only
17233 if (data.charAt(0) === '<' && data.indexOf(' ') !== -1) {
17234 data = data.slice(0, data.indexOf(' ')) + '>';
17235 }
17236
17237 var message =
17238 'unparsable content ' + (data ? data + ' ' : '') + 'detected\n\t' +
17239 'line: ' + line + '\n\t' +
17240 'column: ' + column + '\n\t' +
17241 'nested error: ' + err.message;
17242
17243 if (lax) {
17244 context.addWarning({
17245 message: message,
17246 error: err
17247 });
17248
17249 return true;
17250 } else {
17251 throw error(message);
17252 }
17253 }
17254
17255 function handleWarning(err, getContext) {
17256
17257 // just like handling errors in <lax=true> mode
17258 return handleError(err, getContext, true);
17259 }
17260
17261 /**
17262 * Resolve collected references on parse end.
17263 */
17264 function resolveReferences() {
17265
17266 var elementsById = context.elementsById;
17267 var references = context.references;
17268
17269 var i, r;
17270
17271 for (i = 0; (r = references[i]); i++) {
17272 var element = r.element;
17273 var reference = elementsById[r.id];
17274 var property = getModdleDescriptor(element).propertiesByName[r.property];
17275
17276 if (!reference) {
17277 context.addWarning({
17278 message: 'unresolved reference <' + r.id + '>',
17279 element: r.element,
17280 property: r.property,
17281 value: r.id
17282 });
17283 }
17284
17285 if (property.isMany) {
17286 var collection = element.get(property.name),
17287 idx = collection.indexOf(r);
17288
17289 // we replace an existing place holder (idx != -1) or
17290 // append to the collection instead
17291 if (idx === -1) {
17292 idx = collection.length;
17293 }
17294
17295 if (!reference) {
17296
17297 // remove unresolvable reference
17298 collection.splice(idx, 1);
17299 } else {
17300
17301 // add or update reference in collection
17302 collection[idx] = reference;
17303 }
17304 } else {
17305 element.set(property.name, reference);
17306 }
17307 }
17308 }
17309
17310 function handleClose() {
17311 stack.pop().handleEnd();
17312 }
17313
17314 var PREAMBLE_START_PATTERN = /^<\?xml /i;
17315
17316 var ENCODING_PATTERN = / encoding="([^"]+)"/i;
17317
17318 var UTF_8_PATTERN = /^utf-8$/i;
17319
17320 function handleQuestion(question) {
17321
17322 if (!PREAMBLE_START_PATTERN.test(question)) {
17323 return;
17324 }
17325
17326 var match = ENCODING_PATTERN.exec(question);
17327 var encoding = match && match[1];
17328
17329 if (!encoding || UTF_8_PATTERN.test(encoding)) {
17330 return;
17331 }
17332
17333 context.addWarning({
17334 message:
17335 'unsupported document encoding <' + encoding + '>, ' +
17336 'falling back to UTF-8'
17337 });
17338 }
17339
17340 function handleOpen(node, getContext) {
17341 var handler = stack.peek();
17342
17343 try {
17344 stack.push(handler.handleNode(node));
17345 } catch (err) {
17346
17347 if (handleError(err, getContext, lax)) {
17348 stack.push(new NoopHandler());
17349 }
17350 }
17351 }
17352
17353 function handleCData(text, getContext) {
17354
17355 try {
17356 stack.peek().handleText(text);
17357 } catch (err) {
17358 handleWarning(err, getContext);
17359 }
17360 }
17361
17362 function handleText(text, getContext) {
17363
17364 // strip whitespace only nodes, i.e. before
17365 // <!CDATA[ ... ]> sections and in between tags
17366
17367 if (!text.trim()) {
17368 return;
17369 }
17370
17371 handleCData(text, getContext);
17372 }
17373
17374 var uriMap = model.getPackages().reduce(function(uriMap, p) {
17375 uriMap[p.uri] = p.prefix;
17376
17377 return uriMap;
17378 }, {
17379 'http://www.w3.org/XML/1998/namespace': 'xml' // add default xml ns
17380 });
17381 parser
17382 .ns(uriMap)
17383 .on('openTag', function(obj, decodeStr, selfClosing, getContext) {
17384
17385 // gracefully handle unparsable attributes (attrs=false)
17386 var attrs = obj.attrs || {};
17387
17388 var decodedAttrs = Object.keys(attrs).reduce(function(d, key) {
17389 var value = decodeStr(attrs[key]);
17390
17391 d[key] = value;
17392
17393 return d;
17394 }, {});
17395
17396 var node = {
17397 name: obj.name,
17398 originalName: obj.originalName,
17399 attributes: decodedAttrs,
17400 ns: obj.ns
17401 };
17402
17403 handleOpen(node, getContext);
17404 })
17405 .on('question', handleQuestion)
17406 .on('closeTag', handleClose)
17407 .on('cdata', handleCData)
17408 .on('text', function(text, decodeEntities, getContext) {
17409 handleText(decodeEntities(text), getContext);
17410 })
17411 .on('error', handleError)
17412 .on('warn', handleWarning);
17413
17414 // async XML parsing to make sure the execution environment
17415 // (node or brower) is kept responsive and that certain optimization
17416 // strategies can kick in.
17417 return new Promise(function(resolve, reject) {
17418
17419 var err;
17420
17421 try {
17422 parser.parse(xml);
17423
17424 resolveReferences();
17425 } catch (e) {
17426 err = e;
17427 }
17428
17429 var rootElement = rootHandler.element;
17430
17431 if (!err && !rootElement) {
17432 err = error('failed to parse document as <' + rootHandler.type.$descriptor.name + '>');
17433 }
17434
17435 var warnings = context.warnings;
17436 var references = context.references;
17437 var elementsById = context.elementsById;
17438
17439 if (err) {
17440 err.warnings = warnings;
17441
17442 return reject(err);
17443 } else {
17444 return resolve({
17445 rootElement: rootElement,
17446 elementsById: elementsById,
17447 references: references,
17448 warnings: warnings
17449 });
17450 }
17451 });
17452 };
17453
17454 Reader.prototype.handler = function(name) {
17455 return new RootElementHandler(this.model, name);
17456 };
17457
17458
17459 // helpers //////////////////////////
17460
17461 function createStack() {
17462 var stack = [];
17463
17464 Object.defineProperty(stack, 'peek', {
17465 value: function() {
17466 return this[this.length - 1];
17467 }
17468 });
17469
17470 return stack;
17471 }
17472
17473 var XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>\n';
17474
17475 var ESCAPE_ATTR_CHARS = /<|>|'|"|&|\n\r|\n/g;
17476 var ESCAPE_CHARS = /<|>|&/g;
17477
17478
17479 function Namespaces(parent) {
17480
17481 var prefixMap = {};
17482 var uriMap = {};
17483 var used = {};
17484
17485 var wellknown = [];
17486 var custom = [];
17487
17488 // API
17489
17490 this.byUri = function(uri) {
17491 return uriMap[uri] || (
17492 parent && parent.byUri(uri)
17493 );
17494 };
17495
17496 this.add = function(ns, isWellknown) {
17497
17498 uriMap[ns.uri] = ns;
17499
17500 if (isWellknown) {
17501 wellknown.push(ns);
17502 } else {
17503 custom.push(ns);
17504 }
17505
17506 this.mapPrefix(ns.prefix, ns.uri);
17507 };
17508
17509 this.uriByPrefix = function(prefix) {
17510 return prefixMap[prefix || 'xmlns'];
17511 };
17512
17513 this.mapPrefix = function(prefix, uri) {
17514 prefixMap[prefix || 'xmlns'] = uri;
17515 };
17516
17517 this.getNSKey = function(ns) {
17518 return (ns.prefix !== undefined) ? (ns.uri + '|' + ns.prefix) : ns.uri;
17519 };
17520
17521 this.logUsed = function(ns) {
17522
17523 var uri = ns.uri;
17524 var nsKey = this.getNSKey(ns);
17525
17526 used[nsKey] = this.byUri(uri);
17527
17528 // Inform parent recursively about the usage of this NS
17529 if (parent) {
17530 parent.logUsed(ns);
17531 }
17532 };
17533
17534 this.getUsed = function(ns) {
17535
17536 function isUsed(ns) {
17537 var nsKey = self.getNSKey(ns);
17538
17539 return used[nsKey];
17540 }
17541
17542 var self = this;
17543
17544 var allNs = [].concat(wellknown, custom);
17545
17546 return allNs.filter(isUsed);
17547 };
17548
17549 }
17550
17551 function lower(string) {
17552 return string.charAt(0).toLowerCase() + string.slice(1);
17553 }
17554
17555 function nameToAlias(name, pkg) {
17556 if (hasLowerCaseAlias(pkg)) {
17557 return lower(name);
17558 } else {
17559 return name;
17560 }
17561 }
17562
17563 function inherits(ctor, superCtor) {
17564 ctor.super_ = superCtor;
17565 ctor.prototype = Object.create(superCtor.prototype, {
17566 constructor: {
17567 value: ctor,
17568 enumerable: false,
17569 writable: true,
17570 configurable: true
17571 }
17572 });
17573 }
17574
17575 function nsName(ns) {
17576 if (isString(ns)) {
17577 return ns;
17578 } else {
17579 return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
17580 }
17581 }
17582
17583 function getNsAttrs(namespaces) {
17584
17585 return namespaces.getUsed().filter(function(ns) {
17586
17587 // do not serialize built in <xml> namespace
17588 return ns.prefix !== 'xml';
17589 }).map(function(ns) {
17590 var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
17591 return { name: name, value: ns.uri };
17592 });
17593
17594 }
17595
17596 function getElementNs(ns, descriptor) {
17597 if (descriptor.isGeneric) {
17598 return assign$1({ localName: descriptor.ns.localName }, ns);
17599 } else {
17600 return assign$1({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
17601 }
17602 }
17603
17604 function getPropertyNs(ns, descriptor) {
17605 return assign$1({ localName: descriptor.ns.localName }, ns);
17606 }
17607
17608 function getSerializableProperties(element) {
17609 var descriptor = element.$descriptor;
17610
17611 return filter(descriptor.properties, function(p) {
17612 var name = p.name;
17613
17614 if (p.isVirtual) {
17615 return false;
17616 }
17617
17618 // do not serialize defaults
17619 if (!has$1(element, name)) {
17620 return false;
17621 }
17622
17623 var value = element[name];
17624
17625 // do not serialize default equals
17626 if (value === p.default) {
17627 return false;
17628 }
17629
17630 // do not serialize null properties
17631 if (value === null) {
17632 return false;
17633 }
17634
17635 return p.isMany ? value.length : true;
17636 });
17637 }
17638
17639 var ESCAPE_ATTR_MAP = {
17640 '\n': '#10',
17641 '\n\r': '#10',
17642 '"': '#34',
17643 '\'': '#39',
17644 '<': '#60',
17645 '>': '#62',
17646 '&': '#38'
17647 };
17648
17649 var ESCAPE_MAP = {
17650 '<': 'lt',
17651 '>': 'gt',
17652 '&': 'amp'
17653 };
17654
17655 function escape(str, charPattern, replaceMap) {
17656
17657 // ensure we are handling strings here
17658 str = isString(str) ? str : '' + str;
17659
17660 return str.replace(charPattern, function(s) {
17661 return '&' + replaceMap[s] + ';';
17662 });
17663 }
17664
17665 /**
17666 * Escape a string attribute to not contain any bad values (line breaks, '"', ...)
17667 *
17668 * @param {String} str the string to escape
17669 * @return {String} the escaped string
17670 */
17671 function escapeAttr(str) {
17672 return escape(str, ESCAPE_ATTR_CHARS, ESCAPE_ATTR_MAP);
17673 }
17674
17675 function escapeBody(str) {
17676 return escape(str, ESCAPE_CHARS, ESCAPE_MAP);
17677 }
17678
17679 function filterAttributes(props) {
17680 return filter(props, function(p) { return p.isAttr; });
17681 }
17682
17683 function filterContained(props) {
17684 return filter(props, function(p) { return !p.isAttr; });
17685 }
17686
17687
17688 function ReferenceSerializer(tagName) {
17689 this.tagName = tagName;
17690 }
17691
17692 ReferenceSerializer.prototype.build = function(element) {
17693 this.element = element;
17694 return this;
17695 };
17696
17697 ReferenceSerializer.prototype.serializeTo = function(writer) {
17698 writer
17699 .appendIndent()
17700 .append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')
17701 .appendNewLine();
17702 };
17703
17704 function BodySerializer() {}
17705
17706 BodySerializer.prototype.serializeValue =
17707 BodySerializer.prototype.serializeTo = function(writer) {
17708 writer.append(
17709 this.escape
17710 ? escapeBody(this.value)
17711 : this.value
17712 );
17713 };
17714
17715 BodySerializer.prototype.build = function(prop, value) {
17716 this.value = value;
17717
17718 if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {
17719 this.escape = true;
17720 }
17721
17722 return this;
17723 };
17724
17725 function ValueSerializer(tagName) {
17726 this.tagName = tagName;
17727 }
17728
17729 inherits(ValueSerializer, BodySerializer);
17730
17731 ValueSerializer.prototype.serializeTo = function(writer) {
17732
17733 writer
17734 .appendIndent()
17735 .append('<' + this.tagName + '>');
17736
17737 this.serializeValue(writer);
17738
17739 writer
17740 .append('</' + this.tagName + '>')
17741 .appendNewLine();
17742 };
17743
17744 function ElementSerializer(parent, propertyDescriptor) {
17745 this.body = [];
17746 this.attrs = [];
17747
17748 this.parent = parent;
17749 this.propertyDescriptor = propertyDescriptor;
17750 }
17751
17752 ElementSerializer.prototype.build = function(element) {
17753 this.element = element;
17754
17755 var elementDescriptor = element.$descriptor,
17756 propertyDescriptor = this.propertyDescriptor;
17757
17758 var otherAttrs,
17759 properties;
17760
17761 var isGeneric = elementDescriptor.isGeneric;
17762
17763 if (isGeneric) {
17764 otherAttrs = this.parseGeneric(element);
17765 } else {
17766 otherAttrs = this.parseNsAttributes(element);
17767 }
17768
17769 if (propertyDescriptor) {
17770 this.ns = this.nsPropertyTagName(propertyDescriptor);
17771 } else {
17772 this.ns = this.nsTagName(elementDescriptor);
17773 }
17774
17775 // compute tag name
17776 this.tagName = this.addTagName(this.ns);
17777
17778 if (!isGeneric) {
17779 properties = getSerializableProperties(element);
17780
17781 this.parseAttributes(filterAttributes(properties));
17782 this.parseContainments(filterContained(properties));
17783 }
17784
17785 this.parseGenericAttributes(element, otherAttrs);
17786
17787 return this;
17788 };
17789
17790 ElementSerializer.prototype.nsTagName = function(descriptor) {
17791 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
17792 return getElementNs(effectiveNs, descriptor);
17793 };
17794
17795 ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
17796 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
17797 return getPropertyNs(effectiveNs, descriptor);
17798 };
17799
17800 ElementSerializer.prototype.isLocalNs = function(ns) {
17801 return ns.uri === this.ns.uri;
17802 };
17803
17804 /**
17805 * Get the actual ns attribute name for the given element.
17806 *
17807 * @param {Object} element
17808 * @param {Boolean} [element.inherited=false]
17809 *
17810 * @return {Object} nsName
17811 */
17812 ElementSerializer.prototype.nsAttributeName = function(element) {
17813
17814 var ns;
17815
17816 if (isString(element)) {
17817 ns = parseName(element);
17818 } else {
17819 ns = element.ns;
17820 }
17821
17822 // return just local name for inherited attributes
17823 if (element.inherited) {
17824 return { localName: ns.localName };
17825 }
17826
17827 // parse + log effective ns
17828 var effectiveNs = this.logNamespaceUsed(ns);
17829
17830 // LOG ACTUAL namespace use
17831 this.getNamespaces().logUsed(effectiveNs);
17832
17833 // strip prefix if same namespace like parent
17834 if (this.isLocalNs(effectiveNs)) {
17835 return { localName: ns.localName };
17836 } else {
17837 return assign$1({ localName: ns.localName }, effectiveNs);
17838 }
17839 };
17840
17841 ElementSerializer.prototype.parseGeneric = function(element) {
17842
17843 var self = this,
17844 body = this.body;
17845
17846 var attributes = [];
17847
17848 forEach$1(element, function(val, key) {
17849
17850 var nonNsAttr;
17851
17852 if (key === '$body') {
17853 body.push(new BodySerializer().build({ type: 'String' }, val));
17854 } else
17855 if (key === '$children') {
17856 forEach$1(val, function(child) {
17857 body.push(new ElementSerializer(self).build(child));
17858 });
17859 } else
17860 if (key.indexOf('$') !== 0) {
17861 nonNsAttr = self.parseNsAttribute(element, key, val);
17862
17863 if (nonNsAttr) {
17864 attributes.push({ name: key, value: val });
17865 }
17866 }
17867 });
17868
17869 return attributes;
17870 };
17871
17872 ElementSerializer.prototype.parseNsAttribute = function(element, name, value) {
17873 var model = element.$model;
17874
17875 var nameNs = parseName(name);
17876
17877 var ns;
17878
17879 // parse xmlns:foo="http://foo.bar"
17880 if (nameNs.prefix === 'xmlns') {
17881 ns = { prefix: nameNs.localName, uri: value };
17882 }
17883
17884 // parse xmlns="http://foo.bar"
17885 if (!nameNs.prefix && nameNs.localName === 'xmlns') {
17886 ns = { uri: value };
17887 }
17888
17889 if (!ns) {
17890 return {
17891 name: name,
17892 value: value
17893 };
17894 }
17895
17896 if (model && model.getPackage(value)) {
17897
17898 // register well known namespace
17899 this.logNamespace(ns, true, true);
17900 } else {
17901
17902 // log custom namespace directly as used
17903 var actualNs = this.logNamespaceUsed(ns, true);
17904
17905 this.getNamespaces().logUsed(actualNs);
17906 }
17907 };
17908
17909
17910 /**
17911 * Parse namespaces and return a list of left over generic attributes
17912 *
17913 * @param {Object} element
17914 * @return {Array<Object>}
17915 */
17916 ElementSerializer.prototype.parseNsAttributes = function(element, attrs) {
17917 var self = this;
17918
17919 var genericAttrs = element.$attrs;
17920
17921 var attributes = [];
17922
17923 // parse namespace attributes first
17924 // and log them. push non namespace attributes to a list
17925 // and process them later
17926 forEach$1(genericAttrs, function(value, name) {
17927
17928 var nonNsAttr = self.parseNsAttribute(element, name, value);
17929
17930 if (nonNsAttr) {
17931 attributes.push(nonNsAttr);
17932 }
17933 });
17934
17935 return attributes;
17936 };
17937
17938 ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
17939
17940 var self = this;
17941
17942 forEach$1(attributes, function(attr) {
17943
17944 // do not serialize xsi:type attribute
17945 // it is set manually based on the actual implementation type
17946 if (attr.name === XSI_TYPE) {
17947 return;
17948 }
17949
17950 try {
17951 self.addAttribute(self.nsAttributeName(attr.name), attr.value);
17952 } catch (e) {
17953 /* global console */
17954
17955 console.warn(
17956 'missing namespace information for ',
17957 attr.name, '=', attr.value, 'on', element,
17958 e);
17959 }
17960 });
17961 };
17962
17963 ElementSerializer.prototype.parseContainments = function(properties) {
17964
17965 var self = this,
17966 body = this.body,
17967 element = this.element;
17968
17969 forEach$1(properties, function(p) {
17970 var value = element.get(p.name),
17971 isReference = p.isReference,
17972 isMany = p.isMany;
17973
17974 if (!isMany) {
17975 value = [ value ];
17976 }
17977
17978 if (p.isBody) {
17979 body.push(new BodySerializer().build(p, value[0]));
17980 } else
17981 if (isSimple(p.type)) {
17982 forEach$1(value, function(v) {
17983 body.push(new ValueSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));
17984 });
17985 } else
17986 if (isReference) {
17987 forEach$1(value, function(v) {
17988 body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));
17989 });
17990 } else {
17991
17992 // allow serialization via type
17993 // rather than element name
17994 var asType = serializeAsType(p),
17995 asProperty = serializeAsProperty(p);
17996
17997 forEach$1(value, function(v) {
17998 var serializer;
17999
18000 if (asType) {
18001 serializer = new TypeSerializer(self, p);
18002 } else
18003 if (asProperty) {
18004 serializer = new ElementSerializer(self, p);
18005 } else {
18006 serializer = new ElementSerializer(self);
18007 }
18008
18009 body.push(serializer.build(v));
18010 });
18011 }
18012 });
18013 };
18014
18015 ElementSerializer.prototype.getNamespaces = function(local) {
18016
18017 var namespaces = this.namespaces,
18018 parent = this.parent,
18019 parentNamespaces;
18020
18021 if (!namespaces) {
18022 parentNamespaces = parent && parent.getNamespaces();
18023
18024 if (local || !parentNamespaces) {
18025 this.namespaces = namespaces = new Namespaces(parentNamespaces);
18026 } else {
18027 namespaces = parentNamespaces;
18028 }
18029 }
18030
18031 return namespaces;
18032 };
18033
18034 ElementSerializer.prototype.logNamespace = function(ns, wellknown, local) {
18035 var namespaces = this.getNamespaces(local);
18036
18037 var nsUri = ns.uri,
18038 nsPrefix = ns.prefix;
18039
18040 var existing = namespaces.byUri(nsUri);
18041
18042 if (!existing || local) {
18043 namespaces.add(ns, wellknown);
18044 }
18045
18046 namespaces.mapPrefix(nsPrefix, nsUri);
18047
18048 return ns;
18049 };
18050
18051 ElementSerializer.prototype.logNamespaceUsed = function(ns, local) {
18052 var element = this.element,
18053 model = element.$model,
18054 namespaces = this.getNamespaces(local);
18055
18056 // ns may be
18057 //
18058 // * prefix only
18059 // * prefix:uri
18060 // * localName only
18061
18062 var prefix = ns.prefix,
18063 uri = ns.uri,
18064 newPrefix, idx,
18065 wellknownUri;
18066
18067 // handle anonymous namespaces (elementForm=unqualified), cf. #23
18068 if (!prefix && !uri) {
18069 return { localName: ns.localName };
18070 }
18071
18072 wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri;
18073
18074 uri = uri || wellknownUri || namespaces.uriByPrefix(prefix);
18075
18076 if (!uri) {
18077 throw new Error('no namespace uri given for prefix <' + prefix + '>');
18078 }
18079
18080 ns = namespaces.byUri(uri);
18081
18082 if (!ns) {
18083 newPrefix = prefix;
18084 idx = 1;
18085
18086 // find a prefix that is not mapped yet
18087 while (namespaces.uriByPrefix(newPrefix)) {
18088 newPrefix = prefix + '_' + idx++;
18089 }
18090
18091 ns = this.logNamespace({ prefix: newPrefix, uri: uri }, wellknownUri === uri);
18092 }
18093
18094 if (prefix) {
18095 namespaces.mapPrefix(prefix, uri);
18096 }
18097
18098 return ns;
18099 };
18100
18101 ElementSerializer.prototype.parseAttributes = function(properties) {
18102 var self = this,
18103 element = this.element;
18104
18105 forEach$1(properties, function(p) {
18106
18107 var value = element.get(p.name);
18108
18109 if (p.isReference) {
18110
18111 if (!p.isMany) {
18112 value = value.id;
18113 }
18114 else {
18115 var values = [];
18116 forEach$1(value, function(v) {
18117 values.push(v.id);
18118 });
18119
18120 // IDREFS is a whitespace-separated list of references.
18121 value = values.join(' ');
18122 }
18123
18124 }
18125
18126 self.addAttribute(self.nsAttributeName(p), value);
18127 });
18128 };
18129
18130 ElementSerializer.prototype.addTagName = function(nsTagName) {
18131 var actualNs = this.logNamespaceUsed(nsTagName);
18132
18133 this.getNamespaces().logUsed(actualNs);
18134
18135 return nsName(nsTagName);
18136 };
18137
18138 ElementSerializer.prototype.addAttribute = function(name, value) {
18139 var attrs = this.attrs;
18140
18141 if (isString(value)) {
18142 value = escapeAttr(value);
18143 }
18144
18145 // de-duplicate attributes
18146 // https://github.com/bpmn-io/moddle-xml/issues/66
18147 var idx = findIndex(attrs, function(element) {
18148 return (
18149 element.name.localName === name.localName &&
18150 element.name.uri === name.uri &&
18151 element.name.prefix === name.prefix
18152 );
18153 });
18154
18155 var attr = { name: name, value: value };
18156
18157 if (idx !== -1) {
18158 attrs.splice(idx, 1, attr);
18159 } else {
18160 attrs.push(attr);
18161 }
18162 };
18163
18164 ElementSerializer.prototype.serializeAttributes = function(writer) {
18165 var attrs = this.attrs,
18166 namespaces = this.namespaces;
18167
18168 if (namespaces) {
18169 attrs = getNsAttrs(namespaces).concat(attrs);
18170 }
18171
18172 forEach$1(attrs, function(a) {
18173 writer
18174 .append(' ')
18175 .append(nsName(a.name)).append('="').append(a.value).append('"');
18176 });
18177 };
18178
18179 ElementSerializer.prototype.serializeTo = function(writer) {
18180 var firstBody = this.body[0],
18181 indent = firstBody && firstBody.constructor !== BodySerializer;
18182
18183 writer
18184 .appendIndent()
18185 .append('<' + this.tagName);
18186
18187 this.serializeAttributes(writer);
18188
18189 writer.append(firstBody ? '>' : ' />');
18190
18191 if (firstBody) {
18192
18193 if (indent) {
18194 writer
18195 .appendNewLine()
18196 .indent();
18197 }
18198
18199 forEach$1(this.body, function(b) {
18200 b.serializeTo(writer);
18201 });
18202
18203 if (indent) {
18204 writer
18205 .unindent()
18206 .appendIndent();
18207 }
18208
18209 writer.append('</' + this.tagName + '>');
18210 }
18211
18212 writer.appendNewLine();
18213 };
18214
18215 /**
18216 * A serializer for types that handles serialization of data types
18217 */
18218 function TypeSerializer(parent, propertyDescriptor) {
18219 ElementSerializer.call(this, parent, propertyDescriptor);
18220 }
18221
18222 inherits(TypeSerializer, ElementSerializer);
18223
18224 TypeSerializer.prototype.parseNsAttributes = function(element) {
18225
18226 // extracted attributes
18227 var attributes = ElementSerializer.prototype.parseNsAttributes.call(this, element);
18228
18229 var descriptor = element.$descriptor;
18230
18231 // only serialize xsi:type if necessary
18232 if (descriptor.name === this.propertyDescriptor.type) {
18233 return attributes;
18234 }
18235
18236 var typeNs = this.typeNs = this.nsTagName(descriptor);
18237 this.getNamespaces().logUsed(this.typeNs);
18238
18239 // add xsi:type attribute to represent the elements
18240 // actual type
18241
18242 var pkg = element.$model.getPackage(typeNs.uri),
18243 typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';
18244
18245 this.addAttribute(
18246 this.nsAttributeName(XSI_TYPE),
18247 (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName
18248 );
18249
18250 return attributes;
18251 };
18252
18253 TypeSerializer.prototype.isLocalNs = function(ns) {
18254 return ns.uri === (this.typeNs || this.ns).uri;
18255 };
18256
18257 function SavingWriter() {
18258 this.value = '';
18259
18260 this.write = function(str) {
18261 this.value += str;
18262 };
18263 }
18264
18265 function FormatingWriter(out, format) {
18266
18267 var indent = [ '' ];
18268
18269 this.append = function(str) {
18270 out.write(str);
18271
18272 return this;
18273 };
18274
18275 this.appendNewLine = function() {
18276 if (format) {
18277 out.write('\n');
18278 }
18279
18280 return this;
18281 };
18282
18283 this.appendIndent = function() {
18284 if (format) {
18285 out.write(indent.join(' '));
18286 }
18287
18288 return this;
18289 };
18290
18291 this.indent = function() {
18292 indent.push('');
18293 return this;
18294 };
18295
18296 this.unindent = function() {
18297 indent.pop();
18298 return this;
18299 };
18300 }
18301
18302 /**
18303 * A writer for meta-model backed document trees
18304 *
18305 * @param {Object} options output options to pass into the writer
18306 */
18307 function Writer(options) {
18308
18309 options = assign$1({ format: false, preamble: true }, options || {});
18310
18311 function toXML(tree, writer) {
18312 var internalWriter = writer || new SavingWriter();
18313 var formatingWriter = new FormatingWriter(internalWriter, options.format);
18314
18315 if (options.preamble) {
18316 formatingWriter.append(XML_PREAMBLE);
18317 }
18318
18319 new ElementSerializer().build(tree).serializeTo(formatingWriter);
18320
18321 if (!writer) {
18322 return internalWriter.value;
18323 }
18324 }
18325
18326 return {
18327 toXML: toXML
18328 };
18329 }
18330
18331 /**
18332 * A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
18333 *
18334 * @class BpmnModdle
18335 * @extends Moddle
18336 *
18337 * @param {Object|Array} packages to use for instantiating the model
18338 * @param {Object} [options] additional options to pass over
18339 */
18340 function BpmnModdle(packages, options) {
18341 Moddle.call(this, packages, options);
18342 }
18343
18344 BpmnModdle.prototype = Object.create(Moddle.prototype);
18345
18346 /**
18347 * The fromXML result.
18348 *
18349 * @typedef {Object} ParseResult
18350 *
18351 * @property {ModdleElement} rootElement
18352 * @property {Array<Object>} references
18353 * @property {Array<Error>} warnings
18354 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
18355 */
18356
18357 /**
18358 * The fromXML error.
18359 *
18360 * @typedef {Error} ParseError
18361 *
18362 * @property {Array<Error>} warnings
18363 */
18364
18365 /**
18366 * Instantiates a BPMN model tree from a given xml string.
18367 *
18368 * @param {String} xmlStr
18369 * @param {String} [typeName='bpmn:Definitions'] name of the root element
18370 * @param {Object} [options] options to pass to the underlying reader
18371 *
18372 * @returns {Promise<ParseResult, ParseError>}
18373 */
18374 BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options) {
18375
18376 if (!isString(typeName)) {
18377 options = typeName;
18378 typeName = 'bpmn:Definitions';
18379 }
18380
18381 var reader = new Reader(assign$1({ model: this, lax: true }, options));
18382 var rootHandler = reader.handler(typeName);
18383
18384 return reader.fromXML(xmlStr, rootHandler);
18385 };
18386
18387
18388 /**
18389 * The toXML result.
18390 *
18391 * @typedef {Object} SerializationResult
18392 *
18393 * @property {String} xml
18394 */
18395
18396 /**
18397 * Serializes a BPMN 2.0 object tree to XML.
18398 *
18399 * @param {String} element the root element, typically an instance of `bpmn:Definitions`
18400 * @param {Object} [options] to pass to the underlying writer
18401 *
18402 * @returns {Promise<SerializationResult, Error>}
18403 */
18404 BpmnModdle.prototype.toXML = function(element, options) {
18405
18406 var writer = new Writer(options);
18407
18408 return new Promise(function(resolve, reject) {
18409 try {
18410 var result = writer.toXML(element);
18411
18412 return resolve({
18413 xml: result
18414 });
18415 } catch (err) {
18416 return reject(err);
18417 }
18418 });
18419 };
18420
18421 var name$5 = "BPMN20";
18422 var uri$5 = "http://www.omg.org/spec/BPMN/20100524/MODEL";
18423 var prefix$5 = "bpmn";
18424 var associations$5 = [
18425 ];
18426 var types$5 = [
18427 {
18428 name: "Interface",
18429 superClass: [
18430 "RootElement"
18431 ],
18432 properties: [
18433 {
18434 name: "name",
18435 isAttr: true,
18436 type: "String"
18437 },
18438 {
18439 name: "operations",
18440 type: "Operation",
18441 isMany: true
18442 },
18443 {
18444 name: "implementationRef",
18445 isAttr: true,
18446 type: "String"
18447 }
18448 ]
18449 },
18450 {
18451 name: "Operation",
18452 superClass: [
18453 "BaseElement"
18454 ],
18455 properties: [
18456 {
18457 name: "name",
18458 isAttr: true,
18459 type: "String"
18460 },
18461 {
18462 name: "inMessageRef",
18463 type: "Message",
18464 isReference: true
18465 },
18466 {
18467 name: "outMessageRef",
18468 type: "Message",
18469 isReference: true
18470 },
18471 {
18472 name: "errorRef",
18473 type: "Error",
18474 isMany: true,
18475 isReference: true
18476 },
18477 {
18478 name: "implementationRef",
18479 isAttr: true,
18480 type: "String"
18481 }
18482 ]
18483 },
18484 {
18485 name: "EndPoint",
18486 superClass: [
18487 "RootElement"
18488 ]
18489 },
18490 {
18491 name: "Auditing",
18492 superClass: [
18493 "BaseElement"
18494 ]
18495 },
18496 {
18497 name: "GlobalTask",
18498 superClass: [
18499 "CallableElement"
18500 ],
18501 properties: [
18502 {
18503 name: "resources",
18504 type: "ResourceRole",
18505 isMany: true
18506 }
18507 ]
18508 },
18509 {
18510 name: "Monitoring",
18511 superClass: [
18512 "BaseElement"
18513 ]
18514 },
18515 {
18516 name: "Performer",
18517 superClass: [
18518 "ResourceRole"
18519 ]
18520 },
18521 {
18522 name: "Process",
18523 superClass: [
18524 "FlowElementsContainer",
18525 "CallableElement"
18526 ],
18527 properties: [
18528 {
18529 name: "processType",
18530 type: "ProcessType",
18531 isAttr: true
18532 },
18533 {
18534 name: "isClosed",
18535 isAttr: true,
18536 type: "Boolean"
18537 },
18538 {
18539 name: "auditing",
18540 type: "Auditing"
18541 },
18542 {
18543 name: "monitoring",
18544 type: "Monitoring"
18545 },
18546 {
18547 name: "properties",
18548 type: "Property",
18549 isMany: true
18550 },
18551 {
18552 name: "laneSets",
18553 isMany: true,
18554 replaces: "FlowElementsContainer#laneSets",
18555 type: "LaneSet"
18556 },
18557 {
18558 name: "flowElements",
18559 isMany: true,
18560 replaces: "FlowElementsContainer#flowElements",
18561 type: "FlowElement"
18562 },
18563 {
18564 name: "artifacts",
18565 type: "Artifact",
18566 isMany: true
18567 },
18568 {
18569 name: "resources",
18570 type: "ResourceRole",
18571 isMany: true
18572 },
18573 {
18574 name: "correlationSubscriptions",
18575 type: "CorrelationSubscription",
18576 isMany: true
18577 },
18578 {
18579 name: "supports",
18580 type: "Process",
18581 isMany: true,
18582 isReference: true
18583 },
18584 {
18585 name: "definitionalCollaborationRef",
18586 type: "Collaboration",
18587 isAttr: true,
18588 isReference: true
18589 },
18590 {
18591 name: "isExecutable",
18592 isAttr: true,
18593 type: "Boolean"
18594 }
18595 ]
18596 },
18597 {
18598 name: "LaneSet",
18599 superClass: [
18600 "BaseElement"
18601 ],
18602 properties: [
18603 {
18604 name: "lanes",
18605 type: "Lane",
18606 isMany: true
18607 },
18608 {
18609 name: "name",
18610 isAttr: true,
18611 type: "String"
18612 }
18613 ]
18614 },
18615 {
18616 name: "Lane",
18617 superClass: [
18618 "BaseElement"
18619 ],
18620 properties: [
18621 {
18622 name: "name",
18623 isAttr: true,
18624 type: "String"
18625 },
18626 {
18627 name: "partitionElementRef",
18628 type: "BaseElement",
18629 isAttr: true,
18630 isReference: true
18631 },
18632 {
18633 name: "partitionElement",
18634 type: "BaseElement"
18635 },
18636 {
18637 name: "flowNodeRef",
18638 type: "FlowNode",
18639 isMany: true,
18640 isReference: true
18641 },
18642 {
18643 name: "childLaneSet",
18644 type: "LaneSet",
18645 xml: {
18646 serialize: "xsi:type"
18647 }
18648 }
18649 ]
18650 },
18651 {
18652 name: "GlobalManualTask",
18653 superClass: [
18654 "GlobalTask"
18655 ]
18656 },
18657 {
18658 name: "ManualTask",
18659 superClass: [
18660 "Task"
18661 ]
18662 },
18663 {
18664 name: "UserTask",
18665 superClass: [
18666 "Task"
18667 ],
18668 properties: [
18669 {
18670 name: "renderings",
18671 type: "Rendering",
18672 isMany: true
18673 },
18674 {
18675 name: "implementation",
18676 isAttr: true,
18677 type: "String"
18678 }
18679 ]
18680 },
18681 {
18682 name: "Rendering",
18683 superClass: [
18684 "BaseElement"
18685 ]
18686 },
18687 {
18688 name: "HumanPerformer",
18689 superClass: [
18690 "Performer"
18691 ]
18692 },
18693 {
18694 name: "PotentialOwner",
18695 superClass: [
18696 "HumanPerformer"
18697 ]
18698 },
18699 {
18700 name: "GlobalUserTask",
18701 superClass: [
18702 "GlobalTask"
18703 ],
18704 properties: [
18705 {
18706 name: "implementation",
18707 isAttr: true,
18708 type: "String"
18709 },
18710 {
18711 name: "renderings",
18712 type: "Rendering",
18713 isMany: true
18714 }
18715 ]
18716 },
18717 {
18718 name: "Gateway",
18719 isAbstract: true,
18720 superClass: [
18721 "FlowNode"
18722 ],
18723 properties: [
18724 {
18725 name: "gatewayDirection",
18726 type: "GatewayDirection",
18727 "default": "Unspecified",
18728 isAttr: true
18729 }
18730 ]
18731 },
18732 {
18733 name: "EventBasedGateway",
18734 superClass: [
18735 "Gateway"
18736 ],
18737 properties: [
18738 {
18739 name: "instantiate",
18740 "default": false,
18741 isAttr: true,
18742 type: "Boolean"
18743 },
18744 {
18745 name: "eventGatewayType",
18746 type: "EventBasedGatewayType",
18747 isAttr: true,
18748 "default": "Exclusive"
18749 }
18750 ]
18751 },
18752 {
18753 name: "ComplexGateway",
18754 superClass: [
18755 "Gateway"
18756 ],
18757 properties: [
18758 {
18759 name: "activationCondition",
18760 type: "Expression",
18761 xml: {
18762 serialize: "xsi:type"
18763 }
18764 },
18765 {
18766 name: "default",
18767 type: "SequenceFlow",
18768 isAttr: true,
18769 isReference: true
18770 }
18771 ]
18772 },
18773 {
18774 name: "ExclusiveGateway",
18775 superClass: [
18776 "Gateway"
18777 ],
18778 properties: [
18779 {
18780 name: "default",
18781 type: "SequenceFlow",
18782 isAttr: true,
18783 isReference: true
18784 }
18785 ]
18786 },
18787 {
18788 name: "InclusiveGateway",
18789 superClass: [
18790 "Gateway"
18791 ],
18792 properties: [
18793 {
18794 name: "default",
18795 type: "SequenceFlow",
18796 isAttr: true,
18797 isReference: true
18798 }
18799 ]
18800 },
18801 {
18802 name: "ParallelGateway",
18803 superClass: [
18804 "Gateway"
18805 ]
18806 },
18807 {
18808 name: "RootElement",
18809 isAbstract: true,
18810 superClass: [
18811 "BaseElement"
18812 ]
18813 },
18814 {
18815 name: "Relationship",
18816 superClass: [
18817 "BaseElement"
18818 ],
18819 properties: [
18820 {
18821 name: "type",
18822 isAttr: true,
18823 type: "String"
18824 },
18825 {
18826 name: "direction",
18827 type: "RelationshipDirection",
18828 isAttr: true
18829 },
18830 {
18831 name: "source",
18832 isMany: true,
18833 isReference: true,
18834 type: "Element"
18835 },
18836 {
18837 name: "target",
18838 isMany: true,
18839 isReference: true,
18840 type: "Element"
18841 }
18842 ]
18843 },
18844 {
18845 name: "BaseElement",
18846 isAbstract: true,
18847 properties: [
18848 {
18849 name: "id",
18850 isAttr: true,
18851 type: "String",
18852 isId: true
18853 },
18854 {
18855 name: "documentation",
18856 type: "Documentation",
18857 isMany: true
18858 },
18859 {
18860 name: "extensionDefinitions",
18861 type: "ExtensionDefinition",
18862 isMany: true,
18863 isReference: true
18864 },
18865 {
18866 name: "extensionElements",
18867 type: "ExtensionElements"
18868 }
18869 ]
18870 },
18871 {
18872 name: "Extension",
18873 properties: [
18874 {
18875 name: "mustUnderstand",
18876 "default": false,
18877 isAttr: true,
18878 type: "Boolean"
18879 },
18880 {
18881 name: "definition",
18882 type: "ExtensionDefinition",
18883 isAttr: true,
18884 isReference: true
18885 }
18886 ]
18887 },
18888 {
18889 name: "ExtensionDefinition",
18890 properties: [
18891 {
18892 name: "name",
18893 isAttr: true,
18894 type: "String"
18895 },
18896 {
18897 name: "extensionAttributeDefinitions",
18898 type: "ExtensionAttributeDefinition",
18899 isMany: true
18900 }
18901 ]
18902 },
18903 {
18904 name: "ExtensionAttributeDefinition",
18905 properties: [
18906 {
18907 name: "name",
18908 isAttr: true,
18909 type: "String"
18910 },
18911 {
18912 name: "type",
18913 isAttr: true,
18914 type: "String"
18915 },
18916 {
18917 name: "isReference",
18918 "default": false,
18919 isAttr: true,
18920 type: "Boolean"
18921 },
18922 {
18923 name: "extensionDefinition",
18924 type: "ExtensionDefinition",
18925 isAttr: true,
18926 isReference: true
18927 }
18928 ]
18929 },
18930 {
18931 name: "ExtensionElements",
18932 properties: [
18933 {
18934 name: "valueRef",
18935 isAttr: true,
18936 isReference: true,
18937 type: "Element"
18938 },
18939 {
18940 name: "values",
18941 type: "Element",
18942 isMany: true
18943 },
18944 {
18945 name: "extensionAttributeDefinition",
18946 type: "ExtensionAttributeDefinition",
18947 isAttr: true,
18948 isReference: true
18949 }
18950 ]
18951 },
18952 {
18953 name: "Documentation",
18954 superClass: [
18955 "BaseElement"
18956 ],
18957 properties: [
18958 {
18959 name: "text",
18960 type: "String",
18961 isBody: true
18962 },
18963 {
18964 name: "textFormat",
18965 "default": "text/plain",
18966 isAttr: true,
18967 type: "String"
18968 }
18969 ]
18970 },
18971 {
18972 name: "Event",
18973 isAbstract: true,
18974 superClass: [
18975 "FlowNode",
18976 "InteractionNode"
18977 ],
18978 properties: [
18979 {
18980 name: "properties",
18981 type: "Property",
18982 isMany: true
18983 }
18984 ]
18985 },
18986 {
18987 name: "IntermediateCatchEvent",
18988 superClass: [
18989 "CatchEvent"
18990 ]
18991 },
18992 {
18993 name: "IntermediateThrowEvent",
18994 superClass: [
18995 "ThrowEvent"
18996 ]
18997 },
18998 {
18999 name: "EndEvent",
19000 superClass: [
19001 "ThrowEvent"
19002 ]
19003 },
19004 {
19005 name: "StartEvent",
19006 superClass: [
19007 "CatchEvent"
19008 ],
19009 properties: [
19010 {
19011 name: "isInterrupting",
19012 "default": true,
19013 isAttr: true,
19014 type: "Boolean"
19015 }
19016 ]
19017 },
19018 {
19019 name: "ThrowEvent",
19020 isAbstract: true,
19021 superClass: [
19022 "Event"
19023 ],
19024 properties: [
19025 {
19026 name: "dataInputs",
19027 type: "DataInput",
19028 isMany: true
19029 },
19030 {
19031 name: "dataInputAssociations",
19032 type: "DataInputAssociation",
19033 isMany: true
19034 },
19035 {
19036 name: "inputSet",
19037 type: "InputSet"
19038 },
19039 {
19040 name: "eventDefinitions",
19041 type: "EventDefinition",
19042 isMany: true
19043 },
19044 {
19045 name: "eventDefinitionRef",
19046 type: "EventDefinition",
19047 isMany: true,
19048 isReference: true
19049 }
19050 ]
19051 },
19052 {
19053 name: "CatchEvent",
19054 isAbstract: true,
19055 superClass: [
19056 "Event"
19057 ],
19058 properties: [
19059 {
19060 name: "parallelMultiple",
19061 isAttr: true,
19062 type: "Boolean",
19063 "default": false
19064 },
19065 {
19066 name: "dataOutputs",
19067 type: "DataOutput",
19068 isMany: true
19069 },
19070 {
19071 name: "dataOutputAssociations",
19072 type: "DataOutputAssociation",
19073 isMany: true
19074 },
19075 {
19076 name: "outputSet",
19077 type: "OutputSet"
19078 },
19079 {
19080 name: "eventDefinitions",
19081 type: "EventDefinition",
19082 isMany: true
19083 },
19084 {
19085 name: "eventDefinitionRef",
19086 type: "EventDefinition",
19087 isMany: true,
19088 isReference: true
19089 }
19090 ]
19091 },
19092 {
19093 name: "BoundaryEvent",
19094 superClass: [
19095 "CatchEvent"
19096 ],
19097 properties: [
19098 {
19099 name: "cancelActivity",
19100 "default": true,
19101 isAttr: true,
19102 type: "Boolean"
19103 },
19104 {
19105 name: "attachedToRef",
19106 type: "Activity",
19107 isAttr: true,
19108 isReference: true
19109 }
19110 ]
19111 },
19112 {
19113 name: "EventDefinition",
19114 isAbstract: true,
19115 superClass: [
19116 "RootElement"
19117 ]
19118 },
19119 {
19120 name: "CancelEventDefinition",
19121 superClass: [
19122 "EventDefinition"
19123 ]
19124 },
19125 {
19126 name: "ErrorEventDefinition",
19127 superClass: [
19128 "EventDefinition"
19129 ],
19130 properties: [
19131 {
19132 name: "errorRef",
19133 type: "Error",
19134 isAttr: true,
19135 isReference: true
19136 }
19137 ]
19138 },
19139 {
19140 name: "TerminateEventDefinition",
19141 superClass: [
19142 "EventDefinition"
19143 ]
19144 },
19145 {
19146 name: "EscalationEventDefinition",
19147 superClass: [
19148 "EventDefinition"
19149 ],
19150 properties: [
19151 {
19152 name: "escalationRef",
19153 type: "Escalation",
19154 isAttr: true,
19155 isReference: true
19156 }
19157 ]
19158 },
19159 {
19160 name: "Escalation",
19161 properties: [
19162 {
19163 name: "structureRef",
19164 type: "ItemDefinition",
19165 isAttr: true,
19166 isReference: true
19167 },
19168 {
19169 name: "name",
19170 isAttr: true,
19171 type: "String"
19172 },
19173 {
19174 name: "escalationCode",
19175 isAttr: true,
19176 type: "String"
19177 }
19178 ],
19179 superClass: [
19180 "RootElement"
19181 ]
19182 },
19183 {
19184 name: "CompensateEventDefinition",
19185 superClass: [
19186 "EventDefinition"
19187 ],
19188 properties: [
19189 {
19190 name: "waitForCompletion",
19191 isAttr: true,
19192 type: "Boolean",
19193 "default": true
19194 },
19195 {
19196 name: "activityRef",
19197 type: "Activity",
19198 isAttr: true,
19199 isReference: true
19200 }
19201 ]
19202 },
19203 {
19204 name: "TimerEventDefinition",
19205 superClass: [
19206 "EventDefinition"
19207 ],
19208 properties: [
19209 {
19210 name: "timeDate",
19211 type: "Expression",
19212 xml: {
19213 serialize: "xsi:type"
19214 }
19215 },
19216 {
19217 name: "timeCycle",
19218 type: "Expression",
19219 xml: {
19220 serialize: "xsi:type"
19221 }
19222 },
19223 {
19224 name: "timeDuration",
19225 type: "Expression",
19226 xml: {
19227 serialize: "xsi:type"
19228 }
19229 }
19230 ]
19231 },
19232 {
19233 name: "LinkEventDefinition",
19234 superClass: [
19235 "EventDefinition"
19236 ],
19237 properties: [
19238 {
19239 name: "name",
19240 isAttr: true,
19241 type: "String"
19242 },
19243 {
19244 name: "target",
19245 type: "LinkEventDefinition",
19246 isReference: true
19247 },
19248 {
19249 name: "source",
19250 type: "LinkEventDefinition",
19251 isMany: true,
19252 isReference: true
19253 }
19254 ]
19255 },
19256 {
19257 name: "MessageEventDefinition",
19258 superClass: [
19259 "EventDefinition"
19260 ],
19261 properties: [
19262 {
19263 name: "messageRef",
19264 type: "Message",
19265 isAttr: true,
19266 isReference: true
19267 },
19268 {
19269 name: "operationRef",
19270 type: "Operation",
19271 isAttr: true,
19272 isReference: true
19273 }
19274 ]
19275 },
19276 {
19277 name: "ConditionalEventDefinition",
19278 superClass: [
19279 "EventDefinition"
19280 ],
19281 properties: [
19282 {
19283 name: "condition",
19284 type: "Expression",
19285 xml: {
19286 serialize: "xsi:type"
19287 }
19288 }
19289 ]
19290 },
19291 {
19292 name: "SignalEventDefinition",
19293 superClass: [
19294 "EventDefinition"
19295 ],
19296 properties: [
19297 {
19298 name: "signalRef",
19299 type: "Signal",
19300 isAttr: true,
19301 isReference: true
19302 }
19303 ]
19304 },
19305 {
19306 name: "Signal",
19307 superClass: [
19308 "RootElement"
19309 ],
19310 properties: [
19311 {
19312 name: "structureRef",
19313 type: "ItemDefinition",
19314 isAttr: true,
19315 isReference: true
19316 },
19317 {
19318 name: "name",
19319 isAttr: true,
19320 type: "String"
19321 }
19322 ]
19323 },
19324 {
19325 name: "ImplicitThrowEvent",
19326 superClass: [
19327 "ThrowEvent"
19328 ]
19329 },
19330 {
19331 name: "DataState",
19332 superClass: [
19333 "BaseElement"
19334 ],
19335 properties: [
19336 {
19337 name: "name",
19338 isAttr: true,
19339 type: "String"
19340 }
19341 ]
19342 },
19343 {
19344 name: "ItemAwareElement",
19345 superClass: [
19346 "BaseElement"
19347 ],
19348 properties: [
19349 {
19350 name: "itemSubjectRef",
19351 type: "ItemDefinition",
19352 isAttr: true,
19353 isReference: true
19354 },
19355 {
19356 name: "dataState",
19357 type: "DataState"
19358 }
19359 ]
19360 },
19361 {
19362 name: "DataAssociation",
19363 superClass: [
19364 "BaseElement"
19365 ],
19366 properties: [
19367 {
19368 name: "sourceRef",
19369 type: "ItemAwareElement",
19370 isMany: true,
19371 isReference: true
19372 },
19373 {
19374 name: "targetRef",
19375 type: "ItemAwareElement",
19376 isReference: true
19377 },
19378 {
19379 name: "transformation",
19380 type: "FormalExpression",
19381 xml: {
19382 serialize: "property"
19383 }
19384 },
19385 {
19386 name: "assignment",
19387 type: "Assignment",
19388 isMany: true
19389 }
19390 ]
19391 },
19392 {
19393 name: "DataInput",
19394 superClass: [
19395 "ItemAwareElement"
19396 ],
19397 properties: [
19398 {
19399 name: "name",
19400 isAttr: true,
19401 type: "String"
19402 },
19403 {
19404 name: "isCollection",
19405 "default": false,
19406 isAttr: true,
19407 type: "Boolean"
19408 },
19409 {
19410 name: "inputSetRef",
19411 type: "InputSet",
19412 isMany: true,
19413 isVirtual: true,
19414 isReference: true
19415 },
19416 {
19417 name: "inputSetWithOptional",
19418 type: "InputSet",
19419 isMany: true,
19420 isVirtual: true,
19421 isReference: true
19422 },
19423 {
19424 name: "inputSetWithWhileExecuting",
19425 type: "InputSet",
19426 isMany: true,
19427 isVirtual: true,
19428 isReference: true
19429 }
19430 ]
19431 },
19432 {
19433 name: "DataOutput",
19434 superClass: [
19435 "ItemAwareElement"
19436 ],
19437 properties: [
19438 {
19439 name: "name",
19440 isAttr: true,
19441 type: "String"
19442 },
19443 {
19444 name: "isCollection",
19445 "default": false,
19446 isAttr: true,
19447 type: "Boolean"
19448 },
19449 {
19450 name: "outputSetRef",
19451 type: "OutputSet",
19452 isMany: true,
19453 isVirtual: true,
19454 isReference: true
19455 },
19456 {
19457 name: "outputSetWithOptional",
19458 type: "OutputSet",
19459 isMany: true,
19460 isVirtual: true,
19461 isReference: true
19462 },
19463 {
19464 name: "outputSetWithWhileExecuting",
19465 type: "OutputSet",
19466 isMany: true,
19467 isVirtual: true,
19468 isReference: true
19469 }
19470 ]
19471 },
19472 {
19473 name: "InputSet",
19474 superClass: [
19475 "BaseElement"
19476 ],
19477 properties: [
19478 {
19479 name: "name",
19480 isAttr: true,
19481 type: "String"
19482 },
19483 {
19484 name: "dataInputRefs",
19485 type: "DataInput",
19486 isMany: true,
19487 isReference: true
19488 },
19489 {
19490 name: "optionalInputRefs",
19491 type: "DataInput",
19492 isMany: true,
19493 isReference: true
19494 },
19495 {
19496 name: "whileExecutingInputRefs",
19497 type: "DataInput",
19498 isMany: true,
19499 isReference: true
19500 },
19501 {
19502 name: "outputSetRefs",
19503 type: "OutputSet",
19504 isMany: true,
19505 isReference: true
19506 }
19507 ]
19508 },
19509 {
19510 name: "OutputSet",
19511 superClass: [
19512 "BaseElement"
19513 ],
19514 properties: [
19515 {
19516 name: "dataOutputRefs",
19517 type: "DataOutput",
19518 isMany: true,
19519 isReference: true
19520 },
19521 {
19522 name: "name",
19523 isAttr: true,
19524 type: "String"
19525 },
19526 {
19527 name: "inputSetRefs",
19528 type: "InputSet",
19529 isMany: true,
19530 isReference: true
19531 },
19532 {
19533 name: "optionalOutputRefs",
19534 type: "DataOutput",
19535 isMany: true,
19536 isReference: true
19537 },
19538 {
19539 name: "whileExecutingOutputRefs",
19540 type: "DataOutput",
19541 isMany: true,
19542 isReference: true
19543 }
19544 ]
19545 },
19546 {
19547 name: "Property",
19548 superClass: [
19549 "ItemAwareElement"
19550 ],
19551 properties: [
19552 {
19553 name: "name",
19554 isAttr: true,
19555 type: "String"
19556 }
19557 ]
19558 },
19559 {
19560 name: "DataInputAssociation",
19561 superClass: [
19562 "DataAssociation"
19563 ]
19564 },
19565 {
19566 name: "DataOutputAssociation",
19567 superClass: [
19568 "DataAssociation"
19569 ]
19570 },
19571 {
19572 name: "InputOutputSpecification",
19573 superClass: [
19574 "BaseElement"
19575 ],
19576 properties: [
19577 {
19578 name: "dataInputs",
19579 type: "DataInput",
19580 isMany: true
19581 },
19582 {
19583 name: "dataOutputs",
19584 type: "DataOutput",
19585 isMany: true
19586 },
19587 {
19588 name: "inputSets",
19589 type: "InputSet",
19590 isMany: true
19591 },
19592 {
19593 name: "outputSets",
19594 type: "OutputSet",
19595 isMany: true
19596 }
19597 ]
19598 },
19599 {
19600 name: "DataObject",
19601 superClass: [
19602 "FlowElement",
19603 "ItemAwareElement"
19604 ],
19605 properties: [
19606 {
19607 name: "isCollection",
19608 "default": false,
19609 isAttr: true,
19610 type: "Boolean"
19611 }
19612 ]
19613 },
19614 {
19615 name: "InputOutputBinding",
19616 properties: [
19617 {
19618 name: "inputDataRef",
19619 type: "InputSet",
19620 isAttr: true,
19621 isReference: true
19622 },
19623 {
19624 name: "outputDataRef",
19625 type: "OutputSet",
19626 isAttr: true,
19627 isReference: true
19628 },
19629 {
19630 name: "operationRef",
19631 type: "Operation",
19632 isAttr: true,
19633 isReference: true
19634 }
19635 ]
19636 },
19637 {
19638 name: "Assignment",
19639 superClass: [
19640 "BaseElement"
19641 ],
19642 properties: [
19643 {
19644 name: "from",
19645 type: "Expression",
19646 xml: {
19647 serialize: "xsi:type"
19648 }
19649 },
19650 {
19651 name: "to",
19652 type: "Expression",
19653 xml: {
19654 serialize: "xsi:type"
19655 }
19656 }
19657 ]
19658 },
19659 {
19660 name: "DataStore",
19661 superClass: [
19662 "RootElement",
19663 "ItemAwareElement"
19664 ],
19665 properties: [
19666 {
19667 name: "name",
19668 isAttr: true,
19669 type: "String"
19670 },
19671 {
19672 name: "capacity",
19673 isAttr: true,
19674 type: "Integer"
19675 },
19676 {
19677 name: "isUnlimited",
19678 "default": true,
19679 isAttr: true,
19680 type: "Boolean"
19681 }
19682 ]
19683 },
19684 {
19685 name: "DataStoreReference",
19686 superClass: [
19687 "ItemAwareElement",
19688 "FlowElement"
19689 ],
19690 properties: [
19691 {
19692 name: "dataStoreRef",
19693 type: "DataStore",
19694 isAttr: true,
19695 isReference: true
19696 }
19697 ]
19698 },
19699 {
19700 name: "DataObjectReference",
19701 superClass: [
19702 "ItemAwareElement",
19703 "FlowElement"
19704 ],
19705 properties: [
19706 {
19707 name: "dataObjectRef",
19708 type: "DataObject",
19709 isAttr: true,
19710 isReference: true
19711 }
19712 ]
19713 },
19714 {
19715 name: "ConversationLink",
19716 superClass: [
19717 "BaseElement"
19718 ],
19719 properties: [
19720 {
19721 name: "sourceRef",
19722 type: "InteractionNode",
19723 isAttr: true,
19724 isReference: true
19725 },
19726 {
19727 name: "targetRef",
19728 type: "InteractionNode",
19729 isAttr: true,
19730 isReference: true
19731 },
19732 {
19733 name: "name",
19734 isAttr: true,
19735 type: "String"
19736 }
19737 ]
19738 },
19739 {
19740 name: "ConversationAssociation",
19741 superClass: [
19742 "BaseElement"
19743 ],
19744 properties: [
19745 {
19746 name: "innerConversationNodeRef",
19747 type: "ConversationNode",
19748 isAttr: true,
19749 isReference: true
19750 },
19751 {
19752 name: "outerConversationNodeRef",
19753 type: "ConversationNode",
19754 isAttr: true,
19755 isReference: true
19756 }
19757 ]
19758 },
19759 {
19760 name: "CallConversation",
19761 superClass: [
19762 "ConversationNode"
19763 ],
19764 properties: [
19765 {
19766 name: "calledCollaborationRef",
19767 type: "Collaboration",
19768 isAttr: true,
19769 isReference: true
19770 },
19771 {
19772 name: "participantAssociations",
19773 type: "ParticipantAssociation",
19774 isMany: true
19775 }
19776 ]
19777 },
19778 {
19779 name: "Conversation",
19780 superClass: [
19781 "ConversationNode"
19782 ]
19783 },
19784 {
19785 name: "SubConversation",
19786 superClass: [
19787 "ConversationNode"
19788 ],
19789 properties: [
19790 {
19791 name: "conversationNodes",
19792 type: "ConversationNode",
19793 isMany: true
19794 }
19795 ]
19796 },
19797 {
19798 name: "ConversationNode",
19799 isAbstract: true,
19800 superClass: [
19801 "InteractionNode",
19802 "BaseElement"
19803 ],
19804 properties: [
19805 {
19806 name: "name",
19807 isAttr: true,
19808 type: "String"
19809 },
19810 {
19811 name: "participantRef",
19812 type: "Participant",
19813 isMany: true,
19814 isReference: true
19815 },
19816 {
19817 name: "messageFlowRefs",
19818 type: "MessageFlow",
19819 isMany: true,
19820 isReference: true
19821 },
19822 {
19823 name: "correlationKeys",
19824 type: "CorrelationKey",
19825 isMany: true
19826 }
19827 ]
19828 },
19829 {
19830 name: "GlobalConversation",
19831 superClass: [
19832 "Collaboration"
19833 ]
19834 },
19835 {
19836 name: "PartnerEntity",
19837 superClass: [
19838 "RootElement"
19839 ],
19840 properties: [
19841 {
19842 name: "name",
19843 isAttr: true,
19844 type: "String"
19845 },
19846 {
19847 name: "participantRef",
19848 type: "Participant",
19849 isMany: true,
19850 isReference: true
19851 }
19852 ]
19853 },
19854 {
19855 name: "PartnerRole",
19856 superClass: [
19857 "RootElement"
19858 ],
19859 properties: [
19860 {
19861 name: "name",
19862 isAttr: true,
19863 type: "String"
19864 },
19865 {
19866 name: "participantRef",
19867 type: "Participant",
19868 isMany: true,
19869 isReference: true
19870 }
19871 ]
19872 },
19873 {
19874 name: "CorrelationProperty",
19875 superClass: [
19876 "RootElement"
19877 ],
19878 properties: [
19879 {
19880 name: "correlationPropertyRetrievalExpression",
19881 type: "CorrelationPropertyRetrievalExpression",
19882 isMany: true
19883 },
19884 {
19885 name: "name",
19886 isAttr: true,
19887 type: "String"
19888 },
19889 {
19890 name: "type",
19891 type: "ItemDefinition",
19892 isAttr: true,
19893 isReference: true
19894 }
19895 ]
19896 },
19897 {
19898 name: "Error",
19899 superClass: [
19900 "RootElement"
19901 ],
19902 properties: [
19903 {
19904 name: "structureRef",
19905 type: "ItemDefinition",
19906 isAttr: true,
19907 isReference: true
19908 },
19909 {
19910 name: "name",
19911 isAttr: true,
19912 type: "String"
19913 },
19914 {
19915 name: "errorCode",
19916 isAttr: true,
19917 type: "String"
19918 }
19919 ]
19920 },
19921 {
19922 name: "CorrelationKey",
19923 superClass: [
19924 "BaseElement"
19925 ],
19926 properties: [
19927 {
19928 name: "correlationPropertyRef",
19929 type: "CorrelationProperty",
19930 isMany: true,
19931 isReference: true
19932 },
19933 {
19934 name: "name",
19935 isAttr: true,
19936 type: "String"
19937 }
19938 ]
19939 },
19940 {
19941 name: "Expression",
19942 superClass: [
19943 "BaseElement"
19944 ],
19945 isAbstract: false,
19946 properties: [
19947 {
19948 name: "body",
19949 isBody: true,
19950 type: "String"
19951 }
19952 ]
19953 },
19954 {
19955 name: "FormalExpression",
19956 superClass: [
19957 "Expression"
19958 ],
19959 properties: [
19960 {
19961 name: "language",
19962 isAttr: true,
19963 type: "String"
19964 },
19965 {
19966 name: "evaluatesToTypeRef",
19967 type: "ItemDefinition",
19968 isAttr: true,
19969 isReference: true
19970 }
19971 ]
19972 },
19973 {
19974 name: "Message",
19975 superClass: [
19976 "RootElement"
19977 ],
19978 properties: [
19979 {
19980 name: "name",
19981 isAttr: true,
19982 type: "String"
19983 },
19984 {
19985 name: "itemRef",
19986 type: "ItemDefinition",
19987 isAttr: true,
19988 isReference: true
19989 }
19990 ]
19991 },
19992 {
19993 name: "ItemDefinition",
19994 superClass: [
19995 "RootElement"
19996 ],
19997 properties: [
19998 {
19999 name: "itemKind",
20000 type: "ItemKind",
20001 isAttr: true
20002 },
20003 {
20004 name: "structureRef",
20005 isAttr: true,
20006 type: "String"
20007 },
20008 {
20009 name: "isCollection",
20010 "default": false,
20011 isAttr: true,
20012 type: "Boolean"
20013 },
20014 {
20015 name: "import",
20016 type: "Import",
20017 isAttr: true,
20018 isReference: true
20019 }
20020 ]
20021 },
20022 {
20023 name: "FlowElement",
20024 isAbstract: true,
20025 superClass: [
20026 "BaseElement"
20027 ],
20028 properties: [
20029 {
20030 name: "name",
20031 isAttr: true,
20032 type: "String"
20033 },
20034 {
20035 name: "auditing",
20036 type: "Auditing"
20037 },
20038 {
20039 name: "monitoring",
20040 type: "Monitoring"
20041 },
20042 {
20043 name: "categoryValueRef",
20044 type: "CategoryValue",
20045 isMany: true,
20046 isReference: true
20047 }
20048 ]
20049 },
20050 {
20051 name: "SequenceFlow",
20052 superClass: [
20053 "FlowElement"
20054 ],
20055 properties: [
20056 {
20057 name: "isImmediate",
20058 isAttr: true,
20059 type: "Boolean"
20060 },
20061 {
20062 name: "conditionExpression",
20063 type: "Expression",
20064 xml: {
20065 serialize: "xsi:type"
20066 }
20067 },
20068 {
20069 name: "sourceRef",
20070 type: "FlowNode",
20071 isAttr: true,
20072 isReference: true
20073 },
20074 {
20075 name: "targetRef",
20076 type: "FlowNode",
20077 isAttr: true,
20078 isReference: true
20079 }
20080 ]
20081 },
20082 {
20083 name: "FlowElementsContainer",
20084 isAbstract: true,
20085 superClass: [
20086 "BaseElement"
20087 ],
20088 properties: [
20089 {
20090 name: "laneSets",
20091 type: "LaneSet",
20092 isMany: true
20093 },
20094 {
20095 name: "flowElements",
20096 type: "FlowElement",
20097 isMany: true
20098 }
20099 ]
20100 },
20101 {
20102 name: "CallableElement",
20103 isAbstract: true,
20104 superClass: [
20105 "RootElement"
20106 ],
20107 properties: [
20108 {
20109 name: "name",
20110 isAttr: true,
20111 type: "String"
20112 },
20113 {
20114 name: "ioSpecification",
20115 type: "InputOutputSpecification",
20116 xml: {
20117 serialize: "property"
20118 }
20119 },
20120 {
20121 name: "supportedInterfaceRef",
20122 type: "Interface",
20123 isMany: true,
20124 isReference: true
20125 },
20126 {
20127 name: "ioBinding",
20128 type: "InputOutputBinding",
20129 isMany: true,
20130 xml: {
20131 serialize: "property"
20132 }
20133 }
20134 ]
20135 },
20136 {
20137 name: "FlowNode",
20138 isAbstract: true,
20139 superClass: [
20140 "FlowElement"
20141 ],
20142 properties: [
20143 {
20144 name: "incoming",
20145 type: "SequenceFlow",
20146 isMany: true,
20147 isReference: true
20148 },
20149 {
20150 name: "outgoing",
20151 type: "SequenceFlow",
20152 isMany: true,
20153 isReference: true
20154 },
20155 {
20156 name: "lanes",
20157 type: "Lane",
20158 isMany: true,
20159 isVirtual: true,
20160 isReference: true
20161 }
20162 ]
20163 },
20164 {
20165 name: "CorrelationPropertyRetrievalExpression",
20166 superClass: [
20167 "BaseElement"
20168 ],
20169 properties: [
20170 {
20171 name: "messagePath",
20172 type: "FormalExpression"
20173 },
20174 {
20175 name: "messageRef",
20176 type: "Message",
20177 isAttr: true,
20178 isReference: true
20179 }
20180 ]
20181 },
20182 {
20183 name: "CorrelationPropertyBinding",
20184 superClass: [
20185 "BaseElement"
20186 ],
20187 properties: [
20188 {
20189 name: "dataPath",
20190 type: "FormalExpression"
20191 },
20192 {
20193 name: "correlationPropertyRef",
20194 type: "CorrelationProperty",
20195 isAttr: true,
20196 isReference: true
20197 }
20198 ]
20199 },
20200 {
20201 name: "Resource",
20202 superClass: [
20203 "RootElement"
20204 ],
20205 properties: [
20206 {
20207 name: "name",
20208 isAttr: true,
20209 type: "String"
20210 },
20211 {
20212 name: "resourceParameters",
20213 type: "ResourceParameter",
20214 isMany: true
20215 }
20216 ]
20217 },
20218 {
20219 name: "ResourceParameter",
20220 superClass: [
20221 "BaseElement"
20222 ],
20223 properties: [
20224 {
20225 name: "name",
20226 isAttr: true,
20227 type: "String"
20228 },
20229 {
20230 name: "isRequired",
20231 isAttr: true,
20232 type: "Boolean"
20233 },
20234 {
20235 name: "type",
20236 type: "ItemDefinition",
20237 isAttr: true,
20238 isReference: true
20239 }
20240 ]
20241 },
20242 {
20243 name: "CorrelationSubscription",
20244 superClass: [
20245 "BaseElement"
20246 ],
20247 properties: [
20248 {
20249 name: "correlationKeyRef",
20250 type: "CorrelationKey",
20251 isAttr: true,
20252 isReference: true
20253 },
20254 {
20255 name: "correlationPropertyBinding",
20256 type: "CorrelationPropertyBinding",
20257 isMany: true
20258 }
20259 ]
20260 },
20261 {
20262 name: "MessageFlow",
20263 superClass: [
20264 "BaseElement"
20265 ],
20266 properties: [
20267 {
20268 name: "name",
20269 isAttr: true,
20270 type: "String"
20271 },
20272 {
20273 name: "sourceRef",
20274 type: "InteractionNode",
20275 isAttr: true,
20276 isReference: true
20277 },
20278 {
20279 name: "targetRef",
20280 type: "InteractionNode",
20281 isAttr: true,
20282 isReference: true
20283 },
20284 {
20285 name: "messageRef",
20286 type: "Message",
20287 isAttr: true,
20288 isReference: true
20289 }
20290 ]
20291 },
20292 {
20293 name: "MessageFlowAssociation",
20294 superClass: [
20295 "BaseElement"
20296 ],
20297 properties: [
20298 {
20299 name: "innerMessageFlowRef",
20300 type: "MessageFlow",
20301 isAttr: true,
20302 isReference: true
20303 },
20304 {
20305 name: "outerMessageFlowRef",
20306 type: "MessageFlow",
20307 isAttr: true,
20308 isReference: true
20309 }
20310 ]
20311 },
20312 {
20313 name: "InteractionNode",
20314 isAbstract: true,
20315 properties: [
20316 {
20317 name: "incomingConversationLinks",
20318 type: "ConversationLink",
20319 isMany: true,
20320 isVirtual: true,
20321 isReference: true
20322 },
20323 {
20324 name: "outgoingConversationLinks",
20325 type: "ConversationLink",
20326 isMany: true,
20327 isVirtual: true,
20328 isReference: true
20329 }
20330 ]
20331 },
20332 {
20333 name: "Participant",
20334 superClass: [
20335 "InteractionNode",
20336 "BaseElement"
20337 ],
20338 properties: [
20339 {
20340 name: "name",
20341 isAttr: true,
20342 type: "String"
20343 },
20344 {
20345 name: "interfaceRef",
20346 type: "Interface",
20347 isMany: true,
20348 isReference: true
20349 },
20350 {
20351 name: "participantMultiplicity",
20352 type: "ParticipantMultiplicity"
20353 },
20354 {
20355 name: "endPointRefs",
20356 type: "EndPoint",
20357 isMany: true,
20358 isReference: true
20359 },
20360 {
20361 name: "processRef",
20362 type: "Process",
20363 isAttr: true,
20364 isReference: true
20365 }
20366 ]
20367 },
20368 {
20369 name: "ParticipantAssociation",
20370 superClass: [
20371 "BaseElement"
20372 ],
20373 properties: [
20374 {
20375 name: "innerParticipantRef",
20376 type: "Participant",
20377 isAttr: true,
20378 isReference: true
20379 },
20380 {
20381 name: "outerParticipantRef",
20382 type: "Participant",
20383 isAttr: true,
20384 isReference: true
20385 }
20386 ]
20387 },
20388 {
20389 name: "ParticipantMultiplicity",
20390 properties: [
20391 {
20392 name: "minimum",
20393 "default": 0,
20394 isAttr: true,
20395 type: "Integer"
20396 },
20397 {
20398 name: "maximum",
20399 "default": 1,
20400 isAttr: true,
20401 type: "Integer"
20402 }
20403 ],
20404 superClass: [
20405 "BaseElement"
20406 ]
20407 },
20408 {
20409 name: "Collaboration",
20410 superClass: [
20411 "RootElement"
20412 ],
20413 properties: [
20414 {
20415 name: "name",
20416 isAttr: true,
20417 type: "String"
20418 },
20419 {
20420 name: "isClosed",
20421 isAttr: true,
20422 type: "Boolean"
20423 },
20424 {
20425 name: "participants",
20426 type: "Participant",
20427 isMany: true
20428 },
20429 {
20430 name: "messageFlows",
20431 type: "MessageFlow",
20432 isMany: true
20433 },
20434 {
20435 name: "artifacts",
20436 type: "Artifact",
20437 isMany: true
20438 },
20439 {
20440 name: "conversations",
20441 type: "ConversationNode",
20442 isMany: true
20443 },
20444 {
20445 name: "conversationAssociations",
20446 type: "ConversationAssociation"
20447 },
20448 {
20449 name: "participantAssociations",
20450 type: "ParticipantAssociation",
20451 isMany: true
20452 },
20453 {
20454 name: "messageFlowAssociations",
20455 type: "MessageFlowAssociation",
20456 isMany: true
20457 },
20458 {
20459 name: "correlationKeys",
20460 type: "CorrelationKey",
20461 isMany: true
20462 },
20463 {
20464 name: "choreographyRef",
20465 type: "Choreography",
20466 isMany: true,
20467 isReference: true
20468 },
20469 {
20470 name: "conversationLinks",
20471 type: "ConversationLink",
20472 isMany: true
20473 }
20474 ]
20475 },
20476 {
20477 name: "ChoreographyActivity",
20478 isAbstract: true,
20479 superClass: [
20480 "FlowNode"
20481 ],
20482 properties: [
20483 {
20484 name: "participantRef",
20485 type: "Participant",
20486 isMany: true,
20487 isReference: true
20488 },
20489 {
20490 name: "initiatingParticipantRef",
20491 type: "Participant",
20492 isAttr: true,
20493 isReference: true
20494 },
20495 {
20496 name: "correlationKeys",
20497 type: "CorrelationKey",
20498 isMany: true
20499 },
20500 {
20501 name: "loopType",
20502 type: "ChoreographyLoopType",
20503 "default": "None",
20504 isAttr: true
20505 }
20506 ]
20507 },
20508 {
20509 name: "CallChoreography",
20510 superClass: [
20511 "ChoreographyActivity"
20512 ],
20513 properties: [
20514 {
20515 name: "calledChoreographyRef",
20516 type: "Choreography",
20517 isAttr: true,
20518 isReference: true
20519 },
20520 {
20521 name: "participantAssociations",
20522 type: "ParticipantAssociation",
20523 isMany: true
20524 }
20525 ]
20526 },
20527 {
20528 name: "SubChoreography",
20529 superClass: [
20530 "ChoreographyActivity",
20531 "FlowElementsContainer"
20532 ],
20533 properties: [
20534 {
20535 name: "artifacts",
20536 type: "Artifact",
20537 isMany: true
20538 }
20539 ]
20540 },
20541 {
20542 name: "ChoreographyTask",
20543 superClass: [
20544 "ChoreographyActivity"
20545 ],
20546 properties: [
20547 {
20548 name: "messageFlowRef",
20549 type: "MessageFlow",
20550 isMany: true,
20551 isReference: true
20552 }
20553 ]
20554 },
20555 {
20556 name: "Choreography",
20557 superClass: [
20558 "Collaboration",
20559 "FlowElementsContainer"
20560 ]
20561 },
20562 {
20563 name: "GlobalChoreographyTask",
20564 superClass: [
20565 "Choreography"
20566 ],
20567 properties: [
20568 {
20569 name: "initiatingParticipantRef",
20570 type: "Participant",
20571 isAttr: true,
20572 isReference: true
20573 }
20574 ]
20575 },
20576 {
20577 name: "TextAnnotation",
20578 superClass: [
20579 "Artifact"
20580 ],
20581 properties: [
20582 {
20583 name: "text",
20584 type: "String"
20585 },
20586 {
20587 name: "textFormat",
20588 "default": "text/plain",
20589 isAttr: true,
20590 type: "String"
20591 }
20592 ]
20593 },
20594 {
20595 name: "Group",
20596 superClass: [
20597 "Artifact"
20598 ],
20599 properties: [
20600 {
20601 name: "categoryValueRef",
20602 type: "CategoryValue",
20603 isAttr: true,
20604 isReference: true
20605 }
20606 ]
20607 },
20608 {
20609 name: "Association",
20610 superClass: [
20611 "Artifact"
20612 ],
20613 properties: [
20614 {
20615 name: "associationDirection",
20616 type: "AssociationDirection",
20617 isAttr: true
20618 },
20619 {
20620 name: "sourceRef",
20621 type: "BaseElement",
20622 isAttr: true,
20623 isReference: true
20624 },
20625 {
20626 name: "targetRef",
20627 type: "BaseElement",
20628 isAttr: true,
20629 isReference: true
20630 }
20631 ]
20632 },
20633 {
20634 name: "Category",
20635 superClass: [
20636 "RootElement"
20637 ],
20638 properties: [
20639 {
20640 name: "categoryValue",
20641 type: "CategoryValue",
20642 isMany: true
20643 },
20644 {
20645 name: "name",
20646 isAttr: true,
20647 type: "String"
20648 }
20649 ]
20650 },
20651 {
20652 name: "Artifact",
20653 isAbstract: true,
20654 superClass: [
20655 "BaseElement"
20656 ]
20657 },
20658 {
20659 name: "CategoryValue",
20660 superClass: [
20661 "BaseElement"
20662 ],
20663 properties: [
20664 {
20665 name: "categorizedFlowElements",
20666 type: "FlowElement",
20667 isMany: true,
20668 isVirtual: true,
20669 isReference: true
20670 },
20671 {
20672 name: "value",
20673 isAttr: true,
20674 type: "String"
20675 }
20676 ]
20677 },
20678 {
20679 name: "Activity",
20680 isAbstract: true,
20681 superClass: [
20682 "FlowNode"
20683 ],
20684 properties: [
20685 {
20686 name: "isForCompensation",
20687 "default": false,
20688 isAttr: true,
20689 type: "Boolean"
20690 },
20691 {
20692 name: "default",
20693 type: "SequenceFlow",
20694 isAttr: true,
20695 isReference: true
20696 },
20697 {
20698 name: "ioSpecification",
20699 type: "InputOutputSpecification",
20700 xml: {
20701 serialize: "property"
20702 }
20703 },
20704 {
20705 name: "boundaryEventRefs",
20706 type: "BoundaryEvent",
20707 isMany: true,
20708 isReference: true
20709 },
20710 {
20711 name: "properties",
20712 type: "Property",
20713 isMany: true
20714 },
20715 {
20716 name: "dataInputAssociations",
20717 type: "DataInputAssociation",
20718 isMany: true
20719 },
20720 {
20721 name: "dataOutputAssociations",
20722 type: "DataOutputAssociation",
20723 isMany: true
20724 },
20725 {
20726 name: "startQuantity",
20727 "default": 1,
20728 isAttr: true,
20729 type: "Integer"
20730 },
20731 {
20732 name: "resources",
20733 type: "ResourceRole",
20734 isMany: true
20735 },
20736 {
20737 name: "completionQuantity",
20738 "default": 1,
20739 isAttr: true,
20740 type: "Integer"
20741 },
20742 {
20743 name: "loopCharacteristics",
20744 type: "LoopCharacteristics"
20745 }
20746 ]
20747 },
20748 {
20749 name: "ServiceTask",
20750 superClass: [
20751 "Task"
20752 ],
20753 properties: [
20754 {
20755 name: "implementation",
20756 isAttr: true,
20757 type: "String"
20758 },
20759 {
20760 name: "operationRef",
20761 type: "Operation",
20762 isAttr: true,
20763 isReference: true
20764 }
20765 ]
20766 },
20767 {
20768 name: "SubProcess",
20769 superClass: [
20770 "Activity",
20771 "FlowElementsContainer",
20772 "InteractionNode"
20773 ],
20774 properties: [
20775 {
20776 name: "triggeredByEvent",
20777 "default": false,
20778 isAttr: true,
20779 type: "Boolean"
20780 },
20781 {
20782 name: "artifacts",
20783 type: "Artifact",
20784 isMany: true
20785 }
20786 ]
20787 },
20788 {
20789 name: "LoopCharacteristics",
20790 isAbstract: true,
20791 superClass: [
20792 "BaseElement"
20793 ]
20794 },
20795 {
20796 name: "MultiInstanceLoopCharacteristics",
20797 superClass: [
20798 "LoopCharacteristics"
20799 ],
20800 properties: [
20801 {
20802 name: "isSequential",
20803 "default": false,
20804 isAttr: true,
20805 type: "Boolean"
20806 },
20807 {
20808 name: "behavior",
20809 type: "MultiInstanceBehavior",
20810 "default": "All",
20811 isAttr: true
20812 },
20813 {
20814 name: "loopCardinality",
20815 type: "Expression",
20816 xml: {
20817 serialize: "xsi:type"
20818 }
20819 },
20820 {
20821 name: "loopDataInputRef",
20822 type: "ItemAwareElement",
20823 isReference: true
20824 },
20825 {
20826 name: "loopDataOutputRef",
20827 type: "ItemAwareElement",
20828 isReference: true
20829 },
20830 {
20831 name: "inputDataItem",
20832 type: "DataInput",
20833 xml: {
20834 serialize: "property"
20835 }
20836 },
20837 {
20838 name: "outputDataItem",
20839 type: "DataOutput",
20840 xml: {
20841 serialize: "property"
20842 }
20843 },
20844 {
20845 name: "complexBehaviorDefinition",
20846 type: "ComplexBehaviorDefinition",
20847 isMany: true
20848 },
20849 {
20850 name: "completionCondition",
20851 type: "Expression",
20852 xml: {
20853 serialize: "xsi:type"
20854 }
20855 },
20856 {
20857 name: "oneBehaviorEventRef",
20858 type: "EventDefinition",
20859 isAttr: true,
20860 isReference: true
20861 },
20862 {
20863 name: "noneBehaviorEventRef",
20864 type: "EventDefinition",
20865 isAttr: true,
20866 isReference: true
20867 }
20868 ]
20869 },
20870 {
20871 name: "StandardLoopCharacteristics",
20872 superClass: [
20873 "LoopCharacteristics"
20874 ],
20875 properties: [
20876 {
20877 name: "testBefore",
20878 "default": false,
20879 isAttr: true,
20880 type: "Boolean"
20881 },
20882 {
20883 name: "loopCondition",
20884 type: "Expression",
20885 xml: {
20886 serialize: "xsi:type"
20887 }
20888 },
20889 {
20890 name: "loopMaximum",
20891 type: "Integer",
20892 isAttr: true
20893 }
20894 ]
20895 },
20896 {
20897 name: "CallActivity",
20898 superClass: [
20899 "Activity",
20900 "InteractionNode"
20901 ],
20902 properties: [
20903 {
20904 name: "calledElement",
20905 type: "String",
20906 isAttr: true
20907 }
20908 ]
20909 },
20910 {
20911 name: "Task",
20912 superClass: [
20913 "Activity",
20914 "InteractionNode"
20915 ]
20916 },
20917 {
20918 name: "SendTask",
20919 superClass: [
20920 "Task"
20921 ],
20922 properties: [
20923 {
20924 name: "implementation",
20925 isAttr: true,
20926 type: "String"
20927 },
20928 {
20929 name: "operationRef",
20930 type: "Operation",
20931 isAttr: true,
20932 isReference: true
20933 },
20934 {
20935 name: "messageRef",
20936 type: "Message",
20937 isAttr: true,
20938 isReference: true
20939 }
20940 ]
20941 },
20942 {
20943 name: "ReceiveTask",
20944 superClass: [
20945 "Task"
20946 ],
20947 properties: [
20948 {
20949 name: "implementation",
20950 isAttr: true,
20951 type: "String"
20952 },
20953 {
20954 name: "instantiate",
20955 "default": false,
20956 isAttr: true,
20957 type: "Boolean"
20958 },
20959 {
20960 name: "operationRef",
20961 type: "Operation",
20962 isAttr: true,
20963 isReference: true
20964 },
20965 {
20966 name: "messageRef",
20967 type: "Message",
20968 isAttr: true,
20969 isReference: true
20970 }
20971 ]
20972 },
20973 {
20974 name: "ScriptTask",
20975 superClass: [
20976 "Task"
20977 ],
20978 properties: [
20979 {
20980 name: "scriptFormat",
20981 isAttr: true,
20982 type: "String"
20983 },
20984 {
20985 name: "script",
20986 type: "String"
20987 }
20988 ]
20989 },
20990 {
20991 name: "BusinessRuleTask",
20992 superClass: [
20993 "Task"
20994 ],
20995 properties: [
20996 {
20997 name: "implementation",
20998 isAttr: true,
20999 type: "String"
21000 }
21001 ]
21002 },
21003 {
21004 name: "AdHocSubProcess",
21005 superClass: [
21006 "SubProcess"
21007 ],
21008 properties: [
21009 {
21010 name: "completionCondition",
21011 type: "Expression",
21012 xml: {
21013 serialize: "xsi:type"
21014 }
21015 },
21016 {
21017 name: "ordering",
21018 type: "AdHocOrdering",
21019 isAttr: true
21020 },
21021 {
21022 name: "cancelRemainingInstances",
21023 "default": true,
21024 isAttr: true,
21025 type: "Boolean"
21026 }
21027 ]
21028 },
21029 {
21030 name: "Transaction",
21031 superClass: [
21032 "SubProcess"
21033 ],
21034 properties: [
21035 {
21036 name: "protocol",
21037 isAttr: true,
21038 type: "String"
21039 },
21040 {
21041 name: "method",
21042 isAttr: true,
21043 type: "String"
21044 }
21045 ]
21046 },
21047 {
21048 name: "GlobalScriptTask",
21049 superClass: [
21050 "GlobalTask"
21051 ],
21052 properties: [
21053 {
21054 name: "scriptLanguage",
21055 isAttr: true,
21056 type: "String"
21057 },
21058 {
21059 name: "script",
21060 isAttr: true,
21061 type: "String"
21062 }
21063 ]
21064 },
21065 {
21066 name: "GlobalBusinessRuleTask",
21067 superClass: [
21068 "GlobalTask"
21069 ],
21070 properties: [
21071 {
21072 name: "implementation",
21073 isAttr: true,
21074 type: "String"
21075 }
21076 ]
21077 },
21078 {
21079 name: "ComplexBehaviorDefinition",
21080 superClass: [
21081 "BaseElement"
21082 ],
21083 properties: [
21084 {
21085 name: "condition",
21086 type: "FormalExpression"
21087 },
21088 {
21089 name: "event",
21090 type: "ImplicitThrowEvent"
21091 }
21092 ]
21093 },
21094 {
21095 name: "ResourceRole",
21096 superClass: [
21097 "BaseElement"
21098 ],
21099 properties: [
21100 {
21101 name: "resourceRef",
21102 type: "Resource",
21103 isReference: true
21104 },
21105 {
21106 name: "resourceParameterBindings",
21107 type: "ResourceParameterBinding",
21108 isMany: true
21109 },
21110 {
21111 name: "resourceAssignmentExpression",
21112 type: "ResourceAssignmentExpression"
21113 },
21114 {
21115 name: "name",
21116 isAttr: true,
21117 type: "String"
21118 }
21119 ]
21120 },
21121 {
21122 name: "ResourceParameterBinding",
21123 properties: [
21124 {
21125 name: "expression",
21126 type: "Expression",
21127 xml: {
21128 serialize: "xsi:type"
21129 }
21130 },
21131 {
21132 name: "parameterRef",
21133 type: "ResourceParameter",
21134 isAttr: true,
21135 isReference: true
21136 }
21137 ],
21138 superClass: [
21139 "BaseElement"
21140 ]
21141 },
21142 {
21143 name: "ResourceAssignmentExpression",
21144 properties: [
21145 {
21146 name: "expression",
21147 type: "Expression",
21148 xml: {
21149 serialize: "xsi:type"
21150 }
21151 }
21152 ],
21153 superClass: [
21154 "BaseElement"
21155 ]
21156 },
21157 {
21158 name: "Import",
21159 properties: [
21160 {
21161 name: "importType",
21162 isAttr: true,
21163 type: "String"
21164 },
21165 {
21166 name: "location",
21167 isAttr: true,
21168 type: "String"
21169 },
21170 {
21171 name: "namespace",
21172 isAttr: true,
21173 type: "String"
21174 }
21175 ]
21176 },
21177 {
21178 name: "Definitions",
21179 superClass: [
21180 "BaseElement"
21181 ],
21182 properties: [
21183 {
21184 name: "name",
21185 isAttr: true,
21186 type: "String"
21187 },
21188 {
21189 name: "targetNamespace",
21190 isAttr: true,
21191 type: "String"
21192 },
21193 {
21194 name: "expressionLanguage",
21195 "default": "http://www.w3.org/1999/XPath",
21196 isAttr: true,
21197 type: "String"
21198 },
21199 {
21200 name: "typeLanguage",
21201 "default": "http://www.w3.org/2001/XMLSchema",
21202 isAttr: true,
21203 type: "String"
21204 },
21205 {
21206 name: "imports",
21207 type: "Import",
21208 isMany: true
21209 },
21210 {
21211 name: "extensions",
21212 type: "Extension",
21213 isMany: true
21214 },
21215 {
21216 name: "rootElements",
21217 type: "RootElement",
21218 isMany: true
21219 },
21220 {
21221 name: "diagrams",
21222 isMany: true,
21223 type: "bpmndi:BPMNDiagram"
21224 },
21225 {
21226 name: "exporter",
21227 isAttr: true,
21228 type: "String"
21229 },
21230 {
21231 name: "relationships",
21232 type: "Relationship",
21233 isMany: true
21234 },
21235 {
21236 name: "exporterVersion",
21237 isAttr: true,
21238 type: "String"
21239 }
21240 ]
21241 }
21242 ];
21243 var enumerations$3 = [
21244 {
21245 name: "ProcessType",
21246 literalValues: [
21247 {
21248 name: "None"
21249 },
21250 {
21251 name: "Public"
21252 },
21253 {
21254 name: "Private"
21255 }
21256 ]
21257 },
21258 {
21259 name: "GatewayDirection",
21260 literalValues: [
21261 {
21262 name: "Unspecified"
21263 },
21264 {
21265 name: "Converging"
21266 },
21267 {
21268 name: "Diverging"
21269 },
21270 {
21271 name: "Mixed"
21272 }
21273 ]
21274 },
21275 {
21276 name: "EventBasedGatewayType",
21277 literalValues: [
21278 {
21279 name: "Parallel"
21280 },
21281 {
21282 name: "Exclusive"
21283 }
21284 ]
21285 },
21286 {
21287 name: "RelationshipDirection",
21288 literalValues: [
21289 {
21290 name: "None"
21291 },
21292 {
21293 name: "Forward"
21294 },
21295 {
21296 name: "Backward"
21297 },
21298 {
21299 name: "Both"
21300 }
21301 ]
21302 },
21303 {
21304 name: "ItemKind",
21305 literalValues: [
21306 {
21307 name: "Physical"
21308 },
21309 {
21310 name: "Information"
21311 }
21312 ]
21313 },
21314 {
21315 name: "ChoreographyLoopType",
21316 literalValues: [
21317 {
21318 name: "None"
21319 },
21320 {
21321 name: "Standard"
21322 },
21323 {
21324 name: "MultiInstanceSequential"
21325 },
21326 {
21327 name: "MultiInstanceParallel"
21328 }
21329 ]
21330 },
21331 {
21332 name: "AssociationDirection",
21333 literalValues: [
21334 {
21335 name: "None"
21336 },
21337 {
21338 name: "One"
21339 },
21340 {
21341 name: "Both"
21342 }
21343 ]
21344 },
21345 {
21346 name: "MultiInstanceBehavior",
21347 literalValues: [
21348 {
21349 name: "None"
21350 },
21351 {
21352 name: "One"
21353 },
21354 {
21355 name: "All"
21356 },
21357 {
21358 name: "Complex"
21359 }
21360 ]
21361 },
21362 {
21363 name: "AdHocOrdering",
21364 literalValues: [
21365 {
21366 name: "Parallel"
21367 },
21368 {
21369 name: "Sequential"
21370 }
21371 ]
21372 }
21373 ];
21374 var xml$1 = {
21375 tagAlias: "lowerCase",
21376 typePrefix: "t"
21377 };
21378 var BpmnPackage = {
21379 name: name$5,
21380 uri: uri$5,
21381 prefix: prefix$5,
21382 associations: associations$5,
21383 types: types$5,
21384 enumerations: enumerations$3,
21385 xml: xml$1
21386 };
21387
21388 var name$4 = "BPMNDI";
21389 var uri$4 = "http://www.omg.org/spec/BPMN/20100524/DI";
21390 var prefix$4 = "bpmndi";
21391 var types$4 = [
21392 {
21393 name: "BPMNDiagram",
21394 properties: [
21395 {
21396 name: "plane",
21397 type: "BPMNPlane",
21398 redefines: "di:Diagram#rootElement"
21399 },
21400 {
21401 name: "labelStyle",
21402 type: "BPMNLabelStyle",
21403 isMany: true
21404 }
21405 ],
21406 superClass: [
21407 "di:Diagram"
21408 ]
21409 },
21410 {
21411 name: "BPMNPlane",
21412 properties: [
21413 {
21414 name: "bpmnElement",
21415 isAttr: true,
21416 isReference: true,
21417 type: "bpmn:BaseElement",
21418 redefines: "di:DiagramElement#modelElement"
21419 }
21420 ],
21421 superClass: [
21422 "di:Plane"
21423 ]
21424 },
21425 {
21426 name: "BPMNShape",
21427 properties: [
21428 {
21429 name: "bpmnElement",
21430 isAttr: true,
21431 isReference: true,
21432 type: "bpmn:BaseElement",
21433 redefines: "di:DiagramElement#modelElement"
21434 },
21435 {
21436 name: "isHorizontal",
21437 isAttr: true,
21438 type: "Boolean"
21439 },
21440 {
21441 name: "isExpanded",
21442 isAttr: true,
21443 type: "Boolean"
21444 },
21445 {
21446 name: "isMarkerVisible",
21447 isAttr: true,
21448 type: "Boolean"
21449 },
21450 {
21451 name: "label",
21452 type: "BPMNLabel"
21453 },
21454 {
21455 name: "isMessageVisible",
21456 isAttr: true,
21457 type: "Boolean"
21458 },
21459 {
21460 name: "participantBandKind",
21461 type: "ParticipantBandKind",
21462 isAttr: true
21463 },
21464 {
21465 name: "choreographyActivityShape",
21466 type: "BPMNShape",
21467 isAttr: true,
21468 isReference: true
21469 }
21470 ],
21471 superClass: [
21472 "di:LabeledShape"
21473 ]
21474 },
21475 {
21476 name: "BPMNEdge",
21477 properties: [
21478 {
21479 name: "label",
21480 type: "BPMNLabel"
21481 },
21482 {
21483 name: "bpmnElement",
21484 isAttr: true,
21485 isReference: true,
21486 type: "bpmn:BaseElement",
21487 redefines: "di:DiagramElement#modelElement"
21488 },
21489 {
21490 name: "sourceElement",
21491 isAttr: true,
21492 isReference: true,
21493 type: "di:DiagramElement",
21494 redefines: "di:Edge#source"
21495 },
21496 {
21497 name: "targetElement",
21498 isAttr: true,
21499 isReference: true,
21500 type: "di:DiagramElement",
21501 redefines: "di:Edge#target"
21502 },
21503 {
21504 name: "messageVisibleKind",
21505 type: "MessageVisibleKind",
21506 isAttr: true,
21507 "default": "initiating"
21508 }
21509 ],
21510 superClass: [
21511 "di:LabeledEdge"
21512 ]
21513 },
21514 {
21515 name: "BPMNLabel",
21516 properties: [
21517 {
21518 name: "labelStyle",
21519 type: "BPMNLabelStyle",
21520 isAttr: true,
21521 isReference: true,
21522 redefines: "di:DiagramElement#style"
21523 }
21524 ],
21525 superClass: [
21526 "di:Label"
21527 ]
21528 },
21529 {
21530 name: "BPMNLabelStyle",
21531 properties: [
21532 {
21533 name: "font",
21534 type: "dc:Font"
21535 }
21536 ],
21537 superClass: [
21538 "di:Style"
21539 ]
21540 }
21541 ];
21542 var enumerations$2 = [
21543 {
21544 name: "ParticipantBandKind",
21545 literalValues: [
21546 {
21547 name: "top_initiating"
21548 },
21549 {
21550 name: "middle_initiating"
21551 },
21552 {
21553 name: "bottom_initiating"
21554 },
21555 {
21556 name: "top_non_initiating"
21557 },
21558 {
21559 name: "middle_non_initiating"
21560 },
21561 {
21562 name: "bottom_non_initiating"
21563 }
21564 ]
21565 },
21566 {
21567 name: "MessageVisibleKind",
21568 literalValues: [
21569 {
21570 name: "initiating"
21571 },
21572 {
21573 name: "non_initiating"
21574 }
21575 ]
21576 }
21577 ];
21578 var associations$4 = [
21579 ];
21580 var BpmnDiPackage = {
21581 name: name$4,
21582 uri: uri$4,
21583 prefix: prefix$4,
21584 types: types$4,
21585 enumerations: enumerations$2,
21586 associations: associations$4
21587 };
21588
21589 var name$3 = "DC";
21590 var uri$3 = "http://www.omg.org/spec/DD/20100524/DC";
21591 var prefix$3 = "dc";
21592 var types$3 = [
21593 {
21594 name: "Boolean"
21595 },
21596 {
21597 name: "Integer"
21598 },
21599 {
21600 name: "Real"
21601 },
21602 {
21603 name: "String"
21604 },
21605 {
21606 name: "Font",
21607 properties: [
21608 {
21609 name: "name",
21610 type: "String",
21611 isAttr: true
21612 },
21613 {
21614 name: "size",
21615 type: "Real",
21616 isAttr: true
21617 },
21618 {
21619 name: "isBold",
21620 type: "Boolean",
21621 isAttr: true
21622 },
21623 {
21624 name: "isItalic",
21625 type: "Boolean",
21626 isAttr: true
21627 },
21628 {
21629 name: "isUnderline",
21630 type: "Boolean",
21631 isAttr: true
21632 },
21633 {
21634 name: "isStrikeThrough",
21635 type: "Boolean",
21636 isAttr: true
21637 }
21638 ]
21639 },
21640 {
21641 name: "Point",
21642 properties: [
21643 {
21644 name: "x",
21645 type: "Real",
21646 "default": "0",
21647 isAttr: true
21648 },
21649 {
21650 name: "y",
21651 type: "Real",
21652 "default": "0",
21653 isAttr: true
21654 }
21655 ]
21656 },
21657 {
21658 name: "Bounds",
21659 properties: [
21660 {
21661 name: "x",
21662 type: "Real",
21663 "default": "0",
21664 isAttr: true
21665 },
21666 {
21667 name: "y",
21668 type: "Real",
21669 "default": "0",
21670 isAttr: true
21671 },
21672 {
21673 name: "width",
21674 type: "Real",
21675 isAttr: true
21676 },
21677 {
21678 name: "height",
21679 type: "Real",
21680 isAttr: true
21681 }
21682 ]
21683 }
21684 ];
21685 var associations$3 = [
21686 ];
21687 var DcPackage = {
21688 name: name$3,
21689 uri: uri$3,
21690 prefix: prefix$3,
21691 types: types$3,
21692 associations: associations$3
21693 };
21694
21695 var name$2 = "DI";
21696 var uri$2 = "http://www.omg.org/spec/DD/20100524/DI";
21697 var prefix$2 = "di";
21698 var types$2 = [
21699 {
21700 name: "DiagramElement",
21701 isAbstract: true,
21702 properties: [
21703 {
21704 name: "id",
21705 isAttr: true,
21706 isId: true,
21707 type: "String"
21708 },
21709 {
21710 name: "extension",
21711 type: "Extension"
21712 },
21713 {
21714 name: "owningDiagram",
21715 type: "Diagram",
21716 isReadOnly: true,
21717 isVirtual: true,
21718 isReference: true
21719 },
21720 {
21721 name: "owningElement",
21722 type: "DiagramElement",
21723 isReadOnly: true,
21724 isVirtual: true,
21725 isReference: true
21726 },
21727 {
21728 name: "modelElement",
21729 isReadOnly: true,
21730 isVirtual: true,
21731 isReference: true,
21732 type: "Element"
21733 },
21734 {
21735 name: "style",
21736 type: "Style",
21737 isReadOnly: true,
21738 isVirtual: true,
21739 isReference: true
21740 },
21741 {
21742 name: "ownedElement",
21743 type: "DiagramElement",
21744 isReadOnly: true,
21745 isMany: true,
21746 isVirtual: true
21747 }
21748 ]
21749 },
21750 {
21751 name: "Node",
21752 isAbstract: true,
21753 superClass: [
21754 "DiagramElement"
21755 ]
21756 },
21757 {
21758 name: "Edge",
21759 isAbstract: true,
21760 superClass: [
21761 "DiagramElement"
21762 ],
21763 properties: [
21764 {
21765 name: "source",
21766 type: "DiagramElement",
21767 isReadOnly: true,
21768 isVirtual: true,
21769 isReference: true
21770 },
21771 {
21772 name: "target",
21773 type: "DiagramElement",
21774 isReadOnly: true,
21775 isVirtual: true,
21776 isReference: true
21777 },
21778 {
21779 name: "waypoint",
21780 isUnique: false,
21781 isMany: true,
21782 type: "dc:Point",
21783 xml: {
21784 serialize: "xsi:type"
21785 }
21786 }
21787 ]
21788 },
21789 {
21790 name: "Diagram",
21791 isAbstract: true,
21792 properties: [
21793 {
21794 name: "id",
21795 isAttr: true,
21796 isId: true,
21797 type: "String"
21798 },
21799 {
21800 name: "rootElement",
21801 type: "DiagramElement",
21802 isReadOnly: true,
21803 isVirtual: true
21804 },
21805 {
21806 name: "name",
21807 isAttr: true,
21808 type: "String"
21809 },
21810 {
21811 name: "documentation",
21812 isAttr: true,
21813 type: "String"
21814 },
21815 {
21816 name: "resolution",
21817 isAttr: true,
21818 type: "Real"
21819 },
21820 {
21821 name: "ownedStyle",
21822 type: "Style",
21823 isReadOnly: true,
21824 isMany: true,
21825 isVirtual: true
21826 }
21827 ]
21828 },
21829 {
21830 name: "Shape",
21831 isAbstract: true,
21832 superClass: [
21833 "Node"
21834 ],
21835 properties: [
21836 {
21837 name: "bounds",
21838 type: "dc:Bounds"
21839 }
21840 ]
21841 },
21842 {
21843 name: "Plane",
21844 isAbstract: true,
21845 superClass: [
21846 "Node"
21847 ],
21848 properties: [
21849 {
21850 name: "planeElement",
21851 type: "DiagramElement",
21852 subsettedProperty: "DiagramElement-ownedElement",
21853 isMany: true
21854 }
21855 ]
21856 },
21857 {
21858 name: "LabeledEdge",
21859 isAbstract: true,
21860 superClass: [
21861 "Edge"
21862 ],
21863 properties: [
21864 {
21865 name: "ownedLabel",
21866 type: "Label",
21867 isReadOnly: true,
21868 subsettedProperty: "DiagramElement-ownedElement",
21869 isMany: true,
21870 isVirtual: true
21871 }
21872 ]
21873 },
21874 {
21875 name: "LabeledShape",
21876 isAbstract: true,
21877 superClass: [
21878 "Shape"
21879 ],
21880 properties: [
21881 {
21882 name: "ownedLabel",
21883 type: "Label",
21884 isReadOnly: true,
21885 subsettedProperty: "DiagramElement-ownedElement",
21886 isMany: true,
21887 isVirtual: true
21888 }
21889 ]
21890 },
21891 {
21892 name: "Label",
21893 isAbstract: true,
21894 superClass: [
21895 "Node"
21896 ],
21897 properties: [
21898 {
21899 name: "bounds",
21900 type: "dc:Bounds"
21901 }
21902 ]
21903 },
21904 {
21905 name: "Style",
21906 isAbstract: true,
21907 properties: [
21908 {
21909 name: "id",
21910 isAttr: true,
21911 isId: true,
21912 type: "String"
21913 }
21914 ]
21915 },
21916 {
21917 name: "Extension",
21918 properties: [
21919 {
21920 name: "values",
21921 isMany: true,
21922 type: "Element"
21923 }
21924 ]
21925 }
21926 ];
21927 var associations$2 = [
21928 ];
21929 var xml = {
21930 tagAlias: "lowerCase"
21931 };
21932 var DiPackage = {
21933 name: name$2,
21934 uri: uri$2,
21935 prefix: prefix$2,
21936 types: types$2,
21937 associations: associations$2,
21938 xml: xml
21939 };
21940
21941 var name$1 = "bpmn.io colors for BPMN";
21942 var uri$1 = "http://bpmn.io/schema/bpmn/biocolor/1.0";
21943 var prefix$1 = "bioc";
21944 var types$1 = [
21945 {
21946 name: "ColoredShape",
21947 "extends": [
21948 "bpmndi:BPMNShape"
21949 ],
21950 properties: [
21951 {
21952 name: "stroke",
21953 isAttr: true,
21954 type: "String"
21955 },
21956 {
21957 name: "fill",
21958 isAttr: true,
21959 type: "String"
21960 }
21961 ]
21962 },
21963 {
21964 name: "ColoredEdge",
21965 "extends": [
21966 "bpmndi:BPMNEdge"
21967 ],
21968 properties: [
21969 {
21970 name: "stroke",
21971 isAttr: true,
21972 type: "String"
21973 },
21974 {
21975 name: "fill",
21976 isAttr: true,
21977 type: "String"
21978 }
21979 ]
21980 }
21981 ];
21982 var enumerations$1 = [
21983 ];
21984 var associations$1 = [
21985 ];
21986 var BiocPackage = {
21987 name: name$1,
21988 uri: uri$1,
21989 prefix: prefix$1,
21990 types: types$1,
21991 enumerations: enumerations$1,
21992 associations: associations$1
21993 };
21994
21995 var name = "BPMN in Color";
21996 var uri = "http://www.omg.org/spec/BPMN/non-normative/color/1.0";
21997 var prefix = "color";
21998 var types = [
21999 {
22000 name: "ColoredLabel",
22001 "extends": [
22002 "bpmndi:BPMNLabel"
22003 ],
22004 properties: [
22005 {
22006 name: "color",
22007 isAttr: true,
22008 type: "String"
22009 }
22010 ]
22011 },
22012 {
22013 name: "ColoredShape",
22014 "extends": [
22015 "bpmndi:BPMNShape"
22016 ],
22017 properties: [
22018 {
22019 name: "background-color",
22020 isAttr: true,
22021 type: "String"
22022 },
22023 {
22024 name: "border-color",
22025 isAttr: true,
22026 type: "String"
22027 }
22028 ]
22029 },
22030 {
22031 name: "ColoredEdge",
22032 "extends": [
22033 "bpmndi:BPMNEdge"
22034 ],
22035 properties: [
22036 {
22037 name: "border-color",
22038 isAttr: true,
22039 type: "String"
22040 }
22041 ]
22042 }
22043 ];
22044 var enumerations = [
22045 ];
22046 var associations = [
22047 ];
22048 var BpmnInColorPackage = {
22049 name: name,
22050 uri: uri,
22051 prefix: prefix,
22052 types: types,
22053 enumerations: enumerations,
22054 associations: associations
22055 };
22056
22057 var packages = {
22058 bpmn: BpmnPackage,
22059 bpmndi: BpmnDiPackage,
22060 dc: DcPackage,
22061 di: DiPackage,
22062 bioc: BiocPackage,
22063 color: BpmnInColorPackage
22064 };
22065
22066 function simple(additionalPackages, options) {
22067 var pks = assign$1({}, packages, additionalPackages);
22068
22069 return new BpmnModdle(pks, options);
22070 }
22071
22072 /**
22073 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22074 */
22075
22076
22077 // TODO(nikku): remove with future bpmn-js version
22078
22079 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';
22080
22081 /**
22082 * @private
22083 *
22084 * @param {ModdleElement} businessObject
22085 */
22086 function ensureCompatDiRef(businessObject) {
22087
22088 // bpmnElement can have multiple independent DIs
22089 if (!has$1(businessObject, 'di')) {
22090 Object.defineProperty(businessObject, 'di', {
22091 enumerable: false,
22092 get: function() {
22093 throw new Error(DI_ERROR_MESSAGE);
22094 }
22095 });
22096 }
22097 }
22098
22099 /**
22100 * @typedef {import('diagram-js/lib/i18n/translate/translate').default} Translate
22101 *
22102 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22103 */
22104
22105 /**
22106 * Returns true if an element is of the given meta-model type.
22107 *
22108 * @param {ModdleElement} element
22109 * @param {string} type
22110 *
22111 * @return {boolean}
22112 */
22113 function is(element, type) {
22114 return element.$instanceOf(type);
22115 }
22116
22117
22118 /**
22119 * Find a suitable display candidate for definitions where the DI does not
22120 * correctly specify one.
22121 *
22122 * @param {ModdleElement} definitions
22123 *
22124 * @return {ModdleElement}
22125 */
22126 function findDisplayCandidate(definitions) {
22127 return find(definitions.rootElements, function(e) {
22128 return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration');
22129 });
22130 }
22131
22132 /**
22133 * @param {Record<'element' | 'root' | 'error', Function>} handler
22134 * @param {Translate} translate
22135 */
22136 function BpmnTreeWalker(handler, translate) {
22137
22138 // list of containers already walked
22139 var handledElements = {};
22140
22141 // list of elements to handle deferred to ensure
22142 // prerequisites are drawn
22143 var deferred = [];
22144
22145 var diMap = {};
22146
22147 // Helpers //////////////////////
22148
22149 function contextual(fn, ctx) {
22150 return function(e) {
22151 fn(e, ctx);
22152 };
22153 }
22154
22155 function handled(element) {
22156 handledElements[element.id] = element;
22157 }
22158
22159 function isHandled(element) {
22160 return handledElements[element.id];
22161 }
22162
22163 function visit(element, ctx) {
22164
22165 var gfx = element.gfx;
22166
22167 // avoid multiple rendering of elements
22168 if (gfx) {
22169 throw new Error(
22170 translate('already rendered {element}', { element: elementToString(element) })
22171 );
22172 }
22173
22174 // call handler
22175 return handler.element(element, diMap[element.id], ctx);
22176 }
22177
22178 function visitRoot(element, diagram) {
22179 return handler.root(element, diMap[element.id], diagram);
22180 }
22181
22182 function visitIfDi(element, ctx) {
22183
22184 try {
22185 var gfx = diMap[element.id] && visit(element, ctx);
22186
22187 handled(element);
22188
22189 return gfx;
22190 } catch (e) {
22191 logError(e.message, { element: element, error: e });
22192
22193 console.error(translate('failed to import {element}', { element: elementToString(element) }));
22194 console.error(e);
22195 }
22196 }
22197
22198 function logError(message, context) {
22199 handler.error(message, context);
22200 }
22201
22202 // DI handling //////////////////////
22203
22204 var registerDi = this.registerDi = function registerDi(di) {
22205 var bpmnElement = di.bpmnElement;
22206
22207 if (bpmnElement) {
22208 if (diMap[bpmnElement.id]) {
22209 logError(
22210 translate('multiple DI elements defined for {element}', {
22211 element: elementToString(bpmnElement)
22212 }),
22213 { element: bpmnElement }
22214 );
22215 } else {
22216 diMap[bpmnElement.id] = di;
22217
22218 ensureCompatDiRef(bpmnElement);
22219 }
22220 } else {
22221 logError(
22222 translate('no bpmnElement referenced in {element}', {
22223 element: elementToString(di)
22224 }),
22225 { element: di }
22226 );
22227 }
22228 };
22229
22230 function handleDiagram(diagram) {
22231 handlePlane(diagram.plane);
22232 }
22233
22234 function handlePlane(plane) {
22235 registerDi(plane);
22236
22237 forEach$1(plane.planeElement, handlePlaneElement);
22238 }
22239
22240 function handlePlaneElement(planeElement) {
22241 registerDi(planeElement);
22242 }
22243
22244
22245 // Semantic handling //////////////////////
22246
22247 /**
22248 * Handle definitions and return the rendered diagram (if any).
22249 *
22250 * @param {ModdleElement} definitions to walk and import
22251 * @param {ModdleElement} [diagram] specific diagram to import and display
22252 *
22253 * @throws {Error} if no diagram to display could be found
22254 */
22255 this.handleDefinitions = function handleDefinitions(definitions, diagram) {
22256
22257 // make sure we walk the correct bpmnElement
22258
22259 var diagrams = definitions.diagrams;
22260
22261 if (diagram && diagrams.indexOf(diagram) === -1) {
22262 throw new Error(translate('diagram not part of bpmn:Definitions'));
22263 }
22264
22265 if (!diagram && diagrams && diagrams.length) {
22266 diagram = diagrams[0];
22267 }
22268
22269 // no diagram -> nothing to import
22270 if (!diagram) {
22271 throw new Error(translate('no diagram to display'));
22272 }
22273
22274 // load DI from selected diagram only
22275 diMap = {};
22276 handleDiagram(diagram);
22277
22278
22279 var plane = diagram.plane;
22280
22281 if (!plane) {
22282 throw new Error(translate(
22283 'no plane for {element}',
22284 { element: elementToString(diagram) }
22285 ));
22286 }
22287
22288 var rootElement = plane.bpmnElement;
22289
22290 // ensure we default to a suitable display candidate (process or collaboration),
22291 // even if non is specified in DI
22292 if (!rootElement) {
22293 rootElement = findDisplayCandidate(definitions);
22294
22295 if (!rootElement) {
22296 throw new Error(translate('no process or collaboration to display'));
22297 } else {
22298
22299 logError(
22300 translate('correcting missing bpmnElement on {plane} to {rootElement}', {
22301 plane: elementToString(plane),
22302 rootElement: elementToString(rootElement)
22303 })
22304 );
22305
22306 // correct DI on the fly
22307 plane.bpmnElement = rootElement;
22308 registerDi(plane);
22309 }
22310 }
22311
22312
22313 var ctx = visitRoot(rootElement, plane);
22314
22315 if (is(rootElement, 'bpmn:Process') || is(rootElement, 'bpmn:SubProcess')) {
22316 handleProcess(rootElement, ctx);
22317 } else if (is(rootElement, 'bpmn:Collaboration')) {
22318 handleCollaboration(rootElement, ctx);
22319
22320 // force drawing of everything not yet drawn that is part of the target DI
22321 handleUnhandledProcesses(definitions.rootElements, ctx);
22322 } else {
22323 throw new Error(
22324 translate('unsupported bpmnElement for {plane}: {rootElement}', {
22325 plane: elementToString(plane),
22326 rootElement: elementToString(rootElement)
22327 })
22328 );
22329 }
22330
22331 // handle all deferred elements
22332 handleDeferred(deferred);
22333 };
22334
22335 var handleDeferred = this.handleDeferred = function handleDeferred() {
22336
22337 var fn;
22338
22339 // drain deferred until empty
22340 while (deferred.length) {
22341 fn = deferred.shift();
22342
22343 fn();
22344 }
22345 };
22346
22347 function handleProcess(process, context) {
22348 handleFlowElementsContainer(process, context);
22349 handleIoSpecification(process.ioSpecification, context);
22350
22351 handleArtifacts(process.artifacts, context);
22352
22353 // log process handled
22354 handled(process);
22355 }
22356
22357 function handleUnhandledProcesses(rootElements, ctx) {
22358
22359 // walk through all processes that have not yet been drawn and draw them
22360 // if they contain lanes with DI information.
22361 // we do this to pass the free-floating lane test cases in the MIWG test suite
22362 var processes = filter(rootElements, function(e) {
22363 return !isHandled(e) && is(e, 'bpmn:Process') && e.laneSets;
22364 });
22365
22366 processes.forEach(contextual(handleProcess, ctx));
22367 }
22368
22369 function handleMessageFlow(messageFlow, context) {
22370 visitIfDi(messageFlow, context);
22371 }
22372
22373 function handleMessageFlows(messageFlows, context) {
22374 forEach$1(messageFlows, contextual(handleMessageFlow, context));
22375 }
22376
22377 function handleDataAssociation(association, context) {
22378 visitIfDi(association, context);
22379 }
22380
22381 function handleDataInput(dataInput, context) {
22382 visitIfDi(dataInput, context);
22383 }
22384
22385 function handleDataOutput(dataOutput, context) {
22386 visitIfDi(dataOutput, context);
22387 }
22388
22389 function handleArtifact(artifact, context) {
22390
22391 // bpmn:TextAnnotation
22392 // bpmn:Group
22393 // bpmn:Association
22394
22395 visitIfDi(artifact, context);
22396 }
22397
22398 function handleArtifacts(artifacts, context) {
22399
22400 forEach$1(artifacts, function(e) {
22401 if (is(e, 'bpmn:Association')) {
22402 deferred.push(function() {
22403 handleArtifact(e, context);
22404 });
22405 } else {
22406 handleArtifact(e, context);
22407 }
22408 });
22409 }
22410
22411 function handleIoSpecification(ioSpecification, context) {
22412
22413 if (!ioSpecification) {
22414 return;
22415 }
22416
22417 forEach$1(ioSpecification.dataInputs, contextual(handleDataInput, context));
22418 forEach$1(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
22419 }
22420
22421 var handleSubProcess = this.handleSubProcess = function handleSubProcess(subProcess, context) {
22422 handleFlowElementsContainer(subProcess, context);
22423 handleArtifacts(subProcess.artifacts, context);
22424 };
22425
22426 function handleFlowNode(flowNode, context) {
22427 var childCtx = visitIfDi(flowNode, context);
22428
22429 if (is(flowNode, 'bpmn:SubProcess')) {
22430 handleSubProcess(flowNode, childCtx || context);
22431 }
22432
22433 if (is(flowNode, 'bpmn:Activity')) {
22434 handleIoSpecification(flowNode.ioSpecification, context);
22435 }
22436
22437 // defer handling of associations
22438 // affected types:
22439 //
22440 // * bpmn:Activity
22441 // * bpmn:ThrowEvent
22442 // * bpmn:CatchEvent
22443 //
22444 deferred.push(function() {
22445 forEach$1(flowNode.dataInputAssociations, contextual(handleDataAssociation, context));
22446 forEach$1(flowNode.dataOutputAssociations, contextual(handleDataAssociation, context));
22447 });
22448 }
22449
22450 function handleSequenceFlow(sequenceFlow, context) {
22451 visitIfDi(sequenceFlow, context);
22452 }
22453
22454 function handleDataElement(dataObject, context) {
22455 visitIfDi(dataObject, context);
22456 }
22457
22458 function handleLane(lane, context) {
22459
22460 deferred.push(function() {
22461
22462 var newContext = visitIfDi(lane, context);
22463
22464 if (lane.childLaneSet) {
22465 handleLaneSet(lane.childLaneSet, newContext || context);
22466 }
22467
22468 wireFlowNodeRefs(lane);
22469 });
22470 }
22471
22472 function handleLaneSet(laneSet, context) {
22473 forEach$1(laneSet.lanes, contextual(handleLane, context));
22474 }
22475
22476 function handleLaneSets(laneSets, context) {
22477 forEach$1(laneSets, contextual(handleLaneSet, context));
22478 }
22479
22480 function handleFlowElementsContainer(container, context) {
22481 handleFlowElements(container.flowElements, context);
22482
22483 if (container.laneSets) {
22484 handleLaneSets(container.laneSets, context);
22485 }
22486 }
22487
22488 function handleFlowElements(flowElements, context) {
22489 forEach$1(flowElements, function(e) {
22490 if (is(e, 'bpmn:SequenceFlow')) {
22491 deferred.push(function() {
22492 handleSequenceFlow(e, context);
22493 });
22494 } else if (is(e, 'bpmn:BoundaryEvent')) {
22495 deferred.unshift(function() {
22496 handleFlowNode(e, context);
22497 });
22498 } else if (is(e, 'bpmn:FlowNode')) {
22499 handleFlowNode(e, context);
22500 } else if (is(e, 'bpmn:DataObject')) ; else if (is(e, 'bpmn:DataStoreReference')) {
22501 handleDataElement(e, context);
22502 } else if (is(e, 'bpmn:DataObjectReference')) {
22503 handleDataElement(e, context);
22504 } else {
22505 logError(
22506 translate('unrecognized flowElement {element} in context {context}', {
22507 element: elementToString(e),
22508 context: (context ? elementToString(context.businessObject) : 'null')
22509 }),
22510 { element: e, context: context }
22511 );
22512 }
22513 });
22514 }
22515
22516 function handleParticipant(participant, context) {
22517 var newCtx = visitIfDi(participant, context);
22518
22519 var process = participant.processRef;
22520 if (process) {
22521 handleProcess(process, newCtx || context);
22522 }
22523 }
22524
22525 function handleCollaboration(collaboration, context) {
22526
22527 forEach$1(collaboration.participants, contextual(handleParticipant, context));
22528
22529 handleArtifacts(collaboration.artifacts, context);
22530
22531 // handle message flows latest in the process
22532 deferred.push(function() {
22533 handleMessageFlows(collaboration.messageFlows, context);
22534 });
22535 }
22536
22537
22538 function wireFlowNodeRefs(lane) {
22539
22540 // wire the virtual flowNodeRefs <-> relationship
22541 forEach$1(lane.flowNodeRef, function(flowNode) {
22542 var lanes = flowNode.get('lanes');
22543
22544 if (lanes) {
22545 lanes.push(lane);
22546 }
22547 });
22548 }
22549 }
22550
22551 /**
22552 * @typedef {import('../model/Types').ModdleElement} ModdleElement
22553 *
22554 * @typedef { {
22555 * warnings: string[];
22556 * } } ImportBPMNDiagramResult
22557 *
22558 * @typedef {ImportBPMNDiagramResult & Error} ImportBPMNDiagramError
22559 */
22560
22561 /**
22562 * Import the definitions into a diagram.
22563 *
22564 * Errors and warnings are reported through the specified callback.
22565 *
22566 * @param {ModdleElement} diagram
22567 * @param {ModdleElement} definitions
22568 * @param {ModdleElement} [bpmnDiagram] The diagram to be rendered (if not
22569 * provided, the first one will be rendered).
22570 *
22571 * @return {Promise<ImportBPMNDiagramResult>}
22572 */
22573 function importBpmnDiagram(diagram, definitions, bpmnDiagram) {
22574
22575 var importer,
22576 eventBus,
22577 translate,
22578 canvas;
22579
22580 var error,
22581 warnings = [];
22582
22583 /**
22584 * Walk the diagram semantically, importing (=drawing)
22585 * all elements you encounter.
22586 *
22587 * @param {ModdleElement} definitions
22588 * @param {ModdleElement} bpmnDiagram
22589 */
22590 function render(definitions, bpmnDiagram) {
22591
22592 var visitor = {
22593
22594 root: function(element, di) {
22595 return importer.add(element, di);
22596 },
22597
22598 element: function(element, di, parentShape) {
22599 return importer.add(element, di, parentShape);
22600 },
22601
22602 error: function(message, context) {
22603 warnings.push({ message: message, context: context });
22604 }
22605 };
22606
22607 var walker = new BpmnTreeWalker(visitor, translate);
22608
22609
22610 bpmnDiagram = bpmnDiagram || (definitions.diagrams && definitions.diagrams[0]);
22611
22612 var diagramsToImport = getDiagramsToImport(definitions, bpmnDiagram);
22613
22614 if (!diagramsToImport) {
22615 throw new Error(translate('no diagram to display'));
22616 }
22617
22618 // traverse BPMN 2.0 document model,
22619 // starting at definitions
22620 forEach$1(diagramsToImport, function(diagram) {
22621 walker.handleDefinitions(definitions, diagram);
22622 });
22623
22624 var rootId = bpmnDiagram.plane.bpmnElement.id;
22625
22626 // we do need to account for different ways we create root elements
22627 // each nested imported <root> do have the `_plane` suffix, while
22628 // the root <root> is found under the business object ID
22629 canvas.setRootElement(
22630 canvas.findRoot(rootId + '_plane') || canvas.findRoot(rootId)
22631 );
22632 }
22633
22634 return new Promise(function(resolve, reject) {
22635 try {
22636 importer = diagram.get('bpmnImporter');
22637 eventBus = diagram.get('eventBus');
22638 translate = diagram.get('translate');
22639 canvas = diagram.get('canvas');
22640
22641 eventBus.fire('import.render.start', { definitions: definitions });
22642
22643 render(definitions, bpmnDiagram);
22644
22645 eventBus.fire('import.render.complete', {
22646 error: error,
22647 warnings: warnings
22648 });
22649
22650 return resolve({ warnings: warnings });
22651 } catch (e) {
22652
22653 e.warnings = warnings;
22654 return reject(e);
22655 }
22656 });
22657 }
22658
22659 /**
22660 * Returns all diagrams in the same hierarchy as the requested diagram.
22661 * Includes all parent and sub process diagrams.
22662 *
22663 * @param {ModdleElement} definitions
22664 * @param {ModdleElement} bpmnDiagram
22665 *
22666 * @return {ModdleElement[]}
22667 */
22668 function getDiagramsToImport(definitions, bpmnDiagram) {
22669 if (!bpmnDiagram) {
22670 return;
22671 }
22672
22673 var bpmnElement = bpmnDiagram.plane.bpmnElement,
22674 rootElement = bpmnElement;
22675
22676 if (!is$1(bpmnElement, 'bpmn:Process') && !is$1(bpmnElement, 'bpmn:Collaboration')) {
22677 rootElement = findRootProcess(bpmnElement);
22678 }
22679
22680 // in case the process is part of a collaboration, the plane references the
22681 // collaboration, not the process
22682 var collaboration;
22683
22684 if (is$1(rootElement, 'bpmn:Collaboration')) {
22685 collaboration = rootElement;
22686 } else {
22687 collaboration = find(definitions.rootElements, function(element) {
22688 if (!is$1(element, 'bpmn:Collaboration')) {
22689 return;
22690 }
22691
22692 return find(element.participants, function(participant) {
22693 return participant.processRef === rootElement;
22694 });
22695 });
22696 }
22697
22698 var rootElements = [ rootElement ];
22699
22700 // all collaboration processes can contain sub-diagrams
22701 if (collaboration) {
22702 rootElements = map$1(collaboration.participants, function(participant) {
22703 return participant.processRef;
22704 });
22705
22706 rootElements.push(collaboration);
22707 }
22708
22709 var allChildren = selfAndAllFlowElements(rootElements);
22710
22711 // if we have multiple diagrams referencing the same element, we
22712 // use the first in the file
22713 var diagramsToImport = [ bpmnDiagram ];
22714 var handledElements = [ bpmnElement ];
22715
22716 forEach$1(definitions.diagrams, function(diagram) {
22717 var businessObject = diagram.plane.bpmnElement;
22718
22719 if (
22720 allChildren.indexOf(businessObject) !== -1 &&
22721 handledElements.indexOf(businessObject) === -1
22722 ) {
22723 diagramsToImport.push(diagram);
22724 handledElements.push(businessObject);
22725 }
22726 });
22727
22728
22729 return diagramsToImport;
22730 }
22731
22732 function selfAndAllFlowElements(elements) {
22733 var result = [];
22734
22735 forEach$1(elements, function(element) {
22736 if (!element) {
22737 return;
22738 }
22739
22740 result.push(element);
22741
22742 result = result.concat(selfAndAllFlowElements(element.flowElements));
22743 });
22744
22745 return result;
22746 }
22747
22748 function findRootProcess(element) {
22749 var parent = element;
22750
22751 while (parent) {
22752 if (is$1(parent, 'bpmn:Process')) {
22753 return parent;
22754 }
22755
22756 parent = parent.$parent;
22757 }
22758 }
22759
22760 /**
22761 * This file must not be changed or exchanged.
22762 *
22763 * @see http://bpmn.io/license for more information.
22764 */
22765
22766
22767 // inlined ../../resources/logo.svg
22768 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>';
22769
22770 var BPMNIO_IMG = BPMNIO_LOGO_SVG;
22771
22772 var LOGO_STYLES = {
22773 verticalAlign: 'middle'
22774 };
22775
22776 var LINK_STYLES = {
22777 'color': '#404040'
22778 };
22779
22780 var LIGHTBOX_STYLES = {
22781 'zIndex': '1001',
22782 'position': 'fixed',
22783 'top': '0',
22784 'left': '0',
22785 'right': '0',
22786 'bottom': '0'
22787 };
22788
22789 var BACKDROP_STYLES = {
22790 'width': '100%',
22791 'height': '100%',
22792 'background': 'rgba(40,40,40,0.2)'
22793 };
22794
22795 var NOTICE_STYLES = {
22796 'position': 'absolute',
22797 'left': '50%',
22798 'top': '40%',
22799 'transform': 'translate(-50%)',
22800 'width': '260px',
22801 'padding': '10px',
22802 'background': 'white',
22803 'boxShadow': '0 1px 4px rgba(0,0,0,0.3)',
22804 'fontFamily': 'Helvetica, Arial, sans-serif',
22805 'fontSize': '14px',
22806 'display': 'flex',
22807 'lineHeight': '1.3'
22808 };
22809
22810 var LIGHTBOX_MARKUP =
22811 '<div class="bjs-powered-by-lightbox">' +
22812 '<div class="backdrop"></div>' +
22813 '<div class="notice">' +
22814 '<a href="https://bpmn.io" target="_blank" rel="noopener" class="link">' +
22815 BPMNIO_IMG +
22816 '</a>' +
22817 '<span>' +
22818 'Web-based tooling for BPMN, DMN and forms ' +
22819 'powered by <a href="https://bpmn.io" target="_blank" rel="noopener">bpmn.io</a>.' +
22820 '</span>' +
22821 '</div>' +
22822 '</div>';
22823
22824
22825 var lightbox;
22826
22827 function createLightbox() {
22828 lightbox = domify$1(LIGHTBOX_MARKUP);
22829
22830 assign(lightbox, LIGHTBOX_STYLES);
22831 assign(query('svg', lightbox), LOGO_STYLES);
22832 assign(query('.backdrop', lightbox), BACKDROP_STYLES);
22833 assign(query('.notice', lightbox), NOTICE_STYLES);
22834 assign(query('.link', lightbox), LINK_STYLES, {
22835 'margin': '15px 20px 15px 10px',
22836 'alignSelf': 'center'
22837 });
22838 }
22839
22840 function open() {
22841
22842 if (!lightbox) {
22843 createLightbox();
22844
22845 delegate.bind(lightbox, '.backdrop', 'click', function(event) {
22846 document.body.removeChild(lightbox);
22847 });
22848 }
22849
22850 document.body.appendChild(lightbox);
22851 }
22852
22853 /**
22854 * The code in the <project-logo></project-logo> area
22855 * must not be changed.
22856 *
22857 * @see http://bpmn.io/license for more information.
22858 */
22859
22860 /**
22861 * @template T
22862 *
22863 * @typedef {import('diagram-js/lib/core/EventBus').EventBusEventCallback<T>} EventBusEventCallback
22864 */
22865
22866 /**
22867 * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration
22868 *
22869 * @typedef {import('./model/Types').Moddle} Moddle
22870 * @typedef {import('./model/Types').ModdleElement} ModdleElement
22871 * @typedef {import('./model/Types').ModdleExtension} ModdleExtension
22872 *
22873 * @typedef { {
22874 * width?: number|string;
22875 * height?: number|string;
22876 * position?: string;
22877 * container?: string|HTMLElement;
22878 * moddleExtensions?: ModdleExtensions;
22879 * additionalModules?: ModuleDeclaration[];
22880 * } & Record<string, any> } BaseViewerOptions
22881 *
22882 * @typedef {Record<string, ModdleElement>} ModdleElementsById
22883 *
22884 * @typedef { {
22885 * [key: string]: ModdleExtension;
22886 * } } ModdleExtensions
22887 *
22888 * @typedef { {
22889 * warnings: string[];
22890 * } } ImportXMLResult
22891 *
22892 * @typedef {ImportXMLResult & Error} ImportXMLError
22893 *
22894 * @typedef {ImportXMLResult} ImportDefinitionsResult
22895 *
22896 * @typedef {ImportXMLError} ImportDefinitionsError
22897 *
22898 * @typedef {ImportXMLResult} OpenResult
22899 *
22900 * @typedef {ImportXMLError} OpenError
22901 *
22902 * @typedef { {
22903 * format?: boolean;
22904 * preamble?: boolean;
22905 * } } SaveXMLOptions
22906 *
22907 * @typedef { {
22908 * xml?: string;
22909 * error?: Error;
22910 * } } SaveXMLResult
22911 *
22912 * @typedef { {
22913 * svg: string;
22914 * } } SaveSVGResult
22915 *
22916 * @typedef { {
22917 * xml: string;
22918 * } } ImportParseStartEvent
22919 *
22920 * @typedef { {
22921 * error?: ImportXMLError;
22922 * definitions?: ModdleElement;
22923 * elementsById?: ModdleElementsById;
22924 * references?: ModdleElement[];
22925 * warnings: string[];
22926 * } } ImportParseCompleteEvent
22927 *
22928 * @typedef { {
22929 * error?: ImportXMLError;
22930 * warnings: string[];
22931 * } } ImportDoneEvent
22932 *
22933 * @typedef { {
22934 * definitions: ModdleElement;
22935 * } } SaveXMLStartEvent
22936 *
22937 * @typedef {SaveXMLResult} SaveXMLDoneEvent
22938 *
22939 * @typedef { {
22940 * error?: Error;
22941 * svg: string;
22942 * } } SaveSVGDoneEvent
22943 */
22944
22945 /**
22946 * A base viewer for BPMN 2.0 diagrams.
22947 *
22948 * Have a look at {@link Viewer}, {@link NavigatedViewer} or {@link Modeler} for
22949 * bundles that include actual features.
22950 *
22951 * @param {BaseViewerOptions} [options] The options to configure the viewer.
22952 */
22953 function BaseViewer(options) {
22954
22955 /**
22956 * @type {BaseViewerOptions}
22957 */
22958 options = assign$1({}, DEFAULT_OPTIONS, options);
22959
22960 /**
22961 * @type {Moddle}
22962 */
22963 this._moddle = this._createModdle(options);
22964
22965 /**
22966 * @type {HTMLElement}
22967 */
22968 this._container = this._createContainer(options);
22969
22970 /* <project-logo> */
22971
22972 addProjectLogo(this._container);
22973
22974 /* </project-logo> */
22975
22976 this._init(this._container, this._moddle, options);
22977 }
22978
22979 e(BaseViewer, Diagram);
22980
22981 /**
22982 * Parse and render a BPMN 2.0 diagram.
22983 *
22984 * Once finished the viewer reports back the result to the
22985 * provided callback function with (err, warnings).
22986 *
22987 * ## Life-Cycle Events
22988 *
22989 * During import the viewer will fire life-cycle events:
22990 *
22991 * * import.parse.start (about to read model from XML)
22992 * * import.parse.complete (model read; may have worked or not)
22993 * * import.render.start (graphical import start)
22994 * * import.render.complete (graphical import finished)
22995 * * import.done (everything done)
22996 *
22997 * You can use these events to hook into the life-cycle.
22998 *
22999 * @throws {ImportXMLError} An error thrown during the import of the XML.
23000 *
23001 * @fires BaseViewer#ImportParseStartEvent
23002 * @fires BaseViewer#ImportParseCompleteEvent
23003 * @fires Importer#ImportRenderStartEvent
23004 * @fires Importer#ImportRenderCompleteEvent
23005 * @fires BaseViewer#ImportDoneEvent
23006 *
23007 * @param {string} xml The BPMN 2.0 XML to be imported.
23008 * @param {ModdleElement|string} [bpmnDiagram] The optional diagram or Id of the BPMN diagram to open.
23009 *
23010 * @return {Promise<ImportXMLResult>} A promise resolving with warnings that were produced during the import.
23011 */
23012 BaseViewer.prototype.importXML = async function importXML(xml, bpmnDiagram) {
23013
23014 const self = this;
23015
23016 function ParseCompleteEvent(data) {
23017 return self.get('eventBus').createEvent(data);
23018 }
23019
23020 let aggregatedWarnings = [];
23021 try {
23022
23023 // hook in pre-parse listeners +
23024 // allow xml manipulation
23025
23026 /**
23027 * A `import.parse.start` event.
23028 *
23029 * @event BaseViewer#ImportParseStartEvent
23030 * @type {ImportParseStartEvent}
23031 */
23032 xml = this._emit('import.parse.start', { xml: xml }) || xml;
23033
23034 let parseResult;
23035 try {
23036 parseResult = await this._moddle.fromXML(xml, 'bpmn:Definitions');
23037 } catch (error) {
23038 this._emit('import.parse.complete', {
23039 error
23040 });
23041
23042 throw error;
23043 }
23044
23045 let definitions = parseResult.rootElement;
23046 const references = parseResult.references;
23047 const parseWarnings = parseResult.warnings;
23048 const elementsById = parseResult.elementsById;
23049
23050 aggregatedWarnings = aggregatedWarnings.concat(parseWarnings);
23051
23052 // hook in post parse listeners +
23053 // allow definitions manipulation
23054
23055 /**
23056 * A `import.parse.complete` event.
23057 *
23058 * @event BaseViewer#ImportParseCompleteEvent
23059 * @type {ImportParseCompleteEvent}
23060 */
23061 definitions = this._emit('import.parse.complete', ParseCompleteEvent({
23062 error: null,
23063 definitions: definitions,
23064 elementsById: elementsById,
23065 references: references,
23066 warnings: aggregatedWarnings
23067 })) || definitions;
23068
23069 const importResult = await this.importDefinitions(definitions, bpmnDiagram);
23070
23071 aggregatedWarnings = aggregatedWarnings.concat(importResult.warnings);
23072
23073 /**
23074 * A `import.parse.complete` event.
23075 *
23076 * @event BaseViewer#ImportDoneEvent
23077 * @type {ImportDoneEvent}
23078 */
23079 this._emit('import.done', { error: null, warnings: aggregatedWarnings });
23080
23081 return { warnings: aggregatedWarnings };
23082 } catch (err) {
23083 let error = err;
23084 aggregatedWarnings = aggregatedWarnings.concat(error.warnings || []);
23085 addWarningsToError(error, aggregatedWarnings);
23086
23087 error = checkValidationError(error);
23088
23089 this._emit('import.done', { error, warnings: error.warnings });
23090
23091 throw error;
23092 }
23093 };
23094
23095
23096 /**
23097 * Import parsed definitions and render a BPMN 2.0 diagram.
23098 *
23099 * Once finished the viewer reports back the result to the
23100 * provided callback function with (err, warnings).
23101 *
23102 * ## Life-Cycle Events
23103 *
23104 * During import the viewer will fire life-cycle events:
23105 *
23106 * * import.render.start (graphical import start)
23107 * * import.render.complete (graphical import finished)
23108 *
23109 * You can use these events to hook into the life-cycle.
23110 *
23111 * @throws {ImportDefinitionsError} An error thrown during the import of the definitions.
23112 *
23113 * @param {ModdleElement} definitions The definitions.
23114 * @param {ModdleElement|string} [bpmnDiagram] The optional diagram or ID of the BPMN diagram to open.
23115 *
23116 * @return {Promise<ImportDefinitionsResult>} A promise resolving with warnings that were produced during the import.
23117 */
23118 BaseViewer.prototype.importDefinitions = async function importDefinitions(definitions, bpmnDiagram) {
23119 this._setDefinitions(definitions);
23120 const result = await this.open(bpmnDiagram);
23121
23122 return { warnings: result.warnings };
23123 };
23124
23125
23126 /**
23127 * Open diagram of previously imported XML.
23128 *
23129 * Once finished the viewer reports back the result to the
23130 * provided callback function with (err, warnings).
23131 *
23132 * ## Life-Cycle Events
23133 *
23134 * During switch the viewer will fire life-cycle events:
23135 *
23136 * * import.render.start (graphical import start)
23137 * * import.render.complete (graphical import finished)
23138 *
23139 * You can use these events to hook into the life-cycle.
23140 *
23141 * @throws {OpenError} An error thrown during opening.
23142 *
23143 * @param {ModdleElement|string} bpmnDiagramOrId The diagram or Id of the BPMN diagram to open.
23144 *
23145 * @return {Promise<OpenResult>} A promise resolving with warnings that were produced during opening.
23146 */
23147 BaseViewer.prototype.open = async function open(bpmnDiagramOrId) {
23148
23149 const definitions = this._definitions;
23150 let bpmnDiagram = bpmnDiagramOrId;
23151
23152 if (!definitions) {
23153 const error = new Error('no XML imported');
23154 addWarningsToError(error, []);
23155
23156 throw error;
23157 }
23158
23159 if (typeof bpmnDiagramOrId === 'string') {
23160 bpmnDiagram = findBPMNDiagram(definitions, bpmnDiagramOrId);
23161
23162 if (!bpmnDiagram) {
23163 const error = new Error('BPMNDiagram <' + bpmnDiagramOrId + '> not found');
23164 addWarningsToError(error, []);
23165
23166 throw error;
23167 }
23168 }
23169
23170 // clear existing rendered diagram
23171 // catch synchronous exceptions during #clear()
23172 try {
23173 this.clear();
23174 } catch (error) {
23175 addWarningsToError(error, []);
23176
23177 throw error;
23178 }
23179
23180 // perform graphical import
23181 const { warnings } = await importBpmnDiagram(this, definitions, bpmnDiagram);
23182
23183 return { warnings };
23184 };
23185
23186 /**
23187 * Export the currently displayed BPMN 2.0 diagram as
23188 * a BPMN 2.0 XML document.
23189 *
23190 * ## Life-Cycle Events
23191 *
23192 * During XML saving the viewer will fire life-cycle events:
23193 *
23194 * * saveXML.start (before serialization)
23195 * * saveXML.serialized (after xml generation)
23196 * * saveXML.done (everything done)
23197 *
23198 * You can use these events to hook into the life-cycle.
23199 *
23200 * @throws {Error} An error thrown during export.
23201 *
23202 * @fires BaseViewer#SaveXMLStart
23203 * @fires BaseViewer#SaveXMLDone
23204 *
23205 * @param {SaveXMLOptions} [options] The options.
23206 *
23207 * @return {Promise<SaveXMLResult>} A promise resolving with the XML.
23208 */
23209 BaseViewer.prototype.saveXML = async function saveXML(options) {
23210
23211 options = options || {};
23212
23213 let definitions = this._definitions,
23214 error, xml;
23215
23216 try {
23217 if (!definitions) {
23218 throw new Error('no definitions loaded');
23219 }
23220
23221 // allow to fiddle around with definitions
23222
23223 /**
23224 * A `saveXML.start` event.
23225 *
23226 * @event BaseViewer#SaveXMLStartEvent
23227 * @type {SaveXMLStartEvent}
23228 */
23229 definitions = this._emit('saveXML.start', {
23230 definitions
23231 }) || definitions;
23232
23233 const result = await this._moddle.toXML(definitions, options);
23234 xml = result.xml;
23235
23236 xml = this._emit('saveXML.serialized', {
23237 xml
23238 }) || xml;
23239 } catch (err) {
23240 error = err;
23241 }
23242
23243 const result = error ? { error } : { xml };
23244
23245 /**
23246 * A `saveXML.done` event.
23247 *
23248 * @event BaseViewer#SaveXMLDoneEvent
23249 * @type {SaveXMLDoneEvent}
23250 */
23251 this._emit('saveXML.done', result);
23252
23253 if (error) {
23254 throw error;
23255 }
23256
23257 return result;
23258 };
23259
23260
23261 /**
23262 * Export the currently displayed BPMN 2.0 diagram as
23263 * an SVG image.
23264 *
23265 * ## Life-Cycle Events
23266 *
23267 * During SVG saving the viewer will fire life-cycle events:
23268 *
23269 * * saveSVG.start (before serialization)
23270 * * saveSVG.done (everything done)
23271 *
23272 * You can use these events to hook into the life-cycle.
23273 *
23274 * @throws {Error} An error thrown during export.
23275 *
23276 * @fires BaseViewer#SaveSVGDone
23277 *
23278 * @return {Promise<SaveSVGResult>} A promise resolving with the SVG.
23279 */
23280 BaseViewer.prototype.saveSVG = async function saveSVG() {
23281 this._emit('saveSVG.start');
23282
23283 let svg, err;
23284
23285 try {
23286 const canvas = this.get('canvas');
23287
23288 const contentNode = canvas.getActiveLayer(),
23289 defsNode = query('defs', canvas._svg);
23290
23291 const contents = innerSVG(contentNode),
23292 defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
23293
23294 const bbox = contentNode.getBBox();
23295
23296 svg =
23297 '<?xml version="1.0" encoding="utf-8"?>\n' +
23298 '<!-- created with bpmn-js / http://bpmn.io -->\n' +
23299 '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
23300 '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
23301 'width="' + bbox.width + '" height="' + bbox.height + '" ' +
23302 'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
23303 defs + contents +
23304 '</svg>';
23305 } catch (e) {
23306 err = e;
23307 }
23308
23309 /**
23310 * A `saveSVG.done` event.
23311 *
23312 * @event BaseViewer#SaveSVGDoneEvent
23313 * @type {SaveSVGDoneEvent}
23314 */
23315 this._emit('saveSVG.done', {
23316 error: err,
23317 svg: svg
23318 });
23319
23320 if (err) {
23321 throw err;
23322 }
23323
23324 return { svg };
23325 };
23326
23327 BaseViewer.prototype._setDefinitions = function(definitions) {
23328 this._definitions = definitions;
23329 };
23330
23331 /**
23332 * Return modules to instantiate with.
23333 *
23334 * @return {ModuleDeclaration[]} The modules.
23335 */
23336 BaseViewer.prototype.getModules = function() {
23337 return this._modules;
23338 };
23339
23340 /**
23341 * Remove all drawn elements from the viewer.
23342 *
23343 * After calling this method the viewer can still be reused for opening another
23344 * diagram.
23345 */
23346 BaseViewer.prototype.clear = function() {
23347 if (!this.getDefinitions()) {
23348
23349 // no diagram to clear
23350 return;
23351 }
23352
23353 // remove drawn elements
23354 Diagram.prototype.clear.call(this);
23355 };
23356
23357 /**
23358 * Destroy the viewer instance and remove all its remainders from the document
23359 * tree.
23360 */
23361 BaseViewer.prototype.destroy = function() {
23362
23363 // diagram destroy
23364 Diagram.prototype.destroy.call(this);
23365
23366 // dom detach
23367 remove$1(this._container);
23368 };
23369
23370 /**
23371 * Register an event listener.
23372 *
23373 * Remove an event listener via {@link BaseViewer#off}.
23374 *
23375 * @template T
23376 *
23377 * @param {string|string[]} events The event(s) to listen to.
23378 * @param {number} [priority] The priority with which to listen.
23379 * @param {EventBusEventCallback<T>} callback The callback.
23380 * @param {any} [that] Value of `this` the callback will be called with.
23381 */
23382 BaseViewer.prototype.on = function(events, priority, callback, that) {
23383 return this.get('eventBus').on(events, priority, callback, that);
23384 };
23385
23386 /**
23387 * Remove an event listener.
23388 *
23389 * @param {string|string[]} events The event(s).
23390 * @param {Function} [callback] The callback.
23391 */
23392 BaseViewer.prototype.off = function(events, callback) {
23393 this.get('eventBus').off(events, callback);
23394 };
23395
23396 /**
23397 * Attach the viewer to an HTML element.
23398 *
23399 * @param {HTMLElement} parentNode The parent node to attach to.
23400 */
23401 BaseViewer.prototype.attachTo = function(parentNode) {
23402
23403 if (!parentNode) {
23404 throw new Error('parentNode required');
23405 }
23406
23407 // ensure we detach from the
23408 // previous, old parent
23409 this.detach();
23410
23411 // unwrap jQuery if provided
23412 if (parentNode.get && parentNode.constructor.prototype.jquery) {
23413 parentNode = parentNode.get(0);
23414 }
23415
23416 if (typeof parentNode === 'string') {
23417 parentNode = query(parentNode);
23418 }
23419
23420 parentNode.appendChild(this._container);
23421
23422 this._emit('attach', {});
23423
23424 this.get('canvas').resized();
23425 };
23426
23427 /**
23428 * Get the definitions model element.
23429 *
23430 * @return {ModdleElement} The definitions model element.
23431 */
23432 BaseViewer.prototype.getDefinitions = function() {
23433 return this._definitions;
23434 };
23435
23436 /**
23437 * Detach the viewer.
23438 *
23439 * @fires BaseViewer#DetachEvent
23440 */
23441 BaseViewer.prototype.detach = function() {
23442
23443 const container = this._container,
23444 parentNode = container.parentNode;
23445
23446 if (!parentNode) {
23447 return;
23448 }
23449
23450 /**
23451 * A `detach` event.
23452 *
23453 * @event BaseViewer#DetachEvent
23454 * @type {Object}
23455 */
23456 this._emit('detach', {});
23457
23458 parentNode.removeChild(container);
23459 };
23460
23461 BaseViewer.prototype._init = function(container, moddle, options) {
23462
23463 const baseModules = options.modules || this.getModules(options),
23464 additionalModules = options.additionalModules || [],
23465 staticModules = [
23466 {
23467 bpmnjs: [ 'value', this ],
23468 moddle: [ 'value', moddle ]
23469 }
23470 ];
23471
23472 const diagramModules = [].concat(staticModules, baseModules, additionalModules);
23473
23474 const diagramOptions = assign$1(omit(options, [ 'additionalModules' ]), {
23475 canvas: assign$1({}, options.canvas, { container: container }),
23476 modules: diagramModules
23477 });
23478
23479 // invoke diagram constructor
23480 Diagram.call(this, diagramOptions);
23481
23482 if (options && options.container) {
23483 this.attachTo(options.container);
23484 }
23485 };
23486
23487 /**
23488 * Emit an event on the underlying {@link EventBus}
23489 *
23490 * @param {string} type
23491 * @param {Object} event
23492 *
23493 * @return {Object} The return value after calling all event listeners.
23494 */
23495 BaseViewer.prototype._emit = function(type, event) {
23496 return this.get('eventBus').fire(type, event);
23497 };
23498
23499 /**
23500 * @param {BaseViewerOptions} options
23501 *
23502 * @return {HTMLElement}
23503 */
23504 BaseViewer.prototype._createContainer = function(options) {
23505
23506 const container = domify$1('<div class="bjs-container"></div>');
23507
23508 assign(container, {
23509 width: ensureUnit(options.width),
23510 height: ensureUnit(options.height),
23511 position: options.position
23512 });
23513
23514 return container;
23515 };
23516
23517 /**
23518 * @param {BaseViewerOptions} options
23519 *
23520 * @return {Moddle}
23521 */
23522 BaseViewer.prototype._createModdle = function(options) {
23523 const moddleOptions = assign$1({}, this._moddleExtensions, options.moddleExtensions);
23524
23525 return new simple(moddleOptions);
23526 };
23527
23528 BaseViewer.prototype._modules = [];
23529
23530 // helpers ///////////////
23531
23532 function addWarningsToError(err, warningsAry) {
23533 err.warnings = warningsAry;
23534 return err;
23535 }
23536
23537 function checkValidationError(err) {
23538
23539 // check if we can help the user by indicating wrong BPMN 2.0 xml
23540 // (in case he or the exporting tool did not get that right)
23541
23542 const pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/;
23543 const match = pattern.exec(err.message);
23544
23545 if (match) {
23546 err.message =
23547 'unparsable content <' + match[1] + '> detected; ' +
23548 'this may indicate an invalid BPMN 2.0 diagram file' + match[2];
23549 }
23550
23551 return err;
23552 }
23553
23554 const DEFAULT_OPTIONS = {
23555 width: '100%',
23556 height: '100%',
23557 position: 'relative'
23558 };
23559
23560
23561 /**
23562 * Ensure the passed argument is a proper unit (defaulting to px)
23563 */
23564 function ensureUnit(val) {
23565 return val + (isNumber(val) ? 'px' : '');
23566 }
23567
23568
23569 /**
23570 * Find BPMNDiagram in definitions by ID
23571 *
23572 * @param {ModdleElement<Definitions>} definitions
23573 * @param {string} diagramId
23574 *
23575 * @return {ModdleElement<BPMNDiagram>|null}
23576 */
23577 function findBPMNDiagram(definitions, diagramId) {
23578 if (!diagramId) {
23579 return null;
23580 }
23581
23582 return find(definitions.diagrams, function(element) {
23583 return element.id === diagramId;
23584 }) || null;
23585 }
23586
23587 /**
23588 * Adds the project logo to the diagram container as
23589 * required by the bpmn.io license.
23590 *
23591 * @see http://bpmn.io/license
23592 *
23593 * @param {Element} container
23594 */
23595 function addProjectLogo(container) {
23596 const img = BPMNIO_IMG;
23597
23598 const linkMarkup =
23599 '<a href="http://bpmn.io" ' +
23600 'target="_blank" ' +
23601 'class="bjs-powered-by" ' +
23602 'title="Powered by bpmn.io" ' +
23603 '>' +
23604 img +
23605 '</a>';
23606
23607 const linkElement = domify$1(linkMarkup);
23608
23609 assign(query('svg', linkElement), LOGO_STYLES);
23610 assign(linkElement, LINK_STYLES, {
23611 position: 'absolute',
23612 bottom: '15px',
23613 right: '15px',
23614 zIndex: '100'
23615 });
23616
23617 container.appendChild(linkElement);
23618
23619 event.bind(linkElement, 'click', function(event) {
23620 open();
23621
23622 event.preventDefault();
23623 });
23624 }
23625
23626 /* </project-logo> */
23627
23628 /**
23629 * @typedef { import('./BaseViewer').BaseViewerOptions } BaseViewerOptions
23630 */
23631
23632 /**
23633 * A viewer for BPMN 2.0 diagrams.
23634 *
23635 * Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include
23636 * additional features.
23637 *
23638 *
23639 * ## Extending the Viewer
23640 *
23641 * In order to extend the viewer pass extension modules to bootstrap via the
23642 * `additionalModules` option. An extension module is an object that exposes
23643 * named services.
23644 *
23645 * The following example depicts the integration of a simple
23646 * logging component that integrates with interaction events:
23647 *
23648 *
23649 * ```javascript
23650 *
23651 * // logging component
23652 * function InteractionLogger(eventBus) {
23653 * eventBus.on('element.hover', function(event) {
23654 * console.log()
23655 * })
23656 * }
23657 *
23658 * InteractionLogger.$inject = [ 'eventBus' ]; // minification save
23659 *
23660 * // extension module
23661 * var extensionModule = {
23662 * __init__: [ 'interactionLogger' ],
23663 * interactionLogger: [ 'type', InteractionLogger ]
23664 * };
23665 *
23666 * // extend the viewer
23667 * var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] });
23668 * bpmnViewer.importXML(...);
23669 * ```
23670 *
23671 * @param {BaseViewerOptions} [options] The options to configure the viewer.
23672 */
23673 function Viewer(options) {
23674 BaseViewer.call(this, options);
23675 }
23676
23677 e(Viewer, BaseViewer);
23678
23679 // modules the viewer is composed of
23680 Viewer.prototype._modules = [
23681 CoreModule$1,
23682 DrilldownModdule,
23683 OutlineModule,
23684 OverlaysModule,
23685 SelectionModule,
23686 TranslateModule
23687 ];
23688
23689 // default moddle extensions the viewer is composed of
23690 Viewer.prototype._moddleExtensions = {};
23691
23692 var KEYS_COPY = [ 'c', 'C' ];
23693 var KEYS_PASTE = [ 'v', 'V' ];
23694 var KEYS_REDO = [ 'y', 'Y' ];
23695 var KEYS_UNDO = [ 'z', 'Z' ];
23696
23697 /**
23698 * Returns true if event was triggered with any modifier
23699 * @param {KeyboardEvent} event
23700 */
23701 function hasModifier(event) {
23702 return (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey);
23703 }
23704
23705 /**
23706 * @param {KeyboardEvent} event
23707 * @return {boolean}
23708 */
23709 function isCmd(event) {
23710
23711 // ensure we don't react to AltGr
23712 // (mapped to CTRL + ALT)
23713 if (event.altKey) {
23714 return false;
23715 }
23716
23717 return event.ctrlKey || event.metaKey;
23718 }
23719
23720 /**
23721 * Checks if key pressed is one of provided keys.
23722 *
23723 * @param {string|string[]} keys
23724 * @param {KeyboardEvent} event
23725 * @return {boolean}
23726 */
23727 function isKey(keys, event) {
23728 keys = isArray$2(keys) ? keys : [ keys ];
23729
23730 return keys.indexOf(event.key) !== -1 || keys.indexOf(event.code) !== -1;
23731 }
23732
23733 /**
23734 * @param {KeyboardEvent} event
23735 */
23736 function isShift(event) {
23737 return event.shiftKey;
23738 }
23739
23740 /**
23741 * @param {KeyboardEvent} event
23742 */
23743 function isCopy(event) {
23744 return isCmd(event) && isKey(KEYS_COPY, event);
23745 }
23746
23747 /**
23748 * @param {KeyboardEvent} event
23749 */
23750 function isPaste(event) {
23751 return isCmd(event) && isKey(KEYS_PASTE, event);
23752 }
23753
23754 /**
23755 * @param {KeyboardEvent} event
23756 */
23757 function isUndo(event) {
23758 return isCmd(event) && !isShift(event) && isKey(KEYS_UNDO, event);
23759 }
23760
23761 /**
23762 * @param {KeyboardEvent} event
23763 */
23764 function isRedo(event) {
23765 return isCmd(event) && (
23766 isKey(KEYS_REDO, event) || (
23767 isKey(KEYS_UNDO, event) && isShift(event)
23768 )
23769 );
23770 }
23771
23772 /**
23773 * @typedef {import('../../core/EventBus').default} EventBus
23774 *
23775 * @typedef {({ keyEvent: KeyboardEvent }) => any} Listener
23776 */
23777
23778 var KEYDOWN_EVENT = 'keyboard.keydown',
23779 KEYUP_EVENT = 'keyboard.keyup';
23780
23781 var HANDLE_MODIFIER_ATTRIBUTE = 'input-handle-modified-keys';
23782
23783 var DEFAULT_PRIORITY = 1000;
23784
23785 /**
23786 * A keyboard abstraction that may be activated and
23787 * deactivated by users at will, consuming global key events
23788 * and triggering diagram actions.
23789 *
23790 * For keys pressed down, keyboard fires `keyboard.keydown` event.
23791 * The event context contains one field which is `KeyboardEvent` event.
23792 *
23793 * The implementation fires the following key events that allow
23794 * other components to hook into key handling:
23795 *
23796 * - keyboard.bind
23797 * - keyboard.unbind
23798 * - keyboard.init
23799 * - keyboard.destroy
23800 *
23801 * All events contain one field which is node.
23802 *
23803 * A default binding for the keyboard may be specified via the
23804 * `keyboard.bindTo` configuration option.
23805 *
23806 * @param {Object} config
23807 * @param {EventTarget} [config.bindTo]
23808 * @param {EventBus} eventBus
23809 */
23810 function Keyboard(config, eventBus) {
23811 var self = this;
23812
23813 this._config = config || {};
23814 this._eventBus = eventBus;
23815
23816 this._keydownHandler = this._keydownHandler.bind(this);
23817 this._keyupHandler = this._keyupHandler.bind(this);
23818
23819 // properly clean dom registrations
23820 eventBus.on('diagram.destroy', function() {
23821 self._fire('destroy');
23822
23823 self.unbind();
23824 });
23825
23826 eventBus.on('diagram.init', function() {
23827 self._fire('init');
23828 });
23829
23830 eventBus.on('attach', function() {
23831 if (config && config.bindTo) {
23832 self.bind(config.bindTo);
23833 }
23834 });
23835
23836 eventBus.on('detach', function() {
23837 self.unbind();
23838 });
23839 }
23840
23841 Keyboard.$inject = [
23842 'config.keyboard',
23843 'eventBus'
23844 ];
23845
23846 Keyboard.prototype._keydownHandler = function(event) {
23847 this._keyHandler(event, KEYDOWN_EVENT);
23848 };
23849
23850 Keyboard.prototype._keyupHandler = function(event) {
23851 this._keyHandler(event, KEYUP_EVENT);
23852 };
23853
23854 Keyboard.prototype._keyHandler = function(event, type) {
23855 var eventBusResult;
23856
23857 if (this._isEventIgnored(event)) {
23858 return;
23859 }
23860
23861 var context = {
23862 keyEvent: event
23863 };
23864
23865 eventBusResult = this._eventBus.fire(type || KEYDOWN_EVENT, context);
23866
23867 if (eventBusResult) {
23868 event.preventDefault();
23869 }
23870 };
23871
23872 Keyboard.prototype._isEventIgnored = function(event) {
23873 if (event.defaultPrevented) {
23874 return true;
23875 }
23876
23877 return (
23878 isInput(event.target) || (
23879 isButton(event.target) && isKey([ ' ', 'Enter' ], event)
23880 )
23881 ) && this._isModifiedKeyIgnored(event);
23882 };
23883
23884 Keyboard.prototype._isModifiedKeyIgnored = function(event) {
23885 if (!isCmd(event)) {
23886 return true;
23887 }
23888
23889 var allowedModifiers = this._getAllowedModifiers(event.target);
23890 return allowedModifiers.indexOf(event.key) === -1;
23891 };
23892
23893 Keyboard.prototype._getAllowedModifiers = function(element) {
23894 var modifierContainer = closest(element, '[' + HANDLE_MODIFIER_ATTRIBUTE + ']', true);
23895
23896 if (!modifierContainer || (this._node && !this._node.contains(modifierContainer))) {
23897 return [];
23898 }
23899
23900 return modifierContainer.getAttribute(HANDLE_MODIFIER_ATTRIBUTE).split(',');
23901 };
23902
23903 /**
23904 * Bind keyboard events to the given DOM node.
23905 *
23906 * @param {EventTarget} node
23907 */
23908 Keyboard.prototype.bind = function(node) {
23909
23910 // make sure that the keyboard is only bound once to the DOM
23911 this.unbind();
23912
23913 this._node = node;
23914
23915 // bind key events
23916 event.bind(node, 'keydown', this._keydownHandler);
23917 event.bind(node, 'keyup', this._keyupHandler);
23918
23919 this._fire('bind');
23920 };
23921
23922 /**
23923 * @return {EventTarget}
23924 */
23925 Keyboard.prototype.getBinding = function() {
23926 return this._node;
23927 };
23928
23929 Keyboard.prototype.unbind = function() {
23930 var node = this._node;
23931
23932 if (node) {
23933 this._fire('unbind');
23934
23935 // unbind key events
23936 event.unbind(node, 'keydown', this._keydownHandler);
23937 event.unbind(node, 'keyup', this._keyupHandler);
23938 }
23939
23940 this._node = null;
23941 };
23942
23943 /**
23944 * @param {string} event
23945 */
23946 Keyboard.prototype._fire = function(event) {
23947 this._eventBus.fire('keyboard.' + event, { node: this._node });
23948 };
23949
23950 /**
23951 * Add a listener function that is notified with `KeyboardEvent` whenever
23952 * the keyboard is bound and the user presses a key. If no priority is
23953 * provided, the default value of 1000 is used.
23954 *
23955 * @param {number} [priority]
23956 * @param {Listener} listener
23957 * @param {string} [type='keyboard.keydown']
23958 */
23959 Keyboard.prototype.addListener = function(priority, listener, type) {
23960 if (isFunction(priority)) {
23961 type = listener;
23962 listener = priority;
23963 priority = DEFAULT_PRIORITY;
23964 }
23965
23966 this._eventBus.on(type || KEYDOWN_EVENT, priority, listener);
23967 };
23968
23969 /**
23970 * Remove a listener function.
23971 *
23972 * @param {Listener} listener
23973 * @param {string} [type='keyboard.keydown']
23974 */
23975 Keyboard.prototype.removeListener = function(listener, type) {
23976 this._eventBus.off(type || KEYDOWN_EVENT, listener);
23977 };
23978
23979 Keyboard.prototype.hasModifier = hasModifier;
23980 Keyboard.prototype.isCmd = isCmd;
23981 Keyboard.prototype.isShift = isShift;
23982 Keyboard.prototype.isKey = isKey;
23983
23984
23985
23986 // helpers ///////
23987
23988 function isInput(target) {
23989 return target && (matches(target, 'input, textarea') || target.contentEditable === 'true');
23990 }
23991
23992 function isButton(target) {
23993 return target && matches(target, 'button, input[type=submit], input[type=button], a[href], [aria-role=button]');
23994 }
23995
23996 var LOW_PRIORITY = 500;
23997
23998
23999 /**
24000 * Adds default keyboard bindings.
24001 *
24002 * This does not pull in any features will bind only actions that
24003 * have previously been registered against the editorActions component.
24004 *
24005 * @param {EventBus} eventBus
24006 * @param {Keyboard} keyboard
24007 */
24008 function KeyboardBindings(eventBus, keyboard) {
24009
24010 var self = this;
24011
24012 eventBus.on('editorActions.init', LOW_PRIORITY, function(event) {
24013
24014 var editorActions = event.editorActions;
24015
24016 self.registerBindings(keyboard, editorActions);
24017 });
24018 }
24019
24020 KeyboardBindings.$inject = [
24021 'eventBus',
24022 'keyboard'
24023 ];
24024
24025
24026 /**
24027 * Register available keyboard bindings.
24028 *
24029 * @param {Keyboard} keyboard
24030 * @param {EditorActions} editorActions
24031 */
24032 KeyboardBindings.prototype.registerBindings = function(keyboard, editorActions) {
24033
24034 /**
24035 * Add keyboard binding if respective editor action
24036 * is registered.
24037 *
24038 * @param {string} action name
24039 * @param {Function} fn that implements the key binding
24040 */
24041 function addListener(action, fn) {
24042
24043 if (editorActions.isRegistered(action)) {
24044 keyboard.addListener(fn);
24045 }
24046 }
24047
24048
24049 // undo
24050 // (CTRL|CMD) + Z
24051 addListener('undo', function(context) {
24052
24053 var event = context.keyEvent;
24054
24055 if (isUndo(event)) {
24056 editorActions.trigger('undo');
24057
24058 return true;
24059 }
24060 });
24061
24062 // redo
24063 // CTRL + Y
24064 // CMD + SHIFT + Z
24065 addListener('redo', function(context) {
24066
24067 var event = context.keyEvent;
24068
24069 if (isRedo(event)) {
24070 editorActions.trigger('redo');
24071
24072 return true;
24073 }
24074 });
24075
24076 // copy
24077 // CTRL/CMD + C
24078 addListener('copy', function(context) {
24079
24080 var event = context.keyEvent;
24081
24082 if (isCopy(event)) {
24083 editorActions.trigger('copy');
24084
24085 return true;
24086 }
24087 });
24088
24089 // paste
24090 // CTRL/CMD + V
24091 addListener('paste', function(context) {
24092
24093 var event = context.keyEvent;
24094
24095 if (isPaste(event)) {
24096 editorActions.trigger('paste');
24097
24098 return true;
24099 }
24100 });
24101
24102 // zoom in one step
24103 // CTRL/CMD + +
24104 addListener('stepZoom', function(context) {
24105
24106 var event = context.keyEvent;
24107
24108 // quirk: it has to be triggered by `=` as well to work on international keyboard layout
24109 // cf: https://github.com/bpmn-io/bpmn-js/issues/1362#issuecomment-722989754
24110 if (isKey([ '+', 'Add', '=' ], event) && isCmd(event)) {
24111 editorActions.trigger('stepZoom', { value: 1 });
24112
24113 return true;
24114 }
24115 });
24116
24117 // zoom out one step
24118 // CTRL + -
24119 addListener('stepZoom', function(context) {
24120
24121 var event = context.keyEvent;
24122
24123 if (isKey([ '-', 'Subtract' ], event) && isCmd(event)) {
24124 editorActions.trigger('stepZoom', { value: -1 });
24125
24126 return true;
24127 }
24128 });
24129
24130 // zoom to the default level
24131 // CTRL + 0
24132 addListener('zoom', function(context) {
24133
24134 var event = context.keyEvent;
24135
24136 if (isKey('0', event) && isCmd(event)) {
24137 editorActions.trigger('zoom', { value: 1 });
24138
24139 return true;
24140 }
24141 });
24142
24143 // delete selected element
24144 // DEL
24145 addListener('removeSelection', function(context) {
24146
24147 var event = context.keyEvent;
24148
24149 if (isKey([ 'Backspace', 'Delete', 'Del' ], event)) {
24150 editorActions.trigger('removeSelection');
24151
24152 return true;
24153 }
24154 });
24155 };
24156
24157 /**
24158 * @type { import('didi').ModuleDeclaration }
24159 */
24160 var KeyboardModule = {
24161 __init__: [ 'keyboard', 'keyboardBindings' ],
24162 keyboard: [ 'type', Keyboard ],
24163 keyboardBindings: [ 'type', KeyboardBindings ]
24164 };
24165
24166 /**
24167 * @typedef {import('../../core/Canvas').default} Canvas
24168 * @typedef {import('../../features/keyboard/Keyboard').default} Keyboard
24169 */
24170
24171 var DEFAULT_CONFIG = {
24172 moveSpeed: 50,
24173 moveSpeedAccelerated: 200
24174 };
24175
24176
24177 /**
24178 * A feature that allows users to move the canvas using the keyboard.
24179 *
24180 * @param {Object} config
24181 * @param {number} [config.moveSpeed=50]
24182 * @param {number} [config.moveSpeedAccelerated=200]
24183 * @param {Keyboard} keyboard
24184 * @param {Canvas} canvas
24185 */
24186 function KeyboardMove(
24187 config,
24188 keyboard,
24189 canvas
24190 ) {
24191
24192 var self = this;
24193
24194 this._config = assign$1({}, DEFAULT_CONFIG, config || {});
24195
24196 keyboard.addListener(arrowsListener);
24197
24198
24199 function arrowsListener(context) {
24200
24201 var event = context.keyEvent,
24202 config = self._config;
24203
24204 if (!keyboard.isCmd(event)) {
24205 return;
24206 }
24207
24208 if (keyboard.isKey([
24209 'ArrowLeft', 'Left',
24210 'ArrowUp', 'Up',
24211 'ArrowDown', 'Down',
24212 'ArrowRight', 'Right'
24213 ], event)) {
24214
24215 var speed = (
24216 keyboard.isShift(event) ?
24217 config.moveSpeedAccelerated :
24218 config.moveSpeed
24219 );
24220
24221 var direction;
24222
24223 switch (event.key) {
24224 case 'ArrowLeft':
24225 case 'Left':
24226 direction = 'left';
24227 break;
24228 case 'ArrowUp':
24229 case 'Up':
24230 direction = 'up';
24231 break;
24232 case 'ArrowRight':
24233 case 'Right':
24234 direction = 'right';
24235 break;
24236 case 'ArrowDown':
24237 case 'Down':
24238 direction = 'down';
24239 break;
24240 }
24241
24242 self.moveCanvas({
24243 speed: speed,
24244 direction: direction
24245 });
24246
24247 return true;
24248 }
24249 }
24250
24251 /**
24252 * @param {{
24253 * direction: 'up' | 'down' | 'left' | 'right';
24254 * speed: number;
24255 * }} options
24256 */
24257 this.moveCanvas = function(options) {
24258
24259 var dx = 0,
24260 dy = 0,
24261 speed = options.speed;
24262
24263 var actualSpeed = speed / Math.min(Math.sqrt(canvas.viewbox().scale), 1);
24264
24265 switch (options.direction) {
24266 case 'left': // Left
24267 dx = actualSpeed;
24268 break;
24269 case 'up': // Up
24270 dy = actualSpeed;
24271 break;
24272 case 'right': // Right
24273 dx = -actualSpeed;
24274 break;
24275 case 'down': // Down
24276 dy = -actualSpeed;
24277 break;
24278 }
24279
24280 canvas.scroll({
24281 dx: dx,
24282 dy: dy
24283 });
24284 };
24285
24286 }
24287
24288
24289 KeyboardMove.$inject = [
24290 'config.keyboardMove',
24291 'keyboard',
24292 'canvas'
24293 ];
24294
24295 /**
24296 * @type { import('didi').ModuleDeclaration }
24297 */
24298 var KeyboardMoveModule = {
24299 __depends__: [
24300 KeyboardModule
24301 ],
24302 __init__: [ 'keyboardMove' ],
24303 keyboardMove: [ 'type', KeyboardMove ]
24304 };
24305
24306 var CURSOR_CLS_PATTERN = /^djs-cursor-.*$/;
24307
24308 /**
24309 * @param {string} mode
24310 */
24311 function set(mode) {
24312 var classes$1 = classes(document.body);
24313
24314 classes$1.removeMatching(CURSOR_CLS_PATTERN);
24315
24316 if (mode) {
24317 classes$1.add('djs-cursor-' + mode);
24318 }
24319 }
24320
24321 function unset() {
24322 set(null);
24323 }
24324
24325 /**
24326 * @typedef {import('../core/EventBus').default} EventBus
24327 */
24328
24329 var TRAP_PRIORITY = 5000;
24330
24331 /**
24332 * Installs a click trap that prevents a ghost click following a dragging operation.
24333 *
24334 * @param {EventBus} eventBus
24335 * @param {string} [eventName='element.click']
24336 *
24337 * @return {() => void} a function to immediately remove the installed trap.
24338 */
24339 function install(eventBus, eventName) {
24340
24341 eventName = eventName || 'element.click';
24342
24343 function trap() {
24344 return false;
24345 }
24346
24347 eventBus.once(eventName, TRAP_PRIORITY, trap);
24348
24349 return function() {
24350 eventBus.off(eventName, trap);
24351 };
24352 }
24353
24354 /**
24355 * @typedef {import('../util/Types').Point} Point
24356 * @typedef {import('../util/Types').Rect} Rect
24357 */
24358
24359
24360 /**
24361 * @param {Point} a
24362 * @param {Point} b
24363 * @return {Point}
24364 */
24365 function delta(a, b) {
24366 return {
24367 x: a.x - b.x,
24368 y: a.y - b.y
24369 };
24370 }
24371
24372 /**
24373 * @typedef {import('../../core/Canvas').default} Canvas
24374 * @typedef {import('../../core/EventBus').default} EventBus
24375 */
24376
24377 var THRESHOLD = 15;
24378
24379
24380 /**
24381 * Move the canvas via mouse.
24382 *
24383 * @param {EventBus} eventBus
24384 * @param {Canvas} canvas
24385 */
24386 function MoveCanvas(eventBus, canvas) {
24387
24388 var context;
24389
24390
24391 // listen for move on element mouse down;
24392 // allow others to hook into the event before us though
24393 // (dragging / element moving will do this)
24394 eventBus.on('element.mousedown', 500, function(e) {
24395 return handleStart(e.originalEvent);
24396 });
24397
24398
24399 function handleMove(event) {
24400
24401 var start = context.start,
24402 button = context.button,
24403 position = toPoint(event),
24404 delta$1 = delta(position, start);
24405
24406 if (!context.dragging && length(delta$1) > THRESHOLD) {
24407 context.dragging = true;
24408
24409 if (button === 0) {
24410 install(eventBus);
24411 }
24412
24413 set('grab');
24414 }
24415
24416 if (context.dragging) {
24417
24418 var lastPosition = context.last || context.start;
24419
24420 delta$1 = delta(position, lastPosition);
24421
24422 canvas.scroll({
24423 dx: delta$1.x,
24424 dy: delta$1.y
24425 });
24426
24427 context.last = position;
24428 }
24429
24430 // prevent select
24431 event.preventDefault();
24432 }
24433
24434
24435 function handleEnd(event$1) {
24436 event.unbind(document, 'mousemove', handleMove);
24437 event.unbind(document, 'mouseup', handleEnd);
24438
24439 context = null;
24440
24441 unset();
24442 }
24443
24444 function handleStart(event$1) {
24445
24446 // event is already handled by '.djs-draggable'
24447 if (closest(event$1.target, '.djs-draggable')) {
24448 return;
24449 }
24450
24451 var button = event$1.button;
24452
24453 // reject right mouse button or modifier key
24454 if (button >= 2 || event$1.ctrlKey || event$1.shiftKey || event$1.altKey) {
24455 return;
24456 }
24457
24458 context = {
24459 button: button,
24460 start: toPoint(event$1)
24461 };
24462
24463 event.bind(document, 'mousemove', handleMove);
24464 event.bind(document, 'mouseup', handleEnd);
24465
24466 // we've handled the event
24467 return true;
24468 }
24469
24470 this.isActive = function() {
24471 return !!context;
24472 };
24473
24474 }
24475
24476
24477 MoveCanvas.$inject = [
24478 'eventBus',
24479 'canvas'
24480 ];
24481
24482
24483
24484 // helpers ///////
24485
24486 function length(point) {
24487 return Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
24488 }
24489
24490 /**
24491 * @type { import('didi').ModuleDeclaration }
24492 */
24493 var MoveCanvasModule = {
24494 __init__: [ 'moveCanvas' ],
24495 moveCanvas: [ 'type', MoveCanvas ]
24496 };
24497
24498 /**
24499 * Get the logarithm of x with base 10.
24500 *
24501 * @param {number} x
24502 */
24503 function log10(x) {
24504 return Math.log(x) / Math.log(10);
24505 }
24506
24507 /**
24508 * Get step size for given range and number of steps.
24509 *
24510 * @param {Object} range
24511 * @param {number} range.min
24512 * @param {number} range.max
24513 * @param {number} steps
24514 */
24515 function getStepSize(range, steps) {
24516
24517 var minLinearRange = log10(range.min),
24518 maxLinearRange = log10(range.max);
24519
24520 var absoluteLinearRange = Math.abs(minLinearRange) + Math.abs(maxLinearRange);
24521
24522 return absoluteLinearRange / steps;
24523 }
24524
24525 /**
24526 * @param {Object} range
24527 * @param {number} range.min
24528 * @param {number} range.max
24529 * @param {number} scale
24530 */
24531 function cap(range, scale) {
24532 return Math.max(range.min, Math.min(range.max, scale));
24533 }
24534
24535 /**
24536 * @typedef {import('../../core/Canvas').default} Canvas
24537 * @typedef {import('../../core/EventBus').default} EventBus
24538 *
24539 * @typedef {import('../../util/Types').Point} Point
24540 * @typedef {import('../../util/Types').ScrollDelta} ScrollDelta
24541 */
24542
24543 var sign = Math.sign || function(n) {
24544 return n >= 0 ? 1 : -1;
24545 };
24546
24547 var RANGE = { min: 0.2, max: 4 },
24548 NUM_STEPS = 10;
24549
24550 var DELTA_THRESHOLD = 0.1;
24551
24552 var DEFAULT_SCALE = 0.75;
24553
24554 /**
24555 * An implementation of zooming and scrolling within the
24556 * {@link Canvas} via the mouse wheel.
24557 *
24558 * Mouse wheel zooming / scrolling may be disabled using
24559 * the {@link toggle(enabled)} method.
24560 *
24561 * @param {Object} [config]
24562 * @param {boolean} [config.enabled=true] default enabled state
24563 * @param {number} [config.scale=.75] scroll sensivity
24564 * @param {EventBus} eventBus
24565 * @param {Canvas} canvas
24566 */
24567 function ZoomScroll(config, eventBus, canvas) {
24568
24569 config = config || {};
24570
24571 this._enabled = false;
24572
24573 this._canvas = canvas;
24574 this._container = canvas._container;
24575
24576 this._handleWheel = bind$2(this._handleWheel, this);
24577
24578 this._totalDelta = 0;
24579 this._scale = config.scale || DEFAULT_SCALE;
24580
24581 var self = this;
24582
24583 eventBus.on('canvas.init', function(e) {
24584 self._init(config.enabled !== false);
24585 });
24586 }
24587
24588 ZoomScroll.$inject = [
24589 'config.zoomScroll',
24590 'eventBus',
24591 'canvas'
24592 ];
24593
24594 /**
24595 * @param {ScrollDelta} delta
24596 */
24597 ZoomScroll.prototype.scroll = function scroll(delta) {
24598 this._canvas.scroll(delta);
24599 };
24600
24601
24602 ZoomScroll.prototype.reset = function reset() {
24603 this._canvas.zoom('fit-viewport');
24604 };
24605
24606 /**
24607 * Zoom depending on delta.
24608 *
24609 * @param {number} delta
24610 * @param {Point} position
24611 */
24612 ZoomScroll.prototype.zoom = function zoom(delta, position) {
24613
24614 // zoom with half the step size of stepZoom
24615 var stepSize = getStepSize(RANGE, NUM_STEPS * 2);
24616
24617 // add until threshold reached
24618 this._totalDelta += delta;
24619
24620 if (Math.abs(this._totalDelta) > DELTA_THRESHOLD) {
24621 this._zoom(delta, position, stepSize);
24622
24623 // reset
24624 this._totalDelta = 0;
24625 }
24626 };
24627
24628
24629 ZoomScroll.prototype._handleWheel = function handleWheel(event) {
24630
24631 // event is already handled by '.djs-scrollable'
24632 if (closest(event.target, '.djs-scrollable', true)) {
24633 return;
24634 }
24635
24636 var element = this._container;
24637
24638 event.preventDefault();
24639
24640 // pinch to zoom is mapped to wheel + ctrlKey = true
24641 // in modern browsers (!)
24642
24643 var isZoom = event.ctrlKey || (isMac() && event.metaKey);
24644
24645 var isHorizontalScroll = event.shiftKey;
24646
24647 var factor = -1 * this._scale,
24648 delta;
24649
24650 if (isZoom) {
24651 factor *= event.deltaMode === 0 ? 0.020 : 0.32;
24652 } else {
24653 factor *= event.deltaMode === 0 ? 1.0 : 16.0;
24654 }
24655
24656 if (isZoom) {
24657 var elementRect = element.getBoundingClientRect();
24658
24659 var offset = {
24660 x: event.clientX - elementRect.left,
24661 y: event.clientY - elementRect.top
24662 };
24663
24664 delta = (
24665 Math.sqrt(
24666 Math.pow(event.deltaY, 2) +
24667 Math.pow(event.deltaX, 2)
24668 ) * sign(event.deltaY) * factor
24669 );
24670
24671 // zoom in relative to diagram {x,y} coordinates
24672 this.zoom(delta, offset);
24673 } else {
24674
24675 if (isHorizontalScroll) {
24676 delta = {
24677 dx: factor * event.deltaY,
24678 dy: 0
24679 };
24680 } else {
24681 delta = {
24682 dx: factor * event.deltaX,
24683 dy: factor * event.deltaY
24684 };
24685 }
24686
24687 this.scroll(delta);
24688 }
24689 };
24690
24691 /**
24692 * Zoom with fixed step size.
24693 *
24694 * @param {number} delta Zoom delta (1 for zooming in, -1 for zooming out).
24695 * @param {Point} [position]
24696 */
24697 ZoomScroll.prototype.stepZoom = function stepZoom(delta, position) {
24698
24699 var stepSize = getStepSize(RANGE, NUM_STEPS);
24700
24701 this._zoom(delta, position, stepSize);
24702 };
24703
24704
24705 /**
24706 * Zoom in/out given a step size.
24707 *
24708 * @param {number} delta
24709 * @param {Point} [position]
24710 * @param {number} stepSize
24711 */
24712 ZoomScroll.prototype._zoom = function(delta, position, stepSize) {
24713 var canvas = this._canvas;
24714
24715 var direction = delta > 0 ? 1 : -1;
24716
24717 var currentLinearZoomLevel = log10(canvas.zoom());
24718
24719 // snap to a proximate zoom step
24720 var newLinearZoomLevel = Math.round(currentLinearZoomLevel / stepSize) * stepSize;
24721
24722 // increase or decrease one zoom step in the given direction
24723 newLinearZoomLevel += stepSize * direction;
24724
24725 // calculate the absolute logarithmic zoom level based on the linear zoom level
24726 // (e.g. 2 for an absolute x2 zoom)
24727 var newLogZoomLevel = Math.pow(10, newLinearZoomLevel);
24728
24729 canvas.zoom(cap(RANGE, newLogZoomLevel), position);
24730 };
24731
24732
24733 /**
24734 * Toggle the zoom scroll ability via mouse wheel.
24735 *
24736 * @param {boolean} [newEnabled] new enabled state
24737 */
24738 ZoomScroll.prototype.toggle = function toggle(newEnabled) {
24739
24740 var element = this._container;
24741 var handleWheel = this._handleWheel;
24742
24743 var oldEnabled = this._enabled;
24744
24745 if (typeof newEnabled === 'undefined') {
24746 newEnabled = !oldEnabled;
24747 }
24748
24749 // only react on actual changes
24750 if (oldEnabled !== newEnabled) {
24751
24752 // add or remove wheel listener based on
24753 // changed enabled state
24754 event[newEnabled ? 'bind' : 'unbind'](element, 'wheel', handleWheel, false);
24755 }
24756
24757 this._enabled = newEnabled;
24758
24759 return newEnabled;
24760 };
24761
24762
24763 ZoomScroll.prototype._init = function(newEnabled) {
24764 this.toggle(newEnabled);
24765 };
24766
24767 /**
24768 * @type { import('didi').ModuleDeclaration }
24769 */
24770 var ZoomScrollModule = {
24771 __init__: [ 'zoomScroll' ],
24772 zoomScroll: [ 'type', ZoomScroll ]
24773 };
24774
24775 /**
24776 * @typedef { import('./BaseViewer').BaseViewerOptions } BaseViewerOptions
24777 */
24778
24779 /**
24780 * A viewer with mouse and keyboard navigation features.
24781 *
24782 * @param {BaseViewerOptions} [options]
24783 */
24784 function NavigatedViewer(options) {
24785 Viewer.call(this, options);
24786 }
24787
24788 e(NavigatedViewer, Viewer);
24789
24790
24791 NavigatedViewer.prototype._navigationModules = [
24792 KeyboardMoveModule,
24793 MoveCanvasModule,
24794 ZoomScrollModule
24795 ];
24796
24797 NavigatedViewer.prototype._modules = [].concat(
24798 Viewer.prototype._modules,
24799 NavigatedViewer.prototype._navigationModules
24800 );
24801
24802 return NavigatedViewer;
24803
24804}));