1 /*!
2  * bpmn-js - bpmn-modeler v8.8.2
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: 2021-10-20
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 	var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
20 
21 	var inherits_browser = {exports: {}};
22 
23 	if (typeof Object.create === 'function') {
24 	  // implementation from standard node.js 'util' module
25 	  inherits_browser.exports = function inherits(ctor, superCtor) {
26 	    if (superCtor) {
27 	      ctor.super_ = superCtor;
28 	      ctor.prototype = Object.create(superCtor.prototype, {
29 	        constructor: {
30 	          value: ctor,
31 	          enumerable: false,
32 	          writable: true,
33 	          configurable: true
34 	        }
35 	      });
36 	    }
37 	  };
38 	} else {
39 	  // old school shim for old browsers
40 	  inherits_browser.exports = function inherits(ctor, superCtor) {
41 	    if (superCtor) {
42 	      ctor.super_ = superCtor;
43 	      var TempCtor = function () {};
44 	      TempCtor.prototype = superCtor.prototype;
45 	      ctor.prototype = new TempCtor();
46 	      ctor.prototype.constructor = ctor;
47 	    }
48 	  };
49 	}
50 
51 	var inherits$1 = inherits_browser.exports;
52 
53 	function createCommonjsModule(fn, module) {
54 		return module = { exports: {} }, fn(module, module.exports), module.exports;
55 	}
56 
57 	var hat_1 = createCommonjsModule(function (module) {
58 	var hat = module.exports = function (bits, base) {
59 	    if (!base) base = 16;
60 	    if (bits === undefined) bits = 128;
61 	    if (bits <= 0) return '0';
62 
63 	    var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
64 	    for (var i = 2; digits === Infinity; i *= 2) {
65 	        digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
66 	    }
67 
68 	    var rem = digits - Math.floor(digits);
69 
70 	    var res = '';
71 
72 	    for (var i = 0; i < Math.floor(digits); i++) {
73 	        var x = Math.floor(Math.random() * base).toString(base);
74 	        res = x + res;
75 	    }
76 
77 	    if (rem) {
78 	        var b = Math.pow(base, rem);
79 	        var x = Math.floor(Math.random() * b).toString(base);
80 	        res = x + res;
81 	    }
82 
83 	    var parsed = parseInt(res, base);
84 	    if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
85 	        return hat(bits, base)
86 	    }
87 	    else return res;
88 	};
89 
90 	hat.rack = function (bits, base, expandBy) {
91 	    var fn = function (data) {
92 	        var iters = 0;
93 	        do {
94 	            if (iters ++ > 10) {
95 	                if (expandBy) bits += expandBy;
96 	                else throw new Error('too many ID collisions, use more bits')
97 	            }
98 
99 	            var id = hat(bits, base);
100 	        } while (Object.hasOwnProperty.call(hats, id));
101 
102 	        hats[id] = data;
103 	        return id;
104 	    };
105 	    var hats = fn.hats = {};
106 
107 	    fn.get = function (id) {
108 	        return fn.hats[id];
109 	    };
110 
111 	    fn.set = function (id, value) {
112 	        fn.hats[id] = value;
113 	        return fn;
114 	    };
115 
116 	    fn.bits = bits || 128;
117 	    fn.base = base || 16;
118 	    return fn;
119 	};
120 	});
121 
122 	/**
123 	 * Create a new id generator / cache instance.
124 	 *
125 	 * You may optionally provide a seed that is used internally.
126 	 *
127 	 * @param {Seed} seed
128 	 */
129 
130 	function Ids(seed) {
131 	  if (!(this instanceof Ids)) {
132 	    return new Ids(seed);
133 	  }
134 
135 	  seed = seed || [128, 36, 1];
136 	  this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed;
137 	}
138 	/**
139 	 * Generate a next id.
140 	 *
141 	 * @param {Object} [element] element to bind the id to
142 	 *
143 	 * @return {String} id
144 	 */
145 
146 	Ids.prototype.next = function (element) {
147 	  return this._seed(element || true);
148 	};
149 	/**
150 	 * Generate a next id with a given prefix.
151 	 *
152 	 * @param {Object} [element] element to bind the id to
153 	 *
154 	 * @return {String} id
155 	 */
156 
157 
158 	Ids.prototype.nextPrefixed = function (prefix, element) {
159 	  var id;
160 
161 	  do {
162 	    id = prefix + this.next(true);
163 	  } while (this.assigned(id)); // claim {prefix}{random}
164 
165 
166 	  this.claim(id, element); // return
167 
168 	  return id;
169 	};
170 	/**
171 	 * Manually claim an existing id.
172 	 *
173 	 * @param {String} id
174 	 * @param {String} [element] element the id is claimed by
175 	 */
176 
177 
178 	Ids.prototype.claim = function (id, element) {
179 	  this._seed.set(id, element || true);
180 	};
181 	/**
182 	 * Returns true if the given id has already been assigned.
183 	 *
184 	 * @param  {String} id
185 	 * @return {Boolean}
186 	 */
187 
188 
189 	Ids.prototype.assigned = function (id) {
190 	  return this._seed.get(id) || false;
191 	};
192 	/**
193 	 * Unclaim an id.
194 	 *
195 	 * @param  {String} id the id to unclaim
196 	 */
197 
198 
199 	Ids.prototype.unclaim = function (id) {
200 	  delete this._seed.hats[id];
201 	};
202 	/**
203 	 * Clear all claimed ids.
204 	 */
205 
206 
207 	Ids.prototype.clear = function () {
208 	  var hats = this._seed.hats,
209 	      id;
210 
211 	  for (id in hats) {
212 	    this.unclaim(id);
213 	  }
214 	};
215 
216 	/**
217 	 * Flatten array, one level deep.
218 	 *
219 	 * @param {Array<?>} arr
220 	 *
221 	 * @return {Array<?>}
222 	 */
223 	function flatten(arr) {
224 	  return Array.prototype.concat.apply([], arr);
225 	}
226 
227 	var nativeToString = Object.prototype.toString;
228 	var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
229 	function isUndefined$1(obj) {
230 	  return obj === undefined;
231 	}
232 	function isDefined(obj) {
233 	  return obj !== undefined;
234 	}
235 	function isNil(obj) {
236 	  return obj == null;
237 	}
238 	function isArray$2(obj) {
239 	  return nativeToString.call(obj) === '[object Array]';
240 	}
241 	function isObject(obj) {
242 	  return nativeToString.call(obj) === '[object Object]';
243 	}
244 	function isNumber(obj) {
245 	  return nativeToString.call(obj) === '[object Number]';
246 	}
247 	function isFunction(obj) {
248 	  var tag = nativeToString.call(obj);
249 	  return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]';
250 	}
251 	function isString(obj) {
252 	  return nativeToString.call(obj) === '[object String]';
253 	}
254 	/**
255 	 * Ensure collection is an array.
256 	 *
257 	 * @param {Object} obj
258 	 */
259 
260 	function ensureArray(obj) {
261 	  if (isArray$2(obj)) {
262 	    return;
263 	  }
264 
265 	  throw new Error('must supply array');
266 	}
267 	/**
268 	 * Return true, if target owns a property with the given key.
269 	 *
270 	 * @param {Object} target
271 	 * @param {String} key
272 	 *
273 	 * @return {Boolean}
274 	 */
275 
276 	function has(target, key) {
277 	  return nativeHasOwnProperty.call(target, key);
278 	}
279 
280 	/**
281 	 * Find element in collection.
282 	 *
283 	 * @param  {Array|Object} collection
284 	 * @param  {Function|Object} matcher
285 	 *
286 	 * @return {Object}
287 	 */
288 
289 	function find(collection, matcher) {
290 	  matcher = toMatcher(matcher);
291 	  var match;
292 	  forEach(collection, function (val, key) {
293 	    if (matcher(val, key)) {
294 	      match = val;
295 	      return false;
296 	    }
297 	  });
298 	  return match;
299 	}
300 	/**
301 	 * Find element index in collection.
302 	 *
303 	 * @param  {Array|Object} collection
304 	 * @param  {Function} matcher
305 	 *
306 	 * @return {Object}
307 	 */
308 
309 	function findIndex(collection, matcher) {
310 	  matcher = toMatcher(matcher);
311 	  var idx = isArray$2(collection) ? -1 : undefined;
312 	  forEach(collection, function (val, key) {
313 	    if (matcher(val, key)) {
314 	      idx = key;
315 	      return false;
316 	    }
317 	  });
318 	  return idx;
319 	}
320 	/**
321 	 * Find element in collection.
322 	 *
323 	 * @param  {Array|Object} collection
324 	 * @param  {Function} matcher
325 	 *
326 	 * @return {Array} result
327 	 */
328 
329 	function filter(collection, matcher) {
330 	  var result = [];
331 	  forEach(collection, function (val, key) {
332 	    if (matcher(val, key)) {
333 	      result.push(val);
334 	    }
335 	  });
336 	  return result;
337 	}
338 	/**
339 	 * Iterate over collection; returning something
340 	 * (non-undefined) will stop iteration.
341 	 *
342 	 * @param  {Array|Object} collection
343 	 * @param  {Function} iterator
344 	 *
345 	 * @return {Object} return result that stopped the iteration
346 	 */
347 
348 	function forEach(collection, iterator) {
349 	  var val, result;
350 
351 	  if (isUndefined$1(collection)) {
352 	    return;
353 	  }
354 
355 	  var convertKey = isArray$2(collection) ? toNum : identity;
356 
357 	  for (var key in collection) {
358 	    if (has(collection, key)) {
359 	      val = collection[key];
360 	      result = iterator(val, convertKey(key));
361 
362 	      if (result === false) {
363 	        return val;
364 	      }
365 	    }
366 	  }
367 	}
368 	/**
369 	 * Return collection without element.
370 	 *
371 	 * @param  {Array} arr
372 	 * @param  {Function} matcher
373 	 *
374 	 * @return {Array}
375 	 */
376 
377 	function without(arr, matcher) {
378 	  if (isUndefined$1(arr)) {
379 	    return [];
380 	  }
381 
382 	  ensureArray(arr);
383 	  matcher = toMatcher(matcher);
384 	  return arr.filter(function (el, idx) {
385 	    return !matcher(el, idx);
386 	  });
387 	}
388 	/**
389 	 * Reduce collection, returning a single result.
390 	 *
391 	 * @param  {Object|Array} collection
392 	 * @param  {Function} iterator
393 	 * @param  {Any} result
394 	 *
395 	 * @return {Any} result returned from last iterator
396 	 */
397 
398 	function reduce(collection, iterator, result) {
399 	  forEach(collection, function (value, idx) {
400 	    result = iterator(result, value, idx);
401 	  });
402 	  return result;
403 	}
404 	/**
405 	 * Return true if every element in the collection
406 	 * matches the criteria.
407 	 *
408 	 * @param  {Object|Array} collection
409 	 * @param  {Function} matcher
410 	 *
411 	 * @return {Boolean}
412 	 */
413 
414 	function every(collection, matcher) {
415 	  return !!reduce(collection, function (matches, val, key) {
416 	    return matches && matcher(val, key);
417 	  }, true);
418 	}
419 	/**
420 	 * Return true if some elements in the collection
421 	 * match the criteria.
422 	 *
423 	 * @param  {Object|Array} collection
424 	 * @param  {Function} matcher
425 	 *
426 	 * @return {Boolean}
427 	 */
428 
429 	function some(collection, matcher) {
430 	  return !!find(collection, matcher);
431 	}
432 	/**
433 	 * Transform a collection into another collection
434 	 * by piping each member through the given fn.
435 	 *
436 	 * @param  {Object|Array}   collection
437 	 * @param  {Function} fn
438 	 *
439 	 * @return {Array} transformed collection
440 	 */
441 
442 	function map$1(collection, fn) {
443 	  var result = [];
444 	  forEach(collection, function (val, key) {
445 	    result.push(fn(val, key));
446 	  });
447 	  return result;
448 	}
449 	/**
450 	 * Get the collections keys.
451 	 *
452 	 * @param  {Object|Array} collection
453 	 *
454 	 * @return {Array}
455 	 */
456 
457 	function keys(collection) {
458 	  return collection && Object.keys(collection) || [];
459 	}
460 	/**
461 	 * Shorthand for `keys(o).length`.
462 	 *
463 	 * @param  {Object|Array} collection
464 	 *
465 	 * @return {Number}
466 	 */
467 
468 	function size(collection) {
469 	  return keys(collection).length;
470 	}
471 	/**
472 	 * Get the values in the collection.
473 	 *
474 	 * @param  {Object|Array} collection
475 	 *
476 	 * @return {Array}
477 	 */
478 
479 	function values(collection) {
480 	  return map$1(collection, function (val) {
481 	    return val;
482 	  });
483 	}
484 	/**
485 	 * Group collection members by attribute.
486 	 *
487 	 * @param  {Object|Array} collection
488 	 * @param  {Function} extractor
489 	 *
490 	 * @return {Object} map with { attrValue => [ a, b, c ] }
491 	 */
492 
493 	function groupBy(collection, extractor) {
494 	  var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
495 	  extractor = toExtractor(extractor);
496 	  forEach(collection, function (val) {
497 	    var discriminator = extractor(val) || '_';
498 	    var group = grouped[discriminator];
499 
500 	    if (!group) {
501 	      group = grouped[discriminator] = [];
502 	    }
503 
504 	    group.push(val);
505 	  });
506 	  return grouped;
507 	}
508 	function uniqueBy(extractor) {
509 	  extractor = toExtractor(extractor);
510 	  var grouped = {};
511 
512 	  for (var _len = arguments.length, collections = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
513 	    collections[_key - 1] = arguments[_key];
514 	  }
515 
516 	  forEach(collections, function (c) {
517 	    return groupBy(c, extractor, grouped);
518 	  });
519 	  var result = map$1(grouped, function (val, key) {
520 	    return val[0];
521 	  });
522 	  return result;
523 	}
524 	var unionBy = uniqueBy;
525 	/**
526 	 * Sort collection by criteria.
527 	 *
528 	 * @param  {Object|Array} collection
529 	 * @param  {String|Function} extractor
530 	 *
531 	 * @return {Array}
532 	 */
533 
534 	function sortBy(collection, extractor) {
535 	  extractor = toExtractor(extractor);
536 	  var sorted = [];
537 	  forEach(collection, function (value, key) {
538 	    var disc = extractor(value, key);
539 	    var entry = {
540 	      d: disc,
541 	      v: value
542 	    };
543 
544 	    for (var idx = 0; idx < sorted.length; idx++) {
545 	      var d = sorted[idx].d;
546 
547 	      if (disc < d) {
548 	        sorted.splice(idx, 0, entry);
549 	        return;
550 	      }
551 	    } // not inserted, append (!)
552 
553 
554 	    sorted.push(entry);
555 	  });
556 	  return map$1(sorted, function (e) {
557 	    return e.v;
558 	  });
559 	}
560 	/**
561 	 * Create an object pattern matcher.
562 	 *
563 	 * @example
564 	 *
565 	 * const matcher = matchPattern({ id: 1 });
566 	 *
567 	 * var element = find(elements, matcher);
568 	 *
569 	 * @param  {Object} pattern
570 	 *
571 	 * @return {Function} matcherFn
572 	 */
573 
574 	function matchPattern(pattern) {
575 	  return function (el) {
576 	    return every(pattern, function (val, key) {
577 	      return el[key] === val;
578 	    });
579 	  };
580 	}
581 
582 	function toExtractor(extractor) {
583 	  return isFunction(extractor) ? extractor : function (e) {
584 	    return e[extractor];
585 	  };
586 	}
587 
588 	function toMatcher(matcher) {
589 	  return isFunction(matcher) ? matcher : function (e) {
590 	    return e === matcher;
591 	  };
592 	}
593 
594 	function identity(arg) {
595 	  return arg;
596 	}
597 
598 	function toNum(arg) {
599 	  return Number(arg);
600 	}
601 
602 	/**
603 	 * Debounce fn, calling it only once if
604 	 * the given time elapsed between calls.
605 	 *
606 	 * @param  {Function} fn
607 	 * @param  {Number} timeout
608 	 *
609 	 * @return {Function} debounced function
610 	 */
611 	function debounce(fn, timeout) {
612 	  var timer;
613 	  var lastArgs;
614 	  var lastThis;
615 	  var lastNow;
616 
617 	  function fire() {
618 	    var now = Date.now();
619 	    var scheduledDiff = lastNow + timeout - now;
620 
621 	    if (scheduledDiff > 0) {
622 	      return schedule(scheduledDiff);
623 	    }
624 
625 	    fn.apply(lastThis, lastArgs);
626 	    timer = lastNow = lastArgs = lastThis = undefined;
627 	  }
628 
629 	  function schedule(timeout) {
630 	    timer = setTimeout(fire, timeout);
631 	  }
632 
633 	  return function () {
634 	    lastNow = Date.now();
635 
636 	    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
637 	      args[_key] = arguments[_key];
638 	    }
639 
640 	    lastArgs = args;
641 	    lastThis = this; // ensure an execution is scheduled
642 
643 	    if (!timer) {
644 	      schedule(timeout);
645 	    }
646 	  };
647 	}
648 	/**
649 	 * Bind function against target <this>.
650 	 *
651 	 * @param  {Function} fn
652 	 * @param  {Object}   target
653 	 *
654 	 * @return {Function} bound function
655 	 */
656 
657 	function bind$2(fn, target) {
658 	  return fn.bind(target);
659 	}
660 
661 	function _extends() {
662 	  _extends = Object.assign || function (target) {
663 	    for (var i = 1; i < arguments.length; i++) {
664 	      var source = arguments[i];
665 
666 	      for (var key in source) {
667 	        if (Object.prototype.hasOwnProperty.call(source, key)) {
668 	          target[key] = source[key];
669 	        }
670 	      }
671 	    }
672 
673 	    return target;
674 	  };
675 
676 	  return _extends.apply(this, arguments);
677 	}
678 
679 	/**
680 	 * Convenience wrapper for `Object.assign`.
681 	 *
682 	 * @param {Object} target
683 	 * @param {...Object} others
684 	 *
685 	 * @return {Object} the target
686 	 */
687 
688 	function assign(target) {
689 	  for (var _len = arguments.length, others = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
690 	    others[_key - 1] = arguments[_key];
691 	  }
692 
693 	  return _extends.apply(void 0, [target].concat(others));
694 	}
695 	/**
696 	 * Pick given properties from the target object.
697 	 *
698 	 * @param {Object} target
699 	 * @param {Array} properties
700 	 *
701 	 * @return {Object} target
702 	 */
703 
704 	function pick(target, properties) {
705 	  var result = {};
706 	  var obj = Object(target);
707 	  forEach(properties, function (prop) {
708 	    if (prop in obj) {
709 	      result[prop] = target[prop];
710 	    }
711 	  });
712 	  return result;
713 	}
714 	/**
715 	 * Pick all target properties, excluding the given ones.
716 	 *
717 	 * @param {Object} target
718 	 * @param {Array} properties
719 	 *
720 	 * @return {Object} target
721 	 */
722 
723 	function omit(target, properties) {
724 	  var result = {};
725 	  var obj = Object(target);
726 	  forEach(obj, function (prop, key) {
727 	    if (properties.indexOf(key) === -1) {
728 	      result[key] = prop;
729 	    }
730 	  });
731 	  return result;
732 	}
733 
734 	/**
735 	 * Set attribute `name` to `val`, or get attr `name`.
736 	 *
737 	 * @param {Element} el
738 	 * @param {String} name
739 	 * @param {String} [val]
740 	 * @api public
741 	 */
742 	function attr$1(el, name, val) {
743 	  // get
744 	  if (arguments.length == 2) {
745 	    return el.getAttribute(name);
746 	  }
747 
748 	  // remove
749 	  if (val === null) {
750 	    return el.removeAttribute(name);
751 	  }
752 
753 	  // set
754 	  el.setAttribute(name, val);
755 
756 	  return el;
757 	}
758 
759 	var indexOf$1 = [].indexOf;
760 
761 	var indexof = function(arr, obj){
762 	  if (indexOf$1) return arr.indexOf(obj);
763 	  for (var i = 0; i < arr.length; ++i) {
764 	    if (arr[i] === obj) return i;
765 	  }
766 	  return -1;
767 	};
768 
769 	/**
770 	 * Taken from https://github.com/component/classes
771 	 *
772 	 * Without the component bits.
773 	 */
774 
775 	/**
776 	 * Whitespace regexp.
777 	 */
778 
779 	var re$1 = /\s+/;
780 
781 	/**
782 	 * toString reference.
783 	 */
784 
785 	var toString$1 = Object.prototype.toString;
786 
787 	/**
788 	 * Wrap `el` in a `ClassList`.
789 	 *
790 	 * @param {Element} el
791 	 * @return {ClassList}
792 	 * @api public
793 	 */
794 
795 	function classes$1(el) {
796 	  return new ClassList$1(el);
797 	}
798 
799 	/**
800 	 * Initialize a new ClassList for `el`.
801 	 *
802 	 * @param {Element} el
803 	 * @api private
804 	 */
805 
806 	function ClassList$1(el) {
807 	  if (!el || !el.nodeType) {
808 	    throw new Error('A DOM element reference is required');
809 	  }
810 	  this.el = el;
811 	  this.list = el.classList;
812 	}
813 
814 	/**
815 	 * Add class `name` if not already present.
816 	 *
817 	 * @param {String} name
818 	 * @return {ClassList}
819 	 * @api public
820 	 */
821 
822 	ClassList$1.prototype.add = function (name) {
823 	  // classList
824 	  if (this.list) {
825 	    this.list.add(name);
826 	    return this;
827 	  }
828 
829 	  // fallback
830 	  var arr = this.array();
831 	  var i = indexof(arr, name);
832 	  if (!~i) arr.push(name);
833 	  this.el.className = arr.join(' ');
834 	  return this;
835 	};
836 
837 	/**
838 	 * Remove class `name` when present, or
839 	 * pass a regular expression to remove
840 	 * any which match.
841 	 *
842 	 * @param {String|RegExp} name
843 	 * @return {ClassList}
844 	 * @api public
845 	 */
846 
847 	ClassList$1.prototype.remove = function (name) {
848 	  if ('[object RegExp]' == toString$1.call(name)) {
849 	    return this.removeMatching(name);
850 	  }
851 
852 	  // classList
853 	  if (this.list) {
854 	    this.list.remove(name);
855 	    return this;
856 	  }
857 
858 	  // fallback
859 	  var arr = this.array();
860 	  var i = indexof(arr, name);
861 	  if (~i) arr.splice(i, 1);
862 	  this.el.className = arr.join(' ');
863 	  return this;
864 	};
865 
866 	/**
867 	 * Remove all classes matching `re`.
868 	 *
869 	 * @param {RegExp} re
870 	 * @return {ClassList}
871 	 * @api private
872 	 */
873 
874 	ClassList$1.prototype.removeMatching = function (re) {
875 	  var arr = this.array();
876 	  for (var i = 0; i < arr.length; i++) {
877 	    if (re.test(arr[i])) {
878 	      this.remove(arr[i]);
879 	    }
880 	  }
881 	  return this;
882 	};
883 
884 	/**
885 	 * Toggle class `name`, can force state via `force`.
886 	 *
887 	 * For browsers that support classList, but do not support `force` yet,
888 	 * the mistake will be detected and corrected.
889 	 *
890 	 * @param {String} name
891 	 * @param {Boolean} force
892 	 * @return {ClassList}
893 	 * @api public
894 	 */
895 
896 	ClassList$1.prototype.toggle = function (name, force) {
897 	  // classList
898 	  if (this.list) {
899 	    if ('undefined' !== typeof force) {
900 	      if (force !== this.list.toggle(name, force)) {
901 	        this.list.toggle(name); // toggle again to correct
902 	      }
903 	    } else {
904 	      this.list.toggle(name);
905 	    }
906 	    return this;
907 	  }
908 
909 	  // fallback
910 	  if ('undefined' !== typeof force) {
911 	    if (!force) {
912 	      this.remove(name);
913 	    } else {
914 	      this.add(name);
915 	    }
916 	  } else {
917 	    if (this.has(name)) {
918 	      this.remove(name);
919 	    } else {
920 	      this.add(name);
921 	    }
922 	  }
923 
924 	  return this;
925 	};
926 
927 	/**
928 	 * Return an array of classes.
929 	 *
930 	 * @return {Array}
931 	 * @api public
932 	 */
933 
934 	ClassList$1.prototype.array = function () {
935 	  var className = this.el.getAttribute('class') || '';
936 	  var str = className.replace(/^\s+|\s+$/g, '');
937 	  var arr = str.split(re$1);
938 	  if ('' === arr[0]) arr.shift();
939 	  return arr;
940 	};
941 
942 	/**
943 	 * Check if class `name` is present.
944 	 *
945 	 * @param {String} name
946 	 * @return {ClassList}
947 	 * @api public
948 	 */
949 
950 	ClassList$1.prototype.has = ClassList$1.prototype.contains = function (name) {
951 	  return this.list ? this.list.contains(name) : !!~indexof(this.array(), name);
952 	};
953 
954 	/**
955 	 * Remove all children from the given element.
956 	 */
957 	function clear$1(el) {
958 
959 	  var c;
960 
961 	  while (el.childNodes.length) {
962 	    c = el.childNodes[0];
963 	    el.removeChild(c);
964 	  }
965 
966 	  return el;
967 	}
968 
969 	var proto = typeof Element !== 'undefined' ? Element.prototype : {};
970 	var vendor = proto.matches
971 	  || proto.matchesSelector
972 	  || proto.webkitMatchesSelector
973 	  || proto.mozMatchesSelector
974 	  || proto.msMatchesSelector
975 	  || proto.oMatchesSelector;
976 
977 	var matchesSelector = match;
978 
979 	/**
980 	 * Match `el` to `selector`.
981 	 *
982 	 * @param {Element} el
983 	 * @param {String} selector
984 	 * @return {Boolean}
985 	 * @api public
986 	 */
987 
988 	function match(el, selector) {
989 	  if (!el || el.nodeType !== 1) return false;
990 	  if (vendor) return vendor.call(el, selector);
991 	  var nodes = el.parentNode.querySelectorAll(selector);
992 	  for (var i = 0; i < nodes.length; i++) {
993 	    if (nodes[i] == el) return true;
994 	  }
995 	  return false;
996 	}
997 
998 	/**
999 	 * Closest
1000 	 *
1001 	 * @param {Element} el
1002 	 * @param {String} selector
1003 	 * @param {Boolean} checkYourSelf (optional)
1004 	 */
1005 	function closest (element, selector, checkYourSelf) {
1006 	  var currentElem = checkYourSelf ? element : element.parentNode;
1007 
1008 	  while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE && currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) {
1009 
1010 	    if (matchesSelector(currentElem, selector)) {
1011 	      return currentElem;
1012 	    }
1013 
1014 	    currentElem = currentElem.parentNode;
1015 	  }
1016 
1017 	  return matchesSelector(currentElem, selector) ? currentElem : null;
1018 	}
1019 
1020 	var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
1021 	    unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
1022 	    prefix$6 = bind !== 'addEventListener' ? 'on' : '';
1023 
1024 	/**
1025 	 * Bind `el` event `type` to `fn`.
1026 	 *
1027 	 * @param {Element} el
1028 	 * @param {String} type
1029 	 * @param {Function} fn
1030 	 * @param {Boolean} capture
1031 	 * @return {Function}
1032 	 * @api public
1033 	 */
1034 
1035 	var bind_1 = function(el, type, fn, capture){
1036 	  el[bind](prefix$6 + type, fn, capture || false);
1037 	  return fn;
1038 	};
1039 
1040 	/**
1041 	 * Unbind `el` event `type`'s callback `fn`.
1042 	 *
1043 	 * @param {Element} el
1044 	 * @param {String} type
1045 	 * @param {Function} fn
1046 	 * @param {Boolean} capture
1047 	 * @return {Function}
1048 	 * @api public
1049 	 */
1050 
1051 	var unbind_1 = function(el, type, fn, capture){
1052 	  el[unbind](prefix$6 + type, fn, capture || false);
1053 	  return fn;
1054 	};
1055 
1056 	var componentEvent = {
1057 		bind: bind_1,
1058 		unbind: unbind_1
1059 	};
1060 
1061 	/**
1062 	 * Module dependencies.
1063 	 */
1064 
1065 	/**
1066 	 * Delegate event `type` to `selector`
1067 	 * and invoke `fn(e)`. A callback function
1068 	 * is returned which may be passed to `.unbind()`.
1069 	 *
1070 	 * @param {Element} el
1071 	 * @param {String} selector
1072 	 * @param {String} type
1073 	 * @param {Function} fn
1074 	 * @param {Boolean} capture
1075 	 * @return {Function}
1076 	 * @api public
1077 	 */
1078 
1079 	// Some events don't bubble, so we want to bind to the capture phase instead
1080 	// when delegating.
1081 	var forceCaptureEvents = ['focus', 'blur'];
1082 
1083 	function bind$1(el, selector, type, fn, capture) {
1084 	  if (forceCaptureEvents.indexOf(type) !== -1) {
1085 	    capture = true;
1086 	  }
1087 
1088 	  return componentEvent.bind(el, type, function (e) {
1089 	    var target = e.target || e.srcElement;
1090 	    e.delegateTarget = closest(target, selector, true);
1091 	    if (e.delegateTarget) {
1092 	      fn.call(el, e);
1093 	    }
1094 	  }, capture);
1095 	}
1096 
1097 	/**
1098 	 * Unbind event `type`'s callback `fn`.
1099 	 *
1100 	 * @param {Element} el
1101 	 * @param {String} type
1102 	 * @param {Function} fn
1103 	 * @param {Boolean} capture
1104 	 * @api public
1105 	 */
1106 	function unbind$1(el, type, fn, capture) {
1107 	  if (forceCaptureEvents.indexOf(type) !== -1) {
1108 	    capture = true;
1109 	  }
1110 
1111 	  return componentEvent.unbind(el, type, fn, capture);
1112 	}
1113 
1114 	var delegate = {
1115 	  bind: bind$1,
1116 	  unbind: unbind$1
1117 	};
1118 
1119 	/**
1120 	 * Expose `parse`.
1121 	 */
1122 
1123 	var domify = parse$1;
1124 
1125 	/**
1126 	 * Tests for browser support.
1127 	 */
1128 
1129 	var innerHTMLBug = false;
1130 	var bugTestDiv;
1131 	if (typeof document !== 'undefined') {
1132 	  bugTestDiv = document.createElement('div');
1133 	  // Setup
1134 	  bugTestDiv.innerHTML = '  <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
1135 	  // Make sure that link elements get serialized correctly by innerHTML
1136 	  // This requires a wrapper element in IE
1137 	  innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
1138 	  bugTestDiv = undefined;
1139 	}
1140 
1141 	/**
1142 	 * Wrap map from jquery.
1143 	 */
1144 
1145 	var map = {
1146 	  legend: [1, '<fieldset>', '</fieldset>'],
1147 	  tr: [2, '<table><tbody>', '</tbody></table>'],
1148 	  col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
1149 	  // for script/link/style tags to work in IE6-8, you have to wrap
1150 	  // in a div with a non-whitespace character in front, ha!
1151 	  _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
1152 	};
1153 
1154 	map.td =
1155 	map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
1156 
1157 	map.option =
1158 	map.optgroup = [1, '<select multiple="multiple">', '</select>'];
1159 
1160 	map.thead =
1161 	map.tbody =
1162 	map.colgroup =
1163 	map.caption =
1164 	map.tfoot = [1, '<table>', '</table>'];
1165 
1166 	map.polyline =
1167 	map.ellipse =
1168 	map.polygon =
1169 	map.circle =
1170 	map.text =
1171 	map.line =
1172 	map.path =
1173 	map.rect =
1174 	map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
1175 
1176 	/**
1177 	 * Parse `html` and return a DOM Node instance, which could be a TextNode,
1178 	 * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
1179 	 * instance, depending on the contents of the `html` string.
1180 	 *
1181 	 * @param {String} html - HTML string to "domify"
1182 	 * @param {Document} doc - The `document` instance to create the Node for
1183 	 * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
1184 	 * @api private
1185 	 */
1186 
1187 	function parse$1(html, doc) {
1188 	  if ('string' != typeof html) throw new TypeError('String expected');
1189 
1190 	  // default to the global `document` object
1191 	  if (!doc) doc = document;
1192 
1193 	  // tag name
1194 	  var m = /<([\w:]+)/.exec(html);
1195 	  if (!m) return doc.createTextNode(html);
1196 
1197 	  html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
1198 
1199 	  var tag = m[1];
1200 
1201 	  // body support
1202 	  if (tag == 'body') {
1203 	    var el = doc.createElement('html');
1204 	    el.innerHTML = html;
1205 	    return el.removeChild(el.lastChild);
1206 	  }
1207 
1208 	  // wrap map
1209 	  var wrap = map[tag] || map._default;
1210 	  var depth = wrap[0];
1211 	  var prefix = wrap[1];
1212 	  var suffix = wrap[2];
1213 	  var el = doc.createElement('div');
1214 	  el.innerHTML = prefix + html + suffix;
1215 	  while (depth--) el = el.lastChild;
1216 
1217 	  // one element
1218 	  if (el.firstChild == el.lastChild) {
1219 	    return el.removeChild(el.firstChild);
1220 	  }
1221 
1222 	  // several elements
1223 	  var fragment = doc.createDocumentFragment();
1224 	  while (el.firstChild) {
1225 	    fragment.appendChild(el.removeChild(el.firstChild));
1226 	  }
1227 
1228 	  return fragment;
1229 	}
1230 
1231 	function query(selector, el) {
1232 	  el = el || document;
1233 
1234 	  return el.querySelector(selector);
1235 	}
1236 
1237 	function all(selector, el) {
1238 	  el = el || document;
1239 
1240 	  return el.querySelectorAll(selector);
1241 	}
1242 
1243 	function remove$2(el) {
1244 	  el.parentNode && el.parentNode.removeChild(el);
1245 	}
1246 
1247 	function ensureImported(element, target) {
1248 
1249 	  if (element.ownerDocument !== target.ownerDocument) {
1250 	    try {
1251 	      // may fail on webkit
1252 	      return target.ownerDocument.importNode(element, true);
1253 	    } catch (e) {
1254 	      // ignore
1255 	    }
1256 	  }
1257 
1258 	  return element;
1259 	}
1260 
1261 	/**
1262 	 * appendTo utility
1263 	 */
1264 
1265 	/**
1266 	 * Append a node to a target element and return the appended node.
1267 	 *
1268 	 * @param  {SVGElement} element
1269 	 * @param  {SVGElement} target
1270 	 *
1271 	 * @return {SVGElement} the appended node
1272 	 */
1273 	function appendTo(element, target) {
1274 	  return target.appendChild(ensureImported(element, target));
1275 	}
1276 
1277 	/**
1278 	 * append utility
1279 	 */
1280 
1281 	/**
1282 	 * Append a node to an element
1283 	 *
1284 	 * @param  {SVGElement} element
1285 	 * @param  {SVGElement} node
1286 	 *
1287 	 * @return {SVGElement} the element
1288 	 */
1289 	function append(target, node) {
1290 	  appendTo(node, target);
1291 	  return target;
1292 	}
1293 
1294 	/**
1295 	 * attribute accessor utility
1296 	 */
1297 
1298 	var LENGTH_ATTR = 2;
1299 
1300 	var CSS_PROPERTIES = {
1301 	  'alignment-baseline': 1,
1302 	  'baseline-shift': 1,
1303 	  'clip': 1,
1304 	  'clip-path': 1,
1305 	  'clip-rule': 1,
1306 	  'color': 1,
1307 	  'color-interpolation': 1,
1308 	  'color-interpolation-filters': 1,
1309 	  'color-profile': 1,
1310 	  'color-rendering': 1,
1311 	  'cursor': 1,
1312 	  'direction': 1,
1313 	  'display': 1,
1314 	  'dominant-baseline': 1,
1315 	  'enable-background': 1,
1316 	  'fill': 1,
1317 	  'fill-opacity': 1,
1318 	  'fill-rule': 1,
1319 	  'filter': 1,
1320 	  'flood-color': 1,
1321 	  'flood-opacity': 1,
1322 	  'font': 1,
1323 	  'font-family': 1,
1324 	  'font-size': LENGTH_ATTR,
1325 	  'font-size-adjust': 1,
1326 	  'font-stretch': 1,
1327 	  'font-style': 1,
1328 	  'font-variant': 1,
1329 	  'font-weight': 1,
1330 	  'glyph-orientation-horizontal': 1,
1331 	  'glyph-orientation-vertical': 1,
1332 	  'image-rendering': 1,
1333 	  'kerning': 1,
1334 	  'letter-spacing': 1,
1335 	  'lighting-color': 1,
1336 	  'marker': 1,
1337 	  'marker-end': 1,
1338 	  'marker-mid': 1,
1339 	  'marker-start': 1,
1340 	  'mask': 1,
1341 	  'opacity': 1,
1342 	  'overflow': 1,
1343 	  'pointer-events': 1,
1344 	  'shape-rendering': 1,
1345 	  'stop-color': 1,
1346 	  'stop-opacity': 1,
1347 	  'stroke': 1,
1348 	  'stroke-dasharray': 1,
1349 	  'stroke-dashoffset': 1,
1350 	  'stroke-linecap': 1,
1351 	  'stroke-linejoin': 1,
1352 	  'stroke-miterlimit': 1,
1353 	  'stroke-opacity': 1,
1354 	  'stroke-width': LENGTH_ATTR,
1355 	  'text-anchor': 1,
1356 	  'text-decoration': 1,
1357 	  'text-rendering': 1,
1358 	  'unicode-bidi': 1,
1359 	  'visibility': 1,
1360 	  'word-spacing': 1,
1361 	  'writing-mode': 1
1362 	};
1363 
1364 
1365 	function getAttribute(node, name) {
1366 	  if (CSS_PROPERTIES[name]) {
1367 	    return node.style[name];
1368 	  } else {
1369 	    return node.getAttributeNS(null, name);
1370 	  }
1371 	}
1372 
1373 	function setAttribute(node, name, value) {
1374 	  var hyphenated = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1375 
1376 	  var type = CSS_PROPERTIES[hyphenated];
1377 
1378 	  if (type) {
1379 	    // append pixel unit, unless present
1380 	    if (type === LENGTH_ATTR && typeof value === 'number') {
1381 	      value = String(value) + 'px';
1382 	    }
1383 
1384 	    node.style[hyphenated] = value;
1385 	  } else {
1386 	    node.setAttributeNS(null, name, value);
1387 	  }
1388 	}
1389 
1390 	function setAttributes(node, attrs) {
1391 
1392 	  var names = Object.keys(attrs), i, name;
1393 
1394 	  for (i = 0, name; (name = names[i]); i++) {
1395 	    setAttribute(node, name, attrs[name]);
1396 	  }
1397 	}
1398 
1399 	/**
1400 	 * Gets or sets raw attributes on a node.
1401 	 *
1402 	 * @param  {SVGElement} node
1403 	 * @param  {Object} [attrs]
1404 	 * @param  {String} [name]
1405 	 * @param  {String} [value]
1406 	 *
1407 	 * @return {String}
1408 	 */
1409 	function attr(node, name, value) {
1410 	  if (typeof name === 'string') {
1411 	    if (value !== undefined) {
1412 	      setAttribute(node, name, value);
1413 	    } else {
1414 	      return getAttribute(node, name);
1415 	    }
1416 	  } else {
1417 	    setAttributes(node, name);
1418 	  }
1419 
1420 	  return node;
1421 	}
1422 
1423 	/**
1424 	 * Clear utility
1425 	 */
1426 	function index(arr, obj) {
1427 	  if (arr.indexOf) {
1428 	    return arr.indexOf(obj);
1429 	  }
1430 
1431 
1432 	  for (var i = 0; i < arr.length; ++i) {
1433 	    if (arr[i] === obj) {
1434 	      return i;
1435 	    }
1436 	  }
1437 
1438 	  return -1;
1439 	}
1440 
1441 	var re = /\s+/;
1442 
1443 	var toString = Object.prototype.toString;
1444 
1445 	function defined(o) {
1446 	  return typeof o !== 'undefined';
1447 	}
1448 
1449 	/**
1450 	 * Wrap `el` in a `ClassList`.
1451 	 *
1452 	 * @param {Element} el
1453 	 * @return {ClassList}
1454 	 * @api public
1455 	 */
1456 
1457 	function classes(el) {
1458 	  return new ClassList(el);
1459 	}
1460 
1461 	function ClassList(el) {
1462 	  if (!el || !el.nodeType) {
1463 	    throw new Error('A DOM element reference is required');
1464 	  }
1465 	  this.el = el;
1466 	  this.list = el.classList;
1467 	}
1468 
1469 	/**
1470 	 * Add class `name` if not already present.
1471 	 *
1472 	 * @param {String} name
1473 	 * @return {ClassList}
1474 	 * @api public
1475 	 */
1476 
1477 	ClassList.prototype.add = function(name) {
1478 
1479 	  // classList
1480 	  if (this.list) {
1481 	    this.list.add(name);
1482 	    return this;
1483 	  }
1484 
1485 	  // fallback
1486 	  var arr = this.array();
1487 	  var i = index(arr, name);
1488 	  if (!~i) {
1489 	    arr.push(name);
1490 	  }
1491 
1492 	  if (defined(this.el.className.baseVal)) {
1493 	    this.el.className.baseVal = arr.join(' ');
1494 	  } else {
1495 	    this.el.className = arr.join(' ');
1496 	  }
1497 
1498 	  return this;
1499 	};
1500 
1501 	/**
1502 	 * Remove class `name` when present, or
1503 	 * pass a regular expression to remove
1504 	 * any which match.
1505 	 *
1506 	 * @param {String|RegExp} name
1507 	 * @return {ClassList}
1508 	 * @api public
1509 	 */
1510 
1511 	ClassList.prototype.remove = function(name) {
1512 	  if ('[object RegExp]' === toString.call(name)) {
1513 	    return this.removeMatching(name);
1514 	  }
1515 
1516 	  // classList
1517 	  if (this.list) {
1518 	    this.list.remove(name);
1519 	    return this;
1520 	  }
1521 
1522 	  // fallback
1523 	  var arr = this.array();
1524 	  var i = index(arr, name);
1525 	  if (~i) {
1526 	    arr.splice(i, 1);
1527 	  }
1528 	  this.el.className.baseVal = arr.join(' ');
1529 	  return this;
1530 	};
1531 
1532 	/**
1533 	 * Remove all classes matching `re`.
1534 	 *
1535 	 * @param {RegExp} re
1536 	 * @return {ClassList}
1537 	 * @api private
1538 	 */
1539 
1540 	ClassList.prototype.removeMatching = function(re) {
1541 	  var arr = this.array();
1542 	  for (var i = 0; i < arr.length; i++) {
1543 	    if (re.test(arr[i])) {
1544 	      this.remove(arr[i]);
1545 	    }
1546 	  }
1547 	  return this;
1548 	};
1549 
1550 	/**
1551 	 * Toggle class `name`, can force state via `force`.
1552 	 *
1553 	 * For browsers that support classList, but do not support `force` yet,
1554 	 * the mistake will be detected and corrected.
1555 	 *
1556 	 * @param {String} name
1557 	 * @param {Boolean} force
1558 	 * @return {ClassList}
1559 	 * @api public
1560 	 */
1561 
1562 	ClassList.prototype.toggle = function(name, force) {
1563 	  // classList
1564 	  if (this.list) {
1565 	    if (defined(force)) {
1566 	      if (force !== this.list.toggle(name, force)) {
1567 	        this.list.toggle(name); // toggle again to correct
1568 	      }
1569 	    } else {
1570 	      this.list.toggle(name);
1571 	    }
1572 	    return this;
1573 	  }
1574 
1575 	  // fallback
1576 	  if (defined(force)) {
1577 	    if (!force) {
1578 	      this.remove(name);
1579 	    } else {
1580 	      this.add(name);
1581 	    }
1582 	  } else {
1583 	    if (this.has(name)) {
1584 	      this.remove(name);
1585 	    } else {
1586 	      this.add(name);
1587 	    }
1588 	  }
1589 
1590 	  return this;
1591 	};
1592 
1593 	/**
1594 	 * Return an array of classes.
1595 	 *
1596 	 * @return {Array}
1597 	 * @api public
1598 	 */
1599 
1600 	ClassList.prototype.array = function() {
1601 	  var className = this.el.getAttribute('class') || '';
1602 	  var str = className.replace(/^\s+|\s+$/g, '');
1603 	  var arr = str.split(re);
1604 	  if ('' === arr[0]) {
1605 	    arr.shift();
1606 	  }
1607 	  return arr;
1608 	};
1609 
1610 	/**
1611 	 * Check if class `name` is present.
1612 	 *
1613 	 * @param {String} name
1614 	 * @return {ClassList}
1615 	 * @api public
1616 	 */
1617 
1618 	ClassList.prototype.has =
1619 	ClassList.prototype.contains = function(name) {
1620 	  return (
1621 	    this.list ?
1622 	      this.list.contains(name) :
1623 	      !! ~index(this.array(), name)
1624 	  );
1625 	};
1626 
1627 	function remove$1(element) {
1628 	  var parent = element.parentNode;
1629 
1630 	  if (parent) {
1631 	    parent.removeChild(element);
1632 	  }
1633 
1634 	  return element;
1635 	}
1636 
1637 	/**
1638 	 * Clear utility
1639 	 */
1640 
1641 	/**
1642 	 * Removes all children from the given element
1643 	 *
1644 	 * @param  {DOMElement} element
1645 	 * @return {DOMElement} the element (for chaining)
1646 	 */
1647 	function clear(element) {
1648 	  var child;
1649 
1650 	  while ((child = element.firstChild)) {
1651 	    remove$1(child);
1652 	  }
1653 
1654 	  return element;
1655 	}
1656 
1657 	function clone$1(element) {
1658 	  return element.cloneNode(true);
1659 	}
1660 
1661 	var ns = {
1662 	  svg: 'http://www.w3.org/2000/svg'
1663 	};
1664 
1665 	/**
1666 	 * DOM parsing utility
1667 	 */
1668 
1669 	var SVG_START = '<svg xmlns="' + ns.svg + '"';
1670 
1671 	function parse(svg) {
1672 
1673 	  var unwrap = false;
1674 
1675 	  // ensure we import a valid svg document
1676 	  if (svg.substring(0, 4) === '<svg') {
1677 	    if (svg.indexOf(ns.svg) === -1) {
1678 	      svg = SVG_START + svg.substring(4);
1679 	    }
1680 	  } else {
1681 	    // namespace svg
1682 	    svg = SVG_START + '>' + svg + '</svg>';
1683 	    unwrap = true;
1684 	  }
1685 
1686 	  var parsed = parseDocument(svg);
1687 
1688 	  if (!unwrap) {
1689 	    return parsed;
1690 	  }
1691 
1692 	  var fragment = document.createDocumentFragment();
1693 
1694 	  var parent = parsed.firstChild;
1695 
1696 	  while (parent.firstChild) {
1697 	    fragment.appendChild(parent.firstChild);
1698 	  }
1699 
1700 	  return fragment;
1701 	}
1702 
1703 	function parseDocument(svg) {
1704 
1705 	  var parser;
1706 
1707 	  // parse
1708 	  parser = new DOMParser();
1709 	  parser.async = false;
1710 
1711 	  return parser.parseFromString(svg, 'text/xml');
1712 	}
1713 
1714 	/**
1715 	 * Create utility for SVG elements
1716 	 */
1717 
1718 
1719 	/**
1720 	 * Create a specific type from name or SVG markup.
1721 	 *
1722 	 * @param {String} name the name or markup of the element
1723 	 * @param {Object} [attrs] attributes to set on the element
1724 	 *
1725 	 * @returns {SVGElement}
1726 	 */
1727 	function create$1(name, attrs) {
1728 	  var element;
1729 
1730 	  if (name.charAt(0) === '<') {
1731 	    element = parse(name).firstChild;
1732 	    element = document.importNode(element, true);
1733 	  } else {
1734 	    element = document.createElementNS(ns.svg, name);
1735 	  }
1736 
1737 	  if (attrs) {
1738 	    attr(element, attrs);
1739 	  }
1740 
1741 	  return element;
1742 	}
1743 
1744 	/**
1745 	 * Geometry helpers
1746 	 */
1747 
1748 	// fake node used to instantiate svg geometry elements
1749 	var node = create$1('svg');
1750 
1751 	function extend$1(object, props) {
1752 	  var i, k, keys = Object.keys(props);
1753 
1754 	  for (i = 0; (k = keys[i]); i++) {
1755 	    object[k] = props[k];
1756 	  }
1757 
1758 	  return object;
1759 	}
1760 
1761 	/**
1762 	 * Create matrix via args.
1763 	 *
1764 	 * @example
1765 	 *
1766 	 * createMatrix({ a: 1, b: 1 });
1767 	 * createMatrix();
1768 	 * createMatrix(1, 2, 0, 0, 30, 20);
1769 	 *
1770 	 * @return {SVGMatrix}
1771 	 */
1772 	function createMatrix(a, b, c, d, e, f) {
1773 	  var matrix = node.createSVGMatrix();
1774 
1775 	  switch (arguments.length) {
1776 	  case 0:
1777 	    return matrix;
1778 	  case 1:
1779 	    return extend$1(matrix, a);
1780 	  case 6:
1781 	    return extend$1(matrix, {
1782 	      a: a,
1783 	      b: b,
1784 	      c: c,
1785 	      d: d,
1786 	      e: e,
1787 	      f: f
1788 	    });
1789 	  }
1790 	}
1791 
1792 	function createTransform(matrix) {
1793 	  if (matrix) {
1794 	    return node.createSVGTransformFromMatrix(matrix);
1795 	  } else {
1796 	    return node.createSVGTransform();
1797 	  }
1798 	}
1799 
1800 	/**
1801 	 * Serialization util
1802 	 */
1803 
1804 	var TEXT_ENTITIES = /([&<>]{1})/g;
1805 	var ATTR_ENTITIES = /([\n\r"]{1})/g;
1806 
1807 	var ENTITY_REPLACEMENT = {
1808 	  '&': '&amp;',
1809 	  '<': '&lt;',
1810 	  '>': '&gt;',
1811 	  '"': '\''
1812 	};
1813 
1814 	function escape$1(str, pattern) {
1815 
1816 	  function replaceFn(match, entity) {
1817 	    return ENTITY_REPLACEMENT[entity] || entity;
1818 	  }
1819 
1820 	  return str.replace(pattern, replaceFn);
1821 	}
1822 
1823 	function serialize(node, output) {
1824 
1825 	  var i, len, attrMap, attrNode, childNodes;
1826 
1827 	  switch (node.nodeType) {
1828 	  // TEXT
1829 	  case 3:
1830 	    // replace special XML characters
1831 	    output.push(escape$1(node.textContent, TEXT_ENTITIES));
1832 	    break;
1833 
1834 	  // ELEMENT
1835 	  case 1:
1836 	    output.push('<', node.tagName);
1837 
1838 	    if (node.hasAttributes()) {
1839 	      attrMap = node.attributes;
1840 	      for (i = 0, len = attrMap.length; i < len; ++i) {
1841 	        attrNode = attrMap.item(i);
1842 	        output.push(' ', attrNode.name, '="', escape$1(attrNode.value, ATTR_ENTITIES), '"');
1843 	      }
1844 	    }
1845 
1846 	    if (node.hasChildNodes()) {
1847 	      output.push('>');
1848 	      childNodes = node.childNodes;
1849 	      for (i = 0, len = childNodes.length; i < len; ++i) {
1850 	        serialize(childNodes.item(i), output);
1851 	      }
1852 	      output.push('</', node.tagName, '>');
1853 	    } else {
1854 	      output.push('/>');
1855 	    }
1856 	    break;
1857 
1858 	  // COMMENT
1859 	  case 8:
1860 	    output.push('<!--', escape$1(node.nodeValue, TEXT_ENTITIES), '-->');
1861 	    break;
1862 
1863 	  // CDATA
1864 	  case 4:
1865 	    output.push('<![CDATA[', node.nodeValue, ']]>');
1866 	    break;
1867 
1868 	  default:
1869 	    throw new Error('unable to handle node ' + node.nodeType);
1870 	  }
1871 
1872 	  return output;
1873 	}
1874 
1875 	/**
1876 	 * innerHTML like functionality for SVG elements.
1877 	 * based on innerSVG (https://code.google.com/p/innersvg)
1878 	 */
1879 
1880 
1881 	function set$1(element, svg) {
1882 
1883 	  var parsed = parse(svg);
1884 
1885 	  // clear element contents
1886 	  clear(element);
1887 
1888 	  if (!svg) {
1889 	    return;
1890 	  }
1891 
1892 	  if (!isFragment(parsed)) {
1893 	    // extract <svg> from parsed document
1894 	    parsed = parsed.documentElement;
1895 	  }
1896 
1897 	  var nodes = slice$1(parsed.childNodes);
1898 
1899 	  // import + append each node
1900 	  for (var i = 0; i < nodes.length; i++) {
1901 	    appendTo(nodes[i], element);
1902 	  }
1903 
1904 	}
1905 
1906 	function get$1(element) {
1907 	  var child = element.firstChild,
1908 	      output = [];
1909 
1910 	  while (child) {
1911 	    serialize(child, output);
1912 	    child = child.nextSibling;
1913 	  }
1914 
1915 	  return output.join('');
1916 	}
1917 
1918 	function isFragment(node) {
1919 	  return node.nodeName === '#document-fragment';
1920 	}
1921 
1922 	function innerSVG(element, svg) {
1923 
1924 	  if (svg !== undefined) {
1925 
1926 	    try {
1927 	      set$1(element, svg);
1928 	    } catch (e) {
1929 	      throw new Error('error parsing SVG: ' + e.message);
1930 	    }
1931 
1932 	    return element;
1933 	  } else {
1934 	    return get$1(element);
1935 	  }
1936 	}
1937 
1938 
1939 	function slice$1(arr) {
1940 	  return Array.prototype.slice.call(arr);
1941 	}
1942 
1943 	/**
1944 	 * transform accessor utility
1945 	 */
1946 
1947 	function wrapMatrix(transformList, transform) {
1948 	  if (transform instanceof SVGMatrix) {
1949 	    return transformList.createSVGTransformFromMatrix(transform);
1950 	  }
1951 
1952 	  return transform;
1953 	}
1954 
1955 
1956 	function setTransforms(transformList, transforms) {
1957 	  var i, t;
1958 
1959 	  transformList.clear();
1960 
1961 	  for (i = 0; (t = transforms[i]); i++) {
1962 	    transformList.appendItem(wrapMatrix(transformList, t));
1963 	  }
1964 	}
1965 
1966 	/**
1967 	 * Get or set the transforms on the given node.
1968 	 *
1969 	 * @param {SVGElement} node
1970 	 * @param  {SVGTransform|SVGMatrix|Array<SVGTransform|SVGMatrix>} [transforms]
1971 	 *
1972 	 * @return {SVGTransform} the consolidated transform
1973 	 */
1974 	function transform$1(node, transforms) {
1975 	  var transformList = node.transform.baseVal;
1976 
1977 	  if (transforms) {
1978 
1979 	    if (!Array.isArray(transforms)) {
1980 	      transforms = [ transforms ];
1981 	    }
1982 
1983 	    setTransforms(transformList, transforms);
1984 	  }
1985 
1986 	  return transformList.consolidate();
1987 	}
1988 
1989 	var CLASS_PATTERN = /^class /;
1990 
1991 	function isClass(fn) {
1992 	  return CLASS_PATTERN.test(fn.toString());
1993 	}
1994 
1995 	function isArray$1(obj) {
1996 	  return Object.prototype.toString.call(obj) === '[object Array]';
1997 	}
1998 
1999 	function hasOwnProp(obj, prop) {
2000 	  return Object.prototype.hasOwnProperty.call(obj, prop);
2001 	}
2002 
2003 	function annotate() {
2004 	  var args = Array.prototype.slice.call(arguments);
2005 
2006 	  if (args.length === 1 && isArray$1(args[0])) {
2007 	    args = args[0];
2008 	  }
2009 
2010 	  var fn = args.pop();
2011 
2012 	  fn.$inject = args;
2013 
2014 	  return fn;
2015 	}
2016 
2017 
2018 	// Current limitations:
2019 	// - can't put into "function arg" comments
2020 	// function /* (no parenthesis like this) */ (){}
2021 	// function abc( /* xx (no parenthesis like this) */ a, b) {}
2022 	//
2023 	// Just put the comment before function or inside:
2024 	// /* (((this is fine))) */ function(a, b) {}
2025 	// function abc(a) { /* (((this is fine))) */}
2026 	//
2027 	// - can't reliably auto-annotate constructor; we'll match the
2028 	// first constructor(...) pattern found which may be the one
2029 	// of a nested class, too.
2030 
2031 	var CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
2032 	var FN_ARGS = /^(?:async )?(?:function\s*)?[^(]*\(\s*([^)]*)\)/m;
2033 	var FN_ARG = /\/\*([^*]*)\*\//m;
2034 
2035 	function parseAnnotations(fn) {
2036 
2037 	  if (typeof fn !== 'function') {
2038 	    throw new Error('Cannot annotate "' + fn + '". Expected a function!');
2039 	  }
2040 
2041 	  var match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
2042 
2043 	  // may parse class without constructor
2044 	  if (!match) {
2045 	    return [];
2046 	  }
2047 
2048 	  return match[1] && match[1].split(',').map(function(arg) {
2049 	    match = arg.match(FN_ARG);
2050 	    return match ? match[1].trim() : arg.trim();
2051 	  }) || [];
2052 	}
2053 
2054 	function Module() {
2055 	  var providers = [];
2056 
2057 	  this.factory = function(name, factory) {
2058 	    providers.push([name, 'factory', factory]);
2059 	    return this;
2060 	  };
2061 
2062 	  this.value = function(name, value) {
2063 	    providers.push([name, 'value', value]);
2064 	    return this;
2065 	  };
2066 
2067 	  this.type = function(name, type) {
2068 	    providers.push([name, 'type', type]);
2069 	    return this;
2070 	  };
2071 
2072 	  this.forEach = function(iterator) {
2073 	    providers.forEach(iterator);
2074 	  };
2075 
2076 	}
2077 
2078 	function Injector(modules, parent) {
2079 	  parent = parent || {
2080 	    get: function(name, strict) {
2081 	      currentlyResolving.push(name);
2082 
2083 	      if (strict === false) {
2084 	        return null;
2085 	      } else {
2086 	        throw error('No provider for "' + name + '"!');
2087 	      }
2088 	    }
2089 	  };
2090 
2091 	  var currentlyResolving = [];
2092 	  var providers = this._providers = Object.create(parent._providers || null);
2093 	  var instances = this._instances = Object.create(null);
2094 
2095 	  var self = instances.injector = this;
2096 
2097 	  var error = function(msg) {
2098 	    var stack = currentlyResolving.join(' -> ');
2099 	    currentlyResolving.length = 0;
2100 	    return new Error(stack ? msg + ' (Resolving: ' + stack + ')' : msg);
2101 	  };
2102 
2103 	  /**
2104 	   * Return a named service.
2105 	   *
2106 	   * @param {String} name
2107 	   * @param {Boolean} [strict=true] if false, resolve missing services to null
2108 	   *
2109 	   * @return {Object}
2110 	   */
2111 	  var get = function(name, strict) {
2112 	    if (!providers[name] && name.indexOf('.') !== -1) {
2113 	      var parts = name.split('.');
2114 	      var pivot = get(parts.shift());
2115 
2116 	      while (parts.length) {
2117 	        pivot = pivot[parts.shift()];
2118 	      }
2119 
2120 	      return pivot;
2121 	    }
2122 
2123 	    if (hasOwnProp(instances, name)) {
2124 	      return instances[name];
2125 	    }
2126 
2127 	    if (hasOwnProp(providers, name)) {
2128 	      if (currentlyResolving.indexOf(name) !== -1) {
2129 	        currentlyResolving.push(name);
2130 	        throw error('Cannot resolve circular dependency!');
2131 	      }
2132 
2133 	      currentlyResolving.push(name);
2134 	      instances[name] = providers[name][0](providers[name][1]);
2135 	      currentlyResolving.pop();
2136 
2137 	      return instances[name];
2138 	    }
2139 
2140 	    return parent.get(name, strict);
2141 	  };
2142 
2143 	  var fnDef = function(fn, locals) {
2144 
2145 	    if (typeof locals === 'undefined') {
2146 	      locals = {};
2147 	    }
2148 
2149 	    if (typeof fn !== 'function') {
2150 	      if (isArray$1(fn)) {
2151 	        fn = annotate(fn.slice());
2152 	      } else {
2153 	        throw new Error('Cannot invoke "' + fn + '". Expected a function!');
2154 	      }
2155 	    }
2156 
2157 	    var inject = fn.$inject || parseAnnotations(fn);
2158 	    var dependencies = inject.map(function(dep) {
2159 	      if (hasOwnProp(locals, dep)) {
2160 	        return locals[dep];
2161 	      } else {
2162 	        return get(dep);
2163 	      }
2164 	    });
2165 
2166 	    return {
2167 	      fn: fn,
2168 	      dependencies: dependencies
2169 	    };
2170 	  };
2171 
2172 	  var instantiate = function(Type) {
2173 	    var def = fnDef(Type);
2174 
2175 	    var fn = def.fn,
2176 	        dependencies = def.dependencies;
2177 
2178 	    // instantiate var args constructor
2179 	    var Constructor = Function.prototype.bind.apply(fn, [ null ].concat(dependencies));
2180 
2181 	    return new Constructor();
2182 	  };
2183 
2184 	  var invoke = function(func, context, locals) {
2185 	    var def = fnDef(func, locals);
2186 
2187 	    var fn = def.fn,
2188 	        dependencies = def.dependencies;
2189 
2190 	    return fn.apply(context, dependencies);
2191 	  };
2192 
2193 
2194 	  var createPrivateInjectorFactory = function(privateChildInjector) {
2195 	    return annotate(function(key) {
2196 	      return privateChildInjector.get(key);
2197 	    });
2198 	  };
2199 
2200 	  var createChild = function(modules, forceNewInstances) {
2201 	    if (forceNewInstances && forceNewInstances.length) {
2202 	      var fromParentModule = Object.create(null);
2203 	      var matchedScopes = Object.create(null);
2204 
2205 	      var privateInjectorsCache = [];
2206 	      var privateChildInjectors = [];
2207 	      var privateChildFactories = [];
2208 
2209 	      var provider;
2210 	      var cacheIdx;
2211 	      var privateChildInjector;
2212 	      var privateChildInjectorFactory;
2213 	      for (var name in providers) {
2214 	        provider = providers[name];
2215 
2216 	        if (forceNewInstances.indexOf(name) !== -1) {
2217 	          if (provider[2] === 'private') {
2218 	            cacheIdx = privateInjectorsCache.indexOf(provider[3]);
2219 	            if (cacheIdx === -1) {
2220 	              privateChildInjector = provider[3].createChild([], forceNewInstances);
2221 	              privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
2222 	              privateInjectorsCache.push(provider[3]);
2223 	              privateChildInjectors.push(privateChildInjector);
2224 	              privateChildFactories.push(privateChildInjectorFactory);
2225 	              fromParentModule[name] = [privateChildInjectorFactory, name, 'private', privateChildInjector];
2226 	            } else {
2227 	              fromParentModule[name] = [privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx]];
2228 	            }
2229 	          } else {
2230 	            fromParentModule[name] = [provider[2], provider[1]];
2231 	          }
2232 	          matchedScopes[name] = true;
2233 	        }
2234 
2235 	        if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
2236 	          /* jshint -W083 */
2237 	          forceNewInstances.forEach(function(scope) {
2238 	            if (provider[1].$scope.indexOf(scope) !== -1) {
2239 	              fromParentModule[name] = [provider[2], provider[1]];
2240 	              matchedScopes[scope] = true;
2241 	            }
2242 	          });
2243 	        }
2244 	      }
2245 
2246 	      forceNewInstances.forEach(function(scope) {
2247 	        if (!matchedScopes[scope]) {
2248 	          throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
2249 	        }
2250 	      });
2251 
2252 	      modules.unshift(fromParentModule);
2253 	    }
2254 
2255 	    return new Injector(modules, self);
2256 	  };
2257 
2258 	  var factoryMap = {
2259 	    factory: invoke,
2260 	    type: instantiate,
2261 	    value: function(value) {
2262 	      return value;
2263 	    }
2264 	  };
2265 
2266 	  modules.forEach(function(module) {
2267 
2268 	    function arrayUnwrap(type, value) {
2269 	      if (type !== 'value' && isArray$1(value)) {
2270 	        value = annotate(value.slice());
2271 	      }
2272 
2273 	      return value;
2274 	    }
2275 
2276 	    // TODO(vojta): handle wrong inputs (modules)
2277 	    if (module instanceof Module) {
2278 	      module.forEach(function(provider) {
2279 	        var name = provider[0];
2280 	        var type = provider[1];
2281 	        var value = provider[2];
2282 
2283 	        providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
2284 	      });
2285 	    } else if (typeof module === 'object') {
2286 	      if (module.__exports__) {
2287 	        var clonedModule = Object.keys(module).reduce(function(m, key) {
2288 	          if (key.substring(0, 2) !== '__') {
2289 	            m[key] = module[key];
2290 	          }
2291 	          return m;
2292 	        }, Object.create(null));
2293 
2294 	        var privateInjector = new Injector((module.__modules__ || []).concat([clonedModule]), self);
2295 	        var getFromPrivateInjector = annotate(function(key) {
2296 	          return privateInjector.get(key);
2297 	        });
2298 	        module.__exports__.forEach(function(key) {
2299 	          providers[key] = [getFromPrivateInjector, key, 'private', privateInjector];
2300 	        });
2301 	      } else {
2302 	        Object.keys(module).forEach(function(name) {
2303 	          if (module[name][2] === 'private') {
2304 	            providers[name] = module[name];
2305 	            return;
2306 	          }
2307 
2308 	          var type = module[name][0];
2309 	          var value = module[name][1];
2310 
2311 	          providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
2312 	        });
2313 	      }
2314 	    }
2315 	  });
2316 
2317 	  // public API
2318 	  this.get = get;
2319 	  this.invoke = invoke;
2320 	  this.instantiate = instantiate;
2321 	  this.createChild = createChild;
2322 	}
2323 
2324 	var DEFAULT_RENDER_PRIORITY$1 = 1000;
2325 
2326 	/**
2327 	 * The base implementation of shape and connection renderers.
2328 	 *
2329 	 * @param {EventBus} eventBus
2330 	 * @param {number} [renderPriority=1000]
2331 	 */
2332 	function BaseRenderer(eventBus, renderPriority) {
2333 	  var self = this;
2334 
2335 	  renderPriority = renderPriority || DEFAULT_RENDER_PRIORITY$1;
2336 
2337 	  eventBus.on([ 'render.shape', 'render.connection' ], renderPriority, function(evt, context) {
2338 	    var type = evt.type,
2339 	        element = context.element,
2340 	        visuals = context.gfx;
2341 
2342 	    if (self.canRender(element)) {
2343 	      if (type === 'render.shape') {
2344 	        return self.drawShape(visuals, element);
2345 	      } else {
2346 	        return self.drawConnection(visuals, element);
2347 	      }
2348 	    }
2349 	  });
2350 
2351 	  eventBus.on([ 'render.getShapePath', 'render.getConnectionPath'], renderPriority, function(evt, element) {
2352 	    if (self.canRender(element)) {
2353 	      if (evt.type === 'render.getShapePath') {
2354 	        return self.getShapePath(element);
2355 	      } else {
2356 	        return self.getConnectionPath(element);
2357 	      }
2358 	    }
2359 	  });
2360 	}
2361 
2362 	/**
2363 	 * Should check whether *this* renderer can render
2364 	 * the element/connection.
2365 	 *
2366 	 * @param {element} element
2367 	 *
2368 	 * @returns {boolean}
2369 	 */
2370 	BaseRenderer.prototype.canRender = function() {};
2371 
2372 	/**
2373 	 * Provides the shape's snap svg element to be drawn on the `canvas`.
2374 	 *
2375 	 * @param {djs.Graphics} visuals
2376 	 * @param {Shape} shape
2377 	 *
2378 	 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2379 	 */
2380 	BaseRenderer.prototype.drawShape = function() {};
2381 
2382 	/**
2383 	 * Provides the shape's snap svg element to be drawn on the `canvas`.
2384 	 *
2385 	 * @param {djs.Graphics} visuals
2386 	 * @param {Connection} connection
2387 	 *
2388 	 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2389 	 */
2390 	BaseRenderer.prototype.drawConnection = function() {};
2391 
2392 	/**
2393 	 * Gets the SVG path of a shape that represents it's visual bounds.
2394 	 *
2395 	 * @param {Shape} shape
2396 	 *
2397 	 * @return {string} svg path
2398 	 */
2399 	BaseRenderer.prototype.getShapePath = function() {};
2400 
2401 	/**
2402 	 * Gets the SVG path of a connection that represents it's visual bounds.
2403 	 *
2404 	 * @param {Connection} connection
2405 	 *
2406 	 * @return {string} svg path
2407 	 */
2408 	BaseRenderer.prototype.getConnectionPath = function() {};
2409 
2410 	function componentsToPath(elements) {
2411 	  return elements.join(',').replace(/,?([A-z]),?/g, '$1');
2412 	}
2413 
2414 	function toSVGPoints(points) {
2415 	  var result = '';
2416 
2417 	  for (var i = 0, p; (p = points[i]); i++) {
2418 	    result += p.x + ',' + p.y + ' ';
2419 	  }
2420 
2421 	  return result;
2422 	}
2423 
2424 	function createLine(points, attrs) {
2425 
2426 	  var line = create$1('polyline');
2427 	  attr(line, { points: toSVGPoints(points) });
2428 
2429 	  if (attrs) {
2430 	    attr(line, attrs);
2431 	  }
2432 
2433 	  return line;
2434 	}
2435 
2436 	function updateLine(gfx, points) {
2437 	  attr(gfx, { points: toSVGPoints(points) });
2438 
2439 	  return gfx;
2440 	}
2441 
2442 	/**
2443 	 * Get parent elements.
2444 	 *
2445 	 * @param {Array<djs.model.base>} elements
2446 	 *
2447 	 * @returns {Array<djs.model.Base>}
2448 	 */
2449 	function getParents$1(elements) {
2450 
2451 	  // find elements that are not children of any other elements
2452 	  return filter(elements, function(element) {
2453 	    return !find(elements, function(e) {
2454 	      return e !== element && getParent$1(element, e);
2455 	    });
2456 	  });
2457 	}
2458 
2459 
2460 	function getParent$1(element, parent) {
2461 	  if (!parent) {
2462 	    return;
2463 	  }
2464 
2465 	  if (element === parent) {
2466 	    return parent;
2467 	  }
2468 
2469 	  if (!element.parent) {
2470 	    return;
2471 	  }
2472 
2473 	  return getParent$1(element.parent, parent);
2474 	}
2475 
2476 
2477 	/**
2478 	 * Adds an element to a collection and returns true if the
2479 	 * element was added.
2480 	 *
2481 	 * @param {Array<Object>} elements
2482 	 * @param {Object} e
2483 	 * @param {boolean} unique
2484 	 */
2485 	function add$1(elements, e, unique) {
2486 	  var canAdd = !unique || elements.indexOf(e) === -1;
2487 
2488 	  if (canAdd) {
2489 	    elements.push(e);
2490 	  }
2491 
2492 	  return canAdd;
2493 	}
2494 
2495 
2496 	/**
2497 	 * Iterate over each element in a collection, calling the iterator function `fn`
2498 	 * with (element, index, recursionDepth).
2499 	 *
2500 	 * Recurse into all elements that are returned by `fn`.
2501 	 *
2502 	 * @param  {Object|Array<Object>} elements
2503 	 * @param  {Function} fn iterator function called with (element, index, recursionDepth)
2504 	 * @param  {number} [depth] maximum recursion depth
2505 	 */
2506 	function eachElement(elements, fn, depth) {
2507 
2508 	  depth = depth || 0;
2509 
2510 	  if (!isArray$2(elements)) {
2511 	    elements = [ elements ];
2512 	  }
2513 
2514 	  forEach(elements, function(s, i) {
2515 	    var filter = fn(s, i, depth);
2516 
2517 	    if (isArray$2(filter) && filter.length) {
2518 	      eachElement(filter, fn, depth + 1);
2519 	    }
2520 	  });
2521 	}
2522 
2523 
2524 	/**
2525 	 * Collects self + child elements up to a given depth from a list of elements.
2526 	 *
2527 	 * @param  {djs.model.Base|Array<djs.model.Base>} elements the elements to select the children from
2528 	 * @param  {boolean} unique whether to return a unique result set (no duplicates)
2529 	 * @param  {number} maxDepth the depth to search through or -1 for infinite
2530 	 *
2531 	 * @return {Array<djs.model.Base>} found elements
2532 	 */
2533 	function selfAndChildren(elements, unique, maxDepth) {
2534 	  var result = [],
2535 	      processedChildren = [];
2536 
2537 	  eachElement(elements, function(element, i, depth) {
2538 	    add$1(result, element, unique);
2539 
2540 	    var children = element.children;
2541 
2542 	    // max traversal depth not reached yet
2543 	    if (maxDepth === -1 || depth < maxDepth) {
2544 
2545 	      // children exist && children not yet processed
2546 	      if (children && add$1(processedChildren, children, unique)) {
2547 	        return children;
2548 	      }
2549 	    }
2550 	  });
2551 
2552 	  return result;
2553 	}
2554 
2555 
2556 	/**
2557 	 * Return self + ALL children for a number of elements
2558 	 *
2559 	 * @param  {Array<djs.model.Base>} elements to query
2560 	 * @param  {boolean} allowDuplicates to allow duplicates in the result set
2561 	 *
2562 	 * @return {Array<djs.model.Base>} the collected elements
2563 	 */
2564 	function selfAndAllChildren(elements, allowDuplicates) {
2565 	  return selfAndChildren(elements, !allowDuplicates, -1);
2566 	}
2567 
2568 
2569 	/**
2570 	 * Gets the the closure for all selected elements,
2571 	 * their enclosed children and connections.
2572 	 *
2573 	 * @param {Array<djs.model.Base>} elements
2574 	 * @param {boolean} [isTopLevel=true]
2575 	 * @param {Object} [existingClosure]
2576 	 *
2577 	 * @return {Object} newClosure
2578 	 */
2579 	function getClosure(elements, isTopLevel, closure) {
2580 
2581 	  if (isUndefined$1(isTopLevel)) {
2582 	    isTopLevel = true;
2583 	  }
2584 
2585 	  if (isObject(isTopLevel)) {
2586 	    closure = isTopLevel;
2587 	    isTopLevel = true;
2588 	  }
2589 
2590 
2591 	  closure = closure || {};
2592 
2593 	  var allShapes = copyObject(closure.allShapes),
2594 	      allConnections = copyObject(closure.allConnections),
2595 	      enclosedElements = copyObject(closure.enclosedElements),
2596 	      enclosedConnections = copyObject(closure.enclosedConnections);
2597 
2598 	  var topLevel = copyObject(
2599 	    closure.topLevel,
2600 	    isTopLevel && groupBy(elements, function(e) { return e.id; })
2601 	  );
2602 
2603 
2604 	  function handleConnection(c) {
2605 	    if (topLevel[c.source.id] && topLevel[c.target.id]) {
2606 	      topLevel[c.id] = [ c ];
2607 	    }
2608 
2609 	    // not enclosed as a child, but maybe logically
2610 	    // (connecting two moved elements?)
2611 	    if (allShapes[c.source.id] && allShapes[c.target.id]) {
2612 	      enclosedConnections[c.id] = enclosedElements[c.id] = c;
2613 	    }
2614 
2615 	    allConnections[c.id] = c;
2616 	  }
2617 
2618 	  function handleElement(element) {
2619 
2620 	    enclosedElements[element.id] = element;
2621 
2622 	    if (element.waypoints) {
2623 
2624 	      // remember connection
2625 	      enclosedConnections[element.id] = allConnections[element.id] = element;
2626 	    } else {
2627 
2628 	      // remember shape
2629 	      allShapes[element.id] = element;
2630 
2631 	      // remember all connections
2632 	      forEach(element.incoming, handleConnection);
2633 
2634 	      forEach(element.outgoing, handleConnection);
2635 
2636 	      // recurse into children
2637 	      return element.children;
2638 	    }
2639 	  }
2640 
2641 	  eachElement(elements, handleElement);
2642 
2643 	  return {
2644 	    allShapes: allShapes,
2645 	    allConnections: allConnections,
2646 	    topLevel: topLevel,
2647 	    enclosedConnections: enclosedConnections,
2648 	    enclosedElements: enclosedElements
2649 	  };
2650 	}
2651 
2652 	/**
2653 	 * Returns the surrounding bbox for all elements in
2654 	 * the array or the element primitive.
2655 	 *
2656 	 * @param {Array<djs.model.Shape>|djs.model.Shape} elements
2657 	 * @param {boolean} stopRecursion
2658 	 */
2659 	function getBBox(elements, stopRecursion) {
2660 
2661 	  stopRecursion = !!stopRecursion;
2662 	  if (!isArray$2(elements)) {
2663 	    elements = [elements];
2664 	  }
2665 
2666 	  var minX,
2667 	      minY,
2668 	      maxX,
2669 	      maxY;
2670 
2671 	  forEach(elements, function(element) {
2672 
2673 	    // If element is a connection the bbox must be computed first
2674 	    var bbox = element;
2675 	    if (element.waypoints && !stopRecursion) {
2676 	      bbox = getBBox(element.waypoints, true);
2677 	    }
2678 
2679 	    var x = bbox.x,
2680 	        y = bbox.y,
2681 	        height = bbox.height || 0,
2682 	        width = bbox.width || 0;
2683 
2684 	    if (x < minX || minX === undefined) {
2685 	      minX = x;
2686 	    }
2687 	    if (y < minY || minY === undefined) {
2688 	      minY = y;
2689 	    }
2690 
2691 	    if ((x + width) > maxX || maxX === undefined) {
2692 	      maxX = x + width;
2693 	    }
2694 	    if ((y + height) > maxY || maxY === undefined) {
2695 	      maxY = y + height;
2696 	    }
2697 	  });
2698 
2699 	  return {
2700 	    x: minX,
2701 	    y: minY,
2702 	    height: maxY - minY,
2703 	    width: maxX - minX
2704 	  };
2705 	}
2706 
2707 
2708 	/**
2709 	 * Returns all elements that are enclosed from the bounding box.
2710 	 *
2711 	 *   * If bbox.(width|height) is not specified the method returns
2712 	 *     all elements with element.x/y > bbox.x/y
2713 	 *   * If only bbox.x or bbox.y is specified, method return all elements with
2714 	 *     e.x > bbox.x or e.y > bbox.y
2715 	 *
2716 	 * @param {Array<djs.model.Shape>} elements List of Elements to search through
2717 	 * @param {djs.model.Shape} bbox the enclosing bbox.
2718 	 *
2719 	 * @return {Array<djs.model.Shape>} enclosed elements
2720 	 */
2721 	function getEnclosedElements(elements, bbox) {
2722 
2723 	  var filteredElements = {};
2724 
2725 	  forEach(elements, function(element) {
2726 
2727 	    var e = element;
2728 
2729 	    if (e.waypoints) {
2730 	      e = getBBox(e);
2731 	    }
2732 
2733 	    if (!isNumber(bbox.y) && (e.x > bbox.x)) {
2734 	      filteredElements[element.id] = element;
2735 	    }
2736 	    if (!isNumber(bbox.x) && (e.y > bbox.y)) {
2737 	      filteredElements[element.id] = element;
2738 	    }
2739 	    if (e.x > bbox.x && e.y > bbox.y) {
2740 	      if (isNumber(bbox.width) && isNumber(bbox.height) &&
2741 	          e.width + e.x < bbox.width + bbox.x &&
2742 	          e.height + e.y < bbox.height + bbox.y) {
2743 
2744 	        filteredElements[element.id] = element;
2745 	      } else if (!isNumber(bbox.width) || !isNumber(bbox.height)) {
2746 	        filteredElements[element.id] = element;
2747 	      }
2748 	    }
2749 	  });
2750 
2751 	  return filteredElements;
2752 	}
2753 
2754 
2755 	function getType(element) {
2756 
2757 	  if ('waypoints' in element) {
2758 	    return 'connection';
2759 	  }
2760 
2761 	  if ('x' in element) {
2762 	    return 'shape';
2763 	  }
2764 
2765 	  return 'root';
2766 	}
2767 
2768 	function isFrameElement$1(element) {
2769 
2770 	  return !!(element && element.isFrame);
2771 	}
2772 
2773 	// helpers ///////////////////////////////
2774 
2775 	function copyObject(src1, src2) {
2776 	  return assign({}, src1 || {}, src2 || {});
2777 	}
2778 
2779 	// apply default renderer with lowest possible priority
2780 	// so that it only kicks in if noone else could render
2781 	var DEFAULT_RENDER_PRIORITY = 1;
2782 
2783 	/**
2784 	 * The default renderer used for shapes and connections.
2785 	 *
2786 	 * @param {EventBus} eventBus
2787 	 * @param {Styles} styles
2788 	 */
2789 	function DefaultRenderer(eventBus, styles) {
2790 
2791 	  //
2792 	  BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY);
2793 
2794 	  this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
2795 	  this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
2796 	  this.FRAME_STYLE = styles.style([ 'no-fill' ], { stroke: 'fuchsia', strokeDasharray: 4, strokeWidth: 2 });
2797 	}
2798 
2799 	inherits$1(DefaultRenderer, BaseRenderer);
2800 
2801 
2802 	DefaultRenderer.prototype.canRender = function() {
2803 	  return true;
2804 	};
2805 
2806 	DefaultRenderer.prototype.drawShape = function drawShape(visuals, element) {
2807 	  var rect = create$1('rect');
2808 
2809 	  attr(rect, {
2810 	    x: 0,
2811 	    y: 0,
2812 	    width: element.width || 0,
2813 	    height: element.height || 0
2814 	  });
2815 
2816 	  if (isFrameElement$1(element)) {
2817 	    attr(rect, this.FRAME_STYLE);
2818 	  } else {
2819 	    attr(rect, this.SHAPE_STYLE);
2820 	  }
2821 
2822 	  append(visuals, rect);
2823 
2824 	  return rect;
2825 	};
2826 
2827 	DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection) {
2828 
2829 	  var line = createLine(connection.waypoints, this.CONNECTION_STYLE);
2830 	  append(visuals, line);
2831 
2832 	  return line;
2833 	};
2834 
2835 	DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {
2836 
2837 	  var x = shape.x,
2838 	      y = shape.y,
2839 	      width = shape.width,
2840 	      height = shape.height;
2841 
2842 	  var shapePath = [
2843 	    ['M', x, y],
2844 	    ['l', width, 0],
2845 	    ['l', 0, height],
2846 	    ['l', -width, 0],
2847 	    ['z']
2848 	  ];
2849 
2850 	  return componentsToPath(shapePath);
2851 	};
2852 
2853 	DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
2854 	  var waypoints = connection.waypoints;
2855 
2856 	  var idx, point, connectionPath = [];
2857 
2858 	  for (idx = 0; (point = waypoints[idx]); idx++) {
2859 
2860 	    // take invisible docking into account
2861 	    // when creating the path
2862 	    point = point.original || point;
2863 
2864 	    connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
2865 	  }
2866 
2867 	  return componentsToPath(connectionPath);
2868 	};
2869 
2870 
2871 	DefaultRenderer.$inject = [ 'eventBus', 'styles' ];
2872 
2873 	/**
2874 	 * A component that manages shape styles
2875 	 */
2876 	function Styles() {
2877 
2878 	  var defaultTraits = {
2879 
2880 	    'no-fill': {
2881 	      fill: 'none'
2882 	    },
2883 	    'no-border': {
2884 	      strokeOpacity: 0.0
2885 	    },
2886 	    'no-events': {
2887 	      pointerEvents: 'none'
2888 	    }
2889 	  };
2890 
2891 	  var self = this;
2892 
2893 	  /**
2894 	   * Builds a style definition from a className, a list of traits and an object of additional attributes.
2895 	   *
2896 	   * @param  {string} className
2897 	   * @param  {Array<string>} traits
2898 	   * @param  {Object} additionalAttrs
2899 	   *
2900 	   * @return {Object} the style defintion
2901 	   */
2902 	  this.cls = function(className, traits, additionalAttrs) {
2903 	    var attrs = this.style(traits, additionalAttrs);
2904 
2905 	    return assign(attrs, { 'class': className });
2906 	  };
2907 
2908 	  /**
2909 	   * Builds a style definition from a list of traits and an object of additional attributes.
2910 	   *
2911 	   * @param  {Array<string>} traits
2912 	   * @param  {Object} additionalAttrs
2913 	   *
2914 	   * @return {Object} the style defintion
2915 	   */
2916 	  this.style = function(traits, additionalAttrs) {
2917 
2918 	    if (!isArray$2(traits) && !additionalAttrs) {
2919 	      additionalAttrs = traits;
2920 	      traits = [];
2921 	    }
2922 
2923 	    var attrs = reduce(traits, function(attrs, t) {
2924 	      return assign(attrs, defaultTraits[t] || {});
2925 	    }, {});
2926 
2927 	    return additionalAttrs ? assign(attrs, additionalAttrs) : attrs;
2928 	  };
2929 
2930 	  this.computeStyle = function(custom, traits, defaultStyles) {
2931 	    if (!isArray$2(traits)) {
2932 	      defaultStyles = traits;
2933 	      traits = [];
2934 	    }
2935 
2936 	    return self.style(traits || [], assign({}, defaultStyles, custom || {}));
2937 	  };
2938 	}
2939 
2940 	var DrawModule$1 = {
2941 	  __init__: [ 'defaultRenderer' ],
2942 	  defaultRenderer: [ 'type', DefaultRenderer ],
2943 	  styles: [ 'type', Styles ]
2944 	};
2945 
2946 	/**
2947 	 * Failsafe remove an element from a collection
2948 	 *
2949 	 * @param  {Array<Object>} [collection]
2950 	 * @param  {Object} [element]
2951 	 *
2952 	 * @return {number} the previous index of the element
2953 	 */
2954 	function remove(collection, element) {
2955 
2956 	  if (!collection || !element) {
2957 	    return -1;
2958 	  }
2959 
2960 	  var idx = collection.indexOf(element);
2961 
2962 	  if (idx !== -1) {
2963 	    collection.splice(idx, 1);
2964 	  }
2965 
2966 	  return idx;
2967 	}
2968 
2969 	/**
2970 	 * Fail save add an element to the given connection, ensuring
2971 	 * it does not yet exist.
2972 	 *
2973 	 * @param {Array<Object>} collection
2974 	 * @param {Object} element
2975 	 * @param {number} idx
2976 	 */
2977 	function add(collection, element, idx) {
2978 
2979 	  if (!collection || !element) {
2980 	    return;
2981 	  }
2982 
2983 	  if (typeof idx !== 'number') {
2984 	    idx = -1;
2985 	  }
2986 
2987 	  var currentIdx = collection.indexOf(element);
2988 
2989 	  if (currentIdx !== -1) {
2990 
2991 	    if (currentIdx === idx) {
2992 
2993 	      // nothing to do, position has not changed
2994 	      return;
2995 	    } else {
2996 
2997 	      if (idx !== -1) {
2998 
2999 	        // remove from current position
3000 	        collection.splice(currentIdx, 1);
3001 	      } else {
3002 
3003 	        // already exists in collection
3004 	        return;
3005 	      }
3006 	    }
3007 	  }
3008 
3009 	  if (idx !== -1) {
3010 
3011 	    // insert at specified position
3012 	    collection.splice(idx, 0, element);
3013 	  } else {
3014 
3015 	    // push to end
3016 	    collection.push(element);
3017 	  }
3018 	}
3019 
3020 
3021 	/**
3022 	 * Fail save get the index of an element in a collection.
3023 	 *
3024 	 * @param {Array<Object>} collection
3025 	 * @param {Object} element
3026 	 *
3027 	 * @return {number} the index or -1 if collection or element do
3028 	 *                  not exist or the element is not contained.
3029 	 */
3030 	function indexOf(collection, element) {
3031 
3032 	  if (!collection || !element) {
3033 	    return -1;
3034 	  }
3035 
3036 	  return collection.indexOf(element);
3037 	}
3038 
3039 	/**
3040 	 * Computes the distance between two points
3041 	 *
3042 	 * @param  {Point}  p
3043 	 * @param  {Point}  q
3044 	 *
3045 	 * @return {number}  distance
3046 	 */
3047 	function pointDistance(a, b) {
3048 	  if (!a || !b) {
3049 	    return -1;
3050 	  }
3051 
3052 	  return Math.sqrt(
3053 	    Math.pow(a.x - b.x, 2) +
3054 	    Math.pow(a.y - b.y, 2)
3055 	  );
3056 	}
3057 
3058 
3059 	/**
3060 	 * Returns true if the point r is on the line between p and q
3061 	 *
3062 	 * @param  {Point}  p
3063 	 * @param  {Point}  q
3064 	 * @param  {Point}  r
3065 	 * @param  {number} [accuracy=5] accuracy for points on line check (lower is better)
3066 	 *
3067 	 * @return {boolean}
3068 	 */
3069 	function pointsOnLine(p, q, r, accuracy) {
3070 
3071 	  if (typeof accuracy === 'undefined') {
3072 	    accuracy = 5;
3073 	  }
3074 
3075 	  if (!p || !q || !r) {
3076 	    return false;
3077 	  }
3078 
3079 	  var val = (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x),
3080 	      dist = pointDistance(p, q);
3081 
3082 	  // @see http://stackoverflow.com/a/907491/412190
3083 	  return Math.abs(val / dist) <= accuracy;
3084 	}
3085 
3086 
3087 	var ALIGNED_THRESHOLD = 2;
3088 
3089 	/**
3090 	 * Check whether two points are horizontally or vertically aligned.
3091 	 *
3092 	 * @param {Array<Point>|Point}
3093 	 * @param {Point}
3094 	 *
3095 	 * @return {string|boolean}
3096 	 */
3097 	function pointsAligned(a, b) {
3098 	  var points;
3099 
3100 	  if (isArray$2(a)) {
3101 	    points = a;
3102 	  } else {
3103 	    points = [ a, b ];
3104 	  }
3105 
3106 	  if (pointsAlignedHorizontally(points)) {
3107 	    return 'h';
3108 	  }
3109 
3110 	  if (pointsAlignedVertically(points)) {
3111 	    return 'v';
3112 	  }
3113 
3114 	  return false;
3115 	}
3116 
3117 	function pointsAlignedHorizontally(a, b) {
3118 	  var points;
3119 
3120 	  if (isArray$2(a)) {
3121 	    points = a;
3122 	  } else {
3123 	    points = [ a, b ];
3124 	  }
3125 
3126 	  var firstPoint = points.slice().shift();
3127 
3128 	  return every(points, function(point) {
3129 	    return Math.abs(firstPoint.y - point.y) <= ALIGNED_THRESHOLD;
3130 	  });
3131 	}
3132 
3133 	function pointsAlignedVertically(a, b) {
3134 	  var points;
3135 
3136 	  if (isArray$2(a)) {
3137 	    points = a;
3138 	  } else {
3139 	    points = [ a, b ];
3140 	  }
3141 
3142 	  var firstPoint = points.slice().shift();
3143 
3144 	  return every(points, function(point) {
3145 	    return Math.abs(firstPoint.x - point.x) <= ALIGNED_THRESHOLD;
3146 	  });
3147 	}
3148 
3149 
3150 
3151 	/**
3152 	 * Returns true if the point p is inside the rectangle rect
3153 	 *
3154 	 * @param  {Point}  p
3155 	 * @param  {Rect} rect
3156 	 * @param  {number} tolerance
3157 	 *
3158 	 * @return {boolean}
3159 	 */
3160 	function pointInRect(p, rect, tolerance) {
3161 	  tolerance = tolerance || 0;
3162 
3163 	  return p.x > rect.x - tolerance &&
3164 	         p.y > rect.y - tolerance &&
3165 	         p.x < rect.x + rect.width + tolerance &&
3166 	         p.y < rect.y + rect.height + tolerance;
3167 	}
3168 
3169 	/**
3170 	 * Returns a point in the middle of points p and q
3171 	 *
3172 	 * @param  {Point}  p
3173 	 * @param  {Point}  q
3174 	 *
3175 	 * @return {Point} middle point
3176 	 */
3177 	function getMidPoint(p, q) {
3178 	  return {
3179 	    x: Math.round(p.x + ((q.x - p.x) / 2.0)),
3180 	    y: Math.round(p.y + ((q.y - p.y) / 2.0))
3181 	  };
3182 	}
3183 
3184 	/**
3185 	 * This file contains source code adapted from Snap.svg (licensed Apache-2.0).
3186 	 *
3187 	 * @see https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js
3188 	 */
3189 
3190 	/* eslint no-fallthrough: "off" */
3191 
3192 	var p2s = /,?([a-z]),?/gi,
3193 	    toFloat = parseFloat,
3194 	    math = Math,
3195 	    PI = math.PI,
3196 	    mmin = math.min,
3197 	    mmax = math.max,
3198 	    pow = math.pow,
3199 	    abs$7 = math.abs,
3200 	    pathCommand = /([a-z])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?[\s]*,?[\s]*)+)/ig,
3201 	    pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)[\s]*,?[\s]*/ig;
3202 
3203 	var isArray = Array.isArray || function(o) { return o instanceof Array; };
3204 
3205 	function hasProperty(obj, property) {
3206 	  return Object.prototype.hasOwnProperty.call(obj, property);
3207 	}
3208 
3209 	function clone(obj) {
3210 
3211 	  if (typeof obj == 'function' || Object(obj) !== obj) {
3212 	    return obj;
3213 	  }
3214 
3215 	  var res = new obj.constructor;
3216 
3217 	  for (var key in obj) {
3218 	    if (hasProperty(obj, key)) {
3219 	      res[key] = clone(obj[key]);
3220 	    }
3221 	  }
3222 
3223 	  return res;
3224 	}
3225 
3226 	function repush(array, item) {
3227 	  for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
3228 	    return array.push(array.splice(i, 1)[0]);
3229 	  }
3230 	}
3231 
3232 	function cacher(f) {
3233 
3234 	  function newf() {
3235 
3236 	    var arg = Array.prototype.slice.call(arguments, 0),
3237 	        args = arg.join('\u2400'),
3238 	        cache = newf.cache = newf.cache || {},
3239 	        count = newf.count = newf.count || [];
3240 
3241 	    if (hasProperty(cache, args)) {
3242 	      repush(count, args);
3243 	      return cache[args];
3244 	    }
3245 
3246 	    count.length >= 1e3 && delete cache[count.shift()];
3247 	    count.push(args);
3248 	    cache[args] = f.apply(0, arg);
3249 
3250 	    return cache[args];
3251 	  }
3252 	  return newf;
3253 	}
3254 
3255 	function parsePathString(pathString) {
3256 
3257 	  if (!pathString) {
3258 	    return null;
3259 	  }
3260 
3261 	  var pth = paths(pathString);
3262 
3263 	  if (pth.arr) {
3264 	    return clone(pth.arr);
3265 	  }
3266 
3267 	  var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 },
3268 	      data = [];
3269 
3270 	  if (isArray(pathString) && isArray(pathString[0])) { // rough assumption
3271 	    data = clone(pathString);
3272 	  }
3273 
3274 	  if (!data.length) {
3275 
3276 	    String(pathString).replace(pathCommand, function(a, b, c) {
3277 	      var params = [],
3278 	          name = b.toLowerCase();
3279 
3280 	      c.replace(pathValues, function(a, b) {
3281 	        b && params.push(+b);
3282 	      });
3283 
3284 	      if (name == 'm' && params.length > 2) {
3285 	        data.push([b].concat(params.splice(0, 2)));
3286 	        name = 'l';
3287 	        b = b == 'm' ? 'l' : 'L';
3288 	      }
3289 
3290 	      while (params.length >= paramCounts[name]) {
3291 	        data.push([b].concat(params.splice(0, paramCounts[name])));
3292 	        if (!paramCounts[name]) {
3293 	          break;
3294 	        }
3295 	      }
3296 	    });
3297 	  }
3298 
3299 	  data.toString = paths.toString;
3300 	  pth.arr = clone(data);
3301 
3302 	  return data;
3303 	}
3304 
3305 	function paths(ps) {
3306 	  var p = paths.ps = paths.ps || {};
3307 
3308 	  if (p[ps]) {
3309 	    p[ps].sleep = 100;
3310 	  } else {
3311 	    p[ps] = {
3312 	      sleep: 100
3313 	    };
3314 	  }
3315 
3316 	  setTimeout(function() {
3317 	    for (var key in p) {
3318 	      if (hasProperty(p, key) && key != ps) {
3319 	        p[key].sleep--;
3320 	        !p[key].sleep && delete p[key];
3321 	      }
3322 	    }
3323 	  });
3324 
3325 	  return p[ps];
3326 	}
3327 
3328 	function rectBBox(x, y, width, height) {
3329 
3330 	  if (arguments.length === 1) {
3331 	    y = x.y;
3332 	    width = x.width;
3333 	    height = x.height;
3334 	    x = x.x;
3335 	  }
3336 
3337 	  return {
3338 	    x: x,
3339 	    y: y,
3340 	    width: width,
3341 	    height: height,
3342 	    x2: x + width,
3343 	    y2: y + height
3344 	  };
3345 	}
3346 
3347 	function pathToString() {
3348 	  return this.join(',').replace(p2s, '$1');
3349 	}
3350 
3351 	function pathClone(pathArray) {
3352 	  var res = clone(pathArray);
3353 	  res.toString = pathToString;
3354 	  return res;
3355 	}
3356 
3357 	function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
3358 	  var t1 = 1 - t,
3359 	      t13 = pow(t1, 3),
3360 	      t12 = pow(t1, 2),
3361 	      t2 = t * t,
3362 	      t3 = t2 * t,
3363 	      x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
3364 	      y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y;
3365 
3366 	  return {
3367 	    x: fixError(x),
3368 	    y: fixError(y)
3369 	  };
3370 	}
3371 
3372 	function bezierBBox(points) {
3373 
3374 	  var bbox = curveBBox.apply(null, points);
3375 
3376 	  return rectBBox(
3377 	    bbox.x0,
3378 	    bbox.y0,
3379 	    bbox.x1 - bbox.x0,
3380 	    bbox.y1 - bbox.y0
3381 	  );
3382 	}
3383 
3384 	function isPointInsideBBox$2(bbox, x, y) {
3385 	  return x >= bbox.x &&
3386 	    x <= bbox.x + bbox.width &&
3387 	    y >= bbox.y &&
3388 	    y <= bbox.y + bbox.height;
3389 	}
3390 
3391 	function isBBoxIntersect(bbox1, bbox2) {
3392 	  bbox1 = rectBBox(bbox1);
3393 	  bbox2 = rectBBox(bbox2);
3394 	  return isPointInsideBBox$2(bbox2, bbox1.x, bbox1.y)
3395 	    || isPointInsideBBox$2(bbox2, bbox1.x2, bbox1.y)
3396 	    || isPointInsideBBox$2(bbox2, bbox1.x, bbox1.y2)
3397 	    || isPointInsideBBox$2(bbox2, bbox1.x2, bbox1.y2)
3398 	    || isPointInsideBBox$2(bbox1, bbox2.x, bbox2.y)
3399 	    || isPointInsideBBox$2(bbox1, bbox2.x2, bbox2.y)
3400 	    || isPointInsideBBox$2(bbox1, bbox2.x, bbox2.y2)
3401 	    || isPointInsideBBox$2(bbox1, bbox2.x2, bbox2.y2)
3402 	    || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x
3403 	        || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
3404 	    && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y
3405 	        || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
3406 	}
3407 
3408 	function base3(t, p1, p2, p3, p4) {
3409 	  var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
3410 	      t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
3411 	  return t * t2 - 3 * p1 + 3 * p2;
3412 	}
3413 
3414 	function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
3415 
3416 	  if (z == null) {
3417 	    z = 1;
3418 	  }
3419 
3420 	  z = z > 1 ? 1 : z < 0 ? 0 : z;
3421 
3422 	  var z2 = z / 2,
3423 	      n = 12,
3424 	      Tvalues = [-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],
3425 	      Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
3426 	      sum = 0;
3427 
3428 	  for (var i = 0; i < n; i++) {
3429 	    var ct = z2 * Tvalues[i] + z2,
3430 	        xbase = base3(ct, x1, x2, x3, x4),
3431 	        ybase = base3(ct, y1, y2, y3, y4),
3432 	        comb = xbase * xbase + ybase * ybase;
3433 
3434 	    sum += Cvalues[i] * math.sqrt(comb);
3435 	  }
3436 
3437 	  return z2 * sum;
3438 	}
3439 
3440 
3441 	function intersectLines(x1, y1, x2, y2, x3, y3, x4, y4) {
3442 
3443 	  if (
3444 	    mmax(x1, x2) < mmin(x3, x4) ||
3445 	      mmin(x1, x2) > mmax(x3, x4) ||
3446 	      mmax(y1, y2) < mmin(y3, y4) ||
3447 	      mmin(y1, y2) > mmax(y3, y4)
3448 	  ) {
3449 	    return;
3450 	  }
3451 
3452 	  var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
3453 	      ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
3454 	      denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
3455 
3456 	  if (!denominator) {
3457 	    return;
3458 	  }
3459 
3460 	  var px = fixError(nx / denominator),
3461 	      py = fixError(ny / denominator),
3462 	      px2 = +px.toFixed(2),
3463 	      py2 = +py.toFixed(2);
3464 
3465 	  if (
3466 	    px2 < +mmin(x1, x2).toFixed(2) ||
3467 	      px2 > +mmax(x1, x2).toFixed(2) ||
3468 	      px2 < +mmin(x3, x4).toFixed(2) ||
3469 	      px2 > +mmax(x3, x4).toFixed(2) ||
3470 	      py2 < +mmin(y1, y2).toFixed(2) ||
3471 	      py2 > +mmax(y1, y2).toFixed(2) ||
3472 	      py2 < +mmin(y3, y4).toFixed(2) ||
3473 	      py2 > +mmax(y3, y4).toFixed(2)
3474 	  ) {
3475 	    return;
3476 	  }
3477 
3478 	  return { x: px, y: py };
3479 	}
3480 
3481 	function fixError(number) {
3482 	  return Math.round(number * 100000000000) / 100000000000;
3483 	}
3484 
3485 	function findBezierIntersections(bez1, bez2, justCount) {
3486 	  var bbox1 = bezierBBox(bez1),
3487 	      bbox2 = bezierBBox(bez2);
3488 
3489 	  if (!isBBoxIntersect(bbox1, bbox2)) {
3490 	    return justCount ? 0 : [];
3491 	  }
3492 
3493 	  // As an optimization, lines will have only 1 segment
3494 
3495 	  var l1 = bezlen.apply(0, bez1),
3496 	      l2 = bezlen.apply(0, bez2),
3497 	      n1 = isLine(bez1) ? 1 : ~~(l1 / 5) || 1,
3498 	      n2 = isLine(bez2) ? 1 : ~~(l2 / 5) || 1,
3499 	      dots1 = [],
3500 	      dots2 = [],
3501 	      xy = {},
3502 	      res = justCount ? 0 : [];
3503 
3504 	  for (var i = 0; i < n1 + 1; i++) {
3505 	    var p = findDotsAtSegment.apply(0, bez1.concat(i / n1));
3506 	    dots1.push({ x: p.x, y: p.y, t: i / n1 });
3507 	  }
3508 
3509 	  for (i = 0; i < n2 + 1; i++) {
3510 	    p = findDotsAtSegment.apply(0, bez2.concat(i / n2));
3511 	    dots2.push({ x: p.x, y: p.y, t: i / n2 });
3512 	  }
3513 
3514 	  for (i = 0; i < n1; i++) {
3515 
3516 	    for (var j = 0; j < n2; j++) {
3517 	      var di = dots1[i],
3518 	          di1 = dots1[i + 1],
3519 	          dj = dots2[j],
3520 	          dj1 = dots2[j + 1],
3521 	          ci = abs$7(di1.x - di.x) < .01 ? 'y' : 'x',
3522 	          cj = abs$7(dj1.x - dj.x) < .01 ? 'y' : 'x',
3523 	          is = intersectLines(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y),
3524 	          key;
3525 
3526 	      if (is) {
3527 	        key = is.x.toFixed(9) + '#' + is.y.toFixed(9);
3528 
3529 	        if (xy[key]) {
3530 	          continue;
3531 	        }
3532 
3533 	        xy[key] = true;
3534 
3535 	        var t1 = di.t + abs$7((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
3536 	            t2 = dj.t + abs$7((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
3537 
3538 	        if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {
3539 
3540 	          if (justCount) {
3541 	            res++;
3542 	          } else {
3543 	            res.push({
3544 	              x: is.x,
3545 	              y: is.y,
3546 	              t1: t1,
3547 	              t2: t2
3548 	            });
3549 	          }
3550 	        }
3551 	      }
3552 	    }
3553 	  }
3554 
3555 	  return res;
3556 	}
3557 
3558 
3559 	/**
3560 	 * Find or counts the intersections between two SVG paths.
3561 	 *
3562 	 * Returns a number in counting mode and a list of intersections otherwise.
3563 	 *
3564 	 * A single intersection entry contains the intersection coordinates (x, y)
3565 	 * as well as additional information regarding the intersecting segments
3566 	 * on each path (segment1, segment2) and the relative location of the
3567 	 * intersection on these segments (t1, t2).
3568 	 *
3569 	 * The path may be an SVG path string or a list of path components
3570 	 * such as `[ [ 'M', 0, 10 ], [ 'L', 20, 0 ] ]`.
3571 	 *
3572 	 * @example
3573 	 *
3574 	 * var intersections = findPathIntersections(
3575 	 *   'M0,0L100,100',
3576 	 *   [ [ 'M', 0, 100 ], [ 'L', 100, 0 ] ]
3577 	 * );
3578 	 *
3579 	 * // intersections = [
3580 	 * //   { x: 50, y: 50, segment1: 1, segment2: 1, t1: 0.5, t2: 0.5 }
3581 	 * // ]
3582 	 *
3583 	 * @param {String|Array<PathDef>} path1
3584 	 * @param {String|Array<PathDef>} path2
3585 	 * @param {Boolean} [justCount=false]
3586 	 *
3587 	 * @return {Array<Intersection>|Number}
3588 	 */
3589 	function findPathIntersections(path1, path2, justCount) {
3590 	  path1 = pathToCurve(path1);
3591 	  path2 = pathToCurve(path2);
3592 
3593 	  var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
3594 	      res = justCount ? 0 : [];
3595 
3596 	  for (var i = 0, ii = path1.length; i < ii; i++) {
3597 	    var pi = path1[i];
3598 
3599 	    if (pi[0] == 'M') {
3600 	      x1 = x1m = pi[1];
3601 	      y1 = y1m = pi[2];
3602 	    } else {
3603 
3604 	      if (pi[0] == 'C') {
3605 	        bez1 = [x1, y1].concat(pi.slice(1));
3606 	        x1 = bez1[6];
3607 	        y1 = bez1[7];
3608 	      } else {
3609 	        bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
3610 	        x1 = x1m;
3611 	        y1 = y1m;
3612 	      }
3613 
3614 	      for (var j = 0, jj = path2.length; j < jj; j++) {
3615 	        var pj = path2[j];
3616 
3617 	        if (pj[0] == 'M') {
3618 	          x2 = x2m = pj[1];
3619 	          y2 = y2m = pj[2];
3620 	        } else {
3621 
3622 	          if (pj[0] == 'C') {
3623 	            bez2 = [x2, y2].concat(pj.slice(1));
3624 	            x2 = bez2[6];
3625 	            y2 = bez2[7];
3626 	          } else {
3627 	            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
3628 	            x2 = x2m;
3629 	            y2 = y2m;
3630 	          }
3631 
3632 	          var intr = findBezierIntersections(bez1, bez2, justCount);
3633 
3634 	          if (justCount) {
3635 	            res += intr;
3636 	          } else {
3637 
3638 	            for (var k = 0, kk = intr.length; k < kk; k++) {
3639 	              intr[k].segment1 = i;
3640 	              intr[k].segment2 = j;
3641 	              intr[k].bez1 = bez1;
3642 	              intr[k].bez2 = bez2;
3643 	            }
3644 
3645 	            res = res.concat(intr);
3646 	          }
3647 	        }
3648 	      }
3649 	    }
3650 	  }
3651 
3652 	  return res;
3653 	}
3654 
3655 
3656 	function pathToAbsolute(pathArray) {
3657 	  var pth = paths(pathArray);
3658 
3659 	  if (pth.abs) {
3660 	    return pathClone(pth.abs);
3661 	  }
3662 
3663 	  if (!isArray(pathArray) || !isArray(pathArray && pathArray[0])) { // rough assumption
3664 	    pathArray = parsePathString(pathArray);
3665 	  }
3666 
3667 	  if (!pathArray || !pathArray.length) {
3668 	    return [['M', 0, 0]];
3669 	  }
3670 
3671 	  var res = [],
3672 	      x = 0,
3673 	      y = 0,
3674 	      mx = 0,
3675 	      my = 0,
3676 	      start = 0,
3677 	      pa0;
3678 
3679 	  if (pathArray[0][0] == 'M') {
3680 	    x = +pathArray[0][1];
3681 	    y = +pathArray[0][2];
3682 	    mx = x;
3683 	    my = y;
3684 	    start++;
3685 	    res[0] = ['M', x, y];
3686 	  }
3687 
3688 	  for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
3689 	    res.push(r = []);
3690 	    pa = pathArray[i];
3691 	    pa0 = pa[0];
3692 
3693 	    if (pa0 != pa0.toUpperCase()) {
3694 	      r[0] = pa0.toUpperCase();
3695 
3696 	      switch (r[0]) {
3697 	      case 'A':
3698 	        r[1] = pa[1];
3699 	        r[2] = pa[2];
3700 	        r[3] = pa[3];
3701 	        r[4] = pa[4];
3702 	        r[5] = pa[5];
3703 	        r[6] = +pa[6] + x;
3704 	        r[7] = +pa[7] + y;
3705 	        break;
3706 	      case 'V':
3707 	        r[1] = +pa[1] + y;
3708 	        break;
3709 	      case 'H':
3710 	        r[1] = +pa[1] + x;
3711 	        break;
3712 	      case 'M':
3713 	        mx = +pa[1] + x;
3714 	        my = +pa[2] + y;
3715 	      default:
3716 	        for (var j = 1, jj = pa.length; j < jj; j++) {
3717 	          r[j] = +pa[j] + ((j % 2) ? x : y);
3718 	        }
3719 	      }
3720 	    } else {
3721 	      for (var k = 0, kk = pa.length; k < kk; k++) {
3722 	        r[k] = pa[k];
3723 	      }
3724 	    }
3725 	    pa0 = pa0.toUpperCase();
3726 
3727 	    switch (r[0]) {
3728 	    case 'Z':
3729 	      x = +mx;
3730 	      y = +my;
3731 	      break;
3732 	    case 'H':
3733 	      x = r[1];
3734 	      break;
3735 	    case 'V':
3736 	      y = r[1];
3737 	      break;
3738 	    case 'M':
3739 	      mx = r[r.length - 2];
3740 	      my = r[r.length - 1];
3741 	    default:
3742 	      x = r[r.length - 2];
3743 	      y = r[r.length - 1];
3744 	    }
3745 	  }
3746 
3747 	  res.toString = pathToString;
3748 	  pth.abs = pathClone(res);
3749 
3750 	  return res;
3751 	}
3752 
3753 	function isLine(bez) {
3754 	  return (
3755 	    bez[0] === bez[2] &&
3756 	    bez[1] === bez[3] &&
3757 	    bez[4] === bez[6] &&
3758 	    bez[5] === bez[7]
3759 	  );
3760 	}
3761 
3762 	function lineToCurve(x1, y1, x2, y2) {
3763 	  return [
3764 	    x1, y1, x2,
3765 	    y2, x2, y2
3766 	  ];
3767 	}
3768 
3769 	function qubicToCurve(x1, y1, ax, ay, x2, y2) {
3770 	  var _13 = 1 / 3,
3771 	      _23 = 2 / 3;
3772 
3773 	  return [
3774 	    _13 * x1 + _23 * ax,
3775 	    _13 * y1 + _23 * ay,
3776 	    _13 * x2 + _23 * ax,
3777 	    _13 * y2 + _23 * ay,
3778 	    x2,
3779 	    y2
3780 	  ];
3781 	}
3782 
3783 	function arcToCurve(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
3784 
3785 	  // for more information of where this math came from visit:
3786 	  // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
3787 	  var _120 = PI * 120 / 180,
3788 	      rad = PI / 180 * (+angle || 0),
3789 	      res = [],
3790 	      xy,
3791 	      rotate = cacher(function(x, y, rad) {
3792 	        var X = x * math.cos(rad) - y * math.sin(rad),
3793 	            Y = x * math.sin(rad) + y * math.cos(rad);
3794 
3795 	        return { x: X, y: Y };
3796 	      });
3797 
3798 	  if (!recursive) {
3799 	    xy = rotate(x1, y1, -rad);
3800 	    x1 = xy.x;
3801 	    y1 = xy.y;
3802 	    xy = rotate(x2, y2, -rad);
3803 	    x2 = xy.x;
3804 	    y2 = xy.y;
3805 
3806 	    var x = (x1 - x2) / 2,
3807 	        y = (y1 - y2) / 2;
3808 
3809 	    var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
3810 
3811 	    if (h > 1) {
3812 	      h = math.sqrt(h);
3813 	      rx = h * rx;
3814 	      ry = h * ry;
3815 	    }
3816 
3817 	    var rx2 = rx * rx,
3818 	        ry2 = ry * ry,
3819 	        k = (large_arc_flag == sweep_flag ? -1 : 1) *
3820 	            math.sqrt(abs$7((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
3821 	        cx = k * rx * y / ry + (x1 + x2) / 2,
3822 	        cy = k * -ry * x / rx + (y1 + y2) / 2,
3823 	        f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
3824 	        f2 = math.asin(((y2 - cy) / ry).toFixed(9));
3825 
3826 	    f1 = x1 < cx ? PI - f1 : f1;
3827 	    f2 = x2 < cx ? PI - f2 : f2;
3828 	    f1 < 0 && (f1 = PI * 2 + f1);
3829 	    f2 < 0 && (f2 = PI * 2 + f2);
3830 
3831 	    if (sweep_flag && f1 > f2) {
3832 	      f1 = f1 - PI * 2;
3833 	    }
3834 	    if (!sweep_flag && f2 > f1) {
3835 	      f2 = f2 - PI * 2;
3836 	    }
3837 	  } else {
3838 	    f1 = recursive[0];
3839 	    f2 = recursive[1];
3840 	    cx = recursive[2];
3841 	    cy = recursive[3];
3842 	  }
3843 
3844 	  var df = f2 - f1;
3845 
3846 	  if (abs$7(df) > _120) {
3847 	    var f2old = f2,
3848 	        x2old = x2,
3849 	        y2old = y2;
3850 
3851 	    f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
3852 	    x2 = cx + rx * math.cos(f2);
3853 	    y2 = cy + ry * math.sin(f2);
3854 	    res = arcToCurve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
3855 	  }
3856 
3857 	  df = f2 - f1;
3858 
3859 	  var c1 = math.cos(f1),
3860 	      s1 = math.sin(f1),
3861 	      c2 = math.cos(f2),
3862 	      s2 = math.sin(f2),
3863 	      t = math.tan(df / 4),
3864 	      hx = 4 / 3 * rx * t,
3865 	      hy = 4 / 3 * ry * t,
3866 	      m1 = [x1, y1],
3867 	      m2 = [x1 + hx * s1, y1 - hy * c1],
3868 	      m3 = [x2 + hx * s2, y2 - hy * c2],
3869 	      m4 = [x2, y2];
3870 
3871 	  m2[0] = 2 * m1[0] - m2[0];
3872 	  m2[1] = 2 * m1[1] - m2[1];
3873 
3874 	  if (recursive) {
3875 	    return [m2, m3, m4].concat(res);
3876 	  } else {
3877 	    res = [m2, m3, m4].concat(res).join().split(',');
3878 	    var newres = [];
3879 
3880 	    for (var i = 0, ii = res.length; i < ii; i++) {
3881 	      newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
3882 	    }
3883 
3884 	    return newres;
3885 	  }
3886 	}
3887 
3888 	// Returns bounding box of cubic bezier curve.
3889 	// Source: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
3890 	// Original version: NISHIO Hirokazu
3891 	// Modifications: https://github.com/timo22345
3892 	function curveBBox(x0, y0, x1, y1, x2, y2, x3, y3) {
3893 	  var tvalues = [],
3894 	      bounds = [[], []],
3895 	      a, b, c, t, t1, t2, b2ac, sqrtb2ac;
3896 
3897 	  for (var i = 0; i < 2; ++i) {
3898 
3899 	    if (i == 0) {
3900 	      b = 6 * x0 - 12 * x1 + 6 * x2;
3901 	      a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
3902 	      c = 3 * x1 - 3 * x0;
3903 	    } else {
3904 	      b = 6 * y0 - 12 * y1 + 6 * y2;
3905 	      a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
3906 	      c = 3 * y1 - 3 * y0;
3907 	    }
3908 
3909 	    if (abs$7(a) < 1e-12) {
3910 
3911 	      if (abs$7(b) < 1e-12) {
3912 	        continue;
3913 	      }
3914 
3915 	      t = -c / b;
3916 
3917 	      if (0 < t && t < 1) {
3918 	        tvalues.push(t);
3919 	      }
3920 
3921 	      continue;
3922 	    }
3923 
3924 	    b2ac = b * b - 4 * c * a;
3925 	    sqrtb2ac = math.sqrt(b2ac);
3926 
3927 	    if (b2ac < 0) {
3928 	      continue;
3929 	    }
3930 
3931 	    t1 = (-b + sqrtb2ac) / (2 * a);
3932 
3933 	    if (0 < t1 && t1 < 1) {
3934 	      tvalues.push(t1);
3935 	    }
3936 
3937 	    t2 = (-b - sqrtb2ac) / (2 * a);
3938 
3939 	    if (0 < t2 && t2 < 1) {
3940 	      tvalues.push(t2);
3941 	    }
3942 	  }
3943 
3944 	  var j = tvalues.length,
3945 	      jlen = j,
3946 	      mt;
3947 
3948 	  while (j--) {
3949 	    t = tvalues[j];
3950 	    mt = 1 - t;
3951 	    bounds[0][j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
3952 	    bounds[1][j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
3953 	  }
3954 
3955 	  bounds[0][jlen] = x0;
3956 	  bounds[1][jlen] = y0;
3957 	  bounds[0][jlen + 1] = x3;
3958 	  bounds[1][jlen + 1] = y3;
3959 	  bounds[0].length = bounds[1].length = jlen + 2;
3960 
3961 	  return {
3962 	    x0: mmin.apply(0, bounds[0]),
3963 	    y0: mmin.apply(0, bounds[1]),
3964 	    x1: mmax.apply(0, bounds[0]),
3965 	    y1: mmax.apply(0, bounds[1])
3966 	  };
3967 	}
3968 
3969 	function pathToCurve(path) {
3970 
3971 	  var pth = paths(path);
3972 
3973 	  // return cached curve, if existing
3974 	  if (pth.curve) {
3975 	    return pathClone(pth.curve);
3976 	  }
3977 
3978 	  var curvedPath = pathToAbsolute(path),
3979 	      attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
3980 	      processPath = function(path, d, pathCommand) {
3981 	        var nx, ny;
3982 
3983 	        if (!path) {
3984 	          return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
3985 	        }
3986 
3987 	        !(path[0] in { T: 1, Q: 1 }) && (d.qx = d.qy = null);
3988 
3989 	        switch (path[0]) {
3990 	        case 'M':
3991 	          d.X = path[1];
3992 	          d.Y = path[2];
3993 	          break;
3994 	        case 'A':
3995 	          path = ['C'].concat(arcToCurve.apply(0, [d.x, d.y].concat(path.slice(1))));
3996 	          break;
3997 	        case 'S':
3998 	          if (pathCommand == 'C' || pathCommand == 'S') {
3999 
4000 	            // In 'S' case we have to take into account, if the previous command is C/S.
4001 	            nx = d.x * 2 - d.bx;
4002 
4003 	            // And reflect the previous
4004 	            ny = d.y * 2 - d.by;
4005 
4006 	            // command's control point relative to the current point.
4007 	          }
4008 	          else {
4009 
4010 	            // or some else or nothing
4011 	            nx = d.x;
4012 	            ny = d.y;
4013 	          }
4014 	          path = ['C', nx, ny].concat(path.slice(1));
4015 	          break;
4016 	        case 'T':
4017 	          if (pathCommand == 'Q' || pathCommand == 'T') {
4018 
4019 	            // In 'T' case we have to take into account, if the previous command is Q/T.
4020 	            d.qx = d.x * 2 - d.qx;
4021 
4022 	            // And make a reflection similar
4023 	            d.qy = d.y * 2 - d.qy;
4024 
4025 	            // to case 'S'.
4026 	          }
4027 	          else {
4028 
4029 	            // or something else or nothing
4030 	            d.qx = d.x;
4031 	            d.qy = d.y;
4032 	          }
4033 	          path = ['C'].concat(qubicToCurve(d.x, d.y, d.qx, d.qy, path[1], path[2]));
4034 	          break;
4035 	        case 'Q':
4036 	          d.qx = path[1];
4037 	          d.qy = path[2];
4038 	          path = ['C'].concat(qubicToCurve(d.x, d.y, path[1], path[2], path[3], path[4]));
4039 	          break;
4040 	        case 'L':
4041 	          path = ['C'].concat(lineToCurve(d.x, d.y, path[1], path[2]));
4042 	          break;
4043 	        case 'H':
4044 	          path = ['C'].concat(lineToCurve(d.x, d.y, path[1], d.y));
4045 	          break;
4046 	        case 'V':
4047 	          path = ['C'].concat(lineToCurve(d.x, d.y, d.x, path[1]));
4048 	          break;
4049 	        case 'Z':
4050 	          path = ['C'].concat(lineToCurve(d.x, d.y, d.X, d.Y));
4051 	          break;
4052 	        }
4053 
4054 	        return path;
4055 	      },
4056 
4057 	      fixArc = function(pp, i) {
4058 
4059 	        if (pp[i].length > 7) {
4060 	          pp[i].shift();
4061 	          var pi = pp[i];
4062 
4063 	          while (pi.length) {
4064 	            pathCommands[i] = 'A'; // if created multiple C:s, their original seg is saved
4065 	            pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
4066 	          }
4067 
4068 	          pp.splice(i, 1);
4069 	          ii = curvedPath.length;
4070 	        }
4071 	      },
4072 
4073 	      pathCommands = [], // path commands of original path p
4074 	      pfirst = '', // temporary holder for original path command
4075 	      pathCommand = ''; // holder for previous path command of original path
4076 
4077 	  for (var i = 0, ii = curvedPath.length; i < ii; i++) {
4078 	    curvedPath[i] && (pfirst = curvedPath[i][0]); // save current path command
4079 
4080 	    if (pfirst != 'C') // C is not saved yet, because it may be result of conversion
4081 	    {
4082 	      pathCommands[i] = pfirst; // Save current path command
4083 	      i && (pathCommand = pathCommands[i - 1]); // Get previous path command pathCommand
4084 	    }
4085 	    curvedPath[i] = processPath(curvedPath[i], attrs, pathCommand); // Previous path command is inputted to processPath
4086 
4087 	    if (pathCommands[i] != 'A' && pfirst == 'C') pathCommands[i] = 'C'; // A is the only command
4088 	    // which may produce multiple C:s
4089 	    // so we have to make sure that C is also C in original path
4090 
4091 	    fixArc(curvedPath, i); // fixArc adds also the right amount of A:s to pathCommands
4092 
4093 	    var seg = curvedPath[i],
4094 	        seglen = seg.length;
4095 
4096 	    attrs.x = seg[seglen - 2];
4097 	    attrs.y = seg[seglen - 1];
4098 	    attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
4099 	    attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
4100 	  }
4101 
4102 	  // cache curve
4103 	  pth.curve = pathClone(curvedPath);
4104 
4105 	  return curvedPath;
4106 	}
4107 
4108 	var intersect = findPathIntersections;
4109 
4110 	function roundBounds(bounds) {
4111 	  return {
4112 	    x: Math.round(bounds.x),
4113 	    y: Math.round(bounds.y),
4114 	    width: Math.round(bounds.width),
4115 	    height: Math.round(bounds.height)
4116 	  };
4117 	}
4118 
4119 
4120 	function roundPoint(point) {
4121 
4122 	  return {
4123 	    x: Math.round(point.x),
4124 	    y: Math.round(point.y)
4125 	  };
4126 	}
4127 
4128 
4129 	/**
4130 	 * Convert the given bounds to a { top, left, bottom, right } descriptor.
4131 	 *
4132 	 * @param {Bounds|Point} bounds
4133 	 *
4134 	 * @return {Object}
4135 	 */
4136 	function asTRBL(bounds) {
4137 	  return {
4138 	    top: bounds.y,
4139 	    right: bounds.x + (bounds.width || 0),
4140 	    bottom: bounds.y + (bounds.height || 0),
4141 	    left: bounds.x
4142 	  };
4143 	}
4144 
4145 
4146 	/**
4147 	 * Convert a { top, left, bottom, right } to an objects bounds.
4148 	 *
4149 	 * @param {Object} trbl
4150 	 *
4151 	 * @return {Bounds}
4152 	 */
4153 	function asBounds(trbl) {
4154 	  return {
4155 	    x: trbl.left,
4156 	    y: trbl.top,
4157 	    width: trbl.right - trbl.left,
4158 	    height: trbl.bottom - trbl.top
4159 	  };
4160 	}
4161 
4162 
4163 	/**
4164 	 * Get the mid of the given bounds or point.
4165 	 *
4166 	 * @param {Bounds|Point} bounds
4167 	 *
4168 	 * @return {Point}
4169 	 */
4170 	function getMid(bounds) {
4171 	  return roundPoint({
4172 	    x: bounds.x + (bounds.width || 0) / 2,
4173 	    y: bounds.y + (bounds.height || 0) / 2
4174 	  });
4175 	}
4176 
4177 
4178 	// orientation utils //////////////////////
4179 
4180 	/**
4181 	 * Get orientation of the given rectangle with respect to
4182 	 * the reference rectangle.
4183 	 *
4184 	 * A padding (positive or negative) may be passed to influence
4185 	 * horizontal / vertical orientation and intersection.
4186 	 *
4187 	 * @param {Bounds} rect
4188 	 * @param {Bounds} reference
4189 	 * @param {Point|number} padding
4190 	 *
4191 	 * @return {string} the orientation; one of top, top-left, left, ..., bottom, right or intersect.
4192 	 */
4193 	function getOrientation(rect, reference, padding) {
4194 
4195 	  padding = padding || 0;
4196 
4197 	  // make sure we can use an object, too
4198 	  // for individual { x, y } padding
4199 	  if (!isObject(padding)) {
4200 	    padding = { x: padding, y: padding };
4201 	  }
4202 
4203 
4204 	  var rectOrientation = asTRBL(rect),
4205 	      referenceOrientation = asTRBL(reference);
4206 
4207 	  var top = rectOrientation.bottom + padding.y <= referenceOrientation.top,
4208 	      right = rectOrientation.left - padding.x >= referenceOrientation.right,
4209 	      bottom = rectOrientation.top - padding.y >= referenceOrientation.bottom,
4210 	      left = rectOrientation.right + padding.x <= referenceOrientation.left;
4211 
4212 	  var vertical = top ? 'top' : (bottom ? 'bottom' : null),
4213 	      horizontal = left ? 'left' : (right ? 'right' : null);
4214 
4215 	  if (horizontal && vertical) {
4216 	    return vertical + '-' + horizontal;
4217 	  } else {
4218 	    return horizontal || vertical || 'intersect';
4219 	  }
4220 	}
4221 
4222 
4223 	// intersection utils //////////////////////
4224 
4225 	/**
4226 	 * Get intersection between an element and a line path.
4227 	 *
4228 	 * @param {PathDef} elementPath
4229 	 * @param {PathDef} linePath
4230 	 * @param {boolean} cropStart crop from start or end
4231 	 *
4232 	 * @return {Point}
4233 	 */
4234 	function getElementLineIntersection(elementPath, linePath, cropStart) {
4235 
4236 	  var intersections = getIntersections(elementPath, linePath);
4237 
4238 	  // recognize intersections
4239 	  // only one -> choose
4240 	  // two close together -> choose first
4241 	  // two or more distinct -> pull out appropriate one
4242 	  // none -> ok (fallback to point itself)
4243 	  if (intersections.length === 1) {
4244 	    return roundPoint(intersections[0]);
4245 	  } else if (intersections.length === 2 && pointDistance(intersections[0], intersections[1]) < 1) {
4246 	    return roundPoint(intersections[0]);
4247 	  } else if (intersections.length > 1) {
4248 
4249 	    // sort by intersections based on connection segment +
4250 	    // distance from start
4251 	    intersections = sortBy(intersections, function(i) {
4252 	      var distance = Math.floor(i.t2 * 100) || 1;
4253 
4254 	      distance = 100 - distance;
4255 
4256 	      distance = (distance < 10 ? '0' : '') + distance;
4257 
4258 	      // create a sort string that makes sure we sort
4259 	      // line segment ASC + line segment position DESC (for cropStart)
4260 	      // line segment ASC + line segment position ASC (for cropEnd)
4261 	      return i.segment2 + '#' + distance;
4262 	    });
4263 
4264 	    return roundPoint(intersections[cropStart ? 0 : intersections.length - 1]);
4265 	  }
4266 
4267 	  return null;
4268 	}
4269 
4270 
4271 	function getIntersections(a, b) {
4272 	  return intersect(a, b);
4273 	}
4274 
4275 
4276 	function filterRedundantWaypoints(waypoints) {
4277 
4278 	  // alter copy of waypoints, not original
4279 	  waypoints = waypoints.slice();
4280 
4281 	  var idx = 0,
4282 	      point,
4283 	      previousPoint,
4284 	      nextPoint;
4285 
4286 	  while (waypoints[idx]) {
4287 	    point = waypoints[idx];
4288 	    previousPoint = waypoints[idx - 1];
4289 	    nextPoint = waypoints[idx + 1];
4290 
4291 	    if (pointDistance(point, nextPoint) === 0 ||
4292 	        pointsOnLine(previousPoint, nextPoint, point)) {
4293 
4294 	      // remove point, if overlapping with {nextPoint}
4295 	      // or on line with {previousPoint} -> {point} -> {nextPoint}
4296 	      waypoints.splice(idx, 1);
4297 	    } else {
4298 	      idx++;
4299 	    }
4300 	  }
4301 
4302 	  return waypoints;
4303 	}
4304 
4305 	function round$b(number, resolution) {
4306 	  return Math.round(number * resolution) / resolution;
4307 	}
4308 
4309 	function ensurePx(number) {
4310 	  return isNumber(number) ? number + 'px' : number;
4311 	}
4312 
4313 	function findRoot(element) {
4314 	  while (element.parent) {
4315 	    element = element.parent;
4316 	  }
4317 
4318 	  return element;
4319 	}
4320 
4321 	/**
4322 	 * Creates a HTML container element for a SVG element with
4323 	 * the given configuration
4324 	 *
4325 	 * @param  {Object} options
4326 	 * @return {HTMLElement} the container element
4327 	 */
4328 	function createContainer(options) {
4329 
4330 	  options = assign({}, { width: '100%', height: '100%' }, options);
4331 
4332 	  var container = options.container || document.body;
4333 
4334 	  // create a <div> around the svg element with the respective size
4335 	  // this way we can always get the correct container size
4336 	  // (this is impossible for <svg> elements at the moment)
4337 	  var parent = document.createElement('div');
4338 	  parent.setAttribute('class', 'djs-container');
4339 
4340 	  assign(parent.style, {
4341 	    position: 'relative',
4342 	    overflow: 'hidden',
4343 	    width: ensurePx(options.width),
4344 	    height: ensurePx(options.height)
4345 	  });
4346 
4347 	  container.appendChild(parent);
4348 
4349 	  return parent;
4350 	}
4351 
4352 	function createGroup(parent, cls, childIndex) {
4353 	  var group = create$1('g');
4354 	  classes(group).add(cls);
4355 
4356 	  var index = childIndex !== undefined ? childIndex : parent.childNodes.length - 1;
4357 
4358 	  // must ensure second argument is node or _null_
4359 	  // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
4360 	  parent.insertBefore(group, parent.childNodes[index] || null);
4361 
4362 	  return group;
4363 	}
4364 
4365 	var BASE_LAYER = 'base';
4366 	var HIDDEN_MARKER = 'djs-element-hidden';
4367 
4368 
4369 	var REQUIRED_MODEL_ATTRS = {
4370 	  shape: [ 'x', 'y', 'width', 'height' ],
4371 	  connection: [ 'waypoints' ]
4372 	};
4373 
4374 	/**
4375 	 * The main drawing canvas.
4376 	 *
4377 	 * @class
4378 	 * @constructor
4379 	 *
4380 	 * @emits Canvas#canvas.init
4381 	 *
4382 	 * @param {Object} config
4383 	 * @param {EventBus} eventBus
4384 	 * @param {GraphicsFactory} graphicsFactory
4385 	 * @param {ElementRegistry} elementRegistry
4386 	 */
4387 	function Canvas(config, eventBus, graphicsFactory, elementRegistry) {
4388 
4389 	  this._eventBus = eventBus;
4390 	  this._elementRegistry = elementRegistry;
4391 	  this._graphicsFactory = graphicsFactory;
4392 
4393 	  this._init(config || {});
4394 	}
4395 
4396 	Canvas.$inject = [
4397 	  'config.canvas',
4398 	  'eventBus',
4399 	  'graphicsFactory',
4400 	  'elementRegistry'
4401 	];
4402 
4403 	/**
4404 	 * Creates a <svg> element that is wrapped into a <div>.
4405 	 * This way we are always able to correctly figure out the size of the svg element
4406 	 * by querying the parent node.
4407 
4408 	 * (It is not possible to get the size of a svg element cross browser @ 2014-04-01)
4409 
4410 	 * <div class="djs-container" style="width: {desired-width}, height: {desired-height}">
4411 	 *   <svg width="100%" height="100%">
4412 	 *    ...
4413 	 *   </svg>
4414 	 * </div>
4415 	 */
4416 	Canvas.prototype._init = function(config) {
4417 
4418 	  var eventBus = this._eventBus;
4419 
4420 	  // html container
4421 	  var container = this._container = createContainer(config);
4422 
4423 	  var svg = this._svg = create$1('svg');
4424 	  attr(svg, { width: '100%', height: '100%' });
4425 
4426 	  append(container, svg);
4427 
4428 	  var viewport = this._viewport = createGroup(svg, 'viewport');
4429 
4430 	  this._layers = {};
4431 	  this._planes = {};
4432 
4433 	  // debounce canvas.viewbox.changed events
4434 	  // for smoother diagram interaction
4435 	  if (config.deferUpdate !== false) {
4436 	    this._viewboxChanged = debounce(bind$2(this._viewboxChanged, this), 300);
4437 	  }
4438 
4439 	  eventBus.on('diagram.init', function() {
4440 
4441 	    /**
4442 	     * An event indicating that the canvas is ready to be drawn on.
4443 	     *
4444 	     * @memberOf Canvas
4445 	     *
4446 	     * @event canvas.init
4447 	     *
4448 	     * @type {Object}
4449 	     * @property {SVGElement} svg the created svg element
4450 	     * @property {SVGElement} viewport the direct parent of diagram elements and shapes
4451 	     */
4452 	    eventBus.fire('canvas.init', {
4453 	      svg: svg,
4454 	      viewport: viewport
4455 	    });
4456 
4457 	  }, this);
4458 
4459 	  // reset viewbox on shape changes to
4460 	  // recompute the viewbox
4461 	  eventBus.on([
4462 	    'shape.added',
4463 	    'connection.added',
4464 	    'shape.removed',
4465 	    'connection.removed',
4466 	    'elements.changed'
4467 	  ], function() {
4468 	    delete this._cachedViewbox;
4469 	  }, this);
4470 
4471 	  eventBus.on('diagram.destroy', 500, this._destroy, this);
4472 	  eventBus.on('diagram.clear', 500, this._clear, this);
4473 	};
4474 
4475 	Canvas.prototype._destroy = function(emit) {
4476 	  this._eventBus.fire('canvas.destroy', {
4477 	    svg: this._svg,
4478 	    viewport: this._viewport
4479 	  });
4480 
4481 	  var parent = this._container.parentNode;
4482 
4483 	  if (parent) {
4484 	    parent.removeChild(this._container);
4485 	  }
4486 
4487 	  delete this._svg;
4488 	  delete this._container;
4489 	  delete this._layers;
4490 	  delete this._planes;
4491 	  delete this._activePlane;
4492 	  delete this._viewport;
4493 	};
4494 
4495 	Canvas.prototype._clear = function() {
4496 
4497 	  var self = this;
4498 
4499 	  var allElements = this._elementRegistry.getAll();
4500 
4501 	  // remove all elements
4502 	  allElements.forEach(function(element) {
4503 	    var type = getType(element);
4504 
4505 	    if (type === 'root') {
4506 	      self.setRootElementForPlane(null, self.findPlane(element), true);
4507 	    } else {
4508 	      self._removeElement(element, type);
4509 	    }
4510 	  });
4511 
4512 	  // remove all planes
4513 	  this._activePlane = null;
4514 	  this._planes = {};
4515 
4516 	  // force recomputation of view box
4517 	  delete this._cachedViewbox;
4518 	};
4519 
4520 	/**
4521 	 * Returns the default layer on which
4522 	 * all elements are drawn.
4523 	 *
4524 	 * @returns {SVGElement}
4525 	 */
4526 	Canvas.prototype.getDefaultLayer = function() {
4527 	  return this.getLayer(BASE_LAYER);
4528 	};
4529 
4530 	/**
4531 	 * Returns a layer that is used to draw elements
4532 	 * or annotations on it.
4533 	 *
4534 	 * Non-existing layers retrieved through this method
4535 	 * will be created. During creation, the optional index
4536 	 * may be used to create layers below or above existing layers.
4537 	 * A layer with a certain index is always created above all
4538 	 * existing layers with the same index.
4539 	 *
4540 	 * @param {string} name
4541 	 * @param {number} index
4542 	 *
4543 	 * @returns {SVGElement}
4544 	 */
4545 	Canvas.prototype.getLayer = function(name, index) {
4546 
4547 	  if (!name) {
4548 	    throw new Error('must specify a name');
4549 	  }
4550 
4551 	  var layer = this._layers[name];
4552 
4553 	  if (!layer) {
4554 	    layer = this._layers[name] = this._createLayer(name, index);
4555 	  }
4556 
4557 	  // throw an error if layer creation / retrival is
4558 	  // requested on different index
4559 	  if (typeof index !== 'undefined' && layer.index !== index) {
4560 	    throw new Error('layer <' + name + '> already created at index <' + index + '>');
4561 	  }
4562 
4563 	  return layer.group;
4564 	};
4565 
4566 	/**
4567 	 * Creates a given layer and returns it.
4568 	 *
4569 	 * @param {string} name
4570 	 * @param {number} [index=0]
4571 	 *
4572 	 * @return {Object} layer descriptor with { index, group: SVGGroup }
4573 	 */
4574 	Canvas.prototype._createLayer = function(name, index) {
4575 
4576 	  if (!index) {
4577 	    index = 0;
4578 	  }
4579 
4580 	  var childIndex = reduce(this._layers, function(childIndex, layer) {
4581 	    if (index >= layer.index) {
4582 	      childIndex++;
4583 	    }
4584 
4585 	    return childIndex;
4586 	  }, 0);
4587 
4588 	  return {
4589 	    group: createGroup(this._viewport, 'layer-' + name, childIndex),
4590 	    index: index
4591 	  };
4592 
4593 	};
4594 
4595 	/**
4596 	 * Returns a plane that is used to draw elements on it.
4597 	 *
4598 	 * @param {string} name
4599 	 *
4600 	 * @return {Object} plane descriptor with { layer, rootElement, name }
4601 	 */
4602 	Canvas.prototype.getPlane = function(name) {
4603 	  if (!name) {
4604 	    throw new Error('must specify a name');
4605 	  }
4606 
4607 	  var plane = this._planes[name];
4608 
4609 	  return plane;
4610 	};
4611 
4612 	/**
4613 	 * Creates a plane that is used to draw elements on it. If no
4614 	 * root element is provided, an implicit root will be used.
4615 	 *
4616 	 * @param {string} name
4617 	 * @param {Object|djs.model.Root} [rootElement] optional root element
4618 	 *
4619 	 * @return {Object} plane descriptor with { layer, rootElement, name }
4620 	 */
4621 	Canvas.prototype.createPlane = function(name, rootElement) {
4622 	  if (!name) {
4623 	    throw new Error('must specify a name');
4624 	  }
4625 
4626 	  if (this._planes[name]) {
4627 	    throw new Error('plane ' + name + ' already exists');
4628 	  }
4629 
4630 	  if (!rootElement) {
4631 	    rootElement = {
4632 	      id: '__implicitroot' + name,
4633 	      children: [],
4634 	      isImplicit: true
4635 	    };
4636 	  }
4637 
4638 	  var svgLayer = this.getLayer(name);
4639 	  classes(svgLayer).add(HIDDEN_MARKER);
4640 
4641 	  var plane = this._planes[name] = {
4642 	    layer: svgLayer,
4643 	    name: name,
4644 	    rootElement: null
4645 	  };
4646 
4647 	  this.setRootElementForPlane(rootElement, plane);
4648 
4649 	  return plane;
4650 	};
4651 
4652 	/**
4653 	 * Sets the active plane and hides the previously active plane.
4654 	 *
4655 	 * @param {string|Object} plane
4656 	 *
4657 	 * @return {Object} plane descriptor with { layer, rootElement, name }
4658 	 */
4659 	Canvas.prototype.setActivePlane = function(plane) {
4660 	  if (!plane) {
4661 	    throw new Error('must specify a plane');
4662 	  }
4663 
4664 	  if (typeof plane === 'string') {
4665 	    plane = this.getPlane(plane);
4666 	  }
4667 
4668 	  // hide previous Plane
4669 	  if (this._activePlane) {
4670 	    classes(this._activePlane.layer).add(HIDDEN_MARKER);
4671 	  }
4672 
4673 	  this._activePlane = plane;
4674 
4675 	  // show current Plane
4676 	  classes(plane.layer).remove(HIDDEN_MARKER);
4677 
4678 	  if (plane.rootElement) {
4679 	    this._elementRegistry.updateGraphics(plane.rootElement, this._svg, true);
4680 	  }
4681 
4682 	  this._eventBus.fire('plane.set', { plane: plane });
4683 
4684 	  return plane;
4685 	};
4686 
4687 	/**
4688 	 * Returns the currently active layer
4689 	 *
4690 	 * @returns {SVGElement}
4691 	 */
4692 
4693 	Canvas.prototype.getActiveLayer = function() {
4694 	  return this.getActivePlane().layer;
4695 	};
4696 
4697 	/**
4698 	 * Returns the currently active plane.
4699 	 *
4700 	 * @return {Object} plane descriptor with { layer, rootElement, name }
4701 	 */
4702 	Canvas.prototype.getActivePlane = function() {
4703 	  var plane = this._activePlane;
4704 	  if (!plane) {
4705 	    plane = this.createPlane(BASE_LAYER);
4706 	    this.setActivePlane(BASE_LAYER);
4707 	  }
4708 
4709 	  return plane;
4710 	};
4711 
4712 	/**
4713 	 * Returns the plane which contains the given element.
4714 	 *
4715 	 * @param {string|djs.model.Base} element
4716 	 *
4717 	 * @return {Object} plane descriptor with { layer, rootElement, name }
4718 	 */
4719 	Canvas.prototype.findPlane = function(element) {
4720 	  if (typeof element === 'string') {
4721 	    element = this._elementRegistry.get(element);
4722 	  }
4723 
4724 	  var root = findRoot(element);
4725 
4726 	  return find(this._planes, function(plane) {
4727 	    return plane.rootElement === root;
4728 	  });
4729 	};
4730 
4731 	/**
4732 	 * Returns the html element that encloses the
4733 	 * drawing canvas.
4734 	 *
4735 	 * @return {DOMNode}
4736 	 */
4737 	Canvas.prototype.getContainer = function() {
4738 	  return this._container;
4739 	};
4740 
4741 
4742 	// markers //////////////////////
4743 
4744 	Canvas.prototype._updateMarker = function(element, marker, add) {
4745 	  var container;
4746 
4747 	  if (!element.id) {
4748 	    element = this._elementRegistry.get(element);
4749 	  }
4750 
4751 	  // we need to access all
4752 	  container = this._elementRegistry._elements[element.id];
4753 
4754 	  if (!container) {
4755 	    return;
4756 	  }
4757 
4758 	  forEach([ container.gfx, container.secondaryGfx ], function(gfx) {
4759 	    if (gfx) {
4760 
4761 	      // invoke either addClass or removeClass based on mode
4762 	      if (add) {
4763 	        classes(gfx).add(marker);
4764 	      } else {
4765 	        classes(gfx).remove(marker);
4766 	      }
4767 	    }
4768 	  });
4769 
4770 	  /**
4771 	   * An event indicating that a marker has been updated for an element
4772 	   *
4773 	   * @event element.marker.update
4774 	   * @type {Object}
4775 	   * @property {djs.model.Element} element the shape
4776 	   * @property {Object} gfx the graphical representation of the shape
4777 	   * @property {string} marker
4778 	   * @property {boolean} add true if the marker was added, false if it got removed
4779 	   */
4780 	  this._eventBus.fire('element.marker.update', { element: element, gfx: container.gfx, marker: marker, add: !!add });
4781 	};
4782 
4783 
4784 	/**
4785 	 * Adds a marker to an element (basically a css class).
4786 	 *
4787 	 * Fires the element.marker.update event, making it possible to
4788 	 * integrate extension into the marker life-cycle, too.
4789 	 *
4790 	 * @example
4791 	 * canvas.addMarker('foo', 'some-marker');
4792 	 *
4793 	 * var fooGfx = canvas.getGraphics('foo');
4794 	 *
4795 	 * fooGfx; // <g class="... some-marker"> ... </g>
4796 	 *
4797 	 * @param {string|djs.model.Base} element
4798 	 * @param {string} marker
4799 	 */
4800 	Canvas.prototype.addMarker = function(element, marker) {
4801 	  this._updateMarker(element, marker, true);
4802 	};
4803 
4804 
4805 	/**
4806 	 * Remove a marker from an element.
4807 	 *
4808 	 * Fires the element.marker.update event, making it possible to
4809 	 * integrate extension into the marker life-cycle, too.
4810 	 *
4811 	 * @param  {string|djs.model.Base} element
4812 	 * @param  {string} marker
4813 	 */
4814 	Canvas.prototype.removeMarker = function(element, marker) {
4815 	  this._updateMarker(element, marker, false);
4816 	};
4817 
4818 	/**
4819 	 * Check the existence of a marker on element.
4820 	 *
4821 	 * @param  {string|djs.model.Base} element
4822 	 * @param  {string} marker
4823 	 */
4824 	Canvas.prototype.hasMarker = function(element, marker) {
4825 	  if (!element.id) {
4826 	    element = this._elementRegistry.get(element);
4827 	  }
4828 
4829 	  var gfx = this.getGraphics(element);
4830 
4831 	  return classes(gfx).has(marker);
4832 	};
4833 
4834 	/**
4835 	 * Toggles a marker on an element.
4836 	 *
4837 	 * Fires the element.marker.update event, making it possible to
4838 	 * integrate extension into the marker life-cycle, too.
4839 	 *
4840 	 * @param  {string|djs.model.Base} element
4841 	 * @param  {string} marker
4842 	 */
4843 	Canvas.prototype.toggleMarker = function(element, marker) {
4844 	  if (this.hasMarker(element, marker)) {
4845 	    this.removeMarker(element, marker);
4846 	  } else {
4847 	    this.addMarker(element, marker);
4848 	  }
4849 	};
4850 
4851 	Canvas.prototype.getRootElement = function() {
4852 	  var plane = this.getActivePlane();
4853 
4854 	  return plane.rootElement;
4855 	};
4856 
4857 
4858 
4859 	// root element handling //////////////////////
4860 
4861 	/**
4862 	 * Sets a given element as the new root element for the canvas
4863 	 * and returns the new root element.
4864 	 *
4865 	 * @param {Object|djs.model.Root} element
4866 	 * @param {boolean} [override] whether to override the current root element, if any
4867 	 *
4868 	 * @return {Object|djs.model.Root} new root element
4869 	 */
4870 	Canvas.prototype.setRootElement = function(element, override) {
4871 	  var activePlane = this._activePlane;
4872 
4873 	  if (activePlane) {
4874 	    return this.setRootElementForPlane(element, activePlane, override);
4875 	  } else {
4876 	    var basePlane = this.createPlane(BASE_LAYER, element);
4877 
4878 	    this.setActivePlane(basePlane);
4879 
4880 	    return basePlane.rootElement;
4881 	  }
4882 	};
4883 
4884 
4885 	/**
4886 	 * Sets a given element as the new root element for the canvas
4887 	 * and returns the new root element.
4888 	 *
4889 	 * @param {Object|djs.model.Root} element
4890 	 * @param {Object|djs.model.Root} plane
4891 	 * @param {boolean} [override] whether to override the current root element, if any
4892 	 *
4893 	 * @return {Object|djs.model.Root} new root element
4894 	 */
4895 	Canvas.prototype.setRootElementForPlane = function(element, plane, override) {
4896 
4897 	  if (typeof plane === 'string') {
4898 	    plane = this.getPlane(plane);
4899 	  }
4900 
4901 	  if (element) {
4902 	    this._ensureValid('root', element);
4903 	  }
4904 
4905 	  var currentRoot = plane.rootElement,
4906 	      elementRegistry = this._elementRegistry,
4907 	      eventBus = this._eventBus;
4908 
4909 	  if (currentRoot) {
4910 	    if (!override) {
4911 	      throw new Error('rootElement already set, need to specify override');
4912 	    }
4913 
4914 	    // simulate element remove event sequence
4915 	    eventBus.fire('root.remove', { element: currentRoot });
4916 	    eventBus.fire('root.removed', { element: currentRoot });
4917 
4918 	    elementRegistry.remove(currentRoot);
4919 	  }
4920 
4921 	  if (element) {
4922 	    var gfx = plane.layer;
4923 
4924 	    // resemble element add event sequence
4925 	    eventBus.fire('root.add', { element: element });
4926 
4927 	    elementRegistry.add(element, gfx);
4928 
4929 	    eventBus.fire('root.added', { element: element, gfx: gfx });
4930 
4931 	    // associate SVG with root element when active
4932 	    if (plane === this._activePlane) {
4933 	      this._elementRegistry.updateGraphics(element, this._svg, true);
4934 	    }
4935 	  }
4936 
4937 	  plane.rootElement = element;
4938 
4939 	  return element;
4940 	};
4941 
4942 	// add functionality //////////////////////
4943 
4944 	Canvas.prototype._ensureValid = function(type, element) {
4945 	  if (!element.id) {
4946 	    throw new Error('element must have an id');
4947 	  }
4948 
4949 	  if (this._elementRegistry.get(element.id)) {
4950 	    throw new Error('element with id ' + element.id + ' already exists');
4951 	  }
4952 
4953 	  var requiredAttrs = REQUIRED_MODEL_ATTRS[type];
4954 
4955 	  var valid = every(requiredAttrs, function(attr) {
4956 	    return typeof element[attr] !== 'undefined';
4957 	  });
4958 
4959 	  if (!valid) {
4960 	    throw new Error(
4961 	      'must supply { ' + requiredAttrs.join(', ') + ' } with ' + type);
4962 	  }
4963 	};
4964 
4965 	Canvas.prototype._setParent = function(element, parent, parentIndex) {
4966 	  add(parent.children, element, parentIndex);
4967 	  element.parent = parent;
4968 	};
4969 
4970 	/**
4971 	 * Adds an element to the canvas.
4972 	 *
4973 	 * This wires the parent <-> child relationship between the element and
4974 	 * a explicitly specified parent or an implicit root element.
4975 	 *
4976 	 * During add it emits the events
4977 	 *
4978 	 *  * <{type}.add> (element, parent)
4979 	 *  * <{type}.added> (element, gfx)
4980 	 *
4981 	 * Extensions may hook into these events to perform their magic.
4982 	 *
4983 	 * @param {string} type
4984 	 * @param {Object|djs.model.Base} element
4985 	 * @param {Object|djs.model.Base} [parent]
4986 	 * @param {number} [parentIndex]
4987 	 *
4988 	 * @return {Object|djs.model.Base} the added element
4989 	 */
4990 	Canvas.prototype._addElement = function(type, element, parent, parentIndex) {
4991 
4992 	  parent = parent || this.getRootElement();
4993 
4994 	  var eventBus = this._eventBus,
4995 	      graphicsFactory = this._graphicsFactory;
4996 
4997 	  this._ensureValid(type, element);
4998 
4999 	  eventBus.fire(type + '.add', { element: element, parent: parent });
5000 
5001 	  this._setParent(element, parent, parentIndex);
5002 
5003 	  // create graphics
5004 	  var gfx = graphicsFactory.create(type, element, parentIndex);
5005 
5006 	  this._elementRegistry.add(element, gfx);
5007 
5008 	  // update its visual
5009 	  graphicsFactory.update(type, element, gfx);
5010 
5011 	  eventBus.fire(type + '.added', { element: element, gfx: gfx });
5012 
5013 	  return element;
5014 	};
5015 
5016 	/**
5017 	 * Adds a shape to the canvas
5018 	 *
5019 	 * @param {Object|djs.model.Shape} shape to add to the diagram
5020 	 * @param {djs.model.Base} [parent]
5021 	 * @param {number} [parentIndex]
5022 	 *
5023 	 * @return {djs.model.Shape} the added shape
5024 	 */
5025 	Canvas.prototype.addShape = function(shape, parent, parentIndex) {
5026 	  return this._addElement('shape', shape, parent, parentIndex);
5027 	};
5028 
5029 	/**
5030 	 * Adds a connection to the canvas
5031 	 *
5032 	 * @param {Object|djs.model.Connection} connection to add to the diagram
5033 	 * @param {djs.model.Base} [parent]
5034 	 * @param {number} [parentIndex]
5035 	 *
5036 	 * @return {djs.model.Connection} the added connection
5037 	 */
5038 	Canvas.prototype.addConnection = function(connection, parent, parentIndex) {
5039 	  return this._addElement('connection', connection, parent, parentIndex);
5040 	};
5041 
5042 
5043 	/**
5044 	 * Internal remove element
5045 	 */
5046 	Canvas.prototype._removeElement = function(element, type) {
5047 
5048 	  var elementRegistry = this._elementRegistry,
5049 	      graphicsFactory = this._graphicsFactory,
5050 	      eventBus = this._eventBus;
5051 
5052 	  element = elementRegistry.get(element.id || element);
5053 
5054 	  if (!element) {
5055 
5056 	    // element was removed already
5057 	    return;
5058 	  }
5059 
5060 	  eventBus.fire(type + '.remove', { element: element });
5061 
5062 	  graphicsFactory.remove(element);
5063 
5064 	  // unset parent <-> child relationship
5065 	  remove(element.parent && element.parent.children, element);
5066 	  element.parent = null;
5067 
5068 	  eventBus.fire(type + '.removed', { element: element });
5069 
5070 	  elementRegistry.remove(element);
5071 
5072 	  return element;
5073 	};
5074 
5075 
5076 	/**
5077 	 * Removes a shape from the canvas
5078 	 *
5079 	 * @param {string|djs.model.Shape} shape or shape id to be removed
5080 	 *
5081 	 * @return {djs.model.Shape} the removed shape
5082 	 */
5083 	Canvas.prototype.removeShape = function(shape) {
5084 
5085 	  /**
5086 	   * An event indicating that a shape is about to be removed from the canvas.
5087 	   *
5088 	   * @memberOf Canvas
5089 	   *
5090 	   * @event shape.remove
5091 	   * @type {Object}
5092 	   * @property {djs.model.Shape} element the shape descriptor
5093 	   * @property {Object} gfx the graphical representation of the shape
5094 	   */
5095 
5096 	  /**
5097 	   * An event indicating that a shape has been removed from the canvas.
5098 	   *
5099 	   * @memberOf Canvas
5100 	   *
5101 	   * @event shape.removed
5102 	   * @type {Object}
5103 	   * @property {djs.model.Shape} element the shape descriptor
5104 	   * @property {Object} gfx the graphical representation of the shape
5105 	   */
5106 	  return this._removeElement(shape, 'shape');
5107 	};
5108 
5109 
5110 	/**
5111 	 * Removes a connection from the canvas
5112 	 *
5113 	 * @param {string|djs.model.Connection} connection or connection id to be removed
5114 	 *
5115 	 * @return {djs.model.Connection} the removed connection
5116 	 */
5117 	Canvas.prototype.removeConnection = function(connection) {
5118 
5119 	  /**
5120 	   * An event indicating that a connection is about to be removed from the canvas.
5121 	   *
5122 	   * @memberOf Canvas
5123 	   *
5124 	   * @event connection.remove
5125 	   * @type {Object}
5126 	   * @property {djs.model.Connection} element the connection descriptor
5127 	   * @property {Object} gfx the graphical representation of the connection
5128 	   */
5129 
5130 	  /**
5131 	   * An event indicating that a connection has been removed from the canvas.
5132 	   *
5133 	   * @memberOf Canvas
5134 	   *
5135 	   * @event connection.removed
5136 	   * @type {Object}
5137 	   * @property {djs.model.Connection} element the connection descriptor
5138 	   * @property {Object} gfx the graphical representation of the connection
5139 	   */
5140 	  return this._removeElement(connection, 'connection');
5141 	};
5142 
5143 
5144 	/**
5145 	 * Return the graphical object underlaying a certain diagram element
5146 	 *
5147 	 * @param {string|djs.model.Base} element descriptor of the element
5148 	 * @param {boolean} [secondary=false] whether to return the secondary connected element
5149 	 *
5150 	 * @return {SVGElement}
5151 	 */
5152 	Canvas.prototype.getGraphics = function(element, secondary) {
5153 	  return this._elementRegistry.getGraphics(element, secondary);
5154 	};
5155 
5156 
5157 	/**
5158 	 * Perform a viewbox update via a given change function.
5159 	 *
5160 	 * @param {Function} changeFn
5161 	 */
5162 	Canvas.prototype._changeViewbox = function(changeFn) {
5163 
5164 	  // notify others of the upcoming viewbox change
5165 	  this._eventBus.fire('canvas.viewbox.changing');
5166 
5167 	  // perform actual change
5168 	  changeFn.apply(this);
5169 
5170 	  // reset the cached viewbox so that
5171 	  // a new get operation on viewbox or zoom
5172 	  // triggers a viewbox re-computation
5173 	  this._cachedViewbox = null;
5174 
5175 	  // notify others of the change; this step
5176 	  // may or may not be debounced
5177 	  this._viewboxChanged();
5178 	};
5179 
5180 	Canvas.prototype._viewboxChanged = function() {
5181 	  this._eventBus.fire('canvas.viewbox.changed', { viewbox: this.viewbox() });
5182 	};
5183 
5184 
5185 	/**
5186 	 * Gets or sets the view box of the canvas, i.e. the
5187 	 * area that is currently displayed.
5188 	 *
5189 	 * The getter may return a cached viewbox (if it is currently
5190 	 * changing). To force a recomputation, pass `false` as the first argument.
5191 	 *
5192 	 * @example
5193 	 *
5194 	 * canvas.viewbox({ x: 100, y: 100, width: 500, height: 500 })
5195 	 *
5196 	 * // sets the visible area of the diagram to (100|100) -> (600|100)
5197 	 * // and and scales it according to the diagram width
5198 	 *
5199 	 * var viewbox = canvas.viewbox(); // pass `false` to force recomputing the box.
5200 	 *
5201 	 * console.log(viewbox);
5202 	 * // {
5203 	 * //   inner: Dimensions,
5204 	 * //   outer: Dimensions,
5205 	 * //   scale,
5206 	 * //   x, y,
5207 	 * //   width, height
5208 	 * // }
5209 	 *
5210 	 * // if the current diagram is zoomed and scrolled, you may reset it to the
5211 	 * // default zoom via this method, too:
5212 	 *
5213 	 * var zoomedAndScrolledViewbox = canvas.viewbox();
5214 	 *
5215 	 * canvas.viewbox({
5216 	 *   x: 0,
5217 	 *   y: 0,
5218 	 *   width: zoomedAndScrolledViewbox.outer.width,
5219 	 *   height: zoomedAndScrolledViewbox.outer.height
5220 	 * });
5221 	 *
5222 	 * @param  {Object} [box] the new view box to set
5223 	 * @param  {number} box.x the top left X coordinate of the canvas visible in view box
5224 	 * @param  {number} box.y the top left Y coordinate of the canvas visible in view box
5225 	 * @param  {number} box.width the visible width
5226 	 * @param  {number} box.height
5227 	 *
5228 	 * @return {Object} the current view box
5229 	 */
5230 	Canvas.prototype.viewbox = function(box) {
5231 
5232 	  if (box === undefined && this._cachedViewbox) {
5233 	    return this._cachedViewbox;
5234 	  }
5235 
5236 	  var viewport = this._viewport,
5237 	      innerBox,
5238 	      outerBox = this.getSize(),
5239 	      matrix,
5240 	      transform,
5241 	      scale,
5242 	      x, y;
5243 
5244 	  if (!box) {
5245 
5246 	    // compute the inner box based on the
5247 	    // diagrams default layer. This allows us to exclude
5248 	    // external components, such as overlays
5249 	    innerBox = this.getDefaultLayer().getBBox();
5250 
5251 	    transform = transform$1(viewport);
5252 	    matrix = transform ? transform.matrix : createMatrix();
5253 	    scale = round$b(matrix.a, 1000);
5254 
5255 	    x = round$b(-matrix.e || 0, 1000);
5256 	    y = round$b(-matrix.f || 0, 1000);
5257 
5258 	    box = this._cachedViewbox = {
5259 	      x: x ? x / scale : 0,
5260 	      y: y ? y / scale : 0,
5261 	      width: outerBox.width / scale,
5262 	      height: outerBox.height / scale,
5263 	      scale: scale,
5264 	      inner: {
5265 	        width: innerBox.width,
5266 	        height: innerBox.height,
5267 	        x: innerBox.x,
5268 	        y: innerBox.y
5269 	      },
5270 	      outer: outerBox
5271 	    };
5272 
5273 	    return box;
5274 	  } else {
5275 
5276 	    this._changeViewbox(function() {
5277 	      scale = Math.min(outerBox.width / box.width, outerBox.height / box.height);
5278 
5279 	      var matrix = this._svg.createSVGMatrix()
5280 	        .scale(scale)
5281 	        .translate(-box.x, -box.y);
5282 
5283 	      transform$1(viewport, matrix);
5284 	    });
5285 	  }
5286 
5287 	  return box;
5288 	};
5289 
5290 
5291 	/**
5292 	 * Gets or sets the scroll of the canvas.
5293 	 *
5294 	 * @param {Object} [delta] the new scroll to apply.
5295 	 *
5296 	 * @param {number} [delta.dx]
5297 	 * @param {number} [delta.dy]
5298 	 */
5299 	Canvas.prototype.scroll = function(delta) {
5300 
5301 	  var node = this._viewport;
5302 	  var matrix = node.getCTM();
5303 
5304 	  if (delta) {
5305 	    this._changeViewbox(function() {
5306 	      delta = assign({ dx: 0, dy: 0 }, delta || {});
5307 
5308 	      matrix = this._svg.createSVGMatrix().translate(delta.dx, delta.dy).multiply(matrix);
5309 
5310 	      setCTM(node, matrix);
5311 	    });
5312 	  }
5313 
5314 	  return { x: matrix.e, y: matrix.f };
5315 	};
5316 
5317 	/**
5318 	 * Scrolls the viewbox to contain the given element.
5319 	 * Optionally specify a padding to be applied to the edges.
5320 	 *
5321 	 * @param {Object} [element] the element to scroll to.
5322 	 * @param {Object|Number} [padding=100] the padding to be applied. Can also specify top, bottom, left and right.
5323 	 *
5324 	 */
5325 	Canvas.prototype.scrollToElement = function(element, padding) {
5326 	  var defaultPadding = 100;
5327 
5328 	  // switch to correct Plane
5329 	  var targetPlane = this.findPlane(element);
5330 	  if (targetPlane !== this._activePlane) {
5331 	    this.setActivePlane(targetPlane);
5332 	  }
5333 
5334 	  if (!padding) {
5335 	    padding = {};
5336 	  }
5337 	  if (typeof padding === 'number') {
5338 	    defaultPadding = padding;
5339 	  }
5340 
5341 	  padding = {
5342 	    top: padding.top || defaultPadding,
5343 	    right: padding.right || defaultPadding,
5344 	    bottom: padding.bottom || defaultPadding,
5345 	    left: padding.left || defaultPadding
5346 	  };
5347 
5348 	  var elementBounds = getBBox(element),
5349 	      elementTrbl = asTRBL(elementBounds),
5350 	      viewboxBounds = this.viewbox(),
5351 	      zoom = this.zoom(),
5352 	      dx, dy;
5353 
5354 	  // shrink viewboxBounds with padding
5355 	  viewboxBounds.y += padding.top / zoom;
5356 	  viewboxBounds.x += padding.left / zoom;
5357 	  viewboxBounds.width -= (padding.right + padding.left) / zoom;
5358 	  viewboxBounds.height -= (padding.bottom + padding.top) / zoom;
5359 
5360 	  var viewboxTrbl = asTRBL(viewboxBounds);
5361 
5362 	  var canFit = elementBounds.width < viewboxBounds.width && elementBounds.height < viewboxBounds.height;
5363 
5364 	  if (!canFit) {
5365 
5366 	    // top-left when element can't fit
5367 	    dx = elementBounds.x - viewboxBounds.x;
5368 	    dy = elementBounds.y - viewboxBounds.y;
5369 
5370 	  } else {
5371 
5372 	    var dRight = Math.max(0, elementTrbl.right - viewboxTrbl.right),
5373 	        dLeft = Math.min(0, elementTrbl.left - viewboxTrbl.left),
5374 	        dBottom = Math.max(0, elementTrbl.bottom - viewboxTrbl.bottom),
5375 	        dTop = Math.min(0, elementTrbl.top - viewboxTrbl.top);
5376 
5377 	    dx = dRight || dLeft;
5378 	    dy = dBottom || dTop;
5379 
5380 	  }
5381 
5382 	  this.scroll({ dx: -dx * zoom, dy: -dy * zoom });
5383 	};
5384 
5385 	/**
5386 	 * Gets or sets the current zoom of the canvas, optionally zooming
5387 	 * to the specified position.
5388 	 *
5389 	 * The getter may return a cached zoom level. Call it with `false` as
5390 	 * the first argument to force recomputation of the current level.
5391 	 *
5392 	 * @param {string|number} [newScale] the new zoom level, either a number, i.e. 0.9,
5393 	 *                                   or `fit-viewport` to adjust the size to fit the current viewport
5394 	 * @param {string|Point} [center] the reference point { x: .., y: ..} to zoom to, 'auto' to zoom into mid or null
5395 	 *
5396 	 * @return {number} the current scale
5397 	 */
5398 	Canvas.prototype.zoom = function(newScale, center) {
5399 
5400 	  if (!newScale) {
5401 	    return this.viewbox(newScale).scale;
5402 	  }
5403 
5404 	  if (newScale === 'fit-viewport') {
5405 	    return this._fitViewport(center);
5406 	  }
5407 
5408 	  var outer,
5409 	      matrix;
5410 
5411 	  this._changeViewbox(function() {
5412 
5413 	    if (typeof center !== 'object') {
5414 	      outer = this.viewbox().outer;
5415 
5416 	      center = {
5417 	        x: outer.width / 2,
5418 	        y: outer.height / 2
5419 	      };
5420 	    }
5421 
5422 	    matrix = this._setZoom(newScale, center);
5423 	  });
5424 
5425 	  return round$b(matrix.a, 1000);
5426 	};
5427 
5428 	function setCTM(node, m) {
5429 	  var mstr = 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.e + ',' + m.f + ')';
5430 	  node.setAttribute('transform', mstr);
5431 	}
5432 
5433 	Canvas.prototype._fitViewport = function(center) {
5434 
5435 	  var vbox = this.viewbox(),
5436 	      outer = vbox.outer,
5437 	      inner = vbox.inner,
5438 	      newScale,
5439 	      newViewbox;
5440 
5441 	  // display the complete diagram without zooming in.
5442 	  // instead of relying on internal zoom, we perform a
5443 	  // hard reset on the canvas viewbox to realize this
5444 	  //
5445 	  // if diagram does not need to be zoomed in, we focus it around
5446 	  // the diagram origin instead
5447 
5448 	  if (inner.x >= 0 &&
5449 	      inner.y >= 0 &&
5450 	      inner.x + inner.width <= outer.width &&
5451 	      inner.y + inner.height <= outer.height &&
5452 	      !center) {
5453 
5454 	    newViewbox = {
5455 	      x: 0,
5456 	      y: 0,
5457 	      width: Math.max(inner.width + inner.x, outer.width),
5458 	      height: Math.max(inner.height + inner.y, outer.height)
5459 	    };
5460 	  } else {
5461 
5462 	    newScale = Math.min(1, outer.width / inner.width, outer.height / inner.height);
5463 	    newViewbox = {
5464 	      x: inner.x + (center ? inner.width / 2 - outer.width / newScale / 2 : 0),
5465 	      y: inner.y + (center ? inner.height / 2 - outer.height / newScale / 2 : 0),
5466 	      width: outer.width / newScale,
5467 	      height: outer.height / newScale
5468 	    };
5469 	  }
5470 
5471 	  this.viewbox(newViewbox);
5472 
5473 	  return this.viewbox(false).scale;
5474 	};
5475 
5476 
5477 	Canvas.prototype._setZoom = function(scale, center) {
5478 
5479 	  var svg = this._svg,
5480 	      viewport = this._viewport;
5481 
5482 	  var matrix = svg.createSVGMatrix();
5483 	  var point = svg.createSVGPoint();
5484 
5485 	  var centerPoint,
5486 	      originalPoint,
5487 	      currentMatrix,
5488 	      scaleMatrix,
5489 	      newMatrix;
5490 
5491 	  currentMatrix = viewport.getCTM();
5492 
5493 	  var currentScale = currentMatrix.a;
5494 
5495 	  if (center) {
5496 	    centerPoint = assign(point, center);
5497 
5498 	    // revert applied viewport transformations
5499 	    originalPoint = centerPoint.matrixTransform(currentMatrix.inverse());
5500 
5501 	    // create scale matrix
5502 	    scaleMatrix = matrix
5503 	      .translate(originalPoint.x, originalPoint.y)
5504 	      .scale(1 / currentScale * scale)
5505 	      .translate(-originalPoint.x, -originalPoint.y);
5506 
5507 	    newMatrix = currentMatrix.multiply(scaleMatrix);
5508 	  } else {
5509 	    newMatrix = matrix.scale(scale);
5510 	  }
5511 
5512 	  setCTM(this._viewport, newMatrix);
5513 
5514 	  return newMatrix;
5515 	};
5516 
5517 
5518 	/**
5519 	 * Returns the size of the canvas
5520 	 *
5521 	 * @return {Dimensions}
5522 	 */
5523 	Canvas.prototype.getSize = function() {
5524 	  return {
5525 	    width: this._container.clientWidth,
5526 	    height: this._container.clientHeight
5527 	  };
5528 	};
5529 
5530 
5531 	/**
5532 	 * Return the absolute bounding box for the given element
5533 	 *
5534 	 * The absolute bounding box may be used to display overlays in the
5535 	 * callers (browser) coordinate system rather than the zoomed in/out
5536 	 * canvas coordinates.
5537 	 *
5538 	 * @param  {ElementDescriptor} element
5539 	 * @return {Bounds} the absolute bounding box
5540 	 */
5541 	Canvas.prototype.getAbsoluteBBox = function(element) {
5542 	  var vbox = this.viewbox();
5543 	  var bbox;
5544 
5545 	  // connection
5546 	  // use svg bbox
5547 	  if (element.waypoints) {
5548 	    var gfx = this.getGraphics(element);
5549 
5550 	    bbox = gfx.getBBox();
5551 	  }
5552 
5553 	  // shapes
5554 	  // use data
5555 	  else {
5556 	    bbox = element;
5557 	  }
5558 
5559 	  var x = bbox.x * vbox.scale - vbox.x * vbox.scale;
5560 	  var y = bbox.y * vbox.scale - vbox.y * vbox.scale;
5561 
5562 	  var width = bbox.width * vbox.scale;
5563 	  var height = bbox.height * vbox.scale;
5564 
5565 	  return {
5566 	    x: x,
5567 	    y: y,
5568 	    width: width,
5569 	    height: height
5570 	  };
5571 	};
5572 
5573 	/**
5574 	 * Fires an event in order other modules can react to the
5575 	 * canvas resizing
5576 	 */
5577 	Canvas.prototype.resized = function() {
5578 
5579 	  // force recomputation of view box
5580 	  delete this._cachedViewbox;
5581 
5582 	  this._eventBus.fire('canvas.resized');
5583 	};
5584 
5585 	var ELEMENT_ID = 'data-element-id';
5586 
5587 
5588 	/**
5589 	 * @class
5590 	 *
5591 	 * A registry that keeps track of all shapes in the diagram.
5592 	 */
5593 	function ElementRegistry(eventBus) {
5594 	  this._elements = {};
5595 
5596 	  this._eventBus = eventBus;
5597 	}
5598 
5599 	ElementRegistry.$inject = [ 'eventBus' ];
5600 
5601 	/**
5602 	 * Register a pair of (element, gfx, (secondaryGfx)).
5603 	 *
5604 	 * @param {djs.model.Base} element
5605 	 * @param {SVGElement} gfx
5606 	 * @param {SVGElement} [secondaryGfx] optional other element to register, too
5607 	 */
5608 	ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) {
5609 
5610 	  var id = element.id;
5611 
5612 	  this._validateId(id);
5613 
5614 	  // associate dom node with element
5615 	  attr(gfx, ELEMENT_ID, id);
5616 
5617 	  if (secondaryGfx) {
5618 	    attr(secondaryGfx, ELEMENT_ID, id);
5619 	  }
5620 
5621 	  this._elements[id] = { element: element, gfx: gfx, secondaryGfx: secondaryGfx };
5622 	};
5623 
5624 	/**
5625 	 * Removes an element from the registry.
5626 	 *
5627 	 * @param {djs.model.Base} element
5628 	 */
5629 	ElementRegistry.prototype.remove = function(element) {
5630 	  var elements = this._elements,
5631 	      id = element.id || element,
5632 	      container = id && elements[id];
5633 
5634 	  if (container) {
5635 
5636 	    // unset element id on gfx
5637 	    attr(container.gfx, ELEMENT_ID, '');
5638 
5639 	    if (container.secondaryGfx) {
5640 	      attr(container.secondaryGfx, ELEMENT_ID, '');
5641 	    }
5642 
5643 	    delete elements[id];
5644 	  }
5645 	};
5646 
5647 	/**
5648 	 * Update the id of an element
5649 	 *
5650 	 * @param {djs.model.Base} element
5651 	 * @param {string} newId
5652 	 */
5653 	ElementRegistry.prototype.updateId = function(element, newId) {
5654 
5655 	  this._validateId(newId);
5656 
5657 	  if (typeof element === 'string') {
5658 	    element = this.get(element);
5659 	  }
5660 
5661 	  this._eventBus.fire('element.updateId', {
5662 	    element: element,
5663 	    newId: newId
5664 	  });
5665 
5666 	  var gfx = this.getGraphics(element),
5667 	      secondaryGfx = this.getGraphics(element, true);
5668 
5669 	  this.remove(element);
5670 
5671 	  element.id = newId;
5672 
5673 	  this.add(element, gfx, secondaryGfx);
5674 	};
5675 
5676 	/**
5677 	 * Update the graphics of an element
5678 	 *
5679 	 * @param {djs.model.Base} element
5680 	 * @param {SVGElement} gfx
5681 	 * @param {boolean} [secondary=false] whether to update the secondary connected element
5682 	 */
5683 	ElementRegistry.prototype.updateGraphics = function(filter, gfx, secondary) {
5684 	  var id = filter.id || filter;
5685 
5686 	  var container = this._elements[id];
5687 
5688 	  if (secondary) {
5689 	    container.secondaryGfx = gfx;
5690 	  } else {
5691 	    container.gfx = gfx;
5692 	  }
5693 
5694 	  attr(gfx, ELEMENT_ID, id);
5695 
5696 	  return gfx;
5697 	};
5698 
5699 	/**
5700 	 * Return the model element for a given id or graphics.
5701 	 *
5702 	 * @example
5703 	 *
5704 	 * elementRegistry.get('SomeElementId_1');
5705 	 * elementRegistry.get(gfx);
5706 	 *
5707 	 *
5708 	 * @param {string|SVGElement} filter for selecting the element
5709 	 *
5710 	 * @return {djs.model.Base}
5711 	 */
5712 	ElementRegistry.prototype.get = function(filter) {
5713 	  var id;
5714 
5715 	  if (typeof filter === 'string') {
5716 	    id = filter;
5717 	  } else {
5718 	    id = filter && attr(filter, ELEMENT_ID);
5719 	  }
5720 
5721 	  var container = this._elements[id];
5722 	  return container && container.element;
5723 	};
5724 
5725 	/**
5726 	 * Return all elements that match a given filter function.
5727 	 *
5728 	 * @param {Function} fn
5729 	 *
5730 	 * @return {Array<djs.model.Base>}
5731 	 */
5732 	ElementRegistry.prototype.filter = function(fn) {
5733 
5734 	  var filtered = [];
5735 
5736 	  this.forEach(function(element, gfx) {
5737 	    if (fn(element, gfx)) {
5738 	      filtered.push(element);
5739 	    }
5740 	  });
5741 
5742 	  return filtered;
5743 	};
5744 
5745 	/**
5746 	 * Return the first element that satisfies the provided testing function.
5747 	 *
5748 	 * @param {Function} fn
5749 	 *
5750 	 * @return {djs.model.Base}
5751 	 */
5752 	ElementRegistry.prototype.find = function(fn) {
5753 	  var map = this._elements,
5754 	      keys = Object.keys(map);
5755 
5756 	  for (var i = 0; i < keys.length; i++) {
5757 	    var id = keys[i],
5758 	        container = map[id],
5759 	        element = container.element,
5760 	        gfx = container.gfx;
5761 
5762 	    if (fn(element, gfx)) {
5763 	      return element;
5764 	    }
5765 	  }
5766 	};
5767 
5768 	/**
5769 	 * Return all rendered model elements.
5770 	 *
5771 	 * @return {Array<djs.model.Base>}
5772 	 */
5773 	ElementRegistry.prototype.getAll = function() {
5774 	  return this.filter(function(e) { return e; });
5775 	};
5776 
5777 	/**
5778 	 * Iterate over all diagram elements.
5779 	 *
5780 	 * @param {Function} fn
5781 	 */
5782 	ElementRegistry.prototype.forEach = function(fn) {
5783 
5784 	  var map = this._elements;
5785 
5786 	  Object.keys(map).forEach(function(id) {
5787 	    var container = map[id],
5788 	        element = container.element,
5789 	        gfx = container.gfx;
5790 
5791 	    return fn(element, gfx);
5792 	  });
5793 	};
5794 
5795 	/**
5796 	 * Return the graphical representation of an element or its id.
5797 	 *
5798 	 * @example
5799 	 * elementRegistry.getGraphics('SomeElementId_1');
5800 	 * elementRegistry.getGraphics(rootElement); // <g ...>
5801 	 *
5802 	 * elementRegistry.getGraphics(rootElement, true); // <svg ...>
5803 	 *
5804 	 *
5805 	 * @param {string|djs.model.Base} filter
5806 	 * @param {boolean} [secondary=false] whether to return the secondary connected element
5807 	 *
5808 	 * @return {SVGElement}
5809 	 */
5810 	ElementRegistry.prototype.getGraphics = function(filter, secondary) {
5811 	  var id = filter.id || filter;
5812 
5813 	  var container = this._elements[id];
5814 	  return container && (secondary ? container.secondaryGfx : container.gfx);
5815 	};
5816 
5817 	/**
5818 	 * Validate the suitability of the given id and signals a problem
5819 	 * with an exception.
5820 	 *
5821 	 * @param {string} id
5822 	 *
5823 	 * @throws {Error} if id is empty or already assigned
5824 	 */
5825 	ElementRegistry.prototype._validateId = function(id) {
5826 	  if (!id) {
5827 	    throw new Error('element must have an id');
5828 	  }
5829 
5830 	  if (this._elements[id]) {
5831 	    throw new Error('element with id ' + id + ' already added');
5832 	  }
5833 	};
5834 
5835 	var objectRefs = {exports: {}};
5836 
5837 	var collection = {};
5838 
5839 	/**
5840 	 * An empty collection stub. Use {@link RefsCollection.extend} to extend a
5841 	 * collection with ref semantics.
5842 	 *
5843 	 * @class RefsCollection
5844 	 */
5845 
5846 	/**
5847 	 * Extends a collection with {@link Refs} aware methods
5848 	 *
5849 	 * @memberof RefsCollection
5850 	 * @static
5851 	 *
5852 	 * @param  {Array<Object>} collection
5853 	 * @param  {Refs} refs instance
5854 	 * @param  {Object} property represented by the collection
5855 	 * @param  {Object} target object the collection is attached to
5856 	 *
5857 	 * @return {RefsCollection<Object>} the extended array
5858 	 */
5859 	function extend(collection, refs, property, target) {
5860 
5861 	  var inverseProperty = property.inverse;
5862 
5863 	  /**
5864 	   * Removes the given element from the array and returns it.
5865 	   *
5866 	   * @method RefsCollection#remove
5867 	   *
5868 	   * @param {Object} element the element to remove
5869 	   */
5870 	  Object.defineProperty(collection, 'remove', {
5871 	    value: function(element) {
5872 	      var idx = this.indexOf(element);
5873 	      if (idx !== -1) {
5874 	        this.splice(idx, 1);
5875 
5876 	        // unset inverse
5877 	        refs.unset(element, inverseProperty, target);
5878 	      }
5879 
5880 	      return element;
5881 	    }
5882 	  });
5883 
5884 	  /**
5885 	   * Returns true if the collection contains the given element
5886 	   *
5887 	   * @method RefsCollection#contains
5888 	   *
5889 	   * @param {Object} element the element to check for
5890 	   */
5891 	  Object.defineProperty(collection, 'contains', {
5892 	    value: function(element) {
5893 	      return this.indexOf(element) !== -1;
5894 	    }
5895 	  });
5896 
5897 	  /**
5898 	   * Adds an element to the array, unless it exists already (set semantics).
5899 	   *
5900 	   * @method RefsCollection#add
5901 	   *
5902 	   * @param {Object} element the element to add
5903 	   * @param {Number} optional index to add element to
5904 	   *                 (possibly moving other elements around)
5905 	   */
5906 	  Object.defineProperty(collection, 'add', {
5907 	    value: function(element, idx) {
5908 
5909 	      var currentIdx = this.indexOf(element);
5910 
5911 	      if (typeof idx === 'undefined') {
5912 
5913 	        if (currentIdx !== -1) {
5914 	          // element already in collection (!)
5915 	          return;
5916 	        }
5917 
5918 	        // add to end of array, as no idx is specified
5919 	        idx = this.length;
5920 	      }
5921 
5922 	      // handle already in collection
5923 	      if (currentIdx !== -1) {
5924 
5925 	        // remove element from currentIdx
5926 	        this.splice(currentIdx, 1);
5927 	      }
5928 
5929 	      // add element at idx
5930 	      this.splice(idx, 0, element);
5931 
5932 	      if (currentIdx === -1) {
5933 	        // set inverse, unless element was
5934 	        // in collection already
5935 	        refs.set(element, inverseProperty, target);
5936 	      }
5937 	    }
5938 	  });
5939 
5940 	  // a simple marker, identifying this element
5941 	  // as being a refs collection
5942 	  Object.defineProperty(collection, '__refs_collection', {
5943 	    value: true
5944 	  });
5945 
5946 	  return collection;
5947 	}
5948 
5949 
5950 	function isExtended(collection) {
5951 	  return collection.__refs_collection === true;
5952 	}
5953 
5954 	collection.extend = extend;
5955 
5956 	collection.isExtended = isExtended;
5957 
5958 	var Collection = collection;
5959 
5960 	function hasOwnProperty$1(e, property) {
5961 	  return Object.prototype.hasOwnProperty.call(e, property.name || property);
5962 	}
5963 
5964 	function defineCollectionProperty(ref, property, target) {
5965 
5966 	  var collection = Collection.extend(target[property.name] || [], ref, property, target);
5967 
5968 	  Object.defineProperty(target, property.name, {
5969 	    enumerable: property.enumerable,
5970 	    value: collection
5971 	  });
5972 
5973 	  if (collection.length) {
5974 
5975 	    collection.forEach(function(o) {
5976 	      ref.set(o, property.inverse, target);
5977 	    });
5978 	  }
5979 	}
5980 
5981 
5982 	function defineProperty$1(ref, property, target) {
5983 
5984 	  var inverseProperty = property.inverse;
5985 
5986 	  var _value = target[property.name];
5987 
5988 	  Object.defineProperty(target, property.name, {
5989 	    configurable: property.configurable,
5990 	    enumerable: property.enumerable,
5991 
5992 	    get: function() {
5993 	      return _value;
5994 	    },
5995 
5996 	    set: function(value) {
5997 
5998 	      // return if we already performed all changes
5999 	      if (value === _value) {
6000 	        return;
6001 	      }
6002 
6003 	      var old = _value;
6004 
6005 	      // temporary set null
6006 	      _value = null;
6007 
6008 	      if (old) {
6009 	        ref.unset(old, inverseProperty, target);
6010 	      }
6011 
6012 	      // set new value
6013 	      _value = value;
6014 
6015 	      // set inverse value
6016 	      ref.set(_value, inverseProperty, target);
6017 	    }
6018 	  });
6019 
6020 	}
6021 
6022 	/**
6023 	 * Creates a new references object defining two inversly related
6024 	 * attribute descriptors a and b.
6025 	 *
6026 	 * <p>
6027 	 *   When bound to an object using {@link Refs#bind} the references
6028 	 *   get activated and ensure that add and remove operations are applied
6029 	 *   reversely, too.
6030 	 * </p>
6031 	 *
6032 	 * <p>
6033 	 *   For attributes represented as collections {@link Refs} provides the
6034 	 *   {@link RefsCollection#add}, {@link RefsCollection#remove} and {@link RefsCollection#contains} extensions
6035 	 *   that must be used to properly hook into the inverse change mechanism.
6036 	 * </p>
6037 	 *
6038 	 * @class Refs
6039 	 *
6040 	 * @classdesc A bi-directional reference between two attributes.
6041 	 *
6042 	 * @param {Refs.AttributeDescriptor} a property descriptor
6043 	 * @param {Refs.AttributeDescriptor} b property descriptor
6044 	 *
6045 	 * @example
6046 	 *
6047 	 * var refs = Refs({ name: 'wheels', collection: true, enumerable: true }, { name: 'car' });
6048 	 *
6049 	 * var car = { name: 'toyota' };
6050 	 * var wheels = [{ pos: 'front-left' }, { pos: 'front-right' }];
6051 	 *
6052 	 * refs.bind(car, 'wheels');
6053 	 *
6054 	 * car.wheels // []
6055 	 * car.wheels.add(wheels[0]);
6056 	 * car.wheels.add(wheels[1]);
6057 	 *
6058 	 * car.wheels // [{ pos: 'front-left' }, { pos: 'front-right' }]
6059 	 *
6060 	 * wheels[0].car // { name: 'toyota' };
6061 	 * car.wheels.remove(wheels[0]);
6062 	 *
6063 	 * wheels[0].car // undefined
6064 	 */
6065 	function Refs$1(a, b) {
6066 
6067 	  if (!(this instanceof Refs$1)) {
6068 	    return new Refs$1(a, b);
6069 	  }
6070 
6071 	  // link
6072 	  a.inverse = b;
6073 	  b.inverse = a;
6074 
6075 	  this.props = {};
6076 	  this.props[a.name] = a;
6077 	  this.props[b.name] = b;
6078 	}
6079 
6080 	/**
6081 	 * Binds one side of a bi-directional reference to a
6082 	 * target object.
6083 	 *
6084 	 * @memberOf Refs
6085 	 *
6086 	 * @param  {Object} target
6087 	 * @param  {String} property
6088 	 */
6089 	Refs$1.prototype.bind = function(target, property) {
6090 	  if (typeof property === 'string') {
6091 	    if (!this.props[property]) {
6092 	      throw new Error('no property <' + property + '> in ref');
6093 	    }
6094 	    property = this.props[property];
6095 	  }
6096 
6097 	  if (property.collection) {
6098 	    defineCollectionProperty(this, property, target);
6099 	  } else {
6100 	    defineProperty$1(this, property, target);
6101 	  }
6102 	};
6103 
6104 	Refs$1.prototype.ensureRefsCollection = function(target, property) {
6105 
6106 	  var collection = target[property.name];
6107 
6108 	  if (!Collection.isExtended(collection)) {
6109 	    defineCollectionProperty(this, property, target);
6110 	  }
6111 
6112 	  return collection;
6113 	};
6114 
6115 	Refs$1.prototype.ensureBound = function(target, property) {
6116 	  if (!hasOwnProperty$1(target, property)) {
6117 	    this.bind(target, property);
6118 	  }
6119 	};
6120 
6121 	Refs$1.prototype.unset = function(target, property, value) {
6122 
6123 	  if (target) {
6124 	    this.ensureBound(target, property);
6125 
6126 	    if (property.collection) {
6127 	      this.ensureRefsCollection(target, property).remove(value);
6128 	    } else {
6129 	      target[property.name] = undefined;
6130 	    }
6131 	  }
6132 	};
6133 
6134 	Refs$1.prototype.set = function(target, property, value) {
6135 
6136 	  if (target) {
6137 	    this.ensureBound(target, property);
6138 
6139 	    if (property.collection) {
6140 	      this.ensureRefsCollection(target, property).add(value);
6141 	    } else {
6142 	      target[property.name] = value;
6143 	    }
6144 	  }
6145 	};
6146 
6147 	var refs = Refs$1;
6148 
6149 	objectRefs.exports = refs;
6150 
6151 	objectRefs.exports.Collection = collection;
6152 
6153 	var Refs = objectRefs.exports;
6154 
6155 	var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
6156 	    labelRefs = new Refs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
6157 	    attacherRefs = new Refs({ name: 'attachers', collection: true }, { name: 'host' }),
6158 	    outgoingRefs = new Refs({ name: 'outgoing', collection: true }, { name: 'source' }),
6159 	    incomingRefs = new Refs({ name: 'incoming', collection: true }, { name: 'target' });
6160 
6161 	/**
6162 	 * @namespace djs.model
6163 	 */
6164 
6165 	/**
6166 	 * @memberOf djs.model
6167 	 */
6168 
6169 	/**
6170 	 * The basic graphical representation
6171 	 *
6172 	 * @class
6173 	 *
6174 	 * @abstract
6175 	 */
6176 	function Base$1() {
6177 
6178 	  /**
6179 	   * The object that backs up the shape
6180 	   *
6181 	   * @name Base#businessObject
6182 	   * @type Object
6183 	   */
6184 	  Object.defineProperty(this, 'businessObject', {
6185 	    writable: true
6186 	  });
6187 
6188 
6189 	  /**
6190 	   * Single label support, will mapped to multi label array
6191 	   *
6192 	   * @name Base#label
6193 	   * @type Object
6194 	   */
6195 	  Object.defineProperty(this, 'label', {
6196 	    get: function() {
6197 	      return this.labels[0];
6198 	    },
6199 	    set: function(newLabel) {
6200 
6201 	      var label = this.label,
6202 	          labels = this.labels;
6203 
6204 	      if (!newLabel && label) {
6205 	        labels.remove(label);
6206 	      } else {
6207 	        labels.add(newLabel, 0);
6208 	      }
6209 	    }
6210 	  });
6211 
6212 	  /**
6213 	   * The parent shape
6214 	   *
6215 	   * @name Base#parent
6216 	   * @type Shape
6217 	   */
6218 	  parentRefs.bind(this, 'parent');
6219 
6220 	  /**
6221 	   * The list of labels
6222 	   *
6223 	   * @name Base#labels
6224 	   * @type Label
6225 	   */
6226 	  labelRefs.bind(this, 'labels');
6227 
6228 	  /**
6229 	   * The list of outgoing connections
6230 	   *
6231 	   * @name Base#outgoing
6232 	   * @type Array<Connection>
6233 	   */
6234 	  outgoingRefs.bind(this, 'outgoing');
6235 
6236 	  /**
6237 	   * The list of incoming connections
6238 	   *
6239 	   * @name Base#incoming
6240 	   * @type Array<Connection>
6241 	   */
6242 	  incomingRefs.bind(this, 'incoming');
6243 	}
6244 
6245 
6246 	/**
6247 	 * A graphical object
6248 	 *
6249 	 * @class
6250 	 * @constructor
6251 	 *
6252 	 * @extends Base
6253 	 */
6254 	function Shape() {
6255 	  Base$1.call(this);
6256 
6257 	  /**
6258 	   * Indicates frame shapes
6259 	   *
6260 	   * @name Shape#isFrame
6261 	   * @type boolean
6262 	   */
6263 
6264 	  /**
6265 	   * The list of children
6266 	   *
6267 	   * @name Shape#children
6268 	   * @type Array<Base>
6269 	   */
6270 	  parentRefs.bind(this, 'children');
6271 
6272 	  /**
6273 	   * @name Shape#host
6274 	   * @type Shape
6275 	   */
6276 	  attacherRefs.bind(this, 'host');
6277 
6278 	  /**
6279 	   * @name Shape#attachers
6280 	   * @type Shape
6281 	   */
6282 	  attacherRefs.bind(this, 'attachers');
6283 	}
6284 
6285 	inherits$1(Shape, Base$1);
6286 
6287 
6288 	/**
6289 	 * A root graphical object
6290 	 *
6291 	 * @class
6292 	 * @constructor
6293 	 *
6294 	 * @extends Shape
6295 	 */
6296 	function Root() {
6297 	  Shape.call(this);
6298 	}
6299 
6300 	inherits$1(Root, Shape);
6301 
6302 
6303 	/**
6304 	 * A label for an element
6305 	 *
6306 	 * @class
6307 	 * @constructor
6308 	 *
6309 	 * @extends Shape
6310 	 */
6311 	function Label() {
6312 	  Shape.call(this);
6313 
6314 	  /**
6315 	   * The labeled element
6316 	   *
6317 	   * @name Label#labelTarget
6318 	   * @type Base
6319 	   */
6320 	  labelRefs.bind(this, 'labelTarget');
6321 	}
6322 
6323 	inherits$1(Label, Shape);
6324 
6325 
6326 	/**
6327 	 * A connection between two elements
6328 	 *
6329 	 * @class
6330 	 * @constructor
6331 	 *
6332 	 * @extends Base
6333 	 */
6334 	function Connection() {
6335 	  Base$1.call(this);
6336 
6337 	  /**
6338 	   * The element this connection originates from
6339 	   *
6340 	   * @name Connection#source
6341 	   * @type Base
6342 	   */
6343 	  outgoingRefs.bind(this, 'source');
6344 
6345 	  /**
6346 	   * The element this connection points to
6347 	   *
6348 	   * @name Connection#target
6349 	   * @type Base
6350 	   */
6351 	  incomingRefs.bind(this, 'target');
6352 	}
6353 
6354 	inherits$1(Connection, Base$1);
6355 
6356 
6357 	var types$6 = {
6358 	  connection: Connection,
6359 	  shape: Shape,
6360 	  label: Label,
6361 	  root: Root
6362 	};
6363 
6364 	/**
6365 	 * Creates a new model element of the specified type
6366 	 *
6367 	 * @method create
6368 	 *
6369 	 * @example
6370 	 *
6371 	 * var shape1 = Model.create('shape', { x: 10, y: 10, width: 100, height: 100 });
6372 	 * var shape2 = Model.create('shape', { x: 210, y: 210, width: 100, height: 100 });
6373 	 *
6374 	 * var connection = Model.create('connection', { waypoints: [ { x: 110, y: 55 }, {x: 210, y: 55 } ] });
6375 	 *
6376 	 * @param  {string} type lower-cased model name
6377 	 * @param  {Object} attrs attributes to initialize the new model instance with
6378 	 *
6379 	 * @return {Base} the new model instance
6380 	 */
6381 	function create(type, attrs) {
6382 	  var Type = types$6[type];
6383 	  if (!Type) {
6384 	    throw new Error('unknown type: <' + type + '>');
6385 	  }
6386 	  return assign(new Type(), attrs);
6387 	}
6388 
6389 	/**
6390 	 * A factory for diagram-js shapes
6391 	 */
6392 	function ElementFactory$1() {
6393 	  this._uid = 12;
6394 	}
6395 
6396 
6397 	ElementFactory$1.prototype.createRoot = function(attrs) {
6398 	  return this.create('root', attrs);
6399 	};
6400 
6401 	ElementFactory$1.prototype.createLabel = function(attrs) {
6402 	  return this.create('label', attrs);
6403 	};
6404 
6405 	ElementFactory$1.prototype.createShape = function(attrs) {
6406 	  return this.create('shape', attrs);
6407 	};
6408 
6409 	ElementFactory$1.prototype.createConnection = function(attrs) {
6410 	  return this.create('connection', attrs);
6411 	};
6412 
6413 	/**
6414 	 * Create a model element with the given type and
6415 	 * a number of pre-set attributes.
6416 	 *
6417 	 * @param  {string} type
6418 	 * @param  {Object} attrs
6419 	 * @return {djs.model.Base} the newly created model instance
6420 	 */
6421 	ElementFactory$1.prototype.create = function(type, attrs) {
6422 
6423 	  attrs = assign({}, attrs || {});
6424 
6425 	  if (!attrs.id) {
6426 	    attrs.id = type + '_' + (this._uid++);
6427 	  }
6428 
6429 	  return create(type, attrs);
6430 	};
6431 
6432 	var FN_REF = '__fn';
6433 
6434 	var DEFAULT_PRIORITY$5 = 1000;
6435 
6436 	var slice = Array.prototype.slice;
6437 
6438 	/**
6439 	 * A general purpose event bus.
6440 	 *
6441 	 * This component is used to communicate across a diagram instance.
6442 	 * Other parts of a diagram can use it to listen to and broadcast events.
6443 	 *
6444 	 *
6445 	 * ## Registering for Events
6446 	 *
6447 	 * The event bus provides the {@link EventBus#on} and {@link EventBus#once}
6448 	 * methods to register for events. {@link EventBus#off} can be used to
6449 	 * remove event registrations. Listeners receive an instance of {@link Event}
6450 	 * as the first argument. It allows them to hook into the event execution.
6451 	 *
6452 	 * ```javascript
6453 	 *
6454 	 * // listen for event
6455 	 * eventBus.on('foo', function(event) {
6456 	 *
6457 	 *   // access event type
6458 	 *   event.type; // 'foo'
6459 	 *
6460 	 *   // stop propagation to other listeners
6461 	 *   event.stopPropagation();
6462 	 *
6463 	 *   // prevent event default
6464 	 *   event.preventDefault();
6465 	 * });
6466 	 *
6467 	 * // listen for event with custom payload
6468 	 * eventBus.on('bar', function(event, payload) {
6469 	 *   console.log(payload);
6470 	 * });
6471 	 *
6472 	 * // listen for event returning value
6473 	 * eventBus.on('foobar', function(event) {
6474 	 *
6475 	 *   // stop event propagation + prevent default
6476 	 *   return false;
6477 	 *
6478 	 *   // stop event propagation + return custom result
6479 	 *   return {
6480 	 *     complex: 'listening result'
6481 	 *   };
6482 	 * });
6483 	 *
6484 	 *
6485 	 * // listen with custom priority (default=1000, higher is better)
6486 	 * eventBus.on('priorityfoo', 1500, function(event) {
6487 	 *   console.log('invoked first!');
6488 	 * });
6489 	 *
6490 	 *
6491 	 * // listen for event and pass the context (`this`)
6492 	 * eventBus.on('foobar', function(event) {
6493 	 *   this.foo();
6494 	 * }, this);
6495 	 * ```
6496 	 *
6497 	 *
6498 	 * ## Emitting Events
6499 	 *
6500 	 * Events can be emitted via the event bus using {@link EventBus#fire}.
6501 	 *
6502 	 * ```javascript
6503 	 *
6504 	 * // false indicates that the default action
6505 	 * // was prevented by listeners
6506 	 * if (eventBus.fire('foo') === false) {
6507 	 *   console.log('default has been prevented!');
6508 	 * };
6509 	 *
6510 	 *
6511 	 * // custom args + return value listener
6512 	 * eventBus.on('sum', function(event, a, b) {
6513 	 *   return a + b;
6514 	 * });
6515 	 *
6516 	 * // you can pass custom arguments + retrieve result values.
6517 	 * var sum = eventBus.fire('sum', 1, 2);
6518 	 * console.log(sum); // 3
6519 	 * ```
6520 	 */
6521 	function EventBus() {
6522 	  this._listeners = {};
6523 
6524 	  // cleanup on destroy on lowest priority to allow
6525 	  // message passing until the bitter end
6526 	  this.on('diagram.destroy', 1, this._destroy, this);
6527 	}
6528 
6529 
6530 	/**
6531 	 * Register an event listener for events with the given name.
6532 	 *
6533 	 * The callback will be invoked with `event, ...additionalArguments`
6534 	 * that have been passed to {@link EventBus#fire}.
6535 	 *
6536 	 * Returning false from a listener will prevent the events default action
6537 	 * (if any is specified). To stop an event from being processed further in
6538 	 * other listeners execute {@link Event#stopPropagation}.
6539 	 *
6540 	 * Returning anything but `undefined` from a listener will stop the listener propagation.
6541 	 *
6542 	 * @param {string|Array<string>} events
6543 	 * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
6544 	 * @param {Function} callback
6545 	 * @param {Object} [that] Pass context (`this`) to the callback
6546 	 */
6547 	EventBus.prototype.on = function(events, priority, callback, that) {
6548 
6549 	  events = isArray$2(events) ? events : [ events ];
6550 
6551 	  if (isFunction(priority)) {
6552 	    that = callback;
6553 	    callback = priority;
6554 	    priority = DEFAULT_PRIORITY$5;
6555 	  }
6556 
6557 	  if (!isNumber(priority)) {
6558 	    throw new Error('priority must be a number');
6559 	  }
6560 
6561 	  var actualCallback = callback;
6562 
6563 	  if (that) {
6564 	    actualCallback = bind$2(callback, that);
6565 
6566 	    // make sure we remember and are able to remove
6567 	    // bound callbacks via {@link #off} using the original
6568 	    // callback
6569 	    actualCallback[FN_REF] = callback[FN_REF] || callback;
6570 	  }
6571 
6572 	  var self = this;
6573 
6574 	  events.forEach(function(e) {
6575 	    self._addListener(e, {
6576 	      priority: priority,
6577 	      callback: actualCallback,
6578 	      next: null
6579 	    });
6580 	  });
6581 	};
6582 
6583 
6584 	/**
6585 	 * Register an event listener that is executed only once.
6586 	 *
6587 	 * @param {string} event the event name to register for
6588 	 * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
6589 	 * @param {Function} callback the callback to execute
6590 	 * @param {Object} [that] Pass context (`this`) to the callback
6591 	 */
6592 	EventBus.prototype.once = function(event, priority, callback, that) {
6593 	  var self = this;
6594 
6595 	  if (isFunction(priority)) {
6596 	    that = callback;
6597 	    callback = priority;
6598 	    priority = DEFAULT_PRIORITY$5;
6599 	  }
6600 
6601 	  if (!isNumber(priority)) {
6602 	    throw new Error('priority must be a number');
6603 	  }
6604 
6605 	  function wrappedCallback() {
6606 	    wrappedCallback.__isTomb = true;
6607 
6608 	    var result = callback.apply(that, arguments);
6609 
6610 	    self.off(event, wrappedCallback);
6611 
6612 	    return result;
6613 	  }
6614 
6615 	  // make sure we remember and are able to remove
6616 	  // bound callbacks via {@link #off} using the original
6617 	  // callback
6618 	  wrappedCallback[FN_REF] = callback;
6619 
6620 	  this.on(event, priority, wrappedCallback);
6621 	};
6622 
6623 
6624 	/**
6625 	 * Removes event listeners by event and callback.
6626 	 *
6627 	 * If no callback is given, all listeners for a given event name are being removed.
6628 	 *
6629 	 * @param {string|Array<string>} events
6630 	 * @param {Function} [callback]
6631 	 */
6632 	EventBus.prototype.off = function(events, callback) {
6633 
6634 	  events = isArray$2(events) ? events : [ events ];
6635 
6636 	  var self = this;
6637 
6638 	  events.forEach(function(event) {
6639 	    self._removeListener(event, callback);
6640 	  });
6641 
6642 	};
6643 
6644 
6645 	/**
6646 	 * Create an EventBus event.
6647 	 *
6648 	 * @param {Object} data
6649 	 *
6650 	 * @return {Object} event, recognized by the eventBus
6651 	 */
6652 	EventBus.prototype.createEvent = function(data) {
6653 	  var event = new InternalEvent();
6654 
6655 	  event.init(data);
6656 
6657 	  return event;
6658 	};
6659 
6660 
6661 	/**
6662 	 * Fires a named event.
6663 	 *
6664 	 * @example
6665 	 *
6666 	 * // fire event by name
6667 	 * events.fire('foo');
6668 	 *
6669 	 * // fire event object with nested type
6670 	 * var event = { type: 'foo' };
6671 	 * events.fire(event);
6672 	 *
6673 	 * // fire event with explicit type
6674 	 * var event = { x: 10, y: 20 };
6675 	 * events.fire('element.moved', event);
6676 	 *
6677 	 * // pass additional arguments to the event
6678 	 * events.on('foo', function(event, bar) {
6679 	 *   alert(bar);
6680 	 * });
6681 	 *
6682 	 * events.fire({ type: 'foo' }, 'I am bar!');
6683 	 *
6684 	 * @param {string} [name] the optional event name
6685 	 * @param {Object} [event] the event object
6686 	 * @param {...Object} additional arguments to be passed to the callback functions
6687 	 *
6688 	 * @return {boolean} the events return value, if specified or false if the
6689 	 *                   default action was prevented by listeners
6690 	 */
6691 	EventBus.prototype.fire = function(type, data) {
6692 	  var event,
6693 	      firstListener,
6694 	      returnValue,
6695 	      args;
6696 
6697 	  args = slice.call(arguments);
6698 
6699 	  if (typeof type === 'object') {
6700 	    data = type;
6701 	    type = data.type;
6702 	  }
6703 
6704 	  if (!type) {
6705 	    throw new Error('no event type specified');
6706 	  }
6707 
6708 	  firstListener = this._listeners[type];
6709 
6710 	  if (!firstListener) {
6711 	    return;
6712 	  }
6713 
6714 	  // we make sure we fire instances of our home made
6715 	  // events here. We wrap them only once, though
6716 	  if (data instanceof InternalEvent) {
6717 
6718 	    // we are fine, we alread have an event
6719 	    event = data;
6720 	  } else {
6721 	    event = this.createEvent(data);
6722 	  }
6723 
6724 	  // ensure we pass the event as the first parameter
6725 	  args[0] = event;
6726 
6727 	  // original event type (in case we delegate)
6728 	  var originalType = event.type;
6729 
6730 	  // update event type before delegation
6731 	  if (type !== originalType) {
6732 	    event.type = type;
6733 	  }
6734 
6735 	  try {
6736 	    returnValue = this._invokeListeners(event, args, firstListener);
6737 	  } finally {
6738 
6739 	    // reset event type after delegation
6740 	    if (type !== originalType) {
6741 	      event.type = originalType;
6742 	    }
6743 	  }
6744 
6745 	  // set the return value to false if the event default
6746 	  // got prevented and no other return value exists
6747 	  if (returnValue === undefined && event.defaultPrevented) {
6748 	    returnValue = false;
6749 	  }
6750 
6751 	  return returnValue;
6752 	};
6753 
6754 
6755 	EventBus.prototype.handleError = function(error) {
6756 	  return this.fire('error', { error: error }) === false;
6757 	};
6758 
6759 
6760 	EventBus.prototype._destroy = function() {
6761 	  this._listeners = {};
6762 	};
6763 
6764 	EventBus.prototype._invokeListeners = function(event, args, listener) {
6765 
6766 	  var returnValue;
6767 
6768 	  while (listener) {
6769 
6770 	    // handle stopped propagation
6771 	    if (event.cancelBubble) {
6772 	      break;
6773 	    }
6774 
6775 	    returnValue = this._invokeListener(event, args, listener);
6776 
6777 	    listener = listener.next;
6778 	  }
6779 
6780 	  return returnValue;
6781 	};
6782 
6783 	EventBus.prototype._invokeListener = function(event, args, listener) {
6784 
6785 	  var returnValue;
6786 
6787 	  if (listener.callback.__isTomb) {
6788 	    return returnValue;
6789 	  }
6790 
6791 	  try {
6792 
6793 	    // returning false prevents the default action
6794 	    returnValue = invokeFunction(listener.callback, args);
6795 
6796 	    // stop propagation on return value
6797 	    if (returnValue !== undefined) {
6798 	      event.returnValue = returnValue;
6799 	      event.stopPropagation();
6800 	    }
6801 
6802 	    // prevent default on return false
6803 	    if (returnValue === false) {
6804 	      event.preventDefault();
6805 	    }
6806 	  } catch (error) {
6807 	    if (!this.handleError(error)) {
6808 	      console.error('unhandled error in event listener', error);
6809 
6810 	      throw error;
6811 	    }
6812 	  }
6813 
6814 	  return returnValue;
6815 	};
6816 
6817 	/*
6818 	 * Add new listener with a certain priority to the list
6819 	 * of listeners (for the given event).
6820 	 *
6821 	 * The semantics of listener registration / listener execution are
6822 	 * first register, first serve: New listeners will always be inserted
6823 	 * after existing listeners with the same priority.
6824 	 *
6825 	 * Example: Inserting two listeners with priority 1000 and 1300
6826 	 *
6827 	 *    * before: [ 1500, 1500, 1000, 1000 ]
6828 	 *    * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
6829 	 *
6830 	 * @param {string} event
6831 	 * @param {Object} listener { priority, callback }
6832 	 */
6833 	EventBus.prototype._addListener = function(event, newListener) {
6834 
6835 	  var listener = this._getListeners(event),
6836 	      previousListener;
6837 
6838 	  // no prior listeners
6839 	  if (!listener) {
6840 	    this._setListeners(event, newListener);
6841 
6842 	    return;
6843 	  }
6844 
6845 	  // ensure we order listeners by priority from
6846 	  // 0 (high) to n > 0 (low)
6847 	  while (listener) {
6848 
6849 	    if (listener.priority < newListener.priority) {
6850 
6851 	      newListener.next = listener;
6852 
6853 	      if (previousListener) {
6854 	        previousListener.next = newListener;
6855 	      } else {
6856 	        this._setListeners(event, newListener);
6857 	      }
6858 
6859 	      return;
6860 	    }
6861 
6862 	    previousListener = listener;
6863 	    listener = listener.next;
6864 	  }
6865 
6866 	  // add new listener to back
6867 	  previousListener.next = newListener;
6868 	};
6869 
6870 
6871 	EventBus.prototype._getListeners = function(name) {
6872 	  return this._listeners[name];
6873 	};
6874 
6875 	EventBus.prototype._setListeners = function(name, listener) {
6876 	  this._listeners[name] = listener;
6877 	};
6878 
6879 	EventBus.prototype._removeListener = function(event, callback) {
6880 
6881 	  var listener = this._getListeners(event),
6882 	      nextListener,
6883 	      previousListener,
6884 	      listenerCallback;
6885 
6886 	  if (!callback) {
6887 
6888 	    // clear listeners
6889 	    this._setListeners(event, null);
6890 
6891 	    return;
6892 	  }
6893 
6894 	  while (listener) {
6895 
6896 	    nextListener = listener.next;
6897 
6898 	    listenerCallback = listener.callback;
6899 
6900 	    if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
6901 	      if (previousListener) {
6902 	        previousListener.next = nextListener;
6903 	      } else {
6904 
6905 	        // new first listener
6906 	        this._setListeners(event, nextListener);
6907 	      }
6908 	    }
6909 
6910 	    previousListener = listener;
6911 	    listener = nextListener;
6912 	  }
6913 	};
6914 
6915 	/**
6916 	 * A event that is emitted via the event bus.
6917 	 */
6918 	function InternalEvent() { }
6919 
6920 	InternalEvent.prototype.stopPropagation = function() {
6921 	  this.cancelBubble = true;
6922 	};
6923 
6924 	InternalEvent.prototype.preventDefault = function() {
6925 	  this.defaultPrevented = true;
6926 	};
6927 
6928 	InternalEvent.prototype.init = function(data) {
6929 	  assign(this, data || {});
6930 	};
6931 
6932 
6933 	/**
6934 	 * Invoke function. Be fast...
6935 	 *
6936 	 * @param {Function} fn
6937 	 * @param {Array<Object>} args
6938 	 *
6939 	 * @return {Any}
6940 	 */
6941 	function invokeFunction(fn, args) {
6942 	  return fn.apply(null, args);
6943 	}
6944 
6945 	/**
6946 	 * SVGs for elements are generated by the {@link GraphicsFactory}.
6947 	 *
6948 	 * This utility gives quick access to the important semantic
6949 	 * parts of an element.
6950 	 */
6951 
6952 	/**
6953 	 * Returns the visual part of a diagram element
6954 	 *
6955 	 * @param {Snap<SVGElement>} gfx
6956 	 *
6957 	 * @return {Snap<SVGElement>}
6958 	 */
6959 	function getVisual(gfx) {
6960 	  return gfx.childNodes[0];
6961 	}
6962 
6963 	/**
6964 	 * Returns the children for a given diagram element.
6965 	 *
6966 	 * @param {Snap<SVGElement>} gfx
6967 	 * @return {Snap<SVGElement>}
6968 	 */
6969 	function getChildren$1(gfx) {
6970 	  return gfx.parentNode.childNodes[1];
6971 	}
6972 
6973 	/**
6974 	 * @param {<SVGElement>} element
6975 	 * @param {number} x
6976 	 * @param {number} y
6977 	 * @param {number} angle
6978 	 * @param {number} amount
6979 	 */
6980 	function transform(gfx, x, y, angle, amount) {
6981 	  var translate = createTransform();
6982 	  translate.setTranslate(x, y);
6983 
6984 	  var rotate = createTransform();
6985 	  rotate.setRotate(angle || 0, 0, 0);
6986 
6987 	  var scale = createTransform();
6988 	  scale.setScale(amount || 1, amount || 1);
6989 
6990 	  transform$1(gfx, [ translate, rotate, scale ]);
6991 	}
6992 
6993 
6994 	/**
6995 	 * @param {SVGElement} element
6996 	 * @param {number} x
6997 	 * @param {number} y
6998 	 */
6999 	function translate$2(gfx, x, y) {
7000 	  var translate = createTransform();
7001 	  translate.setTranslate(x, y);
7002 
7003 	  transform$1(gfx, translate);
7004 	}
7005 
7006 
7007 	/**
7008 	 * @param {SVGElement} element
7009 	 * @param {number} angle
7010 	 */
7011 	function rotate(gfx, angle) {
7012 	  var rotate = createTransform();
7013 	  rotate.setRotate(angle, 0, 0);
7014 
7015 	  transform$1(gfx, rotate);
7016 	}
7017 
7018 	/**
7019 	 * A factory that creates graphical elements
7020 	 *
7021 	 * @param {EventBus} eventBus
7022 	 * @param {ElementRegistry} elementRegistry
7023 	 */
7024 	function GraphicsFactory(eventBus, elementRegistry) {
7025 	  this._eventBus = eventBus;
7026 	  this._elementRegistry = elementRegistry;
7027 	}
7028 
7029 	GraphicsFactory.$inject = [ 'eventBus' , 'elementRegistry' ];
7030 
7031 
7032 	GraphicsFactory.prototype._getChildrenContainer = function(element) {
7033 
7034 	  var gfx = this._elementRegistry.getGraphics(element);
7035 
7036 	  var childrenGfx;
7037 
7038 	  // root element
7039 	  if (!element.parent) {
7040 	    childrenGfx = gfx;
7041 	  } else {
7042 	    childrenGfx = getChildren$1(gfx);
7043 	    if (!childrenGfx) {
7044 	      childrenGfx = create$1('g');
7045 	      classes(childrenGfx).add('djs-children');
7046 
7047 	      append(gfx.parentNode, childrenGfx);
7048 	    }
7049 	  }
7050 
7051 	  return childrenGfx;
7052 	};
7053 
7054 	/**
7055 	 * Clears the graphical representation of the element and returns the
7056 	 * cleared visual (the <g class="djs-visual" /> element).
7057 	 */
7058 	GraphicsFactory.prototype._clear = function(gfx) {
7059 	  var visual = getVisual(gfx);
7060 
7061 	  clear$1(visual);
7062 
7063 	  return visual;
7064 	};
7065 
7066 	/**
7067 	 * Creates a gfx container for shapes and connections
7068 	 *
7069 	 * The layout is as follows:
7070 	 *
7071 	 * <g class="djs-group">
7072 	 *
7073 	 *   <!-- the gfx -->
7074 	 *   <g class="djs-element djs-(shape|connection|frame)">
7075 	 *     <g class="djs-visual">
7076 	 *       <!-- the renderer draws in here -->
7077 	 *     </g>
7078 	 *
7079 	 *     <!-- extensions (overlays, click box, ...) goes here
7080 	 *   </g>
7081 	 *
7082 	 *   <!-- the gfx child nodes -->
7083 	 *   <g class="djs-children"></g>
7084 	 * </g>
7085 	 *
7086 	 * @param {string} type the type of the element, i.e. shape | connection
7087 	 * @param {SVGElement} [childrenGfx]
7088 	 * @param {number} [parentIndex] position to create container in parent
7089 	 * @param {boolean} [isFrame] is frame element
7090 	 *
7091 	 * @return {SVGElement}
7092 	 */
7093 	GraphicsFactory.prototype._createContainer = function(
7094 	    type, childrenGfx, parentIndex, isFrame
7095 	) {
7096 	  var outerGfx = create$1('g');
7097 	  classes(outerGfx).add('djs-group');
7098 
7099 	  // insert node at position
7100 	  if (typeof parentIndex !== 'undefined') {
7101 	    prependTo(outerGfx, childrenGfx, childrenGfx.childNodes[parentIndex]);
7102 	  } else {
7103 	    append(childrenGfx, outerGfx);
7104 	  }
7105 
7106 	  var gfx = create$1('g');
7107 	  classes(gfx).add('djs-element');
7108 	  classes(gfx).add('djs-' + type);
7109 
7110 	  if (isFrame) {
7111 	    classes(gfx).add('djs-frame');
7112 	  }
7113 
7114 	  append(outerGfx, gfx);
7115 
7116 	  // create visual
7117 	  var visual = create$1('g');
7118 	  classes(visual).add('djs-visual');
7119 
7120 	  append(gfx, visual);
7121 
7122 	  return gfx;
7123 	};
7124 
7125 	GraphicsFactory.prototype.create = function(type, element, parentIndex) {
7126 	  var childrenGfx = this._getChildrenContainer(element.parent);
7127 	  return this._createContainer(type, childrenGfx, parentIndex, isFrameElement$1(element));
7128 	};
7129 
7130 	GraphicsFactory.prototype.updateContainments = function(elements) {
7131 
7132 	  var self = this,
7133 	      elementRegistry = this._elementRegistry,
7134 	      parents;
7135 
7136 	  parents = reduce(elements, function(map, e) {
7137 
7138 	    if (e.parent) {
7139 	      map[e.parent.id] = e.parent;
7140 	    }
7141 
7142 	    return map;
7143 	  }, {});
7144 
7145 	  // update all parents of changed and reorganized their children
7146 	  // in the correct order (as indicated in our model)
7147 	  forEach(parents, function(parent) {
7148 
7149 	    var children = parent.children;
7150 
7151 	    if (!children) {
7152 	      return;
7153 	    }
7154 
7155 	    var childrenGfx = self._getChildrenContainer(parent);
7156 
7157 	    forEach(children.slice().reverse(), function(child) {
7158 	      var childGfx = elementRegistry.getGraphics(child);
7159 
7160 	      prependTo(childGfx.parentNode, childrenGfx);
7161 	    });
7162 	  });
7163 	};
7164 
7165 	GraphicsFactory.prototype.drawShape = function(visual, element) {
7166 	  var eventBus = this._eventBus;
7167 
7168 	  return eventBus.fire('render.shape', { gfx: visual, element: element });
7169 	};
7170 
7171 	GraphicsFactory.prototype.getShapePath = function(element) {
7172 	  var eventBus = this._eventBus;
7173 
7174 	  return eventBus.fire('render.getShapePath', element);
7175 	};
7176 
7177 	GraphicsFactory.prototype.drawConnection = function(visual, element) {
7178 	  var eventBus = this._eventBus;
7179 
7180 	  return eventBus.fire('render.connection', { gfx: visual, element: element });
7181 	};
7182 
7183 	GraphicsFactory.prototype.getConnectionPath = function(waypoints) {
7184 	  var eventBus = this._eventBus;
7185 
7186 	  return eventBus.fire('render.getConnectionPath', waypoints);
7187 	};
7188 
7189 	GraphicsFactory.prototype.update = function(type, element, gfx) {
7190 
7191 	  // do NOT update root element
7192 	  if (!element.parent) {
7193 	    return;
7194 	  }
7195 
7196 	  var visual = this._clear(gfx);
7197 
7198 	  // redraw
7199 	  if (type === 'shape') {
7200 	    this.drawShape(visual, element);
7201 
7202 	    // update positioning
7203 	    translate$2(gfx, element.x, element.y);
7204 	  } else
7205 	  if (type === 'connection') {
7206 	    this.drawConnection(visual, element);
7207 	  } else {
7208 	    throw new Error('unknown type: ' + type);
7209 	  }
7210 
7211 	  if (element.hidden) {
7212 	    attr(gfx, 'display', 'none');
7213 	  } else {
7214 	    attr(gfx, 'display', 'block');
7215 	  }
7216 	};
7217 
7218 	GraphicsFactory.prototype.remove = function(element) {
7219 	  var gfx = this._elementRegistry.getGraphics(element);
7220 
7221 	  // remove
7222 	  remove$1(gfx.parentNode);
7223 	};
7224 
7225 
7226 	// helpers //////////
7227 
7228 	function prependTo(newNode, parentNode, siblingNode) {
7229 	  var node = siblingNode || parentNode.firstChild;
7230 
7231 	  // do not prepend node to itself to prevent IE from crashing
7232 	  // https://github.com/bpmn-io/bpmn-js/issues/746
7233 	  if (newNode === node) {
7234 	    return;
7235 	  }
7236 
7237 	  parentNode.insertBefore(newNode, node);
7238 	}
7239 
7240 	var CoreModule$1 = {
7241 	  __depends__: [ DrawModule$1 ],
7242 	  __init__: [ 'canvas' ],
7243 	  canvas: [ 'type', Canvas ],
7244 	  elementRegistry: [ 'type', ElementRegistry ],
7245 	  elementFactory: [ 'type', ElementFactory$1 ],
7246 	  eventBus: [ 'type', EventBus ],
7247 	  graphicsFactory: [ 'type', GraphicsFactory ]
7248 	};
7249 
7250 	/**
7251 	 * Bootstrap an injector from a list of modules, instantiating a number of default components
7252 	 *
7253 	 * @ignore
7254 	 * @param {Array<didi.Module>} bootstrapModules
7255 	 *
7256 	 * @return {didi.Injector} a injector to use to access the components
7257 	 */
7258 	function bootstrap(bootstrapModules) {
7259 
7260 	  var modules = [],
7261 	      components = [];
7262 
7263 	  function hasModule(m) {
7264 	    return modules.indexOf(m) >= 0;
7265 	  }
7266 
7267 	  function addModule(m) {
7268 	    modules.push(m);
7269 	  }
7270 
7271 	  function visit(m) {
7272 	    if (hasModule(m)) {
7273 	      return;
7274 	    }
7275 
7276 	    (m.__depends__ || []).forEach(visit);
7277 
7278 	    if (hasModule(m)) {
7279 	      return;
7280 	    }
7281 
7282 	    addModule(m);
7283 
7284 	    (m.__init__ || []).forEach(function(c) {
7285 	      components.push(c);
7286 	    });
7287 	  }
7288 
7289 	  bootstrapModules.forEach(visit);
7290 
7291 	  var injector = new Injector(modules);
7292 
7293 	  components.forEach(function(c) {
7294 
7295 	    try {
7296 
7297 	      // eagerly resolve component (fn or string)
7298 	      injector[typeof c === 'string' ? 'get' : 'invoke'](c);
7299 	    } catch (e) {
7300 	      console.error('Failed to instantiate component');
7301 	      console.error(e.stack);
7302 
7303 	      throw e;
7304 	    }
7305 	  });
7306 
7307 	  return injector;
7308 	}
7309 
7310 	/**
7311 	 * Creates an injector from passed options.
7312 	 *
7313 	 * @ignore
7314 	 * @param  {Object} options
7315 	 * @return {didi.Injector}
7316 	 */
7317 	function createInjector(options) {
7318 
7319 	  options = options || {};
7320 
7321 	  var configModule = {
7322 	    'config': ['value', options]
7323 	  };
7324 
7325 	  var modules = [ configModule, CoreModule$1 ].concat(options.modules || []);
7326 
7327 	  return bootstrap(modules);
7328 	}
7329 
7330 
7331 	/**
7332 	 * The main diagram-js entry point that bootstraps the diagram with the given
7333 	 * configuration.
7334 	 *
7335 	 * To register extensions with the diagram, pass them as Array<didi.Module> to the constructor.
7336 	 *
7337 	 * @class djs.Diagram
7338 	 * @memberOf djs
7339 	 * @constructor
7340 	 *
7341 	 * @example
7342 	 *
7343 	 * <caption>Creating a plug-in that logs whenever a shape is added to the canvas.</caption>
7344 	 *
7345 	 * // plug-in implemenentation
7346 	 * function MyLoggingPlugin(eventBus) {
7347 	 *   eventBus.on('shape.added', function(event) {
7348 	 *     console.log('shape ', event.shape, ' was added to the diagram');
7349 	 *   });
7350 	 * }
7351 	 *
7352 	 * // export as module
7353 	 * export default {
7354 	 *   __init__: [ 'myLoggingPlugin' ],
7355 	 *     myLoggingPlugin: [ 'type', MyLoggingPlugin ]
7356 	 * };
7357 	 *
7358 	 *
7359 	 * // instantiate the diagram with the new plug-in
7360 	 *
7361 	 * import MyLoggingModule from 'path-to-my-logging-plugin';
7362 	 *
7363 	 * var diagram = new Diagram({
7364 	 *   modules: [
7365 	 *     MyLoggingModule
7366 	 *   ]
7367 	 * });
7368 	 *
7369 	 * diagram.invoke([ 'canvas', function(canvas) {
7370 	 *   // add shape to drawing canvas
7371 	 *   canvas.addShape({ x: 10, y: 10 });
7372 	 * });
7373 	 *
7374 	 * // 'shape ... was added to the diagram' logged to console
7375 	 *
7376 	 * @param {Object} options
7377 	 * @param {Array<didi.Module>} [options.modules] external modules to instantiate with the diagram
7378 	 * @param {didi.Injector} [injector] an (optional) injector to bootstrap the diagram with
7379 	 */
7380 	function Diagram(options, injector) {
7381 
7382 	  // create injector unless explicitly specified
7383 	  this.injector = injector = injector || createInjector(options);
7384 
7385 	  // API
7386 
7387 	  /**
7388 	   * Resolves a diagram service
7389 	   *
7390 	   * @method Diagram#get
7391 	   *
7392 	   * @param {string} name the name of the diagram service to be retrieved
7393 	   * @param {boolean} [strict=true] if false, resolve missing services to null
7394 	   */
7395 	  this.get = injector.get;
7396 
7397 	  /**
7398 	   * Executes a function into which diagram services are injected
7399 	   *
7400 	   * @method Diagram#invoke
7401 	   *
7402 	   * @param {Function|Object[]} fn the function to resolve
7403 	   * @param {Object} locals a number of locals to use to resolve certain dependencies
7404 	   */
7405 	  this.invoke = injector.invoke;
7406 
7407 	  // init
7408 
7409 	  // indicate via event
7410 
7411 
7412 	  /**
7413 	   * An event indicating that all plug-ins are loaded.
7414 	   *
7415 	   * Use this event to fire other events to interested plug-ins
7416 	   *
7417 	   * @memberOf Diagram
7418 	   *
7419 	   * @event diagram.init
7420 	   *
7421 	   * @example
7422 	   *
7423 	   * eventBus.on('diagram.init', function() {
7424 	   *   eventBus.fire('my-custom-event', { foo: 'BAR' });
7425 	   * });
7426 	   *
7427 	   * @type {Object}
7428 	   */
7429 	  this.get('eventBus').fire('diagram.init');
7430 	}
7431 
7432 
7433 	/**
7434 	 * Destroys the diagram
7435 	 *
7436 	 * @method  Diagram#destroy
7437 	 */
7438 	Diagram.prototype.destroy = function() {
7439 	  this.get('eventBus').fire('diagram.destroy');
7440 	};
7441 
7442 	/**
7443 	 * Clear the diagram, removing all contents.
7444 	 */
7445 	Diagram.prototype.clear = function() {
7446 	  this.get('eventBus').fire('diagram.clear');
7447 	};
7448 
7449 	/**
7450 	 * Moddle base element.
7451 	 */
7452 	function Base() { }
7453 
7454 	Base.prototype.get = function(name) {
7455 	  return this.$model.properties.get(this, name);
7456 	};
7457 
7458 	Base.prototype.set = function(name, value) {
7459 	  this.$model.properties.set(this, name, value);
7460 	};
7461 
7462 	/**
7463 	 * A model element factory.
7464 	 *
7465 	 * @param {Moddle} model
7466 	 * @param {Properties} properties
7467 	 */
7468 	function Factory(model, properties) {
7469 	  this.model = model;
7470 	  this.properties = properties;
7471 	}
7472 
7473 
7474 	Factory.prototype.createType = function(descriptor) {
7475 
7476 	  var model = this.model;
7477 
7478 	  var props = this.properties,
7479 	      prototype = Object.create(Base.prototype);
7480 
7481 	  // initialize default values
7482 	  forEach(descriptor.properties, function(p) {
7483 	    if (!p.isMany && p.default !== undefined) {
7484 	      prototype[p.name] = p.default;
7485 	    }
7486 	  });
7487 
7488 	  props.defineModel(prototype, model);
7489 	  props.defineDescriptor(prototype, descriptor);
7490 
7491 	  var name = descriptor.ns.name;
7492 
7493 	  /**
7494 	   * The new type constructor
7495 	   */
7496 	  function ModdleElement(attrs) {
7497 	    props.define(this, '$type', { value: name, enumerable: true });
7498 	    props.define(this, '$attrs', { value: {} });
7499 	    props.define(this, '$parent', { writable: true });
7500 
7501 	    forEach(attrs, bind$2(function(val, key) {
7502 	      this.set(key, val);
7503 	    }, this));
7504 	  }
7505 
7506 	  ModdleElement.prototype = prototype;
7507 
7508 	  ModdleElement.hasType = prototype.$instanceOf = this.model.hasType;
7509 
7510 	  // static links
7511 	  props.defineModel(ModdleElement, model);
7512 	  props.defineDescriptor(ModdleElement, descriptor);
7513 
7514 	  return ModdleElement;
7515 	};
7516 
7517 	/**
7518 	 * Built-in moddle types
7519 	 */
7520 	var BUILTINS = {
7521 	  String: true,
7522 	  Boolean: true,
7523 	  Integer: true,
7524 	  Real: true,
7525 	  Element: true
7526 	};
7527 
7528 	/**
7529 	 * Converters for built in types from string representations
7530 	 */
7531 	var TYPE_CONVERTERS = {
7532 	  String: function(s) { return s; },
7533 	  Boolean: function(s) { return s === 'true'; },
7534 	  Integer: function(s) { return parseInt(s, 10); },
7535 	  Real: function(s) { return parseFloat(s); }
7536 	};
7537 
7538 	/**
7539 	 * Convert a type to its real representation
7540 	 */
7541 	function coerceType(type, value) {
7542 
7543 	  var converter = TYPE_CONVERTERS[type];
7544 
7545 	  if (converter) {
7546 	    return converter(value);
7547 	  } else {
7548 	    return value;
7549 	  }
7550 	}
7551 
7552 	/**
7553 	 * Return whether the given type is built-in
7554 	 */
7555 	function isBuiltIn(type) {
7556 	  return !!BUILTINS[type];
7557 	}
7558 
7559 	/**
7560 	 * Return whether the given type is simple
7561 	 */
7562 	function isSimple(type) {
7563 	  return !!TYPE_CONVERTERS[type];
7564 	}
7565 
7566 	/**
7567 	 * Parses a namespaced attribute name of the form (ns:)localName to an object,
7568 	 * given a default prefix to assume in case no explicit namespace is given.
7569 	 *
7570 	 * @param {String} name
7571 	 * @param {String} [defaultPrefix] the default prefix to take, if none is present.
7572 	 *
7573 	 * @return {Object} the parsed name
7574 	 */
7575 	function parseName(name, defaultPrefix) {
7576 	  var parts = name.split(/:/),
7577 	      localName, prefix;
7578 
7579 	  // no prefix (i.e. only local name)
7580 	  if (parts.length === 1) {
7581 	    localName = name;
7582 	    prefix = defaultPrefix;
7583 	  } else
7584 	  // prefix + local name
7585 	  if (parts.length === 2) {
7586 	    localName = parts[1];
7587 	    prefix = parts[0];
7588 	  } else {
7589 	    throw new Error('expected <prefix:localName> or <localName>, got ' + name);
7590 	  }
7591 
7592 	  name = (prefix ? prefix + ':' : '') + localName;
7593 
7594 	  return {
7595 	    name: name,
7596 	    prefix: prefix,
7597 	    localName: localName
7598 	  };
7599 	}
7600 
7601 	/**
7602 	 * A utility to build element descriptors.
7603 	 */
7604 	function DescriptorBuilder(nameNs) {
7605 	  this.ns = nameNs;
7606 	  this.name = nameNs.name;
7607 	  this.allTypes = [];
7608 	  this.allTypesByName = {};
7609 	  this.properties = [];
7610 	  this.propertiesByName = {};
7611 	}
7612 
7613 
7614 	DescriptorBuilder.prototype.build = function() {
7615 	  return pick(this, [
7616 	    'ns',
7617 	    'name',
7618 	    'allTypes',
7619 	    'allTypesByName',
7620 	    'properties',
7621 	    'propertiesByName',
7622 	    'bodyProperty',
7623 	    'idProperty'
7624 	  ]);
7625 	};
7626 
7627 	/**
7628 	 * Add property at given index.
7629 	 *
7630 	 * @param {Object} p
7631 	 * @param {Number} [idx]
7632 	 * @param {Boolean} [validate=true]
7633 	 */
7634 	DescriptorBuilder.prototype.addProperty = function(p, idx, validate) {
7635 
7636 	  if (typeof idx === 'boolean') {
7637 	    validate = idx;
7638 	    idx = undefined;
7639 	  }
7640 
7641 	  this.addNamedProperty(p, validate !== false);
7642 
7643 	  var properties = this.properties;
7644 
7645 	  if (idx !== undefined) {
7646 	    properties.splice(idx, 0, p);
7647 	  } else {
7648 	    properties.push(p);
7649 	  }
7650 	};
7651 
7652 
7653 	DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty, replace) {
7654 	  var oldNameNs = oldProperty.ns;
7655 
7656 	  var props = this.properties,
7657 	      propertiesByName = this.propertiesByName,
7658 	      rename = oldProperty.name !== newProperty.name;
7659 
7660 	  if (oldProperty.isId) {
7661 	    if (!newProperty.isId) {
7662 	      throw new Error(
7663 	        'property <' + newProperty.ns.name + '> must be id property ' +
7664 	        'to refine <' + oldProperty.ns.name + '>');
7665 	    }
7666 
7667 	    this.setIdProperty(newProperty, false);
7668 	  }
7669 
7670 	  if (oldProperty.isBody) {
7671 
7672 	    if (!newProperty.isBody) {
7673 	      throw new Error(
7674 	        'property <' + newProperty.ns.name + '> must be body property ' +
7675 	        'to refine <' + oldProperty.ns.name + '>');
7676 	    }
7677 
7678 	    // TODO: Check compatibility
7679 	    this.setBodyProperty(newProperty, false);
7680 	  }
7681 
7682 	  // validate existence and get location of old property
7683 	  var idx = props.indexOf(oldProperty);
7684 	  if (idx === -1) {
7685 	    throw new Error('property <' + oldNameNs.name + '> not found in property list');
7686 	  }
7687 
7688 	  // remove old property
7689 	  props.splice(idx, 1);
7690 
7691 	  // replacing the named property is intentional
7692 	  //
7693 	  //  * validate only if this is a "rename" operation
7694 	  //  * add at specific index unless we "replace"
7695 	  //
7696 	  this.addProperty(newProperty, replace ? undefined : idx, rename);
7697 
7698 	  // make new property available under old name
7699 	  propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
7700 	};
7701 
7702 
7703 	DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, replace) {
7704 
7705 	  var nsPrefix = p.ns.prefix;
7706 	  var parts = targetPropertyName.split('#');
7707 
7708 	  var name = parseName(parts[0], nsPrefix);
7709 	  var attrName = parseName(parts[1], name.prefix).name;
7710 
7711 	  var redefinedProperty = this.propertiesByName[attrName];
7712 	  if (!redefinedProperty) {
7713 	    throw new Error('refined property <' + attrName + '> not found');
7714 	  } else {
7715 	    this.replaceProperty(redefinedProperty, p, replace);
7716 	  }
7717 
7718 	  delete p.redefines;
7719 	};
7720 
7721 	DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
7722 	  var ns = p.ns,
7723 	      propsByName = this.propertiesByName;
7724 
7725 	  if (validate) {
7726 	    this.assertNotDefined(p, ns.name);
7727 	    this.assertNotDefined(p, ns.localName);
7728 	  }
7729 
7730 	  propsByName[ns.name] = propsByName[ns.localName] = p;
7731 	};
7732 
7733 	DescriptorBuilder.prototype.removeNamedProperty = function(p) {
7734 	  var ns = p.ns,
7735 	      propsByName = this.propertiesByName;
7736 
7737 	  delete propsByName[ns.name];
7738 	  delete propsByName[ns.localName];
7739 	};
7740 
7741 	DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
7742 
7743 	  if (validate && this.bodyProperty) {
7744 	    throw new Error(
7745 	      'body property defined multiple times ' +
7746 	      '(<' + this.bodyProperty.ns.name + '>, <' + p.ns.name + '>)');
7747 	  }
7748 
7749 	  this.bodyProperty = p;
7750 	};
7751 
7752 	DescriptorBuilder.prototype.setIdProperty = function(p, validate) {
7753 
7754 	  if (validate && this.idProperty) {
7755 	    throw new Error(
7756 	      'id property defined multiple times ' +
7757 	      '(<' + this.idProperty.ns.name + '>, <' + p.ns.name + '>)');
7758 	  }
7759 
7760 	  this.idProperty = p;
7761 	};
7762 
7763 	DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
7764 	  var propertyName = p.name,
7765 	      definedProperty = this.propertiesByName[propertyName];
7766 
7767 	  if (definedProperty) {
7768 	    throw new Error(
7769 	      'property <' + propertyName + '> already defined; ' +
7770 	      'override of <' + definedProperty.definedBy.ns.name + '#' + definedProperty.ns.name + '> by ' +
7771 	      '<' + p.definedBy.ns.name + '#' + p.ns.name + '> not allowed without redefines');
7772 	  }
7773 	};
7774 
7775 	DescriptorBuilder.prototype.hasProperty = function(name) {
7776 	  return this.propertiesByName[name];
7777 	};
7778 
7779 	DescriptorBuilder.prototype.addTrait = function(t, inherited) {
7780 
7781 	  var typesByName = this.allTypesByName,
7782 	      types = this.allTypes;
7783 
7784 	  var typeName = t.name;
7785 
7786 	  if (typeName in typesByName) {
7787 	    return;
7788 	  }
7789 
7790 	  forEach(t.properties, bind$2(function(p) {
7791 
7792 	    // clone property to allow extensions
7793 	    p = assign({}, p, {
7794 	      name: p.ns.localName,
7795 	      inherited: inherited
7796 	    });
7797 
7798 	    Object.defineProperty(p, 'definedBy', {
7799 	      value: t
7800 	    });
7801 
7802 	    var replaces = p.replaces,
7803 	        redefines = p.redefines;
7804 
7805 	    // add replace/redefine support
7806 	    if (replaces || redefines) {
7807 	      this.redefineProperty(p, replaces || redefines, replaces);
7808 	    } else {
7809 	      if (p.isBody) {
7810 	        this.setBodyProperty(p);
7811 	      }
7812 	      if (p.isId) {
7813 	        this.setIdProperty(p);
7814 	      }
7815 	      this.addProperty(p);
7816 	    }
7817 	  }, this));
7818 
7819 	  types.push(t);
7820 	  typesByName[typeName] = t;
7821 	};
7822 
7823 	/**
7824 	 * A registry of Moddle packages.
7825 	 *
7826 	 * @param {Array<Package>} packages
7827 	 * @param {Properties} properties
7828 	 */
7829 	function Registry(packages, properties) {
7830 	  this.packageMap = {};
7831 	  this.typeMap = {};
7832 
7833 	  this.packages = [];
7834 
7835 	  this.properties = properties;
7836 
7837 	  forEach(packages, bind$2(this.registerPackage, this));
7838 	}
7839 
7840 
7841 	Registry.prototype.getPackage = function(uriOrPrefix) {
7842 	  return this.packageMap[uriOrPrefix];
7843 	};
7844 
7845 	Registry.prototype.getPackages = function() {
7846 	  return this.packages;
7847 	};
7848 
7849 
7850 	Registry.prototype.registerPackage = function(pkg) {
7851 
7852 	  // copy package
7853 	  pkg = assign({}, pkg);
7854 
7855 	  var pkgMap = this.packageMap;
7856 
7857 	  ensureAvailable(pkgMap, pkg, 'prefix');
7858 	  ensureAvailable(pkgMap, pkg, 'uri');
7859 
7860 	  // register types
7861 	  forEach(pkg.types, bind$2(function(descriptor) {
7862 	    this.registerType(descriptor, pkg);
7863 	  }, this));
7864 
7865 	  pkgMap[pkg.uri] = pkgMap[pkg.prefix] = pkg;
7866 	  this.packages.push(pkg);
7867 	};
7868 
7869 
7870 	/**
7871 	 * Register a type from a specific package with us
7872 	 */
7873 	Registry.prototype.registerType = function(type, pkg) {
7874 
7875 	  type = assign({}, type, {
7876 	    superClass: (type.superClass || []).slice(),
7877 	    extends: (type.extends || []).slice(),
7878 	    properties: (type.properties || []).slice(),
7879 	    meta: assign((type.meta || {}))
7880 	  });
7881 
7882 	  var ns = parseName(type.name, pkg.prefix),
7883 	      name = ns.name,
7884 	      propertiesByName = {};
7885 
7886 	  // parse properties
7887 	  forEach(type.properties, bind$2(function(p) {
7888 
7889 	    // namespace property names
7890 	    var propertyNs = parseName(p.name, ns.prefix),
7891 	        propertyName = propertyNs.name;
7892 
7893 	    // namespace property types
7894 	    if (!isBuiltIn(p.type)) {
7895 	      p.type = parseName(p.type, propertyNs.prefix).name;
7896 	    }
7897 
7898 	    assign(p, {
7899 	      ns: propertyNs,
7900 	      name: propertyName
7901 	    });
7902 
7903 	    propertiesByName[propertyName] = p;
7904 	  }, this));
7905 
7906 	  // update ns + name
7907 	  assign(type, {
7908 	    ns: ns,
7909 	    name: name,
7910 	    propertiesByName: propertiesByName
7911 	  });
7912 
7913 	  forEach(type.extends, bind$2(function(extendsName) {
7914 	    var extended = this.typeMap[extendsName];
7915 
7916 	    extended.traits = extended.traits || [];
7917 	    extended.traits.push(name);
7918 	  }, this));
7919 
7920 	  // link to package
7921 	  this.definePackage(type, pkg);
7922 
7923 	  // register
7924 	  this.typeMap[name] = type;
7925 	};
7926 
7927 
7928 	/**
7929 	 * Traverse the type hierarchy from bottom to top,
7930 	 * calling iterator with (type, inherited) for all elements in
7931 	 * the inheritance chain.
7932 	 *
7933 	 * @param {Object} nsName
7934 	 * @param {Function} iterator
7935 	 * @param {Boolean} [trait=false]
7936 	 */
7937 	Registry.prototype.mapTypes = function(nsName, iterator, trait) {
7938 
7939 	  var type = isBuiltIn(nsName.name) ? { name: nsName.name } : this.typeMap[nsName.name];
7940 
7941 	  var self = this;
7942 
7943 	  /**
7944 	   * Traverse the selected trait.
7945 	   *
7946 	   * @param {String} cls
7947 	   */
7948 	  function traverseTrait(cls) {
7949 	    return traverseSuper(cls, true);
7950 	  }
7951 
7952 	  /**
7953 	   * Traverse the selected super type or trait
7954 	   *
7955 	   * @param {String} cls
7956 	   * @param {Boolean} [trait=false]
7957 	   */
7958 	  function traverseSuper(cls, trait) {
7959 	    var parentNs = parseName(cls, isBuiltIn(cls) ? '' : nsName.prefix);
7960 	    self.mapTypes(parentNs, iterator, trait);
7961 	  }
7962 
7963 	  if (!type) {
7964 	    throw new Error('unknown type <' + nsName.name + '>');
7965 	  }
7966 
7967 	  forEach(type.superClass, trait ? traverseTrait : traverseSuper);
7968 
7969 	  // call iterator with (type, inherited=!trait)
7970 	  iterator(type, !trait);
7971 
7972 	  forEach(type.traits, traverseTrait);
7973 	};
7974 
7975 
7976 	/**
7977 	 * Returns the effective descriptor for a type.
7978 	 *
7979 	 * @param  {String} type the namespaced name (ns:localName) of the type
7980 	 *
7981 	 * @return {Descriptor} the resulting effective descriptor
7982 	 */
7983 	Registry.prototype.getEffectiveDescriptor = function(name) {
7984 
7985 	  var nsName = parseName(name);
7986 
7987 	  var builder = new DescriptorBuilder(nsName);
7988 
7989 	  this.mapTypes(nsName, function(type, inherited) {
7990 	    builder.addTrait(type, inherited);
7991 	  });
7992 
7993 	  var descriptor = builder.build();
7994 
7995 	  // define package link
7996 	  this.definePackage(descriptor, descriptor.allTypes[descriptor.allTypes.length - 1].$pkg);
7997 
7998 	  return descriptor;
7999 	};
8000 
8001 
8002 	Registry.prototype.definePackage = function(target, pkg) {
8003 	  this.properties.define(target, '$pkg', { value: pkg });
8004 	};
8005 
8006 
8007 
8008 	///////// helpers ////////////////////////////
8009 
8010 	function ensureAvailable(packageMap, pkg, identifierKey) {
8011 
8012 	  var value = pkg[identifierKey];
8013 
8014 	  if (value in packageMap) {
8015 	    throw new Error('package with ' + identifierKey + ' <' + value + '> already defined');
8016 	  }
8017 	}
8018 
8019 	/**
8020 	 * A utility that gets and sets properties of model elements.
8021 	 *
8022 	 * @param {Model} model
8023 	 */
8024 	function Properties(model) {
8025 	  this.model = model;
8026 	}
8027 
8028 
8029 	/**
8030 	 * Sets a named property on the target element.
8031 	 * If the value is undefined, the property gets deleted.
8032 	 *
8033 	 * @param {Object} target
8034 	 * @param {String} name
8035 	 * @param {Object} value
8036 	 */
8037 	Properties.prototype.set = function(target, name, value) {
8038 
8039 	  var property = this.model.getPropertyDescriptor(target, name);
8040 
8041 	  var propertyName = property && property.name;
8042 
8043 	  if (isUndefined(value)) {
8044 	    // unset the property, if the specified value is undefined;
8045 	    // delete from $attrs (for extensions) or the target itself
8046 	    if (property) {
8047 	      delete target[propertyName];
8048 	    } else {
8049 	      delete target.$attrs[name];
8050 	    }
8051 	  } else {
8052 	    // set the property, defining well defined properties on the fly
8053 	    // or simply updating them in target.$attrs (for extensions)
8054 	    if (property) {
8055 	      if (propertyName in target) {
8056 	        target[propertyName] = value;
8057 	      } else {
8058 	        defineProperty(target, property, value);
8059 	      }
8060 	    } else {
8061 	      target.$attrs[name] = value;
8062 	    }
8063 	  }
8064 	};
8065 
8066 	/**
8067 	 * Returns the named property of the given element
8068 	 *
8069 	 * @param  {Object} target
8070 	 * @param  {String} name
8071 	 *
8072 	 * @return {Object}
8073 	 */
8074 	Properties.prototype.get = function(target, name) {
8075 
8076 	  var property = this.model.getPropertyDescriptor(target, name);
8077 
8078 	  if (!property) {
8079 	    return target.$attrs[name];
8080 	  }
8081 
8082 	  var propertyName = property.name;
8083 
8084 	  // check if access to collection property and lazily initialize it
8085 	  if (!target[propertyName] && property.isMany) {
8086 	    defineProperty(target, property, []);
8087 	  }
8088 
8089 	  return target[propertyName];
8090 	};
8091 
8092 
8093 	/**
8094 	 * Define a property on the target element
8095 	 *
8096 	 * @param  {Object} target
8097 	 * @param  {String} name
8098 	 * @param  {Object} options
8099 	 */
8100 	Properties.prototype.define = function(target, name, options) {
8101 	  Object.defineProperty(target, name, options);
8102 	};
8103 
8104 
8105 	/**
8106 	 * Define the descriptor for an element
8107 	 */
8108 	Properties.prototype.defineDescriptor = function(target, descriptor) {
8109 	  this.define(target, '$descriptor', { value: descriptor });
8110 	};
8111 
8112 	/**
8113 	 * Define the model for an element
8114 	 */
8115 	Properties.prototype.defineModel = function(target, model) {
8116 	  this.define(target, '$model', { value: model });
8117 	};
8118 
8119 
8120 	function isUndefined(val) {
8121 	  return typeof val === 'undefined';
8122 	}
8123 
8124 	function defineProperty(target, property, value) {
8125 	  Object.defineProperty(target, property.name, {
8126 	    enumerable: !property.isReference,
8127 	    writable: true,
8128 	    value: value,
8129 	    configurable: true
8130 	  });
8131 	}
8132 
8133 	//// Moddle implementation /////////////////////////////////////////////////
8134 
8135 	/**
8136 	 * @class Moddle
8137 	 *
8138 	 * A model that can be used to create elements of a specific type.
8139 	 *
8140 	 * @example
8141 	 *
8142 	 * var Moddle = require('moddle');
8143 	 *
8144 	 * var pkg = {
8145 	 *   name: 'mypackage',
8146 	 *   prefix: 'my',
8147 	 *   types: [
8148 	 *     { name: 'Root' }
8149 	 *   ]
8150 	 * };
8151 	 *
8152 	 * var moddle = new Moddle([pkg]);
8153 	 *
8154 	 * @param {Array<Package>} packages the packages to contain
8155 	 */
8156 	function Moddle(packages) {
8157 
8158 	  this.properties = new Properties(this);
8159 
8160 	  this.factory = new Factory(this, this.properties);
8161 	  this.registry = new Registry(packages, this.properties);
8162 
8163 	  this.typeCache = {};
8164 	}
8165 
8166 
8167 	/**
8168 	 * Create an instance of the specified type.
8169 	 *
8170 	 * @method Moddle#create
8171 	 *
8172 	 * @example
8173 	 *
8174 	 * var foo = moddle.create('my:Foo');
8175 	 * var bar = moddle.create('my:Bar', { id: 'BAR_1' });
8176 	 *
8177 	 * @param  {String|Object} descriptor the type descriptor or name know to the model
8178 	 * @param  {Object} attrs   a number of attributes to initialize the model instance with
8179 	 * @return {Object}         model instance
8180 	 */
8181 	Moddle.prototype.create = function(descriptor, attrs) {
8182 	  var Type = this.getType(descriptor);
8183 
8184 	  if (!Type) {
8185 	    throw new Error('unknown type <' + descriptor + '>');
8186 	  }
8187 
8188 	  return new Type(attrs);
8189 	};
8190 
8191 
8192 	/**
8193 	 * Returns the type representing a given descriptor
8194 	 *
8195 	 * @method Moddle#getType
8196 	 *
8197 	 * @example
8198 	 *
8199 	 * var Foo = moddle.getType('my:Foo');
8200 	 * var foo = new Foo({ 'id' : 'FOO_1' });
8201 	 *
8202 	 * @param  {String|Object} descriptor the type descriptor or name know to the model
8203 	 * @return {Object}         the type representing the descriptor
8204 	 */
8205 	Moddle.prototype.getType = function(descriptor) {
8206 
8207 	  var cache = this.typeCache;
8208 
8209 	  var name = isString(descriptor) ? descriptor : descriptor.ns.name;
8210 
8211 	  var type = cache[name];
8212 
8213 	  if (!type) {
8214 	    descriptor = this.registry.getEffectiveDescriptor(name);
8215 	    type = cache[name] = this.factory.createType(descriptor);
8216 	  }
8217 
8218 	  return type;
8219 	};
8220 
8221 
8222 	/**
8223 	 * Creates an any-element type to be used within model instances.
8224 	 *
8225 	 * This can be used to create custom elements that lie outside the meta-model.
8226 	 * The created element contains all the meta-data required to serialize it
8227 	 * as part of meta-model elements.
8228 	 *
8229 	 * @method Moddle#createAny
8230 	 *
8231 	 * @example
8232 	 *
8233 	 * var foo = moddle.createAny('vendor:Foo', 'http://vendor', {
8234 	 *   value: 'bar'
8235 	 * });
8236 	 *
8237 	 * var container = moddle.create('my:Container', 'http://my', {
8238 	 *   any: [ foo ]
8239 	 * });
8240 	 *
8241 	 * // go ahead and serialize the stuff
8242 	 *
8243 	 *
8244 	 * @param  {String} name  the name of the element
8245 	 * @param  {String} nsUri the namespace uri of the element
8246 	 * @param  {Object} [properties] a map of properties to initialize the instance with
8247 	 * @return {Object} the any type instance
8248 	 */
8249 	Moddle.prototype.createAny = function(name, nsUri, properties) {
8250 
8251 	  var nameNs = parseName(name);
8252 
8253 	  var element = {
8254 	    $type: name,
8255 	    $instanceOf: function(type) {
8256 	      return type === this.$type;
8257 	    }
8258 	  };
8259 
8260 	  var descriptor = {
8261 	    name: name,
8262 	    isGeneric: true,
8263 	    ns: {
8264 	      prefix: nameNs.prefix,
8265 	      localName: nameNs.localName,
8266 	      uri: nsUri
8267 	    }
8268 	  };
8269 
8270 	  this.properties.defineDescriptor(element, descriptor);
8271 	  this.properties.defineModel(element, this);
8272 	  this.properties.define(element, '$parent', { enumerable: false, writable: true });
8273 	  this.properties.define(element, '$instanceOf', { enumerable: false, writable: true });
8274 
8275 	  forEach(properties, function(a, key) {
8276 	    if (isObject(a) && a.value !== undefined) {
8277 	      element[a.name] = a.value;
8278 	    } else {
8279 	      element[key] = a;
8280 	    }
8281 	  });
8282 
8283 	  return element;
8284 	};
8285 
8286 	/**
8287 	 * Returns a registered package by uri or prefix
8288 	 *
8289 	 * @return {Object} the package
8290 	 */
8291 	Moddle.prototype.getPackage = function(uriOrPrefix) {
8292 	  return this.registry.getPackage(uriOrPrefix);
8293 	};
8294 
8295 	/**
8296 	 * Returns a snapshot of all known packages
8297 	 *
8298 	 * @return {Object} the package
8299 	 */
8300 	Moddle.prototype.getPackages = function() {
8301 	  return this.registry.getPackages();
8302 	};
8303 
8304 	/**
8305 	 * Returns the descriptor for an element
8306 	 */
8307 	Moddle.prototype.getElementDescriptor = function(element) {
8308 	  return element.$descriptor;
8309 	};
8310 
8311 	/**
8312 	 * Returns true if the given descriptor or instance
8313 	 * represents the given type.
8314 	 *
8315 	 * May be applied to this, if element is omitted.
8316 	 */
8317 	Moddle.prototype.hasType = function(element, type) {
8318 	  if (type === undefined) {
8319 	    type = element;
8320 	    element = this;
8321 	  }
8322 
8323 	  var descriptor = element.$model.getElementDescriptor(element);
8324 
8325 	  return (type in descriptor.allTypesByName);
8326 	};
8327 
8328 	/**
8329 	 * Returns the descriptor of an elements named property
8330 	 */
8331 	Moddle.prototype.getPropertyDescriptor = function(element, property) {
8332 	  return this.getElementDescriptor(element).propertiesByName[property];
8333 	};
8334 
8335 	/**
8336 	 * Returns a mapped type's descriptor
8337 	 */
8338 	Moddle.prototype.getTypeDescriptor = function(type) {
8339 	  return this.registry.typeMap[type];
8340 	};
8341 
8342 	var fromCharCode = String.fromCharCode;
8343 
8344 	var hasOwnProperty = Object.prototype.hasOwnProperty;
8345 
8346 	var ENTITY_PATTERN = /&#(\d+);|&#x([0-9a-f]+);|&(\w+);/ig;
8347 
8348 	var ENTITY_MAPPING = {
8349 	  'amp': '&',
8350 	  'apos': '\'',
8351 	  'gt': '>',
8352 	  'lt': '<',
8353 	  'quot': '"'
8354 	};
8355 
8356 	// map UPPERCASE variants of supported special chars
8357 	Object.keys(ENTITY_MAPPING).forEach(function(k) {
8358 	  ENTITY_MAPPING[k.toUpperCase()] = ENTITY_MAPPING[k];
8359 	});
8360 
8361 
8362 	function replaceEntities(_, d, x, z) {
8363 
8364 	  // reserved names, i.e. &nbsp;
8365 	  if (z) {
8366 	    if (hasOwnProperty.call(ENTITY_MAPPING, z)) {
8367 	      return ENTITY_MAPPING[z];
8368 	    } else {
8369 
8370 	      // fall back to original value
8371 	      return '&' + z + ';';
8372 	    }
8373 	  }
8374 
8375 	  // decimal encoded char
8376 	  if (d) {
8377 	    return fromCharCode(d);
8378 	  }
8379 
8380 	  // hex encoded char
8381 	  return fromCharCode(parseInt(x, 16));
8382 	}
8383 
8384 
8385 	/**
8386 	 * A basic entity decoder that can decode a minimal
8387 	 * sub-set of reserved names (&amp;) as well as
8388 	 * hex (&#xaaf;) and decimal (&#1231;) encoded characters.
8389 	 *
8390 	 * @param {string} str
8391 	 *
8392 	 * @return {string} decoded string
8393 	 */
8394 	function decodeEntities(s) {
8395 	  if (s.length > 3 && s.indexOf('&') !== -1) {
8396 	    return s.replace(ENTITY_PATTERN, replaceEntities);
8397 	  }
8398 
8399 	  return s;
8400 	}
8401 
8402 	var XSI_URI = 'http://www.w3.org/2001/XMLSchema-instance';
8403 	var XSI_PREFIX = 'xsi';
8404 	var XSI_TYPE$1 = 'xsi:type';
8405 
8406 	var NON_WHITESPACE_OUTSIDE_ROOT_NODE = 'non-whitespace outside of root node';
8407 
8408 	function error$2(msg) {
8409 	  return new Error(msg);
8410 	}
8411 
8412 	function missingNamespaceForPrefix(prefix) {
8413 	  return 'missing namespace for prefix <' + prefix + '>';
8414 	}
8415 
8416 	function getter(getFn) {
8417 	  return {
8418 	    'get': getFn,
8419 	    'enumerable': true
8420 	  };
8421 	}
8422 
8423 	function cloneNsMatrix(nsMatrix) {
8424 	  var clone = {}, key;
8425 	  for (key in nsMatrix) {
8426 	    clone[key] = nsMatrix[key];
8427 	  }
8428 	  return clone;
8429 	}
8430 
8431 	function uriPrefix(prefix) {
8432 	  return prefix + '$uri';
8433 	}
8434 
8435 	function buildNsMatrix(nsUriToPrefix) {
8436 	  var nsMatrix = {},
8437 	      uri,
8438 	      prefix;
8439 
8440 	  for (uri in nsUriToPrefix) {
8441 	    prefix = nsUriToPrefix[uri];
8442 	    nsMatrix[prefix] = prefix;
8443 	    nsMatrix[uriPrefix(prefix)] = uri;
8444 	  }
8445 
8446 	  return nsMatrix;
8447 	}
8448 
8449 	function noopGetContext() {
8450 	  return { 'line': 0, 'column': 0 };
8451 	}
8452 
8453 	function throwFunc(err) {
8454 	  throw err;
8455 	}
8456 
8457 	/**
8458 	 * Creates a new parser with the given options.
8459 	 *
8460 	 * @constructor
8461 	 *
8462 	 * @param  {!Object<string, ?>=} options
8463 	 */
8464 	function Parser(options) {
8465 
8466 	  if (!this) {
8467 	    return new Parser(options);
8468 	  }
8469 
8470 	  var proxy = options && options['proxy'];
8471 
8472 	  var onText,
8473 	      onOpenTag,
8474 	      onCloseTag,
8475 	      onCDATA,
8476 	      onError = throwFunc,
8477 	      onWarning,
8478 	      onComment,
8479 	      onQuestion,
8480 	      onAttention;
8481 
8482 	  var getContext = noopGetContext;
8483 
8484 	  /**
8485 	   * Do we need to parse the current elements attributes for namespaces?
8486 	   *
8487 	   * @type {boolean}
8488 	   */
8489 	  var maybeNS = false;
8490 
8491 	  /**
8492 	   * Do we process namespaces at all?
8493 	   *
8494 	   * @type {boolean}
8495 	   */
8496 	  var isNamespace = false;
8497 
8498 	  /**
8499 	   * The caught error returned on parse end
8500 	   *
8501 	   * @type {Error}
8502 	   */
8503 	  var returnError = null;
8504 
8505 	  /**
8506 	   * Should we stop parsing?
8507 	   *
8508 	   * @type {boolean}
8509 	   */
8510 	  var parseStop = false;
8511 
8512 	  /**
8513 	   * A map of { uri: prefix } used by the parser.
8514 	   *
8515 	   * This map will ensure we can normalize prefixes during processing;
8516 	   * for each uri, only one prefix will be exposed to the handlers.
8517 	   *
8518 	   * @type {!Object<string, string>}}
8519 	   */
8520 	  var nsUriToPrefix;
8521 
8522 	  /**
8523 	   * Handle parse error.
8524 	   *
8525 	   * @param  {string|Error} err
8526 	   */
8527 	  function handleError(err) {
8528 	    if (!(err instanceof Error)) {
8529 	      err = error$2(err);
8530 	    }
8531 
8532 	    returnError = err;
8533 
8534 	    onError(err, getContext);
8535 	  }
8536 
8537 	  /**
8538 	   * Handle parse error.
8539 	   *
8540 	   * @param  {string|Error} err
8541 	   */
8542 	  function handleWarning(err) {
8543 
8544 	    if (!onWarning) {
8545 	      return;
8546 	    }
8547 
8548 	    if (!(err instanceof Error)) {
8549 	      err = error$2(err);
8550 	    }
8551 
8552 	    onWarning(err, getContext);
8553 	  }
8554 
8555 	  /**
8556 	   * Register parse listener.
8557 	   *
8558 	   * @param  {string}   name
8559 	   * @param  {Function} cb
8560 	   *
8561 	   * @return {Parser}
8562 	   */
8563 	  this['on'] = function(name, cb) {
8564 
8565 	    if (typeof cb !== 'function') {
8566 	      throw error$2('required args <name, cb>');
8567 	    }
8568 
8569 	    switch (name) {
8570 	    case 'openTag': onOpenTag = cb; break;
8571 	    case 'text': onText = cb; break;
8572 	    case 'closeTag': onCloseTag = cb; break;
8573 	    case 'error': onError = cb; break;
8574 	    case 'warn': onWarning = cb; break;
8575 	    case 'cdata': onCDATA = cb; break;
8576 	    case 'attention': onAttention = cb; break; // <!XXXXX zzzz="eeee">
8577 	    case 'question': onQuestion = cb; break; // <? ....  ?>
8578 	    case 'comment': onComment = cb; break;
8579 	    default:
8580 	      throw error$2('unsupported event: ' + name);
8581 	    }
8582 
8583 	    return this;
8584 	  };
8585 
8586 	  /**
8587 	   * Set the namespace to prefix mapping.
8588 	   *
8589 	   * @example
8590 	   *
8591 	   * parser.ns({
8592 	   *   'http://foo': 'foo',
8593 	   *   'http://bar': 'bar'
8594 	   * });
8595 	   *
8596 	   * @param  {!Object<string, string>} nsMap
8597 	   *
8598 	   * @return {Parser}
8599 	   */
8600 	  this['ns'] = function(nsMap) {
8601 
8602 	    if (typeof nsMap === 'undefined') {
8603 	      nsMap = {};
8604 	    }
8605 
8606 	    if (typeof nsMap !== 'object') {
8607 	      throw error$2('required args <nsMap={}>');
8608 	    }
8609 
8610 	    var _nsUriToPrefix = {}, k;
8611 
8612 	    for (k in nsMap) {
8613 	      _nsUriToPrefix[k] = nsMap[k];
8614 	    }
8615 
8616 	    // FORCE default mapping for schema instance
8617 	    _nsUriToPrefix[XSI_URI] = XSI_PREFIX;
8618 
8619 	    isNamespace = true;
8620 	    nsUriToPrefix = _nsUriToPrefix;
8621 
8622 	    return this;
8623 	  };
8624 
8625 	  /**
8626 	   * Parse xml string.
8627 	   *
8628 	   * @param  {string} xml
8629 	   *
8630 	   * @return {Error} returnError, if not thrown
8631 	   */
8632 	  this['parse'] = function(xml) {
8633 	    if (typeof xml !== 'string') {
8634 	      throw error$2('required args <xml=string>');
8635 	    }
8636 
8637 	    returnError = null;
8638 
8639 	    parse(xml);
8640 
8641 	    getContext = noopGetContext;
8642 	    parseStop = false;
8643 
8644 	    return returnError;
8645 	  };
8646 
8647 	  /**
8648 	   * Stop parsing.
8649 	   */
8650 	  this['stop'] = function() {
8651 	    parseStop = true;
8652 	  };
8653 
8654 	  /**
8655 	   * Parse string, invoking configured listeners on element.
8656 	   *
8657 	   * @param  {string} xml
8658 	   */
8659 	  function parse(xml) {
8660 	    var nsMatrixStack = isNamespace ? [] : null,
8661 	        nsMatrix = isNamespace ? buildNsMatrix(nsUriToPrefix) : null,
8662 	        _nsMatrix,
8663 	        nodeStack = [],
8664 	        anonymousNsCount = 0,
8665 	        tagStart = false,
8666 	        tagEnd = false,
8667 	        i = 0, j = 0,
8668 	        x, y, q, w, v,
8669 	        xmlns,
8670 	        elementName,
8671 	        _elementName,
8672 	        elementProxy
8673 	        ;
8674 
8675 	    var attrsString = '',
8676 	        attrsStart = 0,
8677 	        cachedAttrs // false = parsed with errors, null = needs parsing
8678 	        ;
8679 
8680 	    /**
8681 	     * Parse attributes on demand and returns the parsed attributes.
8682 	     *
8683 	     * Return semantics: (1) `false` on attribute parse error,
8684 	     * (2) object hash on extracted attrs.
8685 	     *
8686 	     * @return {boolean|Object}
8687 	     */
8688 	    function getAttrs() {
8689 	      if (cachedAttrs !== null) {
8690 	        return cachedAttrs;
8691 	      }
8692 
8693 	      var nsUri,
8694 	          nsUriPrefix,
8695 	          nsName,
8696 	          defaultAlias = isNamespace && nsMatrix['xmlns'],
8697 	          attrList = isNamespace && maybeNS ? [] : null,
8698 	          i = attrsStart,
8699 	          s = attrsString,
8700 	          l = s.length,
8701 	          hasNewMatrix,
8702 	          newalias,
8703 	          value,
8704 	          alias,
8705 	          name,
8706 	          attrs = {},
8707 	          seenAttrs = {},
8708 	          skipAttr,
8709 	          w,
8710 	          j;
8711 
8712 	      parseAttr:
8713 	      for (; i < l; i++) {
8714 	        skipAttr = false;
8715 	        w = s.charCodeAt(i);
8716 
8717 	        if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE={ \f\n\r\t\v}
8718 	          continue;
8719 	        }
8720 
8721 	        // wait for non whitespace character
8722 	        if (w < 65 || w > 122 || (w > 90 && w < 97)) {
8723 	          if (w !== 95 && w !== 58) { // char 95"_" 58":"
8724 	            handleWarning('illegal first char attribute name');
8725 	            skipAttr = true;
8726 	          }
8727 	        }
8728 
8729 	        // parse attribute name
8730 	        for (j = i + 1; j < l; j++) {
8731 	          w = s.charCodeAt(j);
8732 
8733 	          if (
8734 	            w > 96 && w < 123 ||
8735 	            w > 64 && w < 91 ||
8736 	            w > 47 && w < 59 ||
8737 	            w === 46 || // '.'
8738 	            w === 45 || // '-'
8739 	            w === 95 // '_'
8740 	          ) {
8741 	            continue;
8742 	          }
8743 
8744 	          // unexpected whitespace
8745 	          if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
8746 	            handleWarning('missing attribute value');
8747 	            i = j;
8748 
8749 	            continue parseAttr;
8750 	          }
8751 
8752 	          // expected "="
8753 	          if (w === 61) { // "=" == 61
8754 	            break;
8755 	          }
8756 
8757 	          handleWarning('illegal attribute name char');
8758 	          skipAttr = true;
8759 	        }
8760 
8761 	        name = s.substring(i, j);
8762 
8763 	        if (name === 'xmlns:xmlns') {
8764 	          handleWarning('illegal declaration of xmlns');
8765 	          skipAttr = true;
8766 	        }
8767 
8768 	        w = s.charCodeAt(j + 1);
8769 
8770 	        if (w === 34) { // '"'
8771 	          j = s.indexOf('"', i = j + 2);
8772 
8773 	          if (j === -1) {
8774 	            j = s.indexOf('\'', i);
8775 
8776 	            if (j !== -1) {
8777 	              handleWarning('attribute value quote missmatch');
8778 	              skipAttr = true;
8779 	            }
8780 	          }
8781 
8782 	        } else if (w === 39) { // "'"
8783 	          j = s.indexOf('\'', i = j + 2);
8784 
8785 	          if (j === -1) {
8786 	            j = s.indexOf('"', i);
8787 
8788 	            if (j !== -1) {
8789 	              handleWarning('attribute value quote missmatch');
8790 	              skipAttr = true;
8791 	            }
8792 	          }
8793 
8794 	        } else {
8795 	          handleWarning('missing attribute value quotes');
8796 	          skipAttr = true;
8797 
8798 	          // skip to next space
8799 	          for (j = j + 1; j < l; j++) {
8800 	            w = s.charCodeAt(j + 1);
8801 
8802 	            if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
8803 	              break;
8804 	            }
8805 	          }
8806 
8807 	        }
8808 
8809 	        if (j === -1) {
8810 	          handleWarning('missing closing quotes');
8811 
8812 	          j = l;
8813 	          skipAttr = true;
8814 	        }
8815 
8816 	        if (!skipAttr) {
8817 	          value = s.substring(i, j);
8818 	        }
8819 
8820 	        i = j;
8821 
8822 	        // ensure SPACE follows attribute
8823 	        // skip illegal content otherwise
8824 	        // example a="b"c
8825 	        for (; j + 1 < l; j++) {
8826 	          w = s.charCodeAt(j + 1);
8827 
8828 	          if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
8829 	            break;
8830 	          }
8831 
8832 	          // FIRST ILLEGAL CHAR
8833 	          if (i === j) {
8834 	            handleWarning('illegal character after attribute end');
8835 	            skipAttr = true;
8836 	          }
8837 	        }
8838 
8839 	        // advance cursor to next attribute
8840 	        i = j + 1;
8841 
8842 	        if (skipAttr) {
8843 	          continue parseAttr;
8844 	        }
8845 
8846 	        // check attribute re-declaration
8847 	        if (name in seenAttrs) {
8848 	          handleWarning('attribute <' + name + '> already defined');
8849 	          continue;
8850 	        }
8851 
8852 	        seenAttrs[name] = true;
8853 
8854 	        if (!isNamespace) {
8855 	          attrs[name] = value;
8856 	          continue;
8857 	        }
8858 
8859 	        // try to extract namespace information
8860 	        if (maybeNS) {
8861 	          newalias = (
8862 	            name === 'xmlns'
8863 	              ? 'xmlns'
8864 	              : (name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:')
8865 	                ? name.substr(6)
8866 	                : null
8867 	          );
8868 
8869 	          // handle xmlns(:alias) assignment
8870 	          if (newalias !== null) {
8871 	            nsUri = decodeEntities(value);
8872 	            nsUriPrefix = uriPrefix(newalias);
8873 
8874 	            alias = nsUriToPrefix[nsUri];
8875 
8876 	            if (!alias) {
8877 
8878 	              // no prefix defined or prefix collision
8879 	              if (
8880 	                (newalias === 'xmlns') ||
8881 	                (nsUriPrefix in nsMatrix && nsMatrix[nsUriPrefix] !== nsUri)
8882 	              ) {
8883 
8884 	                // alocate free ns prefix
8885 	                do {
8886 	                  alias = 'ns' + (anonymousNsCount++);
8887 	                } while (typeof nsMatrix[alias] !== 'undefined');
8888 	              } else {
8889 	                alias = newalias;
8890 	              }
8891 
8892 	              nsUriToPrefix[nsUri] = alias;
8893 	            }
8894 
8895 	            if (nsMatrix[newalias] !== alias) {
8896 	              if (!hasNewMatrix) {
8897 	                nsMatrix = cloneNsMatrix(nsMatrix);
8898 	                hasNewMatrix = true;
8899 	              }
8900 
8901 	              nsMatrix[newalias] = alias;
8902 	              if (newalias === 'xmlns') {
8903 	                nsMatrix[uriPrefix(alias)] = nsUri;
8904 	                defaultAlias = alias;
8905 	              }
8906 
8907 	              nsMatrix[nsUriPrefix] = nsUri;
8908 	            }
8909 
8910 	            // expose xmlns(:asd)="..." in attributes
8911 	            attrs[name] = value;
8912 	            continue;
8913 	          }
8914 
8915 	          // collect attributes until all namespace
8916 	          // declarations are processed
8917 	          attrList.push(name, value);
8918 	          continue;
8919 
8920 	        } /** end if (maybeNs) */
8921 
8922 	        // handle attributes on element without
8923 	        // namespace declarations
8924 	        w = name.indexOf(':');
8925 	        if (w === -1) {
8926 	          attrs[name] = value;
8927 	          continue;
8928 	        }
8929 
8930 	        // normalize ns attribute name
8931 	        if (!(nsName = nsMatrix[name.substring(0, w)])) {
8932 	          handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
8933 	          continue;
8934 	        }
8935 
8936 	        name = defaultAlias === nsName
8937 	          ? name.substr(w + 1)
8938 	          : nsName + name.substr(w);
8939 
8940 	        // end: normalize ns attribute name
8941 
8942 	        // normalize xsi:type ns attribute value
8943 	        if (name === XSI_TYPE$1) {
8944 	          w = value.indexOf(':');
8945 
8946 	          if (w !== -1) {
8947 	            nsName = value.substring(0, w);
8948 
8949 	            // handle default prefixes, i.e. xs:String gracefully
8950 	            nsName = nsMatrix[nsName] || nsName;
8951 	            value = nsName + value.substring(w);
8952 	          } else {
8953 	            value = defaultAlias + ':' + value;
8954 	          }
8955 	        }
8956 
8957 	        // end: normalize xsi:type ns attribute value
8958 
8959 	        attrs[name] = value;
8960 	      }
8961 
8962 
8963 	      // handle deferred, possibly namespaced attributes
8964 	      if (maybeNS) {
8965 
8966 	        // normalize captured attributes
8967 	        for (i = 0, l = attrList.length; i < l; i++) {
8968 
8969 	          name = attrList[i++];
8970 	          value = attrList[i];
8971 
8972 	          w = name.indexOf(':');
8973 
8974 	          if (w !== -1) {
8975 
8976 	            // normalize ns attribute name
8977 	            if (!(nsName = nsMatrix[name.substring(0, w)])) {
8978 	              handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
8979 	              continue;
8980 	            }
8981 
8982 	            name = defaultAlias === nsName
8983 	              ? name.substr(w + 1)
8984 	              : nsName + name.substr(w);
8985 
8986 	            // end: normalize ns attribute name
8987 
8988 	            // normalize xsi:type ns attribute value
8989 	            if (name === XSI_TYPE$1) {
8990 	              w = value.indexOf(':');
8991 
8992 	              if (w !== -1) {
8993 	                nsName = value.substring(0, w);
8994 
8995 	                // handle default prefixes, i.e. xs:String gracefully
8996 	                nsName = nsMatrix[nsName] || nsName;
8997 	                value = nsName + value.substring(w);
8998 	              } else {
8999 	                value = defaultAlias + ':' + value;
9000 	              }
9001 	            }
9002 
9003 	            // end: normalize xsi:type ns attribute value
9004 	          }
9005 
9006 	          attrs[name] = value;
9007 	        }
9008 
9009 	        // end: normalize captured attributes
9010 	      }
9011 
9012 	      return cachedAttrs = attrs;
9013 	    }
9014 
9015 	    /**
9016 	     * Extract the parse context { line, column, part }
9017 	     * from the current parser position.
9018 	     *
9019 	     * @return {Object} parse context
9020 	     */
9021 	    function getParseContext() {
9022 	      var splitsRe = /(\r\n|\r|\n)/g;
9023 
9024 	      var line = 0;
9025 	      var column = 0;
9026 	      var startOfLine = 0;
9027 	      var endOfLine = j;
9028 	      var match;
9029 	      var data;
9030 
9031 	      while (i >= startOfLine) {
9032 
9033 	        match = splitsRe.exec(xml);
9034 
9035 	        if (!match) {
9036 	          break;
9037 	        }
9038 
9039 	        // end of line = (break idx + break chars)
9040 	        endOfLine = match[0].length + match.index;
9041 
9042 	        if (endOfLine > i) {
9043 	          break;
9044 	        }
9045 
9046 	        // advance to next line
9047 	        line += 1;
9048 
9049 	        startOfLine = endOfLine;
9050 	      }
9051 
9052 	      // EOF errors
9053 	      if (i == -1) {
9054 	        column = endOfLine;
9055 	        data = xml.substring(j);
9056 	      } else
9057 
9058 	      // start errors
9059 	      if (j === 0) {
9060 	        data = xml.substring(j, i);
9061 	      }
9062 
9063 	      // other errors
9064 	      else {
9065 	        column = i - startOfLine;
9066 	        data = (j == -1 ? xml.substring(i) : xml.substring(i, j + 1));
9067 	      }
9068 
9069 	      return {
9070 	        'data': data,
9071 	        'line': line,
9072 	        'column': column
9073 	      };
9074 	    }
9075 
9076 	    getContext = getParseContext;
9077 
9078 
9079 	    if (proxy) {
9080 	      elementProxy = Object.create({}, {
9081 	        'name': getter(function() {
9082 	          return elementName;
9083 	        }),
9084 	        'originalName': getter(function() {
9085 	          return _elementName;
9086 	        }),
9087 	        'attrs': getter(getAttrs),
9088 	        'ns': getter(function() {
9089 	          return nsMatrix;
9090 	        })
9091 	      });
9092 	    }
9093 
9094 	    // actual parse logic
9095 	    while (j !== -1) {
9096 
9097 	      if (xml.charCodeAt(j) === 60) { // "<"
9098 	        i = j;
9099 	      } else {
9100 	        i = xml.indexOf('<', j);
9101 	      }
9102 
9103 	      // parse end
9104 	      if (i === -1) {
9105 	        if (nodeStack.length) {
9106 	          return handleError('unexpected end of file');
9107 	        }
9108 
9109 	        if (j === 0) {
9110 	          return handleError('missing start tag');
9111 	        }
9112 
9113 	        if (j < xml.length) {
9114 	          if (xml.substring(j).trim()) {
9115 	            handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
9116 	          }
9117 	        }
9118 
9119 	        return;
9120 	      }
9121 
9122 	      // parse text
9123 	      if (j !== i) {
9124 
9125 	        if (nodeStack.length) {
9126 	          if (onText) {
9127 	            onText(xml.substring(j, i), decodeEntities, getContext);
9128 
9129 	            if (parseStop) {
9130 	              return;
9131 	            }
9132 	          }
9133 	        } else {
9134 	          if (xml.substring(j, i).trim()) {
9135 	            handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
9136 
9137 	            if (parseStop) {
9138 	              return;
9139 	            }
9140 	          }
9141 	        }
9142 	      }
9143 
9144 	      w = xml.charCodeAt(i+1);
9145 
9146 	      // parse comments + CDATA
9147 	      if (w === 33) { // "!"
9148 	        q = xml.charCodeAt(i+2);
9149 
9150 	        // CDATA section
9151 	        if (q === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
9152 	          j = xml.indexOf(']]>', i);
9153 	          if (j === -1) {
9154 	            return handleError('unclosed cdata');
9155 	          }
9156 
9157 	          if (onCDATA) {
9158 	            onCDATA(xml.substring(i + 9, j), getContext);
9159 	            if (parseStop) {
9160 	              return;
9161 	            }
9162 	          }
9163 
9164 	          j += 3;
9165 	          continue;
9166 	        }
9167 
9168 	        // comment
9169 	        if (q === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
9170 	          j = xml.indexOf('-->', i);
9171 	          if (j === -1) {
9172 	            return handleError('unclosed comment');
9173 	          }
9174 
9175 
9176 	          if (onComment) {
9177 	            onComment(xml.substring(i + 4, j), decodeEntities, getContext);
9178 	            if (parseStop) {
9179 	              return;
9180 	            }
9181 	          }
9182 
9183 	          j += 3;
9184 	          continue;
9185 	        }
9186 	      }
9187 
9188 	      // parse question <? ... ?>
9189 	      if (w === 63) { // "?"
9190 	        j = xml.indexOf('?>', i);
9191 	        if (j === -1) {
9192 	          return handleError('unclosed question');
9193 	        }
9194 
9195 	        if (onQuestion) {
9196 	          onQuestion(xml.substring(i, j + 2), getContext);
9197 	          if (parseStop) {
9198 	            return;
9199 	          }
9200 	        }
9201 
9202 	        j += 2;
9203 	        continue;
9204 	      }
9205 
9206 	      // find matching closing tag for attention or standard tags
9207 	      // for that we must skip through attribute values
9208 	      // (enclosed in single or double quotes)
9209 	      for (x = i + 1; ; x++) {
9210 	        v = xml.charCodeAt(x);
9211 	        if (isNaN(v)) {
9212 	          j = -1;
9213 	          return handleError('unclosed tag');
9214 	        }
9215 
9216 	        // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
9217 	        // skips the quoted string
9218 	        // (double quotes) does not appear in a literal enclosed by (double quotes)
9219 	        // (single quote) does not appear in a literal enclosed by (single quote)
9220 	        if (v === 34) { //  '"'
9221 	          q = xml.indexOf('"', x + 1);
9222 	          x = q !== -1 ? q : x;
9223 	        } else if (v === 39) { // "'"
9224 	          q = xml.indexOf("'", x + 1);
9225 	          x = q !== -1 ? q : x;
9226 	        } else if (v === 62) { // '>'
9227 	          j = x;
9228 	          break;
9229 	        }
9230 	      }
9231 
9232 
9233 	      // parse attention <! ...>
9234 	      // previously comment and CDATA have already been parsed
9235 	      if (w === 33) { // "!"
9236 
9237 	        if (onAttention) {
9238 	          onAttention(xml.substring(i, j + 1), decodeEntities, getContext);
9239 	          if (parseStop) {
9240 	            return;
9241 	          }
9242 	        }
9243 
9244 	        j += 1;
9245 	        continue;
9246 	      }
9247 
9248 	      // don't process attributes;
9249 	      // there are none
9250 	      cachedAttrs = {};
9251 
9252 	      // if (xml.charCodeAt(i+1) === 47) { // </...
9253 	      if (w === 47) { // </...
9254 	        tagStart = false;
9255 	        tagEnd = true;
9256 
9257 	        if (!nodeStack.length) {
9258 	          return handleError('missing open tag');
9259 	        }
9260 
9261 	        // verify open <-> close tag match
9262 	        x = elementName = nodeStack.pop();
9263 	        q = i + 2 + x.length;
9264 
9265 	        if (xml.substring(i + 2, q) !== x) {
9266 	          return handleError('closing tag mismatch');
9267 	        }
9268 
9269 	        // verify chars in close tag
9270 	        for (; q < j; q++) {
9271 	          w = xml.charCodeAt(q);
9272 
9273 	          if (w === 32 || (w > 8 && w < 14)) { // \f\n\r\t\v space
9274 	            continue;
9275 	          }
9276 
9277 	          return handleError('close tag');
9278 	        }
9279 
9280 	      } else {
9281 	        if (xml.charCodeAt(j - 1) === 47) { // .../>
9282 	          x = elementName = xml.substring(i + 1, j - 1);
9283 
9284 	          tagStart = true;
9285 	          tagEnd = true;
9286 
9287 	        } else {
9288 	          x = elementName = xml.substring(i + 1, j);
9289 
9290 	          tagStart = true;
9291 	          tagEnd = false;
9292 	        }
9293 
9294 	        if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) { // char 95"_" 58":"
9295 	          return handleError('illegal first char nodeName');
9296 	        }
9297 
9298 	        for (q = 1, y = x.length; q < y; q++) {
9299 	          w = x.charCodeAt(q);
9300 
9301 	          if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w == 46) {
9302 	            continue;
9303 	          }
9304 
9305 	          if (w === 32 || (w < 14 && w > 8)) { // \f\n\r\t\v space
9306 	            elementName = x.substring(0, q);
9307 
9308 	            // maybe there are attributes
9309 	            cachedAttrs = null;
9310 	            break;
9311 	          }
9312 
9313 	          return handleError('invalid nodeName');
9314 	        }
9315 
9316 	        if (!tagEnd) {
9317 	          nodeStack.push(elementName);
9318 	        }
9319 	      }
9320 
9321 	      if (isNamespace) {
9322 
9323 	        _nsMatrix = nsMatrix;
9324 
9325 	        if (tagStart) {
9326 
9327 	          // remember old namespace
9328 	          // unless we're self-closing
9329 	          if (!tagEnd) {
9330 	            nsMatrixStack.push(_nsMatrix);
9331 	          }
9332 
9333 	          if (cachedAttrs === null) {
9334 
9335 	            // quick check, whether there may be namespace
9336 	            // declarations on the node; if that is the case
9337 	            // we need to eagerly parse the node attributes
9338 	            if ((maybeNS = x.indexOf('xmlns', q) !== -1)) {
9339 	              attrsStart = q;
9340 	              attrsString = x;
9341 
9342 	              getAttrs();
9343 
9344 	              maybeNS = false;
9345 	            }
9346 	          }
9347 	        }
9348 
9349 	        _elementName = elementName;
9350 
9351 	        w = elementName.indexOf(':');
9352 	        if (w !== -1) {
9353 	          xmlns = nsMatrix[elementName.substring(0, w)];
9354 
9355 	          // prefix given; namespace must exist
9356 	          if (!xmlns) {
9357 	            return handleError('missing namespace on <' + _elementName + '>');
9358 	          }
9359 
9360 	          elementName = elementName.substr(w + 1);
9361 	        } else {
9362 	          xmlns = nsMatrix['xmlns'];
9363 
9364 	          // if no default namespace is defined,
9365 	          // we'll import the element as anonymous.
9366 	          //
9367 	          // it is up to users to correct that to the document defined
9368 	          // targetNamespace, or whatever their undersanding of the
9369 	          // XML spec mandates.
9370 	        }
9371 
9372 	        // adjust namespace prefixs as configured
9373 	        if (xmlns) {
9374 	          elementName = xmlns + ':' + elementName;
9375 	        }
9376 
9377 	      }
9378 
9379 	      if (tagStart) {
9380 	        attrsStart = q;
9381 	        attrsString = x;
9382 
9383 	        if (onOpenTag) {
9384 	          if (proxy) {
9385 	            onOpenTag(elementProxy, decodeEntities, tagEnd, getContext);
9386 	          } else {
9387 	            onOpenTag(elementName, getAttrs, decodeEntities, tagEnd, getContext);
9388 	          }
9389 
9390 	          if (parseStop) {
9391 	            return;
9392 	          }
9393 	        }
9394 
9395 	      }
9396 
9397 	      if (tagEnd) {
9398 
9399 	        if (onCloseTag) {
9400 	          onCloseTag(proxy ? elementProxy : elementName, decodeEntities, tagStart, getContext);
9401 
9402 	          if (parseStop) {
9403 	            return;
9404 	          }
9405 	        }
9406 
9407 	        // restore old namespace
9408 	        if (isNamespace) {
9409 	          if (!tagStart) {
9410 	            nsMatrix = nsMatrixStack.pop();
9411 	          } else {
9412 	            nsMatrix = _nsMatrix;
9413 	          }
9414 	        }
9415 	      }
9416 
9417 	      j += 1;
9418 	    }
9419 	  } /** end parse */
9420 
9421 	}
9422 
9423 	function hasLowerCaseAlias(pkg) {
9424 	  return pkg.xml && pkg.xml.tagAlias === 'lowerCase';
9425 	}
9426 
9427 	var DEFAULT_NS_MAP = {
9428 	  'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
9429 	  'xml': 'http://www.w3.org/XML/1998/namespace'
9430 	};
9431 
9432 	var XSI_TYPE = 'xsi:type';
9433 
9434 	function serializeFormat(element) {
9435 	  return element.xml && element.xml.serialize;
9436 	}
9437 
9438 	function serializeAsType(element) {
9439 	  return serializeFormat(element) === XSI_TYPE;
9440 	}
9441 
9442 	function serializeAsProperty(element) {
9443 	  return serializeFormat(element) === 'property';
9444 	}
9445 
9446 	function capitalize(str) {
9447 	  return str.charAt(0).toUpperCase() + str.slice(1);
9448 	}
9449 
9450 	function aliasToName(aliasNs, pkg) {
9451 
9452 	  if (!hasLowerCaseAlias(pkg)) {
9453 	    return aliasNs.name;
9454 	  }
9455 
9456 	  return aliasNs.prefix + ':' + capitalize(aliasNs.localName);
9457 	}
9458 
9459 	function prefixedToName(nameNs, pkg) {
9460 
9461 	  var name = nameNs.name,
9462 	      localName = nameNs.localName;
9463 
9464 	  var typePrefix = pkg.xml && pkg.xml.typePrefix;
9465 
9466 	  if (typePrefix && localName.indexOf(typePrefix) === 0) {
9467 	    return nameNs.prefix + ':' + localName.slice(typePrefix.length);
9468 	  } else {
9469 	    return name;
9470 	  }
9471 	}
9472 
9473 	function normalizeXsiTypeName(name, model) {
9474 
9475 	  var nameNs = parseName(name);
9476 	  var pkg = model.getPackage(nameNs.prefix);
9477 
9478 	  return prefixedToName(nameNs, pkg);
9479 	}
9480 
9481 	function error$1(message) {
9482 	  return new Error(message);
9483 	}
9484 
9485 	/**
9486 	 * Get the moddle descriptor for a given instance or type.
9487 	 *
9488 	 * @param  {ModdleElement|Function} element
9489 	 *
9490 	 * @return {Object} the moddle descriptor
9491 	 */
9492 	function getModdleDescriptor(element) {
9493 	  return element.$descriptor;
9494 	}
9495 
9496 
9497 	/**
9498 	 * A parse context.
9499 	 *
9500 	 * @class
9501 	 *
9502 	 * @param {Object} options
9503 	 * @param {ElementHandler} options.rootHandler the root handler for parsing a document
9504 	 * @param {boolean} [options.lax=false] whether or not to ignore invalid elements
9505 	 */
9506 	function Context(options) {
9507 
9508 	  /**
9509 	   * @property {ElementHandler} rootHandler
9510 	   */
9511 
9512 	  /**
9513 	   * @property {Boolean} lax
9514 	   */
9515 
9516 	  assign(this, options);
9517 
9518 	  this.elementsById = {};
9519 	  this.references = [];
9520 	  this.warnings = [];
9521 
9522 	  /**
9523 	   * Add an unresolved reference.
9524 	   *
9525 	   * @param {Object} reference
9526 	   */
9527 	  this.addReference = function(reference) {
9528 	    this.references.push(reference);
9529 	  };
9530 
9531 	  /**
9532 	   * Add a processed element.
9533 	   *
9534 	   * @param {ModdleElement} element
9535 	   */
9536 	  this.addElement = function(element) {
9537 
9538 	    if (!element) {
9539 	      throw error$1('expected element');
9540 	    }
9541 
9542 	    var elementsById = this.elementsById;
9543 
9544 	    var descriptor = getModdleDescriptor(element);
9545 
9546 	    var idProperty = descriptor.idProperty,
9547 	        id;
9548 
9549 	    if (idProperty) {
9550 	      id = element.get(idProperty.name);
9551 
9552 	      if (id) {
9553 
9554 	        // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
9555 	        if (!/^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i.test(id)) {
9556 	          throw new Error('illegal ID <' + id + '>');
9557 	        }
9558 
9559 	        if (elementsById[id]) {
9560 	          throw error$1('duplicate ID <' + id + '>');
9561 	        }
9562 
9563 	        elementsById[id] = element;
9564 	      }
9565 	    }
9566 	  };
9567 
9568 	  /**
9569 	   * Add an import warning.
9570 	   *
9571 	   * @param {Object} warning
9572 	   * @param {String} warning.message
9573 	   * @param {Error} [warning.error]
9574 	   */
9575 	  this.addWarning = function(warning) {
9576 	    this.warnings.push(warning);
9577 	  };
9578 	}
9579 
9580 	function BaseHandler() {}
9581 
9582 	BaseHandler.prototype.handleEnd = function() {};
9583 	BaseHandler.prototype.handleText = function() {};
9584 	BaseHandler.prototype.handleNode = function() {};
9585 
9586 
9587 	/**
9588 	 * A simple pass through handler that does nothing except for
9589 	 * ignoring all input it receives.
9590 	 *
9591 	 * This is used to ignore unknown elements and
9592 	 * attributes.
9593 	 */
9594 	function NoopHandler() { }
9595 
9596 	NoopHandler.prototype = Object.create(BaseHandler.prototype);
9597 
9598 	NoopHandler.prototype.handleNode = function() {
9599 	  return this;
9600 	};
9601 
9602 	function BodyHandler() {}
9603 
9604 	BodyHandler.prototype = Object.create(BaseHandler.prototype);
9605 
9606 	BodyHandler.prototype.handleText = function(text) {
9607 	  this.body = (this.body || '') + text;
9608 	};
9609 
9610 	function ReferenceHandler(property, context) {
9611 	  this.property = property;
9612 	  this.context = context;
9613 	}
9614 
9615 	ReferenceHandler.prototype = Object.create(BodyHandler.prototype);
9616 
9617 	ReferenceHandler.prototype.handleNode = function(node) {
9618 
9619 	  if (this.element) {
9620 	    throw error$1('expected no sub nodes');
9621 	  } else {
9622 	    this.element = this.createReference(node);
9623 	  }
9624 
9625 	  return this;
9626 	};
9627 
9628 	ReferenceHandler.prototype.handleEnd = function() {
9629 	  this.element.id = this.body;
9630 	};
9631 
9632 	ReferenceHandler.prototype.createReference = function(node) {
9633 	  return {
9634 	    property: this.property.ns.name,
9635 	    id: ''
9636 	  };
9637 	};
9638 
9639 	function ValueHandler(propertyDesc, element) {
9640 	  this.element = element;
9641 	  this.propertyDesc = propertyDesc;
9642 	}
9643 
9644 	ValueHandler.prototype = Object.create(BodyHandler.prototype);
9645 
9646 	ValueHandler.prototype.handleEnd = function() {
9647 
9648 	  var value = this.body || '',
9649 	      element = this.element,
9650 	      propertyDesc = this.propertyDesc;
9651 
9652 	  value = coerceType(propertyDesc.type, value);
9653 
9654 	  if (propertyDesc.isMany) {
9655 	    element.get(propertyDesc.name).push(value);
9656 	  } else {
9657 	    element.set(propertyDesc.name, value);
9658 	  }
9659 	};
9660 
9661 
9662 	function BaseElementHandler() {}
9663 
9664 	BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
9665 
9666 	BaseElementHandler.prototype.handleNode = function(node) {
9667 	  var parser = this,
9668 	      element = this.element;
9669 
9670 	  if (!element) {
9671 	    element = this.element = this.createElement(node);
9672 
9673 	    this.context.addElement(element);
9674 	  } else {
9675 	    parser = this.handleChild(node);
9676 	  }
9677 
9678 	  return parser;
9679 	};
9680 
9681 	/**
9682 	 * @class Reader.ElementHandler
9683 	 *
9684 	 */
9685 	function ElementHandler(model, typeName, context) {
9686 	  this.model = model;
9687 	  this.type = model.getType(typeName);
9688 	  this.context = context;
9689 	}
9690 
9691 	ElementHandler.prototype = Object.create(BaseElementHandler.prototype);
9692 
9693 	ElementHandler.prototype.addReference = function(reference) {
9694 	  this.context.addReference(reference);
9695 	};
9696 
9697 	ElementHandler.prototype.handleText = function(text) {
9698 
9699 	  var element = this.element,
9700 	      descriptor = getModdleDescriptor(element),
9701 	      bodyProperty = descriptor.bodyProperty;
9702 
9703 	  if (!bodyProperty) {
9704 	    throw error$1('unexpected body text <' + text + '>');
9705 	  }
9706 
9707 	  BodyHandler.prototype.handleText.call(this, text);
9708 	};
9709 
9710 	ElementHandler.prototype.handleEnd = function() {
9711 
9712 	  var value = this.body,
9713 	      element = this.element,
9714 	      descriptor = getModdleDescriptor(element),
9715 	      bodyProperty = descriptor.bodyProperty;
9716 
9717 	  if (bodyProperty && value !== undefined) {
9718 	    value = coerceType(bodyProperty.type, value);
9719 	    element.set(bodyProperty.name, value);
9720 	  }
9721 	};
9722 
9723 	/**
9724 	 * Create an instance of the model from the given node.
9725 	 *
9726 	 * @param  {Element} node the xml node
9727 	 */
9728 	ElementHandler.prototype.createElement = function(node) {
9729 	  var attributes = node.attributes,
9730 	      Type = this.type,
9731 	      descriptor = getModdleDescriptor(Type),
9732 	      context = this.context,
9733 	      instance = new Type({}),
9734 	      model = this.model,
9735 	      propNameNs;
9736 
9737 	  forEach(attributes, function(value, name) {
9738 
9739 	    var prop = descriptor.propertiesByName[name],
9740 	        values;
9741 
9742 	    if (prop && prop.isReference) {
9743 
9744 	      if (!prop.isMany) {
9745 	        context.addReference({
9746 	          element: instance,
9747 	          property: prop.ns.name,
9748 	          id: value
9749 	        });
9750 	      } else {
9751 
9752 	        // IDREFS: parse references as whitespace-separated list
9753 	        values = value.split(' ');
9754 
9755 	        forEach(values, function(v) {
9756 	          context.addReference({
9757 	            element: instance,
9758 	            property: prop.ns.name,
9759 	            id: v
9760 	          });
9761 	        });
9762 	      }
9763 
9764 	    } else {
9765 	      if (prop) {
9766 	        value = coerceType(prop.type, value);
9767 	      } else
9768 	      if (name !== 'xmlns') {
9769 	        propNameNs = parseName(name, descriptor.ns.prefix);
9770 
9771 	        // check whether attribute is defined in a well-known namespace
9772 	        // if that is the case we emit a warning to indicate potential misuse
9773 	        if (model.getPackage(propNameNs.prefix)) {
9774 
9775 	          context.addWarning({
9776 	            message: 'unknown attribute <' + name + '>',
9777 	            element: instance,
9778 	            property: name,
9779 	            value: value
9780 	          });
9781 	        }
9782 	      }
9783 
9784 	      instance.set(name, value);
9785 	    }
9786 	  });
9787 
9788 	  return instance;
9789 	};
9790 
9791 	ElementHandler.prototype.getPropertyForNode = function(node) {
9792 
9793 	  var name = node.name;
9794 	  var nameNs = parseName(name);
9795 
9796 	  var type = this.type,
9797 	      model = this.model,
9798 	      descriptor = getModdleDescriptor(type);
9799 
9800 	  var propertyName = nameNs.name,
9801 	      property = descriptor.propertiesByName[propertyName],
9802 	      elementTypeName,
9803 	      elementType;
9804 
9805 	  // search for properties by name first
9806 
9807 	  if (property && !property.isAttr) {
9808 
9809 	    if (serializeAsType(property)) {
9810 	      elementTypeName = node.attributes[XSI_TYPE];
9811 
9812 	      // xsi type is optional, if it does not exists the
9813 	      // default type is assumed
9814 	      if (elementTypeName) {
9815 
9816 	        // take possible type prefixes from XML
9817 	        // into account, i.e.: xsi:type="t{ActualType}"
9818 	        elementTypeName = normalizeXsiTypeName(elementTypeName, model);
9819 
9820 	        elementType = model.getType(elementTypeName);
9821 
9822 	        return assign({}, property, {
9823 	          effectiveType: getModdleDescriptor(elementType).name
9824 	        });
9825 	      }
9826 	    }
9827 
9828 	    // search for properties by name first
9829 	    return property;
9830 	  }
9831 
9832 	  var pkg = model.getPackage(nameNs.prefix);
9833 
9834 	  if (pkg) {
9835 	    elementTypeName = aliasToName(nameNs, pkg);
9836 	    elementType = model.getType(elementTypeName);
9837 
9838 	    // search for collection members later
9839 	    property = find(descriptor.properties, function(p) {
9840 	      return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
9841 	    });
9842 
9843 	    if (property) {
9844 	      return assign({}, property, {
9845 	        effectiveType: getModdleDescriptor(elementType).name
9846 	      });
9847 	    }
9848 	  } else {
9849 
9850 	    // parse unknown element (maybe extension)
9851 	    property = find(descriptor.properties, function(p) {
9852 	      return !p.isReference && !p.isAttribute && p.type === 'Element';
9853 	    });
9854 
9855 	    if (property) {
9856 	      return property;
9857 	    }
9858 	  }
9859 
9860 	  throw error$1('unrecognized element <' + nameNs.name + '>');
9861 	};
9862 
9863 	ElementHandler.prototype.toString = function() {
9864 	  return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';
9865 	};
9866 
9867 	ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
9868 	  return new ValueHandler(propertyDesc, element);
9869 	};
9870 
9871 	ElementHandler.prototype.referenceHandler = function(propertyDesc) {
9872 	  return new ReferenceHandler(propertyDesc, this.context);
9873 	};
9874 
9875 	ElementHandler.prototype.handler = function(type) {
9876 	  if (type === 'Element') {
9877 	    return new GenericElementHandler(this.model, type, this.context);
9878 	  } else {
9879 	    return new ElementHandler(this.model, type, this.context);
9880 	  }
9881 	};
9882 
9883 	/**
9884 	 * Handle the child element parsing
9885 	 *
9886 	 * @param  {Element} node the xml node
9887 	 */
9888 	ElementHandler.prototype.handleChild = function(node) {
9889 	  var propertyDesc, type, element, childHandler;
9890 
9891 	  propertyDesc = this.getPropertyForNode(node);
9892 	  element = this.element;
9893 
9894 	  type = propertyDesc.effectiveType || propertyDesc.type;
9895 
9896 	  if (isSimple(type)) {
9897 	    return this.valueHandler(propertyDesc, element);
9898 	  }
9899 
9900 	  if (propertyDesc.isReference) {
9901 	    childHandler = this.referenceHandler(propertyDesc).handleNode(node);
9902 	  } else {
9903 	    childHandler = this.handler(type).handleNode(node);
9904 	  }
9905 
9906 	  var newElement = childHandler.element;
9907 
9908 	  // child handles may decide to skip elements
9909 	  // by not returning anything
9910 	  if (newElement !== undefined) {
9911 
9912 	    if (propertyDesc.isMany) {
9913 	      element.get(propertyDesc.name).push(newElement);
9914 	    } else {
9915 	      element.set(propertyDesc.name, newElement);
9916 	    }
9917 
9918 	    if (propertyDesc.isReference) {
9919 	      assign(newElement, {
9920 	        element: element
9921 	      });
9922 
9923 	      this.context.addReference(newElement);
9924 	    } else {
9925 
9926 	      // establish child -> parent relationship
9927 	      newElement.$parent = element;
9928 	    }
9929 	  }
9930 
9931 	  return childHandler;
9932 	};
9933 
9934 	/**
9935 	 * An element handler that performs special validation
9936 	 * to ensure the node it gets initialized with matches
9937 	 * the handlers type (namespace wise).
9938 	 *
9939 	 * @param {Moddle} model
9940 	 * @param {String} typeName
9941 	 * @param {Context} context
9942 	 */
9943 	function RootElementHandler(model, typeName, context) {
9944 	  ElementHandler.call(this, model, typeName, context);
9945 	}
9946 
9947 	RootElementHandler.prototype = Object.create(ElementHandler.prototype);
9948 
9949 	RootElementHandler.prototype.createElement = function(node) {
9950 
9951 	  var name = node.name,
9952 	      nameNs = parseName(name),
9953 	      model = this.model,
9954 	      type = this.type,
9955 	      pkg = model.getPackage(nameNs.prefix),
9956 	      typeName = pkg && aliasToName(nameNs, pkg) || name;
9957 
9958 	  // verify the correct namespace if we parse
9959 	  // the first element in the handler tree
9960 	  //
9961 	  // this ensures we don't mistakenly import wrong namespace elements
9962 	  if (!type.hasType(typeName)) {
9963 	    throw error$1('unexpected element <' + node.originalName + '>');
9964 	  }
9965 
9966 	  return ElementHandler.prototype.createElement.call(this, node);
9967 	};
9968 
9969 
9970 	function GenericElementHandler(model, typeName, context) {
9971 	  this.model = model;
9972 	  this.context = context;
9973 	}
9974 
9975 	GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
9976 
9977 	GenericElementHandler.prototype.createElement = function(node) {
9978 
9979 	  var name = node.name,
9980 	      ns = parseName(name),
9981 	      prefix = ns.prefix,
9982 	      uri = node.ns[prefix + '$uri'],
9983 	      attributes = node.attributes;
9984 
9985 	  return this.model.createAny(name, uri, attributes);
9986 	};
9987 
9988 	GenericElementHandler.prototype.handleChild = function(node) {
9989 
9990 	  var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
9991 	      element = this.element;
9992 
9993 	  var newElement = handler.element,
9994 	      children;
9995 
9996 	  if (newElement !== undefined) {
9997 	    children = element.$children = element.$children || [];
9998 	    children.push(newElement);
9999 
10000 	    // establish child -> parent relationship
10001 	    newElement.$parent = element;
10002 	  }
10003 
10004 	  return handler;
10005 	};
10006 
10007 	GenericElementHandler.prototype.handleEnd = function() {
10008 	  if (this.body) {
10009 	    this.element.$body = this.body;
10010 	  }
10011 	};
10012 
10013 	/**
10014 	 * A reader for a meta-model
10015 	 *
10016 	 * @param {Object} options
10017 	 * @param {Model} options.model used to read xml files
10018 	 * @param {Boolean} options.lax whether to make parse errors warnings
10019 	 */
10020 	function Reader(options) {
10021 
10022 	  if (options instanceof Moddle) {
10023 	    options = {
10024 	      model: options
10025 	    };
10026 	  }
10027 
10028 	  assign(this, { lax: false }, options);
10029 	}
10030 
10031 	/**
10032 	 * The fromXML result.
10033 	 *
10034 	 * @typedef {Object} ParseResult
10035 	 *
10036 	 * @property {ModdleElement} rootElement
10037 	 * @property {Array<Object>} references
10038 	 * @property {Array<Error>} warnings
10039 	 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
10040 	 */
10041 
10042 	/**
10043 	 * The fromXML result.
10044 	 *
10045 	 * @typedef {Error} ParseError
10046 	 *
10047 	 * @property {Array<Error>} warnings
10048 	 */
10049 
10050 	/**
10051 	 * Parse the given XML into a moddle document tree.
10052 	 *
10053 	 * @param {String} xml
10054 	 * @param {ElementHandler|Object} options or rootHandler
10055 	 *
10056 	 * @returns {Promise<ParseResult, ParseError>}
10057 	 */
10058 	Reader.prototype.fromXML = function(xml, options, done) {
10059 
10060 	  var rootHandler = options.rootHandler;
10061 
10062 	  if (options instanceof ElementHandler) {
10063 
10064 	    // root handler passed via (xml, { rootHandler: ElementHandler }, ...)
10065 	    rootHandler = options;
10066 	    options = {};
10067 	  } else {
10068 	    if (typeof options === 'string') {
10069 
10070 	      // rootHandler passed via (xml, 'someString', ...)
10071 	      rootHandler = this.handler(options);
10072 	      options = {};
10073 	    } else if (typeof rootHandler === 'string') {
10074 
10075 	      // rootHandler passed via (xml, { rootHandler: 'someString' }, ...)
10076 	      rootHandler = this.handler(rootHandler);
10077 	    }
10078 	  }
10079 
10080 	  var model = this.model,
10081 	      lax = this.lax;
10082 
10083 	  var context = new Context(assign({}, options, { rootHandler: rootHandler })),
10084 	      parser = new Parser({ proxy: true }),
10085 	      stack = createStack();
10086 
10087 	  rootHandler.context = context;
10088 
10089 	  // push root handler
10090 	  stack.push(rootHandler);
10091 
10092 
10093 	  /**
10094 	   * Handle error.
10095 	   *
10096 	   * @param  {Error} err
10097 	   * @param  {Function} getContext
10098 	   * @param  {boolean} lax
10099 	   *
10100 	   * @return {boolean} true if handled
10101 	   */
10102 	  function handleError(err, getContext, lax) {
10103 
10104 	    var ctx = getContext();
10105 
10106 	    var line = ctx.line,
10107 	        column = ctx.column,
10108 	        data = ctx.data;
10109 
10110 	    // we receive the full context data here,
10111 	    // for elements trim down the information
10112 	    // to the tag name, only
10113 	    if (data.charAt(0) === '<' && data.indexOf(' ') !== -1) {
10114 	      data = data.slice(0, data.indexOf(' ')) + '>';
10115 	    }
10116 
10117 	    var message =
10118 	      'unparsable content ' + (data ? data + ' ' : '') + 'detected\n\t' +
10119 	        'line: ' + line + '\n\t' +
10120 	        'column: ' + column + '\n\t' +
10121 	        'nested error: ' + err.message;
10122 
10123 	    if (lax) {
10124 	      context.addWarning({
10125 	        message: message,
10126 	        error: err
10127 	      });
10128 
10129 	      return true;
10130 	    } else {
10131 	      throw error$1(message);
10132 	    }
10133 	  }
10134 
10135 	  function handleWarning(err, getContext) {
10136 
10137 	    // just like handling errors in <lax=true> mode
10138 	    return handleError(err, getContext, true);
10139 	  }
10140 
10141 	  /**
10142 	   * Resolve collected references on parse end.
10143 	   */
10144 	  function resolveReferences() {
10145 
10146 	    var elementsById = context.elementsById;
10147 	    var references = context.references;
10148 
10149 	    var i, r;
10150 
10151 	    for (i = 0; (r = references[i]); i++) {
10152 	      var element = r.element;
10153 	      var reference = elementsById[r.id];
10154 	      var property = getModdleDescriptor(element).propertiesByName[r.property];
10155 
10156 	      if (!reference) {
10157 	        context.addWarning({
10158 	          message: 'unresolved reference <' + r.id + '>',
10159 	          element: r.element,
10160 	          property: r.property,
10161 	          value: r.id
10162 	        });
10163 	      }
10164 
10165 	      if (property.isMany) {
10166 	        var collection = element.get(property.name),
10167 	            idx = collection.indexOf(r);
10168 
10169 	        // we replace an existing place holder (idx != -1) or
10170 	        // append to the collection instead
10171 	        if (idx === -1) {
10172 	          idx = collection.length;
10173 	        }
10174 
10175 	        if (!reference) {
10176 
10177 	          // remove unresolvable reference
10178 	          collection.splice(idx, 1);
10179 	        } else {
10180 
10181 	          // add or update reference in collection
10182 	          collection[idx] = reference;
10183 	        }
10184 	      } else {
10185 	        element.set(property.name, reference);
10186 	      }
10187 	    }
10188 	  }
10189 
10190 	  function handleClose() {
10191 	    stack.pop().handleEnd();
10192 	  }
10193 
10194 	  var PREAMBLE_START_PATTERN = /^<\?xml /i;
10195 
10196 	  var ENCODING_PATTERN = / encoding="([^"]+)"/i;
10197 
10198 	  var UTF_8_PATTERN = /^utf-8$/i;
10199 
10200 	  function handleQuestion(question) {
10201 
10202 	    if (!PREAMBLE_START_PATTERN.test(question)) {
10203 	      return;
10204 	    }
10205 
10206 	    var match = ENCODING_PATTERN.exec(question);
10207 	    var encoding = match && match[1];
10208 
10209 	    if (!encoding || UTF_8_PATTERN.test(encoding)) {
10210 	      return;
10211 	    }
10212 
10213 	    context.addWarning({
10214 	      message:
10215 	        'unsupported document encoding <' + encoding + '>, ' +
10216 	        'falling back to UTF-8'
10217 	    });
10218 	  }
10219 
10220 	  function handleOpen(node, getContext) {
10221 	    var handler = stack.peek();
10222 
10223 	    try {
10224 	      stack.push(handler.handleNode(node));
10225 	    } catch (err) {
10226 
10227 	      if (handleError(err, getContext, lax)) {
10228 	        stack.push(new NoopHandler());
10229 	      }
10230 	    }
10231 	  }
10232 
10233 	  function handleCData(text, getContext) {
10234 
10235 	    try {
10236 	      stack.peek().handleText(text);
10237 	    } catch (err) {
10238 	      handleWarning(err, getContext);
10239 	    }
10240 	  }
10241 
10242 	  function handleText(text, getContext) {
10243 
10244 	    // strip whitespace only nodes, i.e. before
10245 	    // <!CDATA[ ... ]> sections and in between tags
10246 
10247 	    if (!text.trim()) {
10248 	      return;
10249 	    }
10250 
10251 	    handleCData(text, getContext);
10252 	  }
10253 
10254 	  var uriMap = model.getPackages().reduce(function(uriMap, p) {
10255 	    uriMap[p.uri] = p.prefix;
10256 
10257 	    return uriMap;
10258 	  }, {
10259 	    'http://www.w3.org/XML/1998/namespace': 'xml' // add default xml ns
10260 	  });
10261 	  parser
10262 	    .ns(uriMap)
10263 	    .on('openTag', function(obj, decodeStr, selfClosing, getContext) {
10264 
10265 	      // gracefully handle unparsable attributes (attrs=false)
10266 	      var attrs = obj.attrs || {};
10267 
10268 	      var decodedAttrs = Object.keys(attrs).reduce(function(d, key) {
10269 	        var value = decodeStr(attrs[key]);
10270 
10271 	        d[key] = value;
10272 
10273 	        return d;
10274 	      }, {});
10275 
10276 	      var node = {
10277 	        name: obj.name,
10278 	        originalName: obj.originalName,
10279 	        attributes: decodedAttrs,
10280 	        ns: obj.ns
10281 	      };
10282 
10283 	      handleOpen(node, getContext);
10284 	    })
10285 	    .on('question', handleQuestion)
10286 	    .on('closeTag', handleClose)
10287 	    .on('cdata', handleCData)
10288 	    .on('text', function(text, decodeEntities, getContext) {
10289 	      handleText(decodeEntities(text), getContext);
10290 	    })
10291 	    .on('error', handleError)
10292 	    .on('warn', handleWarning);
10293 
10294 	  // async XML parsing to make sure the execution environment
10295 	  // (node or brower) is kept responsive and that certain optimization
10296 	  // strategies can kick in.
10297 	  return new Promise(function(resolve, reject) {
10298 
10299 	    var err;
10300 
10301 	    try {
10302 	      parser.parse(xml);
10303 
10304 	      resolveReferences();
10305 	    } catch (e) {
10306 	      err = e;
10307 	    }
10308 
10309 	    var rootElement = rootHandler.element;
10310 
10311 	    if (!err && !rootElement) {
10312 	      err = error$1('failed to parse document as <' + rootHandler.type.$descriptor.name + '>');
10313 	    }
10314 
10315 	    var warnings = context.warnings;
10316 	    var references = context.references;
10317 	    var elementsById = context.elementsById;
10318 
10319 	    if (err) {
10320 	      err.warnings = warnings;
10321 
10322 	      return reject(err);
10323 	    } else {
10324 	      return resolve({
10325 	        rootElement: rootElement,
10326 	        elementsById: elementsById,
10327 	        references: references,
10328 	        warnings: warnings
10329 	      });
10330 	    }
10331 	  });
10332 	};
10333 
10334 	Reader.prototype.handler = function(name) {
10335 	  return new RootElementHandler(this.model, name);
10336 	};
10337 
10338 
10339 	// helpers //////////////////////////
10340 
10341 	function createStack() {
10342 	  var stack = [];
10343 
10344 	  Object.defineProperty(stack, 'peek', {
10345 	    value: function() {
10346 	      return this[this.length - 1];
10347 	    }
10348 	  });
10349 
10350 	  return stack;
10351 	}
10352 
10353 	var XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>\n';
10354 
10355 	var ESCAPE_ATTR_CHARS = /<|>|'|"|&|\n\r|\n/g;
10356 	var ESCAPE_CHARS = /<|>|&/g;
10357 
10358 
10359 	function Namespaces(parent) {
10360 
10361 	  var prefixMap = {};
10362 	  var uriMap = {};
10363 	  var used = {};
10364 
10365 	  var wellknown = [];
10366 	  var custom = [];
10367 
10368 	  // API
10369 
10370 	  this.byUri = function(uri) {
10371 	    return uriMap[uri] || (
10372 	      parent && parent.byUri(uri)
10373 	    );
10374 	  };
10375 
10376 	  this.add = function(ns, isWellknown) {
10377 
10378 	    uriMap[ns.uri] = ns;
10379 
10380 	    if (isWellknown) {
10381 	      wellknown.push(ns);
10382 	    } else {
10383 	      custom.push(ns);
10384 	    }
10385 
10386 	    this.mapPrefix(ns.prefix, ns.uri);
10387 	  };
10388 
10389 	  this.uriByPrefix = function(prefix) {
10390 	    return prefixMap[prefix || 'xmlns'];
10391 	  };
10392 
10393 	  this.mapPrefix = function(prefix, uri) {
10394 	    prefixMap[prefix || 'xmlns'] = uri;
10395 	  };
10396 
10397 	  this.getNSKey = function(ns) {
10398 	    return (ns.prefix !== undefined) ? (ns.uri + '|' + ns.prefix) : ns.uri;
10399 	  };
10400 
10401 	  this.logUsed = function(ns) {
10402 
10403 	    var uri = ns.uri;
10404 	    var nsKey = this.getNSKey(ns);
10405 
10406 	    used[nsKey] = this.byUri(uri);
10407 
10408 	    // Inform parent recursively about the usage of this NS
10409 	    if (parent) {
10410 	      parent.logUsed(ns);
10411 	    }
10412 	  };
10413 
10414 	  this.getUsed = function(ns) {
10415 
10416 	    function isUsed(ns) {
10417 	      var nsKey = self.getNSKey(ns);
10418 
10419 	      return used[nsKey];
10420 	    }
10421 
10422 	    var self = this;
10423 
10424 	    var allNs = [].concat(wellknown, custom);
10425 
10426 	    return allNs.filter(isUsed);
10427 	  };
10428 
10429 	}
10430 
10431 	function lower(string) {
10432 	  return string.charAt(0).toLowerCase() + string.slice(1);
10433 	}
10434 
10435 	function nameToAlias(name, pkg) {
10436 	  if (hasLowerCaseAlias(pkg)) {
10437 	    return lower(name);
10438 	  } else {
10439 	    return name;
10440 	  }
10441 	}
10442 
10443 	function inherits(ctor, superCtor) {
10444 	  ctor.super_ = superCtor;
10445 	  ctor.prototype = Object.create(superCtor.prototype, {
10446 	    constructor: {
10447 	      value: ctor,
10448 	      enumerable: false,
10449 	      writable: true,
10450 	      configurable: true
10451 	    }
10452 	  });
10453 	}
10454 
10455 	function nsName(ns) {
10456 	  if (isString(ns)) {
10457 	    return ns;
10458 	  } else {
10459 	    return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
10460 	  }
10461 	}
10462 
10463 	function getNsAttrs(namespaces) {
10464 
10465 	  return namespaces.getUsed().filter(function(ns) {
10466 
10467 	    // do not serialize built in <xml> namespace
10468 	    return ns.prefix !== 'xml';
10469 	  }).map(function(ns) {
10470 	    var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
10471 	    return { name: name, value: ns.uri };
10472 	  });
10473 
10474 	}
10475 
10476 	function getElementNs(ns, descriptor) {
10477 	  if (descriptor.isGeneric) {
10478 	    return assign({ localName: descriptor.ns.localName }, ns);
10479 	  } else {
10480 	    return assign({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
10481 	  }
10482 	}
10483 
10484 	function getPropertyNs(ns, descriptor) {
10485 	  return assign({ localName: descriptor.ns.localName }, ns);
10486 	}
10487 
10488 	function getSerializableProperties(element) {
10489 	  var descriptor = element.$descriptor;
10490 
10491 	  return filter(descriptor.properties, function(p) {
10492 	    var name = p.name;
10493 
10494 	    if (p.isVirtual) {
10495 	      return false;
10496 	    }
10497 
10498 	    // do not serialize defaults
10499 	    if (!has(element, name)) {
10500 	      return false;
10501 	    }
10502 
10503 	    var value = element[name];
10504 
10505 	    // do not serialize default equals
10506 	    if (value === p.default) {
10507 	      return false;
10508 	    }
10509 
10510 	    // do not serialize null properties
10511 	    if (value === null) {
10512 	      return false;
10513 	    }
10514 
10515 	    return p.isMany ? value.length : true;
10516 	  });
10517 	}
10518 
10519 	var ESCAPE_ATTR_MAP = {
10520 	  '\n': '#10',
10521 	  '\n\r': '#10',
10522 	  '"': '#34',
10523 	  '\'': '#39',
10524 	  '<': '#60',
10525 	  '>': '#62',
10526 	  '&': '#38'
10527 	};
10528 
10529 	var ESCAPE_MAP = {
10530 	  '<': 'lt',
10531 	  '>': 'gt',
10532 	  '&': 'amp'
10533 	};
10534 
10535 	function escape(str, charPattern, replaceMap) {
10536 
10537 	  // ensure we are handling strings here
10538 	  str = isString(str) ? str : '' + str;
10539 
10540 	  return str.replace(charPattern, function(s) {
10541 	    return '&' + replaceMap[s] + ';';
10542 	  });
10543 	}
10544 
10545 	/**
10546 	 * Escape a string attribute to not contain any bad values (line breaks, '"', ...)
10547 	 *
10548 	 * @param {String} str the string to escape
10549 	 * @return {String} the escaped string
10550 	 */
10551 	function escapeAttr(str) {
10552 	  return escape(str, ESCAPE_ATTR_CHARS, ESCAPE_ATTR_MAP);
10553 	}
10554 
10555 	function escapeBody(str) {
10556 	  return escape(str, ESCAPE_CHARS, ESCAPE_MAP);
10557 	}
10558 
10559 	function filterAttributes(props) {
10560 	  return filter(props, function(p) { return p.isAttr; });
10561 	}
10562 
10563 	function filterContained(props) {
10564 	  return filter(props, function(p) { return !p.isAttr; });
10565 	}
10566 
10567 
10568 	function ReferenceSerializer(tagName) {
10569 	  this.tagName = tagName;
10570 	}
10571 
10572 	ReferenceSerializer.prototype.build = function(element) {
10573 	  this.element = element;
10574 	  return this;
10575 	};
10576 
10577 	ReferenceSerializer.prototype.serializeTo = function(writer) {
10578 	  writer
10579 	    .appendIndent()
10580 	    .append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')
10581 	    .appendNewLine();
10582 	};
10583 
10584 	function BodySerializer() {}
10585 
10586 	BodySerializer.prototype.serializeValue =
10587 	BodySerializer.prototype.serializeTo = function(writer) {
10588 	  writer.append(
10589 	    this.escape
10590 	      ? escapeBody(this.value)
10591 	      : this.value
10592 	  );
10593 	};
10594 
10595 	BodySerializer.prototype.build = function(prop, value) {
10596 	  this.value = value;
10597 
10598 	  if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {
10599 	    this.escape = true;
10600 	  }
10601 
10602 	  return this;
10603 	};
10604 
10605 	function ValueSerializer(tagName) {
10606 	  this.tagName = tagName;
10607 	}
10608 
10609 	inherits(ValueSerializer, BodySerializer);
10610 
10611 	ValueSerializer.prototype.serializeTo = function(writer) {
10612 
10613 	  writer
10614 	    .appendIndent()
10615 	    .append('<' + this.tagName + '>');
10616 
10617 	  this.serializeValue(writer);
10618 
10619 	  writer
10620 	    .append('</' + this.tagName + '>')
10621 	    .appendNewLine();
10622 	};
10623 
10624 	function ElementSerializer(parent, propertyDescriptor) {
10625 	  this.body = [];
10626 	  this.attrs = [];
10627 
10628 	  this.parent = parent;
10629 	  this.propertyDescriptor = propertyDescriptor;
10630 	}
10631 
10632 	ElementSerializer.prototype.build = function(element) {
10633 	  this.element = element;
10634 
10635 	  var elementDescriptor = element.$descriptor,
10636 	      propertyDescriptor = this.propertyDescriptor;
10637 
10638 	  var otherAttrs,
10639 	      properties;
10640 
10641 	  var isGeneric = elementDescriptor.isGeneric;
10642 
10643 	  if (isGeneric) {
10644 	    otherAttrs = this.parseGeneric(element);
10645 	  } else {
10646 	    otherAttrs = this.parseNsAttributes(element);
10647 	  }
10648 
10649 	  if (propertyDescriptor) {
10650 	    this.ns = this.nsPropertyTagName(propertyDescriptor);
10651 	  } else {
10652 	    this.ns = this.nsTagName(elementDescriptor);
10653 	  }
10654 
10655 	  // compute tag name
10656 	  this.tagName = this.addTagName(this.ns);
10657 
10658 	  if (!isGeneric) {
10659 	    properties = getSerializableProperties(element);
10660 
10661 	    this.parseAttributes(filterAttributes(properties));
10662 	    this.parseContainments(filterContained(properties));
10663 	  }
10664 
10665 	  this.parseGenericAttributes(element, otherAttrs);
10666 
10667 	  return this;
10668 	};
10669 
10670 	ElementSerializer.prototype.nsTagName = function(descriptor) {
10671 	  var effectiveNs = this.logNamespaceUsed(descriptor.ns);
10672 	  return getElementNs(effectiveNs, descriptor);
10673 	};
10674 
10675 	ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
10676 	  var effectiveNs = this.logNamespaceUsed(descriptor.ns);
10677 	  return getPropertyNs(effectiveNs, descriptor);
10678 	};
10679 
10680 	ElementSerializer.prototype.isLocalNs = function(ns) {
10681 	  return ns.uri === this.ns.uri;
10682 	};
10683 
10684 	/**
10685 	 * Get the actual ns attribute name for the given element.
10686 	 *
10687 	 * @param {Object} element
10688 	 * @param {Boolean} [element.inherited=false]
10689 	 *
10690 	 * @return {Object} nsName
10691 	 */
10692 	ElementSerializer.prototype.nsAttributeName = function(element) {
10693 
10694 	  var ns;
10695 
10696 	  if (isString(element)) {
10697 	    ns = parseName(element);
10698 	  } else {
10699 	    ns = element.ns;
10700 	  }
10701 
10702 	  // return just local name for inherited attributes
10703 	  if (element.inherited) {
10704 	    return { localName: ns.localName };
10705 	  }
10706 
10707 	  // parse + log effective ns
10708 	  var effectiveNs = this.logNamespaceUsed(ns);
10709 
10710 	  // LOG ACTUAL namespace use
10711 	  this.getNamespaces().logUsed(effectiveNs);
10712 
10713 	  // strip prefix if same namespace like parent
10714 	  if (this.isLocalNs(effectiveNs)) {
10715 	    return { localName: ns.localName };
10716 	  } else {
10717 	    return assign({ localName: ns.localName }, effectiveNs);
10718 	  }
10719 	};
10720 
10721 	ElementSerializer.prototype.parseGeneric = function(element) {
10722 
10723 	  var self = this,
10724 	      body = this.body;
10725 
10726 	  var attributes = [];
10727 
10728 	  forEach(element, function(val, key) {
10729 
10730 	    var nonNsAttr;
10731 
10732 	    if (key === '$body') {
10733 	      body.push(new BodySerializer().build({ type: 'String' }, val));
10734 	    } else
10735 	    if (key === '$children') {
10736 	      forEach(val, function(child) {
10737 	        body.push(new ElementSerializer(self).build(child));
10738 	      });
10739 	    } else
10740 	    if (key.indexOf('$') !== 0) {
10741 	      nonNsAttr = self.parseNsAttribute(element, key, val);
10742 
10743 	      if (nonNsAttr) {
10744 	        attributes.push({ name: key, value: val });
10745 	      }
10746 	    }
10747 	  });
10748 
10749 	  return attributes;
10750 	};
10751 
10752 	ElementSerializer.prototype.parseNsAttribute = function(element, name, value) {
10753 	  var model = element.$model;
10754 
10755 	  var nameNs = parseName(name);
10756 
10757 	  var ns;
10758 
10759 	  // parse xmlns:foo="http://foo.bar"
10760 	  if (nameNs.prefix === 'xmlns') {
10761 	    ns = { prefix: nameNs.localName, uri: value };
10762 	  }
10763 
10764 	  // parse xmlns="http://foo.bar"
10765 	  if (!nameNs.prefix && nameNs.localName === 'xmlns') {
10766 	    ns = { uri: value };
10767 	  }
10768 
10769 	  if (!ns) {
10770 	    return {
10771 	      name: name,
10772 	      value: value
10773 	    };
10774 	  }
10775 
10776 	  if (model && model.getPackage(value)) {
10777 
10778 	    // register well known namespace
10779 	    this.logNamespace(ns, true, true);
10780 	  } else {
10781 
10782 	    // log custom namespace directly as used
10783 	    var actualNs = this.logNamespaceUsed(ns, true);
10784 
10785 	    this.getNamespaces().logUsed(actualNs);
10786 	  }
10787 	};
10788 
10789 
10790 	/**
10791 	 * Parse namespaces and return a list of left over generic attributes
10792 	 *
10793 	 * @param  {Object} element
10794 	 * @return {Array<Object>}
10795 	 */
10796 	ElementSerializer.prototype.parseNsAttributes = function(element, attrs) {
10797 	  var self = this;
10798 
10799 	  var genericAttrs = element.$attrs;
10800 
10801 	  var attributes = [];
10802 
10803 	  // parse namespace attributes first
10804 	  // and log them. push non namespace attributes to a list
10805 	  // and process them later
10806 	  forEach(genericAttrs, function(value, name) {
10807 
10808 	    var nonNsAttr = self.parseNsAttribute(element, name, value);
10809 
10810 	    if (nonNsAttr) {
10811 	      attributes.push(nonNsAttr);
10812 	    }
10813 	  });
10814 
10815 	  return attributes;
10816 	};
10817 
10818 	ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
10819 
10820 	  var self = this;
10821 
10822 	  forEach(attributes, function(attr) {
10823 
10824 	    // do not serialize xsi:type attribute
10825 	    // it is set manually based on the actual implementation type
10826 	    if (attr.name === XSI_TYPE) {
10827 	      return;
10828 	    }
10829 
10830 	    try {
10831 	      self.addAttribute(self.nsAttributeName(attr.name), attr.value);
10832 	    } catch (e) {
10833 	      console.warn(
10834 	        'missing namespace information for ',
10835 	        attr.name, '=', attr.value, 'on', element,
10836 	        e);
10837 	    }
10838 	  });
10839 	};
10840 
10841 	ElementSerializer.prototype.parseContainments = function(properties) {
10842 
10843 	  var self = this,
10844 	      body = this.body,
10845 	      element = this.element;
10846 
10847 	  forEach(properties, function(p) {
10848 	    var value = element.get(p.name),
10849 	        isReference = p.isReference,
10850 	        isMany = p.isMany;
10851 
10852 	    if (!isMany) {
10853 	      value = [ value ];
10854 	    }
10855 
10856 	    if (p.isBody) {
10857 	      body.push(new BodySerializer().build(p, value[0]));
10858 	    } else
10859 	    if (isSimple(p.type)) {
10860 	      forEach(value, function(v) {
10861 	        body.push(new ValueSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));
10862 	      });
10863 	    } else
10864 	    if (isReference) {
10865 	      forEach(value, function(v) {
10866 	        body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));
10867 	      });
10868 	    } else {
10869 
10870 	      // allow serialization via type
10871 	      // rather than element name
10872 	      var asType = serializeAsType(p),
10873 	          asProperty = serializeAsProperty(p);
10874 
10875 	      forEach(value, function(v) {
10876 	        var serializer;
10877 
10878 	        if (asType) {
10879 	          serializer = new TypeSerializer(self, p);
10880 	        } else
10881 	        if (asProperty) {
10882 	          serializer = new ElementSerializer(self, p);
10883 	        } else {
10884 	          serializer = new ElementSerializer(self);
10885 	        }
10886 
10887 	        body.push(serializer.build(v));
10888 	      });
10889 	    }
10890 	  });
10891 	};
10892 
10893 	ElementSerializer.prototype.getNamespaces = function(local) {
10894 
10895 	  var namespaces = this.namespaces,
10896 	      parent = this.parent,
10897 	      parentNamespaces;
10898 
10899 	  if (!namespaces) {
10900 	    parentNamespaces = parent && parent.getNamespaces();
10901 
10902 	    if (local || !parentNamespaces) {
10903 	      this.namespaces = namespaces = new Namespaces(parentNamespaces);
10904 	    } else {
10905 	      namespaces = parentNamespaces;
10906 	    }
10907 	  }
10908 
10909 	  return namespaces;
10910 	};
10911 
10912 	ElementSerializer.prototype.logNamespace = function(ns, wellknown, local) {
10913 	  var namespaces = this.getNamespaces(local);
10914 
10915 	  var nsUri = ns.uri,
10916 	      nsPrefix = ns.prefix;
10917 
10918 	  var existing = namespaces.byUri(nsUri);
10919 
10920 	  if (!existing || local) {
10921 	    namespaces.add(ns, wellknown);
10922 	  }
10923 
10924 	  namespaces.mapPrefix(nsPrefix, nsUri);
10925 
10926 	  return ns;
10927 	};
10928 
10929 	ElementSerializer.prototype.logNamespaceUsed = function(ns, local) {
10930 	  var element = this.element,
10931 	      model = element.$model,
10932 	      namespaces = this.getNamespaces(local);
10933 
10934 	  // ns may be
10935 	  //
10936 	  //   * prefix only
10937 	  //   * prefix:uri
10938 	  //   * localName only
10939 
10940 	  var prefix = ns.prefix,
10941 	      uri = ns.uri,
10942 	      newPrefix, idx,
10943 	      wellknownUri;
10944 
10945 	  // handle anonymous namespaces (elementForm=unqualified), cf. #23
10946 	  if (!prefix && !uri) {
10947 	    return { localName: ns.localName };
10948 	  }
10949 
10950 	  wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri;
10951 
10952 	  uri = uri || wellknownUri || namespaces.uriByPrefix(prefix);
10953 
10954 	  if (!uri) {
10955 	    throw new Error('no namespace uri given for prefix <' + prefix + '>');
10956 	  }
10957 
10958 	  ns = namespaces.byUri(uri);
10959 
10960 	  if (!ns) {
10961 	    newPrefix = prefix;
10962 	    idx = 1;
10963 
10964 	    // find a prefix that is not mapped yet
10965 	    while (namespaces.uriByPrefix(newPrefix)) {
10966 	      newPrefix = prefix + '_' + idx++;
10967 	    }
10968 
10969 	    ns = this.logNamespace({ prefix: newPrefix, uri: uri }, wellknownUri === uri);
10970 	  }
10971 
10972 	  if (prefix) {
10973 	    namespaces.mapPrefix(prefix, uri);
10974 	  }
10975 
10976 	  return ns;
10977 	};
10978 
10979 	ElementSerializer.prototype.parseAttributes = function(properties) {
10980 	  var self = this,
10981 	      element = this.element;
10982 
10983 	  forEach(properties, function(p) {
10984 
10985 	    var value = element.get(p.name);
10986 
10987 	    if (p.isReference) {
10988 
10989 	      if (!p.isMany) {
10990 	        value = value.id;
10991 	      }
10992 	      else {
10993 	        var values = [];
10994 	        forEach(value, function(v) {
10995 	          values.push(v.id);
10996 	        });
10997 
10998 	        // IDREFS is a whitespace-separated list of references.
10999 	        value = values.join(' ');
11000 	      }
11001 
11002 	    }
11003 
11004 	    self.addAttribute(self.nsAttributeName(p), value);
11005 	  });
11006 	};
11007 
11008 	ElementSerializer.prototype.addTagName = function(nsTagName) {
11009 	  var actualNs = this.logNamespaceUsed(nsTagName);
11010 
11011 	  this.getNamespaces().logUsed(actualNs);
11012 
11013 	  return nsName(nsTagName);
11014 	};
11015 
11016 	ElementSerializer.prototype.addAttribute = function(name, value) {
11017 	  var attrs = this.attrs;
11018 
11019 	  if (isString(value)) {
11020 	    value = escapeAttr(value);
11021 	  }
11022 
11023 	  attrs.push({ name: name, value: value });
11024 	};
11025 
11026 	ElementSerializer.prototype.serializeAttributes = function(writer) {
11027 	  var attrs = this.attrs,
11028 	      namespaces = this.namespaces;
11029 
11030 	  if (namespaces) {
11031 	    attrs = getNsAttrs(namespaces).concat(attrs);
11032 	  }
11033 
11034 	  forEach(attrs, function(a) {
11035 	    writer
11036 	      .append(' ')
11037 	      .append(nsName(a.name)).append('="').append(a.value).append('"');
11038 	  });
11039 	};
11040 
11041 	ElementSerializer.prototype.serializeTo = function(writer) {
11042 	  var firstBody = this.body[0],
11043 	      indent = firstBody && firstBody.constructor !== BodySerializer;
11044 
11045 	  writer
11046 	    .appendIndent()
11047 	    .append('<' + this.tagName);
11048 
11049 	  this.serializeAttributes(writer);
11050 
11051 	  writer.append(firstBody ? '>' : ' />');
11052 
11053 	  if (firstBody) {
11054 
11055 	    if (indent) {
11056 	      writer
11057 	        .appendNewLine()
11058 	        .indent();
11059 	    }
11060 
11061 	    forEach(this.body, function(b) {
11062 	      b.serializeTo(writer);
11063 	    });
11064 
11065 	    if (indent) {
11066 	      writer
11067 	        .unindent()
11068 	        .appendIndent();
11069 	    }
11070 
11071 	    writer.append('</' + this.tagName + '>');
11072 	  }
11073 
11074 	  writer.appendNewLine();
11075 	};
11076 
11077 	/**
11078 	 * A serializer for types that handles serialization of data types
11079 	 */
11080 	function TypeSerializer(parent, propertyDescriptor) {
11081 	  ElementSerializer.call(this, parent, propertyDescriptor);
11082 	}
11083 
11084 	inherits(TypeSerializer, ElementSerializer);
11085 
11086 	TypeSerializer.prototype.parseNsAttributes = function(element) {
11087 
11088 	  // extracted attributes
11089 	  var attributes = ElementSerializer.prototype.parseNsAttributes.call(this, element);
11090 
11091 	  var descriptor = element.$descriptor;
11092 
11093 	  // only serialize xsi:type if necessary
11094 	  if (descriptor.name === this.propertyDescriptor.type) {
11095 	    return attributes;
11096 	  }
11097 
11098 	  var typeNs = this.typeNs = this.nsTagName(descriptor);
11099 	  this.getNamespaces().logUsed(this.typeNs);
11100 
11101 	  // add xsi:type attribute to represent the elements
11102 	  // actual type
11103 
11104 	  var pkg = element.$model.getPackage(typeNs.uri),
11105 	      typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';
11106 
11107 	  this.addAttribute(
11108 	    this.nsAttributeName(XSI_TYPE),
11109 	    (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName
11110 	  );
11111 
11112 	  return attributes;
11113 	};
11114 
11115 	TypeSerializer.prototype.isLocalNs = function(ns) {
11116 	  return ns.uri === (this.typeNs || this.ns).uri;
11117 	};
11118 
11119 	function SavingWriter() {
11120 	  this.value = '';
11121 
11122 	  this.write = function(str) {
11123 	    this.value += str;
11124 	  };
11125 	}
11126 
11127 	function FormatingWriter(out, format) {
11128 
11129 	  var indent = [''];
11130 
11131 	  this.append = function(str) {
11132 	    out.write(str);
11133 
11134 	    return this;
11135 	  };
11136 
11137 	  this.appendNewLine = function() {
11138 	    if (format) {
11139 	      out.write('\n');
11140 	    }
11141 
11142 	    return this;
11143 	  };
11144 
11145 	  this.appendIndent = function() {
11146 	    if (format) {
11147 	      out.write(indent.join('  '));
11148 	    }
11149 
11150 	    return this;
11151 	  };
11152 
11153 	  this.indent = function() {
11154 	    indent.push('');
11155 	    return this;
11156 	  };
11157 
11158 	  this.unindent = function() {
11159 	    indent.pop();
11160 	    return this;
11161 	  };
11162 	}
11163 
11164 	/**
11165 	 * A writer for meta-model backed document trees
11166 	 *
11167 	 * @param {Object} options output options to pass into the writer
11168 	 */
11169 	function Writer(options) {
11170 
11171 	  options = assign({ format: false, preamble: true }, options || {});
11172 
11173 	  function toXML(tree, writer) {
11174 	    var internalWriter = writer || new SavingWriter();
11175 	    var formatingWriter = new FormatingWriter(internalWriter, options.format);
11176 
11177 	    if (options.preamble) {
11178 	      formatingWriter.append(XML_PREAMBLE);
11179 	    }
11180 
11181 	    new ElementSerializer().build(tree).serializeTo(formatingWriter);
11182 
11183 	    if (!writer) {
11184 	      return internalWriter.value;
11185 	    }
11186 	  }
11187 
11188 	  return {
11189 	    toXML: toXML
11190 	  };
11191 	}
11192 
11193 	/**
11194 	 * A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
11195 	 *
11196 	 * @class BpmnModdle
11197 	 * @extends Moddle
11198 	 *
11199 	 * @param {Object|Array} packages to use for instantiating the model
11200 	 * @param {Object} [options] additional options to pass over
11201 	 */
11202 	function BpmnModdle(packages, options) {
11203 	  Moddle.call(this, packages, options);
11204 	}
11205 
11206 	BpmnModdle.prototype = Object.create(Moddle.prototype);
11207 
11208 	/**
11209 	 * The fromXML result.
11210 	 *
11211 	 * @typedef {Object} ParseResult
11212 	 *
11213 	 * @property {ModdleElement} rootElement
11214 	 * @property {Array<Object>} references
11215 	 * @property {Array<Error>} warnings
11216 	 * @property {Object} elementsById - a mapping containing each ID -> ModdleElement
11217 	 */
11218 
11219 	/**
11220 	 * The fromXML error.
11221 	 *
11222 	 * @typedef {Error} ParseError
11223 	 *
11224 	 * @property {Array<Error>} warnings
11225 	 */
11226 
11227 	/**
11228 	 * Instantiates a BPMN model tree from a given xml string.
11229 	 *
11230 	 * @param {String}   xmlStr
11231 	 * @param {String}   [typeName='bpmn:Definitions'] name of the root element
11232 	 * @param {Object}   [options]  options to pass to the underlying reader
11233 	 *
11234 	 * @returns {Promise<ParseResult, ParseError>}
11235 	 */
11236 	BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options) {
11237 
11238 	  if (!isString(typeName)) {
11239 	    options = typeName;
11240 	    typeName = 'bpmn:Definitions';
11241 	  }
11242 
11243 	  var reader = new Reader(assign({ model: this, lax: true }, options));
11244 	  var rootHandler = reader.handler(typeName);
11245 
11246 	  return reader.fromXML(xmlStr, rootHandler);
11247 	};
11248 
11249 
11250 	/**
11251 	 * The toXML result.
11252 	 *
11253 	 * @typedef {Object} SerializationResult
11254 	 *
11255 	 * @property {String} xml
11256 	 */
11257 
11258 	/**
11259 	 * Serializes a BPMN 2.0 object tree to XML.
11260 	 *
11261 	 * @param {String}   element    the root element, typically an instance of `bpmn:Definitions`
11262 	 * @param {Object}   [options]  to pass to the underlying writer
11263 	 *
11264 	 * @returns {Promise<SerializationResult, Error>}
11265 	 */
11266 	BpmnModdle.prototype.toXML = function(element, options) {
11267 
11268 	  var writer = new Writer(options);
11269 
11270 	  return new Promise(function(resolve, reject) {
11271 	    try {
11272 	      var result = writer.toXML(element);
11273 
11274 	      return resolve({
11275 	        xml: result
11276 	      });
11277 	    } catch (err) {
11278 	      return reject(err);
11279 	    }
11280 	  });
11281 	};
11282 
11283 	var name = "BPMN20";
11284 	var uri = "http://www.omg.org/spec/BPMN/20100524/MODEL";
11285 	var prefix = "bpmn";
11286 	var associations = [
11287 	];
11288 	var types = [
11289 		{
11290 			name: "Interface",
11291 			superClass: [
11292 				"RootElement"
11293 			],
11294 			properties: [
11295 				{
11296 					name: "name",
11297 					isAttr: true,
11298 					type: "String"
11299 				},
11300 				{
11301 					name: "operations",
11302 					type: "Operation",
11303 					isMany: true
11304 				},
11305 				{
11306 					name: "implementationRef",
11307 					isAttr: true,
11308 					type: "String"
11309 				}
11310 			]
11311 		},
11312 		{
11313 			name: "Operation",
11314 			superClass: [
11315 				"BaseElement"
11316 			],
11317 			properties: [
11318 				{
11319 					name: "name",
11320 					isAttr: true,
11321 					type: "String"
11322 				},
11323 				{
11324 					name: "inMessageRef",
11325 					type: "Message",
11326 					isReference: true
11327 				},
11328 				{
11329 					name: "outMessageRef",
11330 					type: "Message",
11331 					isReference: true
11332 				},
11333 				{
11334 					name: "errorRef",
11335 					type: "Error",
11336 					isMany: true,
11337 					isReference: true
11338 				},
11339 				{
11340 					name: "implementationRef",
11341 					isAttr: true,
11342 					type: "String"
11343 				}
11344 			]
11345 		},
11346 		{
11347 			name: "EndPoint",
11348 			superClass: [
11349 				"RootElement"
11350 			]
11351 		},
11352 		{
11353 			name: "Auditing",
11354 			superClass: [
11355 				"BaseElement"
11356 			]
11357 		},
11358 		{
11359 			name: "GlobalTask",
11360 			superClass: [
11361 				"CallableElement"
11362 			],
11363 			properties: [
11364 				{
11365 					name: "resources",
11366 					type: "ResourceRole",
11367 					isMany: true
11368 				}
11369 			]
11370 		},
11371 		{
11372 			name: "Monitoring",
11373 			superClass: [
11374 				"BaseElement"
11375 			]
11376 		},
11377 		{
11378 			name: "Performer",
11379 			superClass: [
11380 				"ResourceRole"
11381 			]
11382 		},
11383 		{
11384 			name: "Process",
11385 			superClass: [
11386 				"FlowElementsContainer",
11387 				"CallableElement"
11388 			],
11389 			properties: [
11390 				{
11391 					name: "processType",
11392 					type: "ProcessType",
11393 					isAttr: true
11394 				},
11395 				{
11396 					name: "isClosed",
11397 					isAttr: true,
11398 					type: "Boolean"
11399 				},
11400 				{
11401 					name: "auditing",
11402 					type: "Auditing"
11403 				},
11404 				{
11405 					name: "monitoring",
11406 					type: "Monitoring"
11407 				},
11408 				{
11409 					name: "properties",
11410 					type: "Property",
11411 					isMany: true
11412 				},
11413 				{
11414 					name: "laneSets",
11415 					isMany: true,
11416 					replaces: "FlowElementsContainer#laneSets",
11417 					type: "LaneSet"
11418 				},
11419 				{
11420 					name: "flowElements",
11421 					isMany: true,
11422 					replaces: "FlowElementsContainer#flowElements",
11423 					type: "FlowElement"
11424 				},
11425 				{
11426 					name: "artifacts",
11427 					type: "Artifact",
11428 					isMany: true
11429 				},
11430 				{
11431 					name: "resources",
11432 					type: "ResourceRole",
11433 					isMany: true
11434 				},
11435 				{
11436 					name: "correlationSubscriptions",
11437 					type: "CorrelationSubscription",
11438 					isMany: true
11439 				},
11440 				{
11441 					name: "supports",
11442 					type: "Process",
11443 					isMany: true,
11444 					isReference: true
11445 				},
11446 				{
11447 					name: "definitionalCollaborationRef",
11448 					type: "Collaboration",
11449 					isAttr: true,
11450 					isReference: true
11451 				},
11452 				{
11453 					name: "isExecutable",
11454 					isAttr: true,
11455 					type: "Boolean"
11456 				}
11457 			]
11458 		},
11459 		{
11460 			name: "LaneSet",
11461 			superClass: [
11462 				"BaseElement"
11463 			],
11464 			properties: [
11465 				{
11466 					name: "lanes",
11467 					type: "Lane",
11468 					isMany: true
11469 				},
11470 				{
11471 					name: "name",
11472 					isAttr: true,
11473 					type: "String"
11474 				}
11475 			]
11476 		},
11477 		{
11478 			name: "Lane",
11479 			superClass: [
11480 				"BaseElement"
11481 			],
11482 			properties: [
11483 				{
11484 					name: "name",
11485 					isAttr: true,
11486 					type: "String"
11487 				},
11488 				{
11489 					name: "partitionElementRef",
11490 					type: "BaseElement",
11491 					isAttr: true,
11492 					isReference: true
11493 				},
11494 				{
11495 					name: "partitionElement",
11496 					type: "BaseElement"
11497 				},
11498 				{
11499 					name: "flowNodeRef",
11500 					type: "FlowNode",
11501 					isMany: true,
11502 					isReference: true
11503 				},
11504 				{
11505 					name: "childLaneSet",
11506 					type: "LaneSet",
11507 					xml: {
11508 						serialize: "xsi:type"
11509 					}
11510 				}
11511 			]
11512 		},
11513 		{
11514 			name: "GlobalManualTask",
11515 			superClass: [
11516 				"GlobalTask"
11517 			]
11518 		},
11519 		{
11520 			name: "ManualTask",
11521 			superClass: [
11522 				"Task"
11523 			]
11524 		},
11525 		{
11526 			name: "UserTask",
11527 			superClass: [
11528 				"Task"
11529 			],
11530 			properties: [
11531 				{
11532 					name: "renderings",
11533 					type: "Rendering",
11534 					isMany: true
11535 				},
11536 				{
11537 					name: "implementation",
11538 					isAttr: true,
11539 					type: "String"
11540 				}
11541 			]
11542 		},
11543 		{
11544 			name: "Rendering",
11545 			superClass: [
11546 				"BaseElement"
11547 			]
11548 		},
11549 		{
11550 			name: "HumanPerformer",
11551 			superClass: [
11552 				"Performer"
11553 			]
11554 		},
11555 		{
11556 			name: "PotentialOwner",
11557 			superClass: [
11558 				"HumanPerformer"
11559 			]
11560 		},
11561 		{
11562 			name: "GlobalUserTask",
11563 			superClass: [
11564 				"GlobalTask"
11565 			],
11566 			properties: [
11567 				{
11568 					name: "implementation",
11569 					isAttr: true,
11570 					type: "String"
11571 				},
11572 				{
11573 					name: "renderings",
11574 					type: "Rendering",
11575 					isMany: true
11576 				}
11577 			]
11578 		},
11579 		{
11580 			name: "Gateway",
11581 			isAbstract: true,
11582 			superClass: [
11583 				"FlowNode"
11584 			],
11585 			properties: [
11586 				{
11587 					name: "gatewayDirection",
11588 					type: "GatewayDirection",
11589 					"default": "Unspecified",
11590 					isAttr: true
11591 				}
11592 			]
11593 		},
11594 		{
11595 			name: "EventBasedGateway",
11596 			superClass: [
11597 				"Gateway"
11598 			],
11599 			properties: [
11600 				{
11601 					name: "instantiate",
11602 					"default": false,
11603 					isAttr: true,
11604 					type: "Boolean"
11605 				},
11606 				{
11607 					name: "eventGatewayType",
11608 					type: "EventBasedGatewayType",
11609 					isAttr: true,
11610 					"default": "Exclusive"
11611 				}
11612 			]
11613 		},
11614 		{
11615 			name: "ComplexGateway",
11616 			superClass: [
11617 				"Gateway"
11618 			],
11619 			properties: [
11620 				{
11621 					name: "activationCondition",
11622 					type: "Expression",
11623 					xml: {
11624 						serialize: "xsi:type"
11625 					}
11626 				},
11627 				{
11628 					name: "default",
11629 					type: "SequenceFlow",
11630 					isAttr: true,
11631 					isReference: true
11632 				}
11633 			]
11634 		},
11635 		{
11636 			name: "ExclusiveGateway",
11637 			superClass: [
11638 				"Gateway"
11639 			],
11640 			properties: [
11641 				{
11642 					name: "default",
11643 					type: "SequenceFlow",
11644 					isAttr: true,
11645 					isReference: true
11646 				}
11647 			]
11648 		},
11649 		{
11650 			name: "InclusiveGateway",
11651 			superClass: [
11652 				"Gateway"
11653 			],
11654 			properties: [
11655 				{
11656 					name: "default",
11657 					type: "SequenceFlow",
11658 					isAttr: true,
11659 					isReference: true
11660 				}
11661 			]
11662 		},
11663 		{
11664 			name: "ParallelGateway",
11665 			superClass: [
11666 				"Gateway"
11667 			]
11668 		},
11669 		{
11670 			name: "RootElement",
11671 			isAbstract: true,
11672 			superClass: [
11673 				"BaseElement"
11674 			]
11675 		},
11676 		{
11677 			name: "Relationship",
11678 			superClass: [
11679 				"BaseElement"
11680 			],
11681 			properties: [
11682 				{
11683 					name: "type",
11684 					isAttr: true,
11685 					type: "String"
11686 				},
11687 				{
11688 					name: "direction",
11689 					type: "RelationshipDirection",
11690 					isAttr: true
11691 				},
11692 				{
11693 					name: "source",
11694 					isMany: true,
11695 					isReference: true,
11696 					type: "Element"
11697 				},
11698 				{
11699 					name: "target",
11700 					isMany: true,
11701 					isReference: true,
11702 					type: "Element"
11703 				}
11704 			]
11705 		},
11706 		{
11707 			name: "BaseElement",
11708 			isAbstract: true,
11709 			properties: [
11710 				{
11711 					name: "id",
11712 					isAttr: true,
11713 					type: "String",
11714 					isId: true
11715 				},
11716 				{
11717 					name: "documentation",
11718 					type: "Documentation",
11719 					isMany: true
11720 				},
11721 				{
11722 					name: "extensionDefinitions",
11723 					type: "ExtensionDefinition",
11724 					isMany: true,
11725 					isReference: true
11726 				},
11727 				{
11728 					name: "extensionElements",
11729 					type: "ExtensionElements"
11730 				}
11731 			]
11732 		},
11733 		{
11734 			name: "Extension",
11735 			properties: [
11736 				{
11737 					name: "mustUnderstand",
11738 					"default": false,
11739 					isAttr: true,
11740 					type: "Boolean"
11741 				},
11742 				{
11743 					name: "definition",
11744 					type: "ExtensionDefinition",
11745 					isAttr: true,
11746 					isReference: true
11747 				}
11748 			]
11749 		},
11750 		{
11751 			name: "ExtensionDefinition",
11752 			properties: [
11753 				{
11754 					name: "name",
11755 					isAttr: true,
11756 					type: "String"
11757 				},
11758 				{
11759 					name: "extensionAttributeDefinitions",
11760 					type: "ExtensionAttributeDefinition",
11761 					isMany: true
11762 				}
11763 			]
11764 		},
11765 		{
11766 			name: "ExtensionAttributeDefinition",
11767 			properties: [
11768 				{
11769 					name: "name",
11770 					isAttr: true,
11771 					type: "String"
11772 				},
11773 				{
11774 					name: "type",
11775 					isAttr: true,
11776 					type: "String"
11777 				},
11778 				{
11779 					name: "isReference",
11780 					"default": false,
11781 					isAttr: true,
11782 					type: "Boolean"
11783 				},
11784 				{
11785 					name: "extensionDefinition",
11786 					type: "ExtensionDefinition",
11787 					isAttr: true,
11788 					isReference: true
11789 				}
11790 			]
11791 		},
11792 		{
11793 			name: "ExtensionElements",
11794 			properties: [
11795 				{
11796 					name: "valueRef",
11797 					isAttr: true,
11798 					isReference: true,
11799 					type: "Element"
11800 				},
11801 				{
11802 					name: "values",
11803 					type: "Element",
11804 					isMany: true
11805 				},
11806 				{
11807 					name: "extensionAttributeDefinition",
11808 					type: "ExtensionAttributeDefinition",
11809 					isAttr: true,
11810 					isReference: true
11811 				}
11812 			]
11813 		},
11814 		{
11815 			name: "Documentation",
11816 			superClass: [
11817 				"BaseElement"
11818 			],
11819 			properties: [
11820 				{
11821 					name: "text",
11822 					type: "String",
11823 					isBody: true
11824 				},
11825 				{
11826 					name: "textFormat",
11827 					"default": "text/plain",
11828 					isAttr: true,
11829 					type: "String"
11830 				}
11831 			]
11832 		},
11833 		{
11834 			name: "Event",
11835 			isAbstract: true,
11836 			superClass: [
11837 				"FlowNode",
11838 				"InteractionNode"
11839 			],
11840 			properties: [
11841 				{
11842 					name: "properties",
11843 					type: "Property",
11844 					isMany: true
11845 				}
11846 			]
11847 		},
11848 		{
11849 			name: "IntermediateCatchEvent",
11850 			superClass: [
11851 				"CatchEvent"
11852 			]
11853 		},
11854 		{
11855 			name: "IntermediateThrowEvent",
11856 			superClass: [
11857 				"ThrowEvent"
11858 			]
11859 		},
11860 		{
11861 			name: "EndEvent",
11862 			superClass: [
11863 				"ThrowEvent"
11864 			]
11865 		},
11866 		{
11867 			name: "StartEvent",
11868 			superClass: [
11869 				"CatchEvent"
11870 			],
11871 			properties: [
11872 				{
11873 					name: "isInterrupting",
11874 					"default": true,
11875 					isAttr: true,
11876 					type: "Boolean"
11877 				}
11878 			]
11879 		},
11880 		{
11881 			name: "ThrowEvent",
11882 			isAbstract: true,
11883 			superClass: [
11884 				"Event"
11885 			],
11886 			properties: [
11887 				{
11888 					name: "dataInputs",
11889 					type: "DataInput",
11890 					isMany: true
11891 				},
11892 				{
11893 					name: "dataInputAssociations",
11894 					type: "DataInputAssociation",
11895 					isMany: true
11896 				},
11897 				{
11898 					name: "inputSet",
11899 					type: "InputSet"
11900 				},
11901 				{
11902 					name: "eventDefinitions",
11903 					type: "EventDefinition",
11904 					isMany: true
11905 				},
11906 				{
11907 					name: "eventDefinitionRef",
11908 					type: "EventDefinition",
11909 					isMany: true,
11910 					isReference: true
11911 				}
11912 			]
11913 		},
11914 		{
11915 			name: "CatchEvent",
11916 			isAbstract: true,
11917 			superClass: [
11918 				"Event"
11919 			],
11920 			properties: [
11921 				{
11922 					name: "parallelMultiple",
11923 					isAttr: true,
11924 					type: "Boolean",
11925 					"default": false
11926 				},
11927 				{
11928 					name: "dataOutputs",
11929 					type: "DataOutput",
11930 					isMany: true
11931 				},
11932 				{
11933 					name: "dataOutputAssociations",
11934 					type: "DataOutputAssociation",
11935 					isMany: true
11936 				},
11937 				{
11938 					name: "outputSet",
11939 					type: "OutputSet"
11940 				},
11941 				{
11942 					name: "eventDefinitions",
11943 					type: "EventDefinition",
11944 					isMany: true
11945 				},
11946 				{
11947 					name: "eventDefinitionRef",
11948 					type: "EventDefinition",
11949 					isMany: true,
11950 					isReference: true
11951 				}
11952 			]
11953 		},
11954 		{
11955 			name: "BoundaryEvent",
11956 			superClass: [
11957 				"CatchEvent"
11958 			],
11959 			properties: [
11960 				{
11961 					name: "cancelActivity",
11962 					"default": true,
11963 					isAttr: true,
11964 					type: "Boolean"
11965 				},
11966 				{
11967 					name: "attachedToRef",
11968 					type: "Activity",
11969 					isAttr: true,
11970 					isReference: true
11971 				}
11972 			]
11973 		},
11974 		{
11975 			name: "EventDefinition",
11976 			isAbstract: true,
11977 			superClass: [
11978 				"RootElement"
11979 			]
11980 		},
11981 		{
11982 			name: "CancelEventDefinition",
11983 			superClass: [
11984 				"EventDefinition"
11985 			]
11986 		},
11987 		{
11988 			name: "ErrorEventDefinition",
11989 			superClass: [
11990 				"EventDefinition"
11991 			],
11992 			properties: [
11993 				{
11994 					name: "errorRef",
11995 					type: "Error",
11996 					isAttr: true,
11997 					isReference: true
11998 				}
11999 			]
12000 		},
12001 		{
12002 			name: "TerminateEventDefinition",
12003 			superClass: [
12004 				"EventDefinition"
12005 			]
12006 		},
12007 		{
12008 			name: "EscalationEventDefinition",
12009 			superClass: [
12010 				"EventDefinition"
12011 			],
12012 			properties: [
12013 				{
12014 					name: "escalationRef",
12015 					type: "Escalation",
12016 					isAttr: true,
12017 					isReference: true
12018 				}
12019 			]
12020 		},
12021 		{
12022 			name: "Escalation",
12023 			properties: [
12024 				{
12025 					name: "structureRef",
12026 					type: "ItemDefinition",
12027 					isAttr: true,
12028 					isReference: true
12029 				},
12030 				{
12031 					name: "name",
12032 					isAttr: true,
12033 					type: "String"
12034 				},
12035 				{
12036 					name: "escalationCode",
12037 					isAttr: true,
12038 					type: "String"
12039 				}
12040 			],
12041 			superClass: [
12042 				"RootElement"
12043 			]
12044 		},
12045 		{
12046 			name: "CompensateEventDefinition",
12047 			superClass: [
12048 				"EventDefinition"
12049 			],
12050 			properties: [
12051 				{
12052 					name: "waitForCompletion",
12053 					isAttr: true,
12054 					type: "Boolean",
12055 					"default": true
12056 				},
12057 				{
12058 					name: "activityRef",
12059 					type: "Activity",
12060 					isAttr: true,
12061 					isReference: true
12062 				}
12063 			]
12064 		},
12065 		{
12066 			name: "TimerEventDefinition",
12067 			superClass: [
12068 				"EventDefinition"
12069 			],
12070 			properties: [
12071 				{
12072 					name: "timeDate",
12073 					type: "Expression",
12074 					xml: {
12075 						serialize: "xsi:type"
12076 					}
12077 				},
12078 				{
12079 					name: "timeCycle",
12080 					type: "Expression",
12081 					xml: {
12082 						serialize: "xsi:type"
12083 					}
12084 				},
12085 				{
12086 					name: "timeDuration",
12087 					type: "Expression",
12088 					xml: {
12089 						serialize: "xsi:type"
12090 					}
12091 				}
12092 			]
12093 		},
12094 		{
12095 			name: "LinkEventDefinition",
12096 			superClass: [
12097 				"EventDefinition"
12098 			],
12099 			properties: [
12100 				{
12101 					name: "name",
12102 					isAttr: true,
12103 					type: "String"
12104 				},
12105 				{
12106 					name: "target",
12107 					type: "LinkEventDefinition",
12108 					isAttr: true,
12109 					isReference: true
12110 				},
12111 				{
12112 					name: "source",
12113 					type: "LinkEventDefinition",
12114 					isMany: true,
12115 					isReference: true
12116 				}
12117 			]
12118 		},
12119 		{
12120 			name: "MessageEventDefinition",
12121 			superClass: [
12122 				"EventDefinition"
12123 			],
12124 			properties: [
12125 				{
12126 					name: "messageRef",
12127 					type: "Message",
12128 					isAttr: true,
12129 					isReference: true
12130 				},
12131 				{
12132 					name: "operationRef",
12133 					type: "Operation",
12134 					isAttr: true,
12135 					isReference: true
12136 				}
12137 			]
12138 		},
12139 		{
12140 			name: "ConditionalEventDefinition",
12141 			superClass: [
12142 				"EventDefinition"
12143 			],
12144 			properties: [
12145 				{
12146 					name: "condition",
12147 					type: "Expression",
12148 					xml: {
12149 						serialize: "xsi:type"
12150 					}
12151 				}
12152 			]
12153 		},
12154 		{
12155 			name: "SignalEventDefinition",
12156 			superClass: [
12157 				"EventDefinition"
12158 			],
12159 			properties: [
12160 				{
12161 					name: "signalRef",
12162 					type: "Signal",
12163 					isAttr: true,
12164 					isReference: true
12165 				}
12166 			]
12167 		},
12168 		{
12169 			name: "Signal",
12170 			superClass: [
12171 				"RootElement"
12172 			],
12173 			properties: [
12174 				{
12175 					name: "structureRef",
12176 					type: "ItemDefinition",
12177 					isAttr: true,
12178 					isReference: true
12179 				},
12180 				{
12181 					name: "name",
12182 					isAttr: true,
12183 					type: "String"
12184 				}
12185 			]
12186 		},
12187 		{
12188 			name: "ImplicitThrowEvent",
12189 			superClass: [
12190 				"ThrowEvent"
12191 			]
12192 		},
12193 		{
12194 			name: "DataState",
12195 			superClass: [
12196 				"BaseElement"
12197 			],
12198 			properties: [
12199 				{
12200 					name: "name",
12201 					isAttr: true,
12202 					type: "String"
12203 				}
12204 			]
12205 		},
12206 		{
12207 			name: "ItemAwareElement",
12208 			superClass: [
12209 				"BaseElement"
12210 			],
12211 			properties: [
12212 				{
12213 					name: "itemSubjectRef",
12214 					type: "ItemDefinition",
12215 					isAttr: true,
12216 					isReference: true
12217 				},
12218 				{
12219 					name: "dataState",
12220 					type: "DataState"
12221 				}
12222 			]
12223 		},
12224 		{
12225 			name: "DataAssociation",
12226 			superClass: [
12227 				"BaseElement"
12228 			],
12229 			properties: [
12230 				{
12231 					name: "sourceRef",
12232 					type: "ItemAwareElement",
12233 					isMany: true,
12234 					isReference: true
12235 				},
12236 				{
12237 					name: "targetRef",
12238 					type: "ItemAwareElement",
12239 					isReference: true
12240 				},
12241 				{
12242 					name: "transformation",
12243 					type: "FormalExpression",
12244 					xml: {
12245 						serialize: "property"
12246 					}
12247 				},
12248 				{
12249 					name: "assignment",
12250 					type: "Assignment",
12251 					isMany: true
12252 				}
12253 			]
12254 		},
12255 		{
12256 			name: "DataInput",
12257 			superClass: [
12258 				"ItemAwareElement"
12259 			],
12260 			properties: [
12261 				{
12262 					name: "name",
12263 					isAttr: true,
12264 					type: "String"
12265 				},
12266 				{
12267 					name: "isCollection",
12268 					"default": false,
12269 					isAttr: true,
12270 					type: "Boolean"
12271 				},
12272 				{
12273 					name: "inputSetRef",
12274 					type: "InputSet",
12275 					isMany: true,
12276 					isVirtual: true,
12277 					isReference: true
12278 				},
12279 				{
12280 					name: "inputSetWithOptional",
12281 					type: "InputSet",
12282 					isMany: true,
12283 					isVirtual: true,
12284 					isReference: true
12285 				},
12286 				{
12287 					name: "inputSetWithWhileExecuting",
12288 					type: "InputSet",
12289 					isMany: true,
12290 					isVirtual: true,
12291 					isReference: true
12292 				}
12293 			]
12294 		},
12295 		{
12296 			name: "DataOutput",
12297 			superClass: [
12298 				"ItemAwareElement"
12299 			],
12300 			properties: [
12301 				{
12302 					name: "name",
12303 					isAttr: true,
12304 					type: "String"
12305 				},
12306 				{
12307 					name: "isCollection",
12308 					"default": false,
12309 					isAttr: true,
12310 					type: "Boolean"
12311 				},
12312 				{
12313 					name: "outputSetRef",
12314 					type: "OutputSet",
12315 					isMany: true,
12316 					isVirtual: true,
12317 					isReference: true
12318 				},
12319 				{
12320 					name: "outputSetWithOptional",
12321 					type: "OutputSet",
12322 					isMany: true,
12323 					isVirtual: true,
12324 					isReference: true
12325 				},
12326 				{
12327 					name: "outputSetWithWhileExecuting",
12328 					type: "OutputSet",
12329 					isMany: true,
12330 					isVirtual: true,
12331 					isReference: true
12332 				}
12333 			]
12334 		},
12335 		{
12336 			name: "InputSet",
12337 			superClass: [
12338 				"BaseElement"
12339 			],
12340 			properties: [
12341 				{
12342 					name: "name",
12343 					isAttr: true,
12344 					type: "String"
12345 				},
12346 				{
12347 					name: "dataInputRefs",
12348 					type: "DataInput",
12349 					isMany: true,
12350 					isReference: true
12351 				},
12352 				{
12353 					name: "optionalInputRefs",
12354 					type: "DataInput",
12355 					isMany: true,
12356 					isReference: true
12357 				},
12358 				{
12359 					name: "whileExecutingInputRefs",
12360 					type: "DataInput",
12361 					isMany: true,
12362 					isReference: true
12363 				},
12364 				{
12365 					name: "outputSetRefs",
12366 					type: "OutputSet",
12367 					isMany: true,
12368 					isReference: true
12369 				}
12370 			]
12371 		},
12372 		{
12373 			name: "OutputSet",
12374 			superClass: [
12375 				"BaseElement"
12376 			],
12377 			properties: [
12378 				{
12379 					name: "dataOutputRefs",
12380 					type: "DataOutput",
12381 					isMany: true,
12382 					isReference: true
12383 				},
12384 				{
12385 					name: "name",
12386 					isAttr: true,
12387 					type: "String"
12388 				},
12389 				{
12390 					name: "inputSetRefs",
12391 					type: "InputSet",
12392 					isMany: true,
12393 					isReference: true
12394 				},
12395 				{
12396 					name: "optionalOutputRefs",
12397 					type: "DataOutput",
12398 					isMany: true,
12399 					isReference: true
12400 				},
12401 				{
12402 					name: "whileExecutingOutputRefs",
12403 					type: "DataOutput",
12404 					isMany: true,
12405 					isReference: true
12406 				}
12407 			]
12408 		},
12409 		{
12410 			name: "Property",
12411 			superClass: [
12412 				"ItemAwareElement"
12413 			],
12414 			properties: [
12415 				{
12416 					name: "name",
12417 					isAttr: true,
12418 					type: "String"
12419 				}
12420 			]
12421 		},
12422 		{
12423 			name: "DataInputAssociation",
12424 			superClass: [
12425 				"DataAssociation"
12426 			]
12427 		},
12428 		{
12429 			name: "DataOutputAssociation",
12430 			superClass: [
12431 				"DataAssociation"
12432 			]
12433 		},
12434 		{
12435 			name: "InputOutputSpecification",
12436 			superClass: [
12437 				"BaseElement"
12438 			],
12439 			properties: [
12440 				{
12441 					name: "dataInputs",
12442 					type: "DataInput",
12443 					isMany: true
12444 				},
12445 				{
12446 					name: "dataOutputs",
12447 					type: "DataOutput",
12448 					isMany: true
12449 				},
12450 				{
12451 					name: "inputSets",
12452 					type: "InputSet",
12453 					isMany: true
12454 				},
12455 				{
12456 					name: "outputSets",
12457 					type: "OutputSet",
12458 					isMany: true
12459 				}
12460 			]
12461 		},
12462 		{
12463 			name: "DataObject",
12464 			superClass: [
12465 				"FlowElement",
12466 				"ItemAwareElement"
12467 			],
12468 			properties: [
12469 				{
12470 					name: "isCollection",
12471 					"default": false,
12472 					isAttr: true,
12473 					type: "Boolean"
12474 				}
12475 			]
12476 		},
12477 		{
12478 			name: "InputOutputBinding",
12479 			properties: [
12480 				{
12481 					name: "inputDataRef",
12482 					type: "InputSet",
12483 					isAttr: true,
12484 					isReference: true
12485 				},
12486 				{
12487 					name: "outputDataRef",
12488 					type: "OutputSet",
12489 					isAttr: true,
12490 					isReference: true
12491 				},
12492 				{
12493 					name: "operationRef",
12494 					type: "Operation",
12495 					isAttr: true,
12496 					isReference: true
12497 				}
12498 			]
12499 		},
12500 		{
12501 			name: "Assignment",
12502 			superClass: [
12503 				"BaseElement"
12504 			],
12505 			properties: [
12506 				{
12507 					name: "from",
12508 					type: "Expression",
12509 					xml: {
12510 						serialize: "xsi:type"
12511 					}
12512 				},
12513 				{
12514 					name: "to",
12515 					type: "Expression",
12516 					xml: {
12517 						serialize: "xsi:type"
12518 					}
12519 				}
12520 			]
12521 		},
12522 		{
12523 			name: "DataStore",
12524 			superClass: [
12525 				"RootElement",
12526 				"ItemAwareElement"
12527 			],
12528 			properties: [
12529 				{
12530 					name: "name",
12531 					isAttr: true,
12532 					type: "String"
12533 				},
12534 				{
12535 					name: "capacity",
12536 					isAttr: true,
12537 					type: "Integer"
12538 				},
12539 				{
12540 					name: "isUnlimited",
12541 					"default": true,
12542 					isAttr: true,
12543 					type: "Boolean"
12544 				}
12545 			]
12546 		},
12547 		{
12548 			name: "DataStoreReference",
12549 			superClass: [
12550 				"ItemAwareElement",
12551 				"FlowElement"
12552 			],
12553 			properties: [
12554 				{
12555 					name: "dataStoreRef",
12556 					type: "DataStore",
12557 					isAttr: true,
12558 					isReference: true
12559 				}
12560 			]
12561 		},
12562 		{
12563 			name: "DataObjectReference",
12564 			superClass: [
12565 				"ItemAwareElement",
12566 				"FlowElement"
12567 			],
12568 			properties: [
12569 				{
12570 					name: "dataObjectRef",
12571 					type: "DataObject",
12572 					isAttr: true,
12573 					isReference: true
12574 				}
12575 			]
12576 		},
12577 		{
12578 			name: "ConversationLink",
12579 			superClass: [
12580 				"BaseElement"
12581 			],
12582 			properties: [
12583 				{
12584 					name: "sourceRef",
12585 					type: "InteractionNode",
12586 					isAttr: true,
12587 					isReference: true
12588 				},
12589 				{
12590 					name: "targetRef",
12591 					type: "InteractionNode",
12592 					isAttr: true,
12593 					isReference: true
12594 				},
12595 				{
12596 					name: "name",
12597 					isAttr: true,
12598 					type: "String"
12599 				}
12600 			]
12601 		},
12602 		{
12603 			name: "ConversationAssociation",
12604 			superClass: [
12605 				"BaseElement"
12606 			],
12607 			properties: [
12608 				{
12609 					name: "innerConversationNodeRef",
12610 					type: "ConversationNode",
12611 					isAttr: true,
12612 					isReference: true
12613 				},
12614 				{
12615 					name: "outerConversationNodeRef",
12616 					type: "ConversationNode",
12617 					isAttr: true,
12618 					isReference: true
12619 				}
12620 			]
12621 		},
12622 		{
12623 			name: "CallConversation",
12624 			superClass: [
12625 				"ConversationNode"
12626 			],
12627 			properties: [
12628 				{
12629 					name: "calledCollaborationRef",
12630 					type: "Collaboration",
12631 					isAttr: true,
12632 					isReference: true
12633 				},
12634 				{
12635 					name: "participantAssociations",
12636 					type: "ParticipantAssociation",
12637 					isMany: true
12638 				}
12639 			]
12640 		},
12641 		{
12642 			name: "Conversation",
12643 			superClass: [
12644 				"ConversationNode"
12645 			]
12646 		},
12647 		{
12648 			name: "SubConversation",
12649 			superClass: [
12650 				"ConversationNode"
12651 			],
12652 			properties: [
12653 				{
12654 					name: "conversationNodes",
12655 					type: "ConversationNode",
12656 					isMany: true
12657 				}
12658 			]
12659 		},
12660 		{
12661 			name: "ConversationNode",
12662 			isAbstract: true,
12663 			superClass: [
12664 				"InteractionNode",
12665 				"BaseElement"
12666 			],
12667 			properties: [
12668 				{
12669 					name: "name",
12670 					isAttr: true,
12671 					type: "String"
12672 				},
12673 				{
12674 					name: "participantRef",
12675 					type: "Participant",
12676 					isMany: true,
12677 					isReference: true
12678 				},
12679 				{
12680 					name: "messageFlowRefs",
12681 					type: "MessageFlow",
12682 					isMany: true,
12683 					isReference: true
12684 				},
12685 				{
12686 					name: "correlationKeys",
12687 					type: "CorrelationKey",
12688 					isMany: true
12689 				}
12690 			]
12691 		},
12692 		{
12693 			name: "GlobalConversation",
12694 			superClass: [
12695 				"Collaboration"
12696 			]
12697 		},
12698 		{
12699 			name: "PartnerEntity",
12700 			superClass: [
12701 				"RootElement"
12702 			],
12703 			properties: [
12704 				{
12705 					name: "name",
12706 					isAttr: true,
12707 					type: "String"
12708 				},
12709 				{
12710 					name: "participantRef",
12711 					type: "Participant",
12712 					isMany: true,
12713 					isReference: true
12714 				}
12715 			]
12716 		},
12717 		{
12718 			name: "PartnerRole",
12719 			superClass: [
12720 				"RootElement"
12721 			],
12722 			properties: [
12723 				{
12724 					name: "name",
12725 					isAttr: true,
12726 					type: "String"
12727 				},
12728 				{
12729 					name: "participantRef",
12730 					type: "Participant",
12731 					isMany: true,
12732 					isReference: true
12733 				}
12734 			]
12735 		},
12736 		{
12737 			name: "CorrelationProperty",
12738 			superClass: [
12739 				"RootElement"
12740 			],
12741 			properties: [
12742 				{
12743 					name: "correlationPropertyRetrievalExpression",
12744 					type: "CorrelationPropertyRetrievalExpression",
12745 					isMany: true
12746 				},
12747 				{
12748 					name: "name",
12749 					isAttr: true,
12750 					type: "String"
12751 				},
12752 				{
12753 					name: "type",
12754 					type: "ItemDefinition",
12755 					isAttr: true,
12756 					isReference: true
12757 				}
12758 			]
12759 		},
12760 		{
12761 			name: "Error",
12762 			superClass: [
12763 				"RootElement"
12764 			],
12765 			properties: [
12766 				{
12767 					name: "structureRef",
12768 					type: "ItemDefinition",
12769 					isAttr: true,
12770 					isReference: true
12771 				},
12772 				{
12773 					name: "name",
12774 					isAttr: true,
12775 					type: "String"
12776 				},
12777 				{
12778 					name: "errorCode",
12779 					isAttr: true,
12780 					type: "String"
12781 				}
12782 			]
12783 		},
12784 		{
12785 			name: "CorrelationKey",
12786 			superClass: [
12787 				"BaseElement"
12788 			],
12789 			properties: [
12790 				{
12791 					name: "correlationPropertyRef",
12792 					type: "CorrelationProperty",
12793 					isMany: true,
12794 					isReference: true
12795 				},
12796 				{
12797 					name: "name",
12798 					isAttr: true,
12799 					type: "String"
12800 				}
12801 			]
12802 		},
12803 		{
12804 			name: "Expression",
12805 			superClass: [
12806 				"BaseElement"
12807 			],
12808 			isAbstract: false,
12809 			properties: [
12810 				{
12811 					name: "body",
12812 					isBody: true,
12813 					type: "String"
12814 				}
12815 			]
12816 		},
12817 		{
12818 			name: "FormalExpression",
12819 			superClass: [
12820 				"Expression"
12821 			],
12822 			properties: [
12823 				{
12824 					name: "language",
12825 					isAttr: true,
12826 					type: "String"
12827 				},
12828 				{
12829 					name: "evaluatesToTypeRef",
12830 					type: "ItemDefinition",
12831 					isAttr: true,
12832 					isReference: true
12833 				}
12834 			]
12835 		},
12836 		{
12837 			name: "Message",
12838 			superClass: [
12839 				"RootElement"
12840 			],
12841 			properties: [
12842 				{
12843 					name: "name",
12844 					isAttr: true,
12845 					type: "String"
12846 				},
12847 				{
12848 					name: "itemRef",
12849 					type: "ItemDefinition",
12850 					isAttr: true,
12851 					isReference: true
12852 				}
12853 			]
12854 		},
12855 		{
12856 			name: "ItemDefinition",
12857 			superClass: [
12858 				"RootElement"
12859 			],
12860 			properties: [
12861 				{
12862 					name: "itemKind",
12863 					type: "ItemKind",
12864 					isAttr: true
12865 				},
12866 				{
12867 					name: "structureRef",
12868 					isAttr: true,
12869 					type: "String"
12870 				},
12871 				{
12872 					name: "isCollection",
12873 					"default": false,
12874 					isAttr: true,
12875 					type: "Boolean"
12876 				},
12877 				{
12878 					name: "import",
12879 					type: "Import",
12880 					isAttr: true,
12881 					isReference: true
12882 				}
12883 			]
12884 		},
12885 		{
12886 			name: "FlowElement",
12887 			isAbstract: true,
12888 			superClass: [
12889 				"BaseElement"
12890 			],
12891 			properties: [
12892 				{
12893 					name: "name",
12894 					isAttr: true,
12895 					type: "String"
12896 				},
12897 				{
12898 					name: "auditing",
12899 					type: "Auditing"
12900 				},
12901 				{
12902 					name: "monitoring",
12903 					type: "Monitoring"
12904 				},
12905 				{
12906 					name: "categoryValueRef",
12907 					type: "CategoryValue",
12908 					isMany: true,
12909 					isReference: true
12910 				}
12911 			]
12912 		},
12913 		{
12914 			name: "SequenceFlow",
12915 			superClass: [
12916 				"FlowElement"
12917 			],
12918 			properties: [
12919 				{
12920 					name: "isImmediate",
12921 					isAttr: true,
12922 					type: "Boolean"
12923 				},
12924 				{
12925 					name: "conditionExpression",
12926 					type: "Expression",
12927 					xml: {
12928 						serialize: "xsi:type"
12929 					}
12930 				},
12931 				{
12932 					name: "sourceRef",
12933 					type: "FlowNode",
12934 					isAttr: true,
12935 					isReference: true
12936 				},
12937 				{
12938 					name: "targetRef",
12939 					type: "FlowNode",
12940 					isAttr: true,
12941 					isReference: true
12942 				}
12943 			]
12944 		},
12945 		{
12946 			name: "FlowElementsContainer",
12947 			isAbstract: true,
12948 			superClass: [
12949 				"BaseElement"
12950 			],
12951 			properties: [
12952 				{
12953 					name: "laneSets",
12954 					type: "LaneSet",
12955 					isMany: true
12956 				},
12957 				{
12958 					name: "flowElements",
12959 					type: "FlowElement",
12960 					isMany: true
12961 				}
12962 			]
12963 		},
12964 		{
12965 			name: "CallableElement",
12966 			isAbstract: true,
12967 			superClass: [
12968 				"RootElement"
12969 			],
12970 			properties: [
12971 				{
12972 					name: "name",
12973 					isAttr: true,
12974 					type: "String"
12975 				},
12976 				{
12977 					name: "ioSpecification",
12978 					type: "InputOutputSpecification",
12979 					xml: {
12980 						serialize: "property"
12981 					}
12982 				},
12983 				{
12984 					name: "supportedInterfaceRef",
12985 					type: "Interface",
12986 					isMany: true,
12987 					isReference: true
12988 				},
12989 				{
12990 					name: "ioBinding",
12991 					type: "InputOutputBinding",
12992 					isMany: true,
12993 					xml: {
12994 						serialize: "property"
12995 					}
12996 				}
12997 			]
12998 		},
12999 		{
13000 			name: "FlowNode",
13001 			isAbstract: true,
13002 			superClass: [
13003 				"FlowElement"
13004 			],
13005 			properties: [
13006 				{
13007 					name: "incoming",
13008 					type: "SequenceFlow",
13009 					isMany: true,
13010 					isReference: true
13011 				},
13012 				{
13013 					name: "outgoing",
13014 					type: "SequenceFlow",
13015 					isMany: true,
13016 					isReference: true
13017 				},
13018 				{
13019 					name: "lanes",
13020 					type: "Lane",
13021 					isMany: true,
13022 					isVirtual: true,
13023 					isReference: true
13024 				}
13025 			]
13026 		},
13027 		{
13028 			name: "CorrelationPropertyRetrievalExpression",
13029 			superClass: [
13030 				"BaseElement"
13031 			],
13032 			properties: [
13033 				{
13034 					name: "messagePath",
13035 					type: "FormalExpression"
13036 				},
13037 				{
13038 					name: "messageRef",
13039 					type: "Message",
13040 					isAttr: true,
13041 					isReference: true
13042 				}
13043 			]
13044 		},
13045 		{
13046 			name: "CorrelationPropertyBinding",
13047 			superClass: [
13048 				"BaseElement"
13049 			],
13050 			properties: [
13051 				{
13052 					name: "dataPath",
13053 					type: "FormalExpression"
13054 				},
13055 				{
13056 					name: "correlationPropertyRef",
13057 					type: "CorrelationProperty",
13058 					isAttr: true,
13059 					isReference: true
13060 				}
13061 			]
13062 		},
13063 		{
13064 			name: "Resource",
13065 			superClass: [
13066 				"RootElement"
13067 			],
13068 			properties: [
13069 				{
13070 					name: "name",
13071 					isAttr: true,
13072 					type: "String"
13073 				},
13074 				{
13075 					name: "resourceParameters",
13076 					type: "ResourceParameter",
13077 					isMany: true
13078 				}
13079 			]
13080 		},
13081 		{
13082 			name: "ResourceParameter",
13083 			superClass: [
13084 				"BaseElement"
13085 			],
13086 			properties: [
13087 				{
13088 					name: "name",
13089 					isAttr: true,
13090 					type: "String"
13091 				},
13092 				{
13093 					name: "isRequired",
13094 					isAttr: true,
13095 					type: "Boolean"
13096 				},
13097 				{
13098 					name: "type",
13099 					type: "ItemDefinition",
13100 					isAttr: true,
13101 					isReference: true
13102 				}
13103 			]
13104 		},
13105 		{
13106 			name: "CorrelationSubscription",
13107 			superClass: [
13108 				"BaseElement"
13109 			],
13110 			properties: [
13111 				{
13112 					name: "correlationKeyRef",
13113 					type: "CorrelationKey",
13114 					isAttr: true,
13115 					isReference: true
13116 				},
13117 				{
13118 					name: "correlationPropertyBinding",
13119 					type: "CorrelationPropertyBinding",
13120 					isMany: true
13121 				}
13122 			]
13123 		},
13124 		{
13125 			name: "MessageFlow",
13126 			superClass: [
13127 				"BaseElement"
13128 			],
13129 			properties: [
13130 				{
13131 					name: "name",
13132 					isAttr: true,
13133 					type: "String"
13134 				},
13135 				{
13136 					name: "sourceRef",
13137 					type: "InteractionNode",
13138 					isAttr: true,
13139 					isReference: true
13140 				},
13141 				{
13142 					name: "targetRef",
13143 					type: "InteractionNode",
13144 					isAttr: true,
13145 					isReference: true
13146 				},
13147 				{
13148 					name: "messageRef",
13149 					type: "Message",
13150 					isAttr: true,
13151 					isReference: true
13152 				}
13153 			]
13154 		},
13155 		{
13156 			name: "MessageFlowAssociation",
13157 			superClass: [
13158 				"BaseElement"
13159 			],
13160 			properties: [
13161 				{
13162 					name: "innerMessageFlowRef",
13163 					type: "MessageFlow",
13164 					isAttr: true,
13165 					isReference: true
13166 				},
13167 				{
13168 					name: "outerMessageFlowRef",
13169 					type: "MessageFlow",
13170 					isAttr: true,
13171 					isReference: true
13172 				}
13173 			]
13174 		},
13175 		{
13176 			name: "InteractionNode",
13177 			isAbstract: true,
13178 			properties: [
13179 				{
13180 					name: "incomingConversationLinks",
13181 					type: "ConversationLink",
13182 					isMany: true,
13183 					isVirtual: true,
13184 					isReference: true
13185 				},
13186 				{
13187 					name: "outgoingConversationLinks",
13188 					type: "ConversationLink",
13189 					isMany: true,
13190 					isVirtual: true,
13191 					isReference: true
13192 				}
13193 			]
13194 		},
13195 		{
13196 			name: "Participant",
13197 			superClass: [
13198 				"InteractionNode",
13199 				"BaseElement"
13200 			],
13201 			properties: [
13202 				{
13203 					name: "name",
13204 					isAttr: true,
13205 					type: "String"
13206 				},
13207 				{
13208 					name: "interfaceRef",
13209 					type: "Interface",
13210 					isMany: true,
13211 					isReference: true
13212 				},
13213 				{
13214 					name: "participantMultiplicity",
13215 					type: "ParticipantMultiplicity"
13216 				},
13217 				{
13218 					name: "endPointRefs",
13219 					type: "EndPoint",
13220 					isMany: true,
13221 					isReference: true
13222 				},
13223 				{
13224 					name: "processRef",
13225 					type: "Process",
13226 					isAttr: true,
13227 					isReference: true
13228 				}
13229 			]
13230 		},
13231 		{
13232 			name: "ParticipantAssociation",
13233 			superClass: [
13234 				"BaseElement"
13235 			],
13236 			properties: [
13237 				{
13238 					name: "innerParticipantRef",
13239 					type: "Participant",
13240 					isAttr: true,
13241 					isReference: true
13242 				},
13243 				{
13244 					name: "outerParticipantRef",
13245 					type: "Participant",
13246 					isAttr: true,
13247 					isReference: true
13248 				}
13249 			]
13250 		},
13251 		{
13252 			name: "ParticipantMultiplicity",
13253 			properties: [
13254 				{
13255 					name: "minimum",
13256 					"default": 0,
13257 					isAttr: true,
13258 					type: "Integer"
13259 				},
13260 				{
13261 					name: "maximum",
13262 					"default": 1,
13263 					isAttr: true,
13264 					type: "Integer"
13265 				}
13266 			],
13267 			superClass: [
13268 				"BaseElement"
13269 			]
13270 		},
13271 		{
13272 			name: "Collaboration",
13273 			superClass: [
13274 				"RootElement"
13275 			],
13276 			properties: [
13277 				{
13278 					name: "name",
13279 					isAttr: true,
13280 					type: "String"
13281 				},
13282 				{
13283 					name: "isClosed",
13284 					isAttr: true,
13285 					type: "Boolean"
13286 				},
13287 				{
13288 					name: "participants",
13289 					type: "Participant",
13290 					isMany: true
13291 				},
13292 				{
13293 					name: "messageFlows",
13294 					type: "MessageFlow",
13295 					isMany: true
13296 				},
13297 				{
13298 					name: "artifacts",
13299 					type: "Artifact",
13300 					isMany: true
13301 				},
13302 				{
13303 					name: "conversations",
13304 					type: "ConversationNode",
13305 					isMany: true
13306 				},
13307 				{
13308 					name: "conversationAssociations",
13309 					type: "ConversationAssociation"
13310 				},
13311 				{
13312 					name: "participantAssociations",
13313 					type: "ParticipantAssociation",
13314 					isMany: true
13315 				},
13316 				{
13317 					name: "messageFlowAssociations",
13318 					type: "MessageFlowAssociation",
13319 					isMany: true
13320 				},
13321 				{
13322 					name: "correlationKeys",
13323 					type: "CorrelationKey",
13324 					isMany: true
13325 				},
13326 				{
13327 					name: "choreographyRef",
13328 					type: "Choreography",
13329 					isMany: true,
13330 					isReference: true
13331 				},
13332 				{
13333 					name: "conversationLinks",
13334 					type: "ConversationLink",
13335 					isMany: true
13336 				}
13337 			]
13338 		},
13339 		{
13340 			name: "ChoreographyActivity",
13341 			isAbstract: true,
13342 			superClass: [
13343 				"FlowNode"
13344 			],
13345 			properties: [
13346 				{
13347 					name: "participantRef",
13348 					type: "Participant",
13349 					isMany: true,
13350 					isReference: true
13351 				},
13352 				{
13353 					name: "initiatingParticipantRef",
13354 					type: "Participant",
13355 					isAttr: true,
13356 					isReference: true
13357 				},
13358 				{
13359 					name: "correlationKeys",
13360 					type: "CorrelationKey",
13361 					isMany: true
13362 				},
13363 				{
13364 					name: "loopType",
13365 					type: "ChoreographyLoopType",
13366 					"default": "None",
13367 					isAttr: true
13368 				}
13369 			]
13370 		},
13371 		{
13372 			name: "CallChoreography",
13373 			superClass: [
13374 				"ChoreographyActivity"
13375 			],
13376 			properties: [
13377 				{
13378 					name: "calledChoreographyRef",
13379 					type: "Choreography",
13380 					isAttr: true,
13381 					isReference: true
13382 				},
13383 				{
13384 					name: "participantAssociations",
13385 					type: "ParticipantAssociation",
13386 					isMany: true
13387 				}
13388 			]
13389 		},
13390 		{
13391 			name: "SubChoreography",
13392 			superClass: [
13393 				"ChoreographyActivity",
13394 				"FlowElementsContainer"
13395 			],
13396 			properties: [
13397 				{
13398 					name: "artifacts",
13399 					type: "Artifact",
13400 					isMany: true
13401 				}
13402 			]
13403 		},
13404 		{
13405 			name: "ChoreographyTask",
13406 			superClass: [
13407 				"ChoreographyActivity"
13408 			],
13409 			properties: [
13410 				{
13411 					name: "messageFlowRef",
13412 					type: "MessageFlow",
13413 					isMany: true,
13414 					isReference: true
13415 				}
13416 			]
13417 		},
13418 		{
13419 			name: "Choreography",
13420 			superClass: [
13421 				"Collaboration",
13422 				"FlowElementsContainer"
13423 			]
13424 		},
13425 		{
13426 			name: "GlobalChoreographyTask",
13427 			superClass: [
13428 				"Choreography"
13429 			],
13430 			properties: [
13431 				{
13432 					name: "initiatingParticipantRef",
13433 					type: "Participant",
13434 					isAttr: true,
13435 					isReference: true
13436 				}
13437 			]
13438 		},
13439 		{
13440 			name: "TextAnnotation",
13441 			superClass: [
13442 				"Artifact"
13443 			],
13444 			properties: [
13445 				{
13446 					name: "text",
13447 					type: "String"
13448 				},
13449 				{
13450 					name: "textFormat",
13451 					"default": "text/plain",
13452 					isAttr: true,
13453 					type: "String"
13454 				}
13455 			]
13456 		},
13457 		{
13458 			name: "Group",
13459 			superClass: [
13460 				"Artifact"
13461 			],
13462 			properties: [
13463 				{
13464 					name: "categoryValueRef",
13465 					type: "CategoryValue",
13466 					isAttr: true,
13467 					isReference: true
13468 				}
13469 			]
13470 		},
13471 		{
13472 			name: "Association",
13473 			superClass: [
13474 				"Artifact"
13475 			],
13476 			properties: [
13477 				{
13478 					name: "associationDirection",
13479 					type: "AssociationDirection",
13480 					isAttr: true
13481 				},
13482 				{
13483 					name: "sourceRef",
13484 					type: "BaseElement",
13485 					isAttr: true,
13486 					isReference: true
13487 				},
13488 				{
13489 					name: "targetRef",
13490 					type: "BaseElement",
13491 					isAttr: true,
13492 					isReference: true
13493 				}
13494 			]
13495 		},
13496 		{
13497 			name: "Category",
13498 			superClass: [
13499 				"RootElement"
13500 			],
13501 			properties: [
13502 				{
13503 					name: "categoryValue",
13504 					type: "CategoryValue",
13505 					isMany: true
13506 				},
13507 				{
13508 					name: "name",
13509 					isAttr: true,
13510 					type: "String"
13511 				}
13512 			]
13513 		},
13514 		{
13515 			name: "Artifact",
13516 			isAbstract: true,
13517 			superClass: [
13518 				"BaseElement"
13519 			]
13520 		},
13521 		{
13522 			name: "CategoryValue",
13523 			superClass: [
13524 				"BaseElement"
13525 			],
13526 			properties: [
13527 				{
13528 					name: "categorizedFlowElements",
13529 					type: "FlowElement",
13530 					isMany: true,
13531 					isVirtual: true,
13532 					isReference: true
13533 				},
13534 				{
13535 					name: "value",
13536 					isAttr: true,
13537 					type: "String"
13538 				}
13539 			]
13540 		},
13541 		{
13542 			name: "Activity",
13543 			isAbstract: true,
13544 			superClass: [
13545 				"FlowNode"
13546 			],
13547 			properties: [
13548 				{
13549 					name: "isForCompensation",
13550 					"default": false,
13551 					isAttr: true,
13552 					type: "Boolean"
13553 				},
13554 				{
13555 					name: "default",
13556 					type: "SequenceFlow",
13557 					isAttr: true,
13558 					isReference: true
13559 				},
13560 				{
13561 					name: "ioSpecification",
13562 					type: "InputOutputSpecification",
13563 					xml: {
13564 						serialize: "property"
13565 					}
13566 				},
13567 				{
13568 					name: "boundaryEventRefs",
13569 					type: "BoundaryEvent",
13570 					isMany: true,
13571 					isReference: true
13572 				},
13573 				{
13574 					name: "properties",
13575 					type: "Property",
13576 					isMany: true
13577 				},
13578 				{
13579 					name: "dataInputAssociations",
13580 					type: "DataInputAssociation",
13581 					isMany: true
13582 				},
13583 				{
13584 					name: "dataOutputAssociations",
13585 					type: "DataOutputAssociation",
13586 					isMany: true
13587 				},
13588 				{
13589 					name: "startQuantity",
13590 					"default": 1,
13591 					isAttr: true,
13592 					type: "Integer"
13593 				},
13594 				{
13595 					name: "resources",
13596 					type: "ResourceRole",
13597 					isMany: true
13598 				},
13599 				{
13600 					name: "completionQuantity",
13601 					"default": 1,
13602 					isAttr: true,
13603 					type: "Integer"
13604 				},
13605 				{
13606 					name: "loopCharacteristics",
13607 					type: "LoopCharacteristics"
13608 				}
13609 			]
13610 		},
13611 		{
13612 			name: "ServiceTask",
13613 			superClass: [
13614 				"Task"
13615 			],
13616 			properties: [
13617 				{
13618 					name: "implementation",
13619 					isAttr: true,
13620 					type: "String"
13621 				},
13622 				{
13623 					name: "operationRef",
13624 					type: "Operation",
13625 					isAttr: true,
13626 					isReference: true
13627 				}
13628 			]
13629 		},
13630 		{
13631 			name: "SubProcess",
13632 			superClass: [
13633 				"Activity",
13634 				"FlowElementsContainer",
13635 				"InteractionNode"
13636 			],
13637 			properties: [
13638 				{
13639 					name: "triggeredByEvent",
13640 					"default": false,
13641 					isAttr: true,
13642 					type: "Boolean"
13643 				},
13644 				{
13645 					name: "artifacts",
13646 					type: "Artifact",
13647 					isMany: true
13648 				}
13649 			]
13650 		},
13651 		{
13652 			name: "LoopCharacteristics",
13653 			isAbstract: true,
13654 			superClass: [
13655 				"BaseElement"
13656 			]
13657 		},
13658 		{
13659 			name: "MultiInstanceLoopCharacteristics",
13660 			superClass: [
13661 				"LoopCharacteristics"
13662 			],
13663 			properties: [
13664 				{
13665 					name: "isSequential",
13666 					"default": false,
13667 					isAttr: true,
13668 					type: "Boolean"
13669 				},
13670 				{
13671 					name: "behavior",
13672 					type: "MultiInstanceBehavior",
13673 					"default": "All",
13674 					isAttr: true
13675 				},
13676 				{
13677 					name: "loopCardinality",
13678 					type: "Expression",
13679 					xml: {
13680 						serialize: "xsi:type"
13681 					}
13682 				},
13683 				{
13684 					name: "loopDataInputRef",
13685 					type: "ItemAwareElement",
13686 					isReference: true
13687 				},
13688 				{
13689 					name: "loopDataOutputRef",
13690 					type: "ItemAwareElement",
13691 					isReference: true
13692 				},
13693 				{
13694 					name: "inputDataItem",
13695 					type: "DataInput",
13696 					xml: {
13697 						serialize: "property"
13698 					}
13699 				},
13700 				{
13701 					name: "outputDataItem",
13702 					type: "DataOutput",
13703 					xml: {
13704 						serialize: "property"
13705 					}
13706 				},
13707 				{
13708 					name: "complexBehaviorDefinition",
13709 					type: "ComplexBehaviorDefinition",
13710 					isMany: true
13711 				},
13712 				{
13713 					name: "completionCondition",
13714 					type: "Expression",
13715 					xml: {
13716 						serialize: "xsi:type"
13717 					}
13718 				},
13719 				{
13720 					name: "oneBehaviorEventRef",
13721 					type: "EventDefinition",
13722 					isAttr: true,
13723 					isReference: true
13724 				},
13725 				{
13726 					name: "noneBehaviorEventRef",
13727 					type: "EventDefinition",
13728 					isAttr: true,
13729 					isReference: true
13730 				}
13731 			]
13732 		},
13733 		{
13734 			name: "StandardLoopCharacteristics",
13735 			superClass: [
13736 				"LoopCharacteristics"
13737 			],
13738 			properties: [
13739 				{
13740 					name: "testBefore",
13741 					"default": false,
13742 					isAttr: true,
13743 					type: "Boolean"
13744 				},
13745 				{
13746 					name: "loopCondition",
13747 					type: "Expression",
13748 					xml: {
13749 						serialize: "xsi:type"
13750 					}
13751 				},
13752 				{
13753 					name: "loopMaximum",
13754 					type: "Integer",
13755 					isAttr: true
13756 				}
13757 			]
13758 		},
13759 		{
13760 			name: "CallActivity",
13761 			superClass: [
13762 				"Activity",
13763 				"InteractionNode"
13764 			],
13765 			properties: [
13766 				{
13767 					name: "calledElement",
13768 					type: "String",
13769 					isAttr: true
13770 				}
13771 			]
13772 		},
13773 		{
13774 			name: "Task",
13775 			superClass: [
13776 				"Activity",
13777 				"InteractionNode"
13778 			]
13779 		},
13780 		{
13781 			name: "SendTask",
13782 			superClass: [
13783 				"Task"
13784 			],
13785 			properties: [
13786 				{
13787 					name: "implementation",
13788 					isAttr: true,
13789 					type: "String"
13790 				},
13791 				{
13792 					name: "operationRef",
13793 					type: "Operation",
13794 					isAttr: true,
13795 					isReference: true
13796 				},
13797 				{
13798 					name: "messageRef",
13799 					type: "Message",
13800 					isAttr: true,
13801 					isReference: true
13802 				}
13803 			]
13804 		},
13805 		{
13806 			name: "ReceiveTask",
13807 			superClass: [
13808 				"Task"
13809 			],
13810 			properties: [
13811 				{
13812 					name: "implementation",
13813 					isAttr: true,
13814 					type: "String"
13815 				},
13816 				{
13817 					name: "instantiate",
13818 					"default": false,
13819 					isAttr: true,
13820 					type: "Boolean"
13821 				},
13822 				{
13823 					name: "operationRef",
13824 					type: "Operation",
13825 					isAttr: true,
13826 					isReference: true
13827 				},
13828 				{
13829 					name: "messageRef",
13830 					type: "Message",
13831 					isAttr: true,
13832 					isReference: true
13833 				}
13834 			]
13835 		},
13836 		{
13837 			name: "ScriptTask",
13838 			superClass: [
13839 				"Task"
13840 			],
13841 			properties: [
13842 				{
13843 					name: "scriptFormat",
13844 					isAttr: true,
13845 					type: "String"
13846 				},
13847 				{
13848 					name: "script",
13849 					type: "String"
13850 				}
13851 			]
13852 		},
13853 		{
13854 			name: "BusinessRuleTask",
13855 			superClass: [
13856 				"Task"
13857 			],
13858 			properties: [
13859 				{
13860 					name: "implementation",
13861 					isAttr: true,
13862 					type: "String"
13863 				}
13864 			]
13865 		},
13866 		{
13867 			name: "AdHocSubProcess",
13868 			superClass: [
13869 				"SubProcess"
13870 			],
13871 			properties: [
13872 				{
13873 					name: "completionCondition",
13874 					type: "Expression",
13875 					xml: {
13876 						serialize: "xsi:type"
13877 					}
13878 				},
13879 				{
13880 					name: "ordering",
13881 					type: "AdHocOrdering",
13882 					isAttr: true
13883 				},
13884 				{
13885 					name: "cancelRemainingInstances",
13886 					"default": true,
13887 					isAttr: true,
13888 					type: "Boolean"
13889 				}
13890 			]
13891 		},
13892 		{
13893 			name: "Transaction",
13894 			superClass: [
13895 				"SubProcess"
13896 			],
13897 			properties: [
13898 				{
13899 					name: "protocol",
13900 					isAttr: true,
13901 					type: "String"
13902 				},
13903 				{
13904 					name: "method",
13905 					isAttr: true,
13906 					type: "String"
13907 				}
13908 			]
13909 		},
13910 		{
13911 			name: "GlobalScriptTask",
13912 			superClass: [
13913 				"GlobalTask"
13914 			],
13915 			properties: [
13916 				{
13917 					name: "scriptLanguage",
13918 					isAttr: true,
13919 					type: "String"
13920 				},
13921 				{
13922 					name: "script",
13923 					isAttr: true,
13924 					type: "String"
13925 				}
13926 			]
13927 		},
13928 		{
13929 			name: "GlobalBusinessRuleTask",
13930 			superClass: [
13931 				"GlobalTask"
13932 			],
13933 			properties: [
13934 				{
13935 					name: "implementation",
13936 					isAttr: true,
13937 					type: "String"
13938 				}
13939 			]
13940 		},
13941 		{
13942 			name: "ComplexBehaviorDefinition",
13943 			superClass: [
13944 				"BaseElement"
13945 			],
13946 			properties: [
13947 				{
13948 					name: "condition",
13949 					type: "FormalExpression"
13950 				},
13951 				{
13952 					name: "event",
13953 					type: "ImplicitThrowEvent"
13954 				}
13955 			]
13956 		},
13957 		{
13958 			name: "ResourceRole",
13959 			superClass: [
13960 				"BaseElement"
13961 			],
13962 			properties: [
13963 				{
13964 					name: "resourceRef",
13965 					type: "Resource",
13966 					isReference: true
13967 				},
13968 				{
13969 					name: "resourceParameterBindings",
13970 					type: "ResourceParameterBinding",
13971 					isMany: true
13972 				},
13973 				{
13974 					name: "resourceAssignmentExpression",
13975 					type: "ResourceAssignmentExpression"
13976 				},
13977 				{
13978 					name: "name",
13979 					isAttr: true,
13980 					type: "String"
13981 				}
13982 			]
13983 		},
13984 		{
13985 			name: "ResourceParameterBinding",
13986 			properties: [
13987 				{
13988 					name: "expression",
13989 					type: "Expression",
13990 					xml: {
13991 						serialize: "xsi:type"
13992 					}
13993 				},
13994 				{
13995 					name: "parameterRef",
13996 					type: "ResourceParameter",
13997 					isAttr: true,
13998 					isReference: true
13999 				}
14000 			],
14001 			superClass: [
14002 				"BaseElement"
14003 			]
14004 		},
14005 		{
14006 			name: "ResourceAssignmentExpression",
14007 			properties: [
14008 				{
14009 					name: "expression",
14010 					type: "Expression",
14011 					xml: {
14012 						serialize: "xsi:type"
14013 					}
14014 				}
14015 			],
14016 			superClass: [
14017 				"BaseElement"
14018 			]
14019 		},
14020 		{
14021 			name: "Import",
14022 			properties: [
14023 				{
14024 					name: "importType",
14025 					isAttr: true,
14026 					type: "String"
14027 				},
14028 				{
14029 					name: "location",
14030 					isAttr: true,
14031 					type: "String"
14032 				},
14033 				{
14034 					name: "namespace",
14035 					isAttr: true,
14036 					type: "String"
14037 				}
14038 			]
14039 		},
14040 		{
14041 			name: "Definitions",
14042 			superClass: [
14043 				"BaseElement"
14044 			],
14045 			properties: [
14046 				{
14047 					name: "name",
14048 					isAttr: true,
14049 					type: "String"
14050 				},
14051 				{
14052 					name: "targetNamespace",
14053 					isAttr: true,
14054 					type: "String"
14055 				},
14056 				{
14057 					name: "expressionLanguage",
14058 					"default": "http://www.w3.org/1999/XPath",
14059 					isAttr: true,
14060 					type: "String"
14061 				},
14062 				{
14063 					name: "typeLanguage",
14064 					"default": "http://www.w3.org/2001/XMLSchema",
14065 					isAttr: true,
14066 					type: "String"
14067 				},
14068 				{
14069 					name: "imports",
14070 					type: "Import",
14071 					isMany: true
14072 				},
14073 				{
14074 					name: "extensions",
14075 					type: "Extension",
14076 					isMany: true
14077 				},
14078 				{
14079 					name: "rootElements",
14080 					type: "RootElement",
14081 					isMany: true
14082 				},
14083 				{
14084 					name: "diagrams",
14085 					isMany: true,
14086 					type: "bpmndi:BPMNDiagram"
14087 				},
14088 				{
14089 					name: "exporter",
14090 					isAttr: true,
14091 					type: "String"
14092 				},
14093 				{
14094 					name: "relationships",
14095 					type: "Relationship",
14096 					isMany: true
14097 				},
14098 				{
14099 					name: "exporterVersion",
14100 					isAttr: true,
14101 					type: "String"
14102 				}
14103 			]
14104 		}
14105 	];
14106 	var enumerations = [
14107 		{
14108 			name: "ProcessType",
14109 			literalValues: [
14110 				{
14111 					name: "None"
14112 				},
14113 				{
14114 					name: "Public"
14115 				},
14116 				{
14117 					name: "Private"
14118 				}
14119 			]
14120 		},
14121 		{
14122 			name: "GatewayDirection",
14123 			literalValues: [
14124 				{
14125 					name: "Unspecified"
14126 				},
14127 				{
14128 					name: "Converging"
14129 				},
14130 				{
14131 					name: "Diverging"
14132 				},
14133 				{
14134 					name: "Mixed"
14135 				}
14136 			]
14137 		},
14138 		{
14139 			name: "EventBasedGatewayType",
14140 			literalValues: [
14141 				{
14142 					name: "Parallel"
14143 				},
14144 				{
14145 					name: "Exclusive"
14146 				}
14147 			]
14148 		},
14149 		{
14150 			name: "RelationshipDirection",
14151 			literalValues: [
14152 				{
14153 					name: "None"
14154 				},
14155 				{
14156 					name: "Forward"
14157 				},
14158 				{
14159 					name: "Backward"
14160 				},
14161 				{
14162 					name: "Both"
14163 				}
14164 			]
14165 		},
14166 		{
14167 			name: "ItemKind",
14168 			literalValues: [
14169 				{
14170 					name: "Physical"
14171 				},
14172 				{
14173 					name: "Information"
14174 				}
14175 			]
14176 		},
14177 		{
14178 			name: "ChoreographyLoopType",
14179 			literalValues: [
14180 				{
14181 					name: "None"
14182 				},
14183 				{
14184 					name: "Standard"
14185 				},
14186 				{
14187 					name: "MultiInstanceSequential"
14188 				},
14189 				{
14190 					name: "MultiInstanceParallel"
14191 				}
14192 			]
14193 		},
14194 		{
14195 			name: "AssociationDirection",
14196 			literalValues: [
14197 				{
14198 					name: "None"
14199 				},
14200 				{
14201 					name: "One"
14202 				},
14203 				{
14204 					name: "Both"
14205 				}
14206 			]
14207 		},
14208 		{
14209 			name: "MultiInstanceBehavior",
14210 			literalValues: [
14211 				{
14212 					name: "None"
14213 				},
14214 				{
14215 					name: "One"
14216 				},
14217 				{
14218 					name: "All"
14219 				},
14220 				{
14221 					name: "Complex"
14222 				}
14223 			]
14224 		},
14225 		{
14226 			name: "AdHocOrdering",
14227 			literalValues: [
14228 				{
14229 					name: "Parallel"
14230 				},
14231 				{
14232 					name: "Sequential"
14233 				}
14234 			]
14235 		}
14236 	];
14237 	var xml = {
14238 		tagAlias: "lowerCase",
14239 		typePrefix: "t"
14240 	};
14241 	var BpmnPackage = {
14242 		name: name,
14243 		uri: uri,
14244 		prefix: prefix,
14245 		associations: associations,
14246 		types: types,
14247 		enumerations: enumerations,
14248 		xml: xml
14249 	};
14250 
14251 	var name$1 = "BPMNDI";
14252 	var uri$1 = "http://www.omg.org/spec/BPMN/20100524/DI";
14253 	var prefix$1 = "bpmndi";
14254 	var types$1 = [
14255 		{
14256 			name: "BPMNDiagram",
14257 			properties: [
14258 				{
14259 					name: "plane",
14260 					type: "BPMNPlane",
14261 					redefines: "di:Diagram#rootElement"
14262 				},
14263 				{
14264 					name: "labelStyle",
14265 					type: "BPMNLabelStyle",
14266 					isMany: true
14267 				}
14268 			],
14269 			superClass: [
14270 				"di:Diagram"
14271 			]
14272 		},
14273 		{
14274 			name: "BPMNPlane",
14275 			properties: [
14276 				{
14277 					name: "bpmnElement",
14278 					isAttr: true,
14279 					isReference: true,
14280 					type: "bpmn:BaseElement",
14281 					redefines: "di:DiagramElement#modelElement"
14282 				}
14283 			],
14284 			superClass: [
14285 				"di:Plane"
14286 			]
14287 		},
14288 		{
14289 			name: "BPMNShape",
14290 			properties: [
14291 				{
14292 					name: "bpmnElement",
14293 					isAttr: true,
14294 					isReference: true,
14295 					type: "bpmn:BaseElement",
14296 					redefines: "di:DiagramElement#modelElement"
14297 				},
14298 				{
14299 					name: "isHorizontal",
14300 					isAttr: true,
14301 					type: "Boolean"
14302 				},
14303 				{
14304 					name: "isExpanded",
14305 					isAttr: true,
14306 					type: "Boolean"
14307 				},
14308 				{
14309 					name: "isMarkerVisible",
14310 					isAttr: true,
14311 					type: "Boolean"
14312 				},
14313 				{
14314 					name: "label",
14315 					type: "BPMNLabel"
14316 				},
14317 				{
14318 					name: "isMessageVisible",
14319 					isAttr: true,
14320 					type: "Boolean"
14321 				},
14322 				{
14323 					name: "participantBandKind",
14324 					type: "ParticipantBandKind",
14325 					isAttr: true
14326 				},
14327 				{
14328 					name: "choreographyActivityShape",
14329 					type: "BPMNShape",
14330 					isAttr: true,
14331 					isReference: true
14332 				}
14333 			],
14334 			superClass: [
14335 				"di:LabeledShape"
14336 			]
14337 		},
14338 		{
14339 			name: "BPMNEdge",
14340 			properties: [
14341 				{
14342 					name: "label",
14343 					type: "BPMNLabel"
14344 				},
14345 				{
14346 					name: "bpmnElement",
14347 					isAttr: true,
14348 					isReference: true,
14349 					type: "bpmn:BaseElement",
14350 					redefines: "di:DiagramElement#modelElement"
14351 				},
14352 				{
14353 					name: "sourceElement",
14354 					isAttr: true,
14355 					isReference: true,
14356 					type: "di:DiagramElement",
14357 					redefines: "di:Edge#source"
14358 				},
14359 				{
14360 					name: "targetElement",
14361 					isAttr: true,
14362 					isReference: true,
14363 					type: "di:DiagramElement",
14364 					redefines: "di:Edge#target"
14365 				},
14366 				{
14367 					name: "messageVisibleKind",
14368 					type: "MessageVisibleKind",
14369 					isAttr: true,
14370 					"default": "initiating"
14371 				}
14372 			],
14373 			superClass: [
14374 				"di:LabeledEdge"
14375 			]
14376 		},
14377 		{
14378 			name: "BPMNLabel",
14379 			properties: [
14380 				{
14381 					name: "labelStyle",
14382 					type: "BPMNLabelStyle",
14383 					isAttr: true,
14384 					isReference: true,
14385 					redefines: "di:DiagramElement#style"
14386 				}
14387 			],
14388 			superClass: [
14389 				"di:Label"
14390 			]
14391 		},
14392 		{
14393 			name: "BPMNLabelStyle",
14394 			properties: [
14395 				{
14396 					name: "font",
14397 					type: "dc:Font"
14398 				}
14399 			],
14400 			superClass: [
14401 				"di:Style"
14402 			]
14403 		}
14404 	];
14405 	var enumerations$1 = [
14406 		{
14407 			name: "ParticipantBandKind",
14408 			literalValues: [
14409 				{
14410 					name: "top_initiating"
14411 				},
14412 				{
14413 					name: "middle_initiating"
14414 				},
14415 				{
14416 					name: "bottom_initiating"
14417 				},
14418 				{
14419 					name: "top_non_initiating"
14420 				},
14421 				{
14422 					name: "middle_non_initiating"
14423 				},
14424 				{
14425 					name: "bottom_non_initiating"
14426 				}
14427 			]
14428 		},
14429 		{
14430 			name: "MessageVisibleKind",
14431 			literalValues: [
14432 				{
14433 					name: "initiating"
14434 				},
14435 				{
14436 					name: "non_initiating"
14437 				}
14438 			]
14439 		}
14440 	];
14441 	var associations$1 = [
14442 	];
14443 	var BpmnDiPackage = {
14444 		name: name$1,
14445 		uri: uri$1,
14446 		prefix: prefix$1,
14447 		types: types$1,
14448 		enumerations: enumerations$1,
14449 		associations: associations$1
14450 	};
14451 
14452 	var name$2 = "DC";
14453 	var uri$2 = "http://www.omg.org/spec/DD/20100524/DC";
14454 	var prefix$2 = "dc";
14455 	var types$2 = [
14456 		{
14457 			name: "Boolean"
14458 		},
14459 		{
14460 			name: "Integer"
14461 		},
14462 		{
14463 			name: "Real"
14464 		},
14465 		{
14466 			name: "String"
14467 		},
14468 		{
14469 			name: "Font",
14470 			properties: [
14471 				{
14472 					name: "name",
14473 					type: "String",
14474 					isAttr: true
14475 				},
14476 				{
14477 					name: "size",
14478 					type: "Real",
14479 					isAttr: true
14480 				},
14481 				{
14482 					name: "isBold",
14483 					type: "Boolean",
14484 					isAttr: true
14485 				},
14486 				{
14487 					name: "isItalic",
14488 					type: "Boolean",
14489 					isAttr: true
14490 				},
14491 				{
14492 					name: "isUnderline",
14493 					type: "Boolean",
14494 					isAttr: true
14495 				},
14496 				{
14497 					name: "isStrikeThrough",
14498 					type: "Boolean",
14499 					isAttr: true
14500 				}
14501 			]
14502 		},
14503 		{
14504 			name: "Point",
14505 			properties: [
14506 				{
14507 					name: "x",
14508 					type: "Real",
14509 					"default": "0",
14510 					isAttr: true
14511 				},
14512 				{
14513 					name: "y",
14514 					type: "Real",
14515 					"default": "0",
14516 					isAttr: true
14517 				}
14518 			]
14519 		},
14520 		{
14521 			name: "Bounds",
14522 			properties: [
14523 				{
14524 					name: "x",
14525 					type: "Real",
14526 					"default": "0",
14527 					isAttr: true
14528 				},
14529 				{
14530 					name: "y",
14531 					type: "Real",
14532 					"default": "0",
14533 					isAttr: true
14534 				},
14535 				{
14536 					name: "width",
14537 					type: "Real",
14538 					isAttr: true
14539 				},
14540 				{
14541 					name: "height",
14542 					type: "Real",
14543 					isAttr: true
14544 				}
14545 			]
14546 		}
14547 	];
14548 	var associations$2 = [
14549 	];
14550 	var DcPackage = {
14551 		name: name$2,
14552 		uri: uri$2,
14553 		prefix: prefix$2,
14554 		types: types$2,
14555 		associations: associations$2
14556 	};
14557 
14558 	var name$3 = "DI";
14559 	var uri$3 = "http://www.omg.org/spec/DD/20100524/DI";
14560 	var prefix$3 = "di";
14561 	var types$3 = [
14562 		{
14563 			name: "DiagramElement",
14564 			isAbstract: true,
14565 			properties: [
14566 				{
14567 					name: "id",
14568 					isAttr: true,
14569 					isId: true,
14570 					type: "String"
14571 				},
14572 				{
14573 					name: "extension",
14574 					type: "Extension"
14575 				},
14576 				{
14577 					name: "owningDiagram",
14578 					type: "Diagram",
14579 					isReadOnly: true,
14580 					isVirtual: true,
14581 					isReference: true
14582 				},
14583 				{
14584 					name: "owningElement",
14585 					type: "DiagramElement",
14586 					isReadOnly: true,
14587 					isVirtual: true,
14588 					isReference: true
14589 				},
14590 				{
14591 					name: "modelElement",
14592 					isReadOnly: true,
14593 					isVirtual: true,
14594 					isReference: true,
14595 					type: "Element"
14596 				},
14597 				{
14598 					name: "style",
14599 					type: "Style",
14600 					isReadOnly: true,
14601 					isVirtual: true,
14602 					isReference: true
14603 				},
14604 				{
14605 					name: "ownedElement",
14606 					type: "DiagramElement",
14607 					isReadOnly: true,
14608 					isMany: true,
14609 					isVirtual: true
14610 				}
14611 			]
14612 		},
14613 		{
14614 			name: "Node",
14615 			isAbstract: true,
14616 			superClass: [
14617 				"DiagramElement"
14618 			]
14619 		},
14620 		{
14621 			name: "Edge",
14622 			isAbstract: true,
14623 			superClass: [
14624 				"DiagramElement"
14625 			],
14626 			properties: [
14627 				{
14628 					name: "source",
14629 					type: "DiagramElement",
14630 					isReadOnly: true,
14631 					isVirtual: true,
14632 					isReference: true
14633 				},
14634 				{
14635 					name: "target",
14636 					type: "DiagramElement",
14637 					isReadOnly: true,
14638 					isVirtual: true,
14639 					isReference: true
14640 				},
14641 				{
14642 					name: "waypoint",
14643 					isUnique: false,
14644 					isMany: true,
14645 					type: "dc:Point",
14646 					xml: {
14647 						serialize: "xsi:type"
14648 					}
14649 				}
14650 			]
14651 		},
14652 		{
14653 			name: "Diagram",
14654 			isAbstract: true,
14655 			properties: [
14656 				{
14657 					name: "id",
14658 					isAttr: true,
14659 					isId: true,
14660 					type: "String"
14661 				},
14662 				{
14663 					name: "rootElement",
14664 					type: "DiagramElement",
14665 					isReadOnly: true,
14666 					isVirtual: true
14667 				},
14668 				{
14669 					name: "name",
14670 					isAttr: true,
14671 					type: "String"
14672 				},
14673 				{
14674 					name: "documentation",
14675 					isAttr: true,
14676 					type: "String"
14677 				},
14678 				{
14679 					name: "resolution",
14680 					isAttr: true,
14681 					type: "Real"
14682 				},
14683 				{
14684 					name: "ownedStyle",
14685 					type: "Style",
14686 					isReadOnly: true,
14687 					isMany: true,
14688 					isVirtual: true
14689 				}
14690 			]
14691 		},
14692 		{
14693 			name: "Shape",
14694 			isAbstract: true,
14695 			superClass: [
14696 				"Node"
14697 			],
14698 			properties: [
14699 				{
14700 					name: "bounds",
14701 					type: "dc:Bounds"
14702 				}
14703 			]
14704 		},
14705 		{
14706 			name: "Plane",
14707 			isAbstract: true,
14708 			superClass: [
14709 				"Node"
14710 			],
14711 			properties: [
14712 				{
14713 					name: "planeElement",
14714 					type: "DiagramElement",
14715 					subsettedProperty: "DiagramElement-ownedElement",
14716 					isMany: true
14717 				}
14718 			]
14719 		},
14720 		{
14721 			name: "LabeledEdge",
14722 			isAbstract: true,
14723 			superClass: [
14724 				"Edge"
14725 			],
14726 			properties: [
14727 				{
14728 					name: "ownedLabel",
14729 					type: "Label",
14730 					isReadOnly: true,
14731 					subsettedProperty: "DiagramElement-ownedElement",
14732 					isMany: true,
14733 					isVirtual: true
14734 				}
14735 			]
14736 		},
14737 		{
14738 			name: "LabeledShape",
14739 			isAbstract: true,
14740 			superClass: [
14741 				"Shape"
14742 			],
14743 			properties: [
14744 				{
14745 					name: "ownedLabel",
14746 					type: "Label",
14747 					isReadOnly: true,
14748 					subsettedProperty: "DiagramElement-ownedElement",
14749 					isMany: true,
14750 					isVirtual: true
14751 				}
14752 			]
14753 		},
14754 		{
14755 			name: "Label",
14756 			isAbstract: true,
14757 			superClass: [
14758 				"Node"
14759 			],
14760 			properties: [
14761 				{
14762 					name: "bounds",
14763 					type: "dc:Bounds"
14764 				}
14765 			]
14766 		},
14767 		{
14768 			name: "Style",
14769 			isAbstract: true,
14770 			properties: [
14771 				{
14772 					name: "id",
14773 					isAttr: true,
14774 					isId: true,
14775 					type: "String"
14776 				}
14777 			]
14778 		},
14779 		{
14780 			name: "Extension",
14781 			properties: [
14782 				{
14783 					name: "values",
14784 					isMany: true,
14785 					type: "Element"
14786 				}
14787 			]
14788 		}
14789 	];
14790 	var associations$3 = [
14791 	];
14792 	var xml$1 = {
14793 		tagAlias: "lowerCase"
14794 	};
14795 	var DiPackage = {
14796 		name: name$3,
14797 		uri: uri$3,
14798 		prefix: prefix$3,
14799 		types: types$3,
14800 		associations: associations$3,
14801 		xml: xml$1
14802 	};
14803 
14804 	var name$4 = "bpmn.io colors for BPMN";
14805 	var uri$4 = "http://bpmn.io/schema/bpmn/biocolor/1.0";
14806 	var prefix$4 = "bioc";
14807 	var types$4 = [
14808 		{
14809 			name: "ColoredShape",
14810 			"extends": [
14811 				"bpmndi:BPMNShape"
14812 			],
14813 			properties: [
14814 				{
14815 					name: "stroke",
14816 					isAttr: true,
14817 					type: "String"
14818 				},
14819 				{
14820 					name: "fill",
14821 					isAttr: true,
14822 					type: "String"
14823 				}
14824 			]
14825 		},
14826 		{
14827 			name: "ColoredEdge",
14828 			"extends": [
14829 				"bpmndi:BPMNEdge"
14830 			],
14831 			properties: [
14832 				{
14833 					name: "stroke",
14834 					isAttr: true,
14835 					type: "String"
14836 				},
14837 				{
14838 					name: "fill",
14839 					isAttr: true,
14840 					type: "String"
14841 				}
14842 			]
14843 		}
14844 	];
14845 	var enumerations$2 = [
14846 	];
14847 	var associations$4 = [
14848 	];
14849 	var BiocPackage = {
14850 		name: name$4,
14851 		uri: uri$4,
14852 		prefix: prefix$4,
14853 		types: types$4,
14854 		enumerations: enumerations$2,
14855 		associations: associations$4
14856 	};
14857 
14858 	var name$5 = "BPMN in Color";
14859 	var uri$5 = "http://www.omg.org/spec/BPMN/non-normative/color/1.0";
14860 	var prefix$5 = "color";
14861 	var types$5 = [
14862 		{
14863 			name: "ColoredLabel",
14864 			"extends": [
14865 				"bpmndi:BPMNLabel"
14866 			],
14867 			properties: [
14868 				{
14869 					name: "color",
14870 					isAttr: true,
14871 					type: "String"
14872 				}
14873 			]
14874 		},
14875 		{
14876 			name: "ColoredShape",
14877 			"extends": [
14878 				"bpmndi:BPMNShape"
14879 			],
14880 			properties: [
14881 				{
14882 					name: "background-color",
14883 					isAttr: true,
14884 					type: "String"
14885 				},
14886 				{
14887 					name: "border-color",
14888 					isAttr: true,
14889 					type: "String"
14890 				}
14891 			]
14892 		},
14893 		{
14894 			name: "ColoredEdge",
14895 			"extends": [
14896 				"bpmndi:BPMNEdge"
14897 			],
14898 			properties: [
14899 				{
14900 					name: "border-color",
14901 					isAttr: true,
14902 					type: "String"
14903 				}
14904 			]
14905 		}
14906 	];
14907 	var enumerations$3 = [
14908 	];
14909 	var associations$5 = [
14910 	];
14911 	var BpmnInColorPackage = {
14912 		name: name$5,
14913 		uri: uri$5,
14914 		prefix: prefix$5,
14915 		types: types$5,
14916 		enumerations: enumerations$3,
14917 		associations: associations$5
14918 	};
14919 
14920 	var packages = {
14921 	  bpmn: BpmnPackage,
14922 	  bpmndi: BpmnDiPackage,
14923 	  dc: DcPackage,
14924 	  di: DiPackage,
14925 	  bioc: BiocPackage,
14926 	  color: BpmnInColorPackage
14927 	};
14928 
14929 	function simple(additionalPackages, options) {
14930 	  var pks = assign({}, packages, additionalPackages);
14931 
14932 	  return new BpmnModdle(pks, options);
14933 	}
14934 
14935 	function elementToString(e) {
14936 	  if (!e) {
14937 	    return '<null>';
14938 	  }
14939 
14940 	  return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
14941 	}
14942 
14943 	var diRefs = new Refs(
14944 	  { name: 'bpmnElement', enumerable: true },
14945 	  { name: 'di', configurable: true }
14946 	);
14947 
14948 	/**
14949 	 * Returns true if an element has the given meta-model type
14950 	 *
14951 	 * @param  {ModdleElement}  element
14952 	 * @param  {string}         type
14953 	 *
14954 	 * @return {boolean}
14955 	 */
14956 	function is$2(element, type) {
14957 	  return element.$instanceOf(type);
14958 	}
14959 
14960 
14961 	/**
14962 	 * Find a suitable display candidate for definitions where the DI does not
14963 	 * correctly specify one.
14964 	 */
14965 	function findDisplayCandidate(definitions) {
14966 	  return find(definitions.rootElements, function(e) {
14967 	    return is$2(e, 'bpmn:Process') || is$2(e, 'bpmn:Collaboration');
14968 	  });
14969 	}
14970 
14971 
14972 	function BpmnTreeWalker(handler, translate) {
14973 
14974 	  // list of containers already walked
14975 	  var handledElements = {};
14976 
14977 	  // list of elements to handle deferred to ensure
14978 	  // prerequisites are drawn
14979 	  var deferred = [];
14980 
14981 	  // Helpers //////////////////////
14982 
14983 	  function contextual(fn, ctx) {
14984 	    return function(e) {
14985 	      fn(e, ctx);
14986 	    };
14987 	  }
14988 
14989 	  function handled(element) {
14990 	    handledElements[element.id] = element;
14991 	  }
14992 
14993 	  function isHandled(element) {
14994 	    return handledElements[element.id];
14995 	  }
14996 
14997 	  function visit(element, ctx) {
14998 
14999 	    var gfx = element.gfx;
15000 
15001 	    // avoid multiple rendering of elements
15002 	    if (gfx) {
15003 	      throw new Error(
15004 	        translate('already rendered {element}', { element: elementToString(element) })
15005 	      );
15006 	    }
15007 
15008 	    // call handler
15009 	    return handler.element(element, ctx);
15010 	  }
15011 
15012 	  function visitRoot(element, diagram) {
15013 	    return handler.root(element, diagram);
15014 	  }
15015 
15016 	  function visitIfDi(element, ctx) {
15017 
15018 	    try {
15019 	      var gfx = element.di && visit(element, ctx);
15020 
15021 	      handled(element);
15022 
15023 	      return gfx;
15024 	    } catch (e) {
15025 	      logError(e.message, { element: element, error: e });
15026 
15027 	      console.error(translate('failed to import {element}', { element: elementToString(element) }));
15028 	      console.error(e);
15029 	    }
15030 	  }
15031 
15032 	  function logError(message, context) {
15033 	    handler.error(message, context);
15034 	  }
15035 
15036 	  // DI handling //////////////////////
15037 
15038 	  function registerDi(di) {
15039 	    var bpmnElement = di.bpmnElement;
15040 
15041 	    if (bpmnElement) {
15042 	      if (bpmnElement.di) {
15043 	        logError(
15044 	          translate('multiple DI elements defined for {element}', {
15045 	            element: elementToString(bpmnElement)
15046 	          }),
15047 	          { element: bpmnElement }
15048 	        );
15049 	      } else {
15050 	        diRefs.bind(bpmnElement, 'di');
15051 	        bpmnElement.di = di;
15052 	      }
15053 	    } else {
15054 	      logError(
15055 	        translate('no bpmnElement referenced in {element}', {
15056 	          element: elementToString(di)
15057 	        }),
15058 	        { element: di }
15059 	      );
15060 	    }
15061 	  }
15062 
15063 	  function handleDiagram(diagram) {
15064 	    handlePlane(diagram.plane);
15065 	  }
15066 
15067 	  function handlePlane(plane) {
15068 	    registerDi(plane);
15069 
15070 	    forEach(plane.planeElement, handlePlaneElement);
15071 	  }
15072 
15073 	  function handlePlaneElement(planeElement) {
15074 	    registerDi(planeElement);
15075 	  }
15076 
15077 
15078 	  // Semantic handling //////////////////////
15079 
15080 	  /**
15081 	   * Handle definitions and return the rendered diagram (if any)
15082 	   *
15083 	   * @param {ModdleElement} definitions to walk and import
15084 	   * @param {ModdleElement} [diagram] specific diagram to import and display
15085 	   *
15086 	   * @throws {Error} if no diagram to display could be found
15087 	   */
15088 	  function handleDefinitions(definitions, diagram) {
15089 
15090 	    // make sure we walk the correct bpmnElement
15091 
15092 	    var diagrams = definitions.diagrams;
15093 
15094 	    if (diagram && diagrams.indexOf(diagram) === -1) {
15095 	      throw new Error(translate('diagram not part of bpmn:Definitions'));
15096 	    }
15097 
15098 	    if (!diagram && diagrams && diagrams.length) {
15099 	      diagram = diagrams[0];
15100 	    }
15101 
15102 	    // no diagram -> nothing to import
15103 	    if (!diagram) {
15104 	      throw new Error(translate('no diagram to display'));
15105 	    }
15106 
15107 	    // load DI from selected diagram only
15108 	    handleDiagram(diagram);
15109 
15110 
15111 	    var plane = diagram.plane;
15112 
15113 	    if (!plane) {
15114 	      throw new Error(translate(
15115 	        'no plane for {element}',
15116 	        { element: elementToString(diagram) }
15117 	      ));
15118 	    }
15119 
15120 	    var rootElement = plane.bpmnElement;
15121 
15122 	    // ensure we default to a suitable display candidate (process or collaboration),
15123 	    // even if non is specified in DI
15124 	    if (!rootElement) {
15125 	      rootElement = findDisplayCandidate(definitions);
15126 
15127 	      if (!rootElement) {
15128 	        throw new Error(translate('no process or collaboration to display'));
15129 	      } else {
15130 
15131 	        logError(
15132 	          translate('correcting missing bpmnElement on {plane} to {rootElement}', {
15133 	            plane: elementToString(plane),
15134 	            rootElement: elementToString(rootElement)
15135 	          })
15136 	        );
15137 
15138 	        // correct DI on the fly
15139 	        plane.bpmnElement = rootElement;
15140 	        registerDi(plane);
15141 	      }
15142 	    }
15143 
15144 
15145 	    var ctx = visitRoot(rootElement, plane);
15146 
15147 	    if (is$2(rootElement, 'bpmn:Process')) {
15148 	      handleProcess(rootElement, ctx);
15149 	    } else if (is$2(rootElement, 'bpmn:Collaboration')) {
15150 	      handleCollaboration(rootElement);
15151 
15152 	      // force drawing of everything not yet drawn that is part of the target DI
15153 	      handleUnhandledProcesses(definitions.rootElements, ctx);
15154 	    } else {
15155 	      throw new Error(
15156 	        translate('unsupported bpmnElement for {plane}: {rootElement}', {
15157 	          plane: elementToString(plane),
15158 	          rootElement: elementToString(rootElement)
15159 	        })
15160 	      );
15161 	    }
15162 
15163 	    // handle all deferred elements
15164 	    handleDeferred();
15165 	  }
15166 
15167 	  function handleDeferred() {
15168 
15169 	    var fn;
15170 
15171 	    // drain deferred until empty
15172 	    while (deferred.length) {
15173 	      fn = deferred.shift();
15174 
15175 	      fn();
15176 	    }
15177 	  }
15178 
15179 	  function handleProcess(process, context) {
15180 	    handleFlowElementsContainer(process, context);
15181 	    handleIoSpecification(process.ioSpecification, context);
15182 
15183 	    handleArtifacts(process.artifacts, context);
15184 
15185 	    // log process handled
15186 	    handled(process);
15187 	  }
15188 
15189 	  function handleUnhandledProcesses(rootElements, ctx) {
15190 
15191 	    // walk through all processes that have not yet been drawn and draw them
15192 	    // if they contain lanes with DI information.
15193 	    // we do this to pass the free-floating lane test cases in the MIWG test suite
15194 	    var processes = filter(rootElements, function(e) {
15195 	      return !isHandled(e) && is$2(e, 'bpmn:Process') && e.laneSets;
15196 	    });
15197 
15198 	    processes.forEach(contextual(handleProcess, ctx));
15199 	  }
15200 
15201 	  function handleMessageFlow(messageFlow, context) {
15202 	    visitIfDi(messageFlow, context);
15203 	  }
15204 
15205 	  function handleMessageFlows(messageFlows, context) {
15206 	    forEach(messageFlows, contextual(handleMessageFlow, context));
15207 	  }
15208 
15209 	  function handleDataAssociation(association, context) {
15210 	    visitIfDi(association, context);
15211 	  }
15212 
15213 	  function handleDataInput(dataInput, context) {
15214 	    visitIfDi(dataInput, context);
15215 	  }
15216 
15217 	  function handleDataOutput(dataOutput, context) {
15218 	    visitIfDi(dataOutput, context);
15219 	  }
15220 
15221 	  function handleArtifact(artifact, context) {
15222 
15223 	    // bpmn:TextAnnotation
15224 	    // bpmn:Group
15225 	    // bpmn:Association
15226 
15227 	    visitIfDi(artifact, context);
15228 	  }
15229 
15230 	  function handleArtifacts(artifacts, context) {
15231 
15232 	    forEach(artifacts, function(e) {
15233 	      if (is$2(e, 'bpmn:Association')) {
15234 	        deferred.push(function() {
15235 	          handleArtifact(e, context);
15236 	        });
15237 	      } else {
15238 	        handleArtifact(e, context);
15239 	      }
15240 	    });
15241 	  }
15242 
15243 	  function handleIoSpecification(ioSpecification, context) {
15244 
15245 	    if (!ioSpecification) {
15246 	      return;
15247 	    }
15248 
15249 	    forEach(ioSpecification.dataInputs, contextual(handleDataInput, context));
15250 	    forEach(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
15251 	  }
15252 
15253 	  function handleSubProcess(subProcess, context) {
15254 	    handleFlowElementsContainer(subProcess, context);
15255 	    handleArtifacts(subProcess.artifacts, context);
15256 	  }
15257 
15258 	  function handleFlowNode(flowNode, context) {
15259 	    var childCtx = visitIfDi(flowNode, context);
15260 
15261 	    if (is$2(flowNode, 'bpmn:SubProcess')) {
15262 	      handleSubProcess(flowNode, childCtx || context);
15263 	    }
15264 
15265 	    if (is$2(flowNode, 'bpmn:Activity')) {
15266 	      handleIoSpecification(flowNode.ioSpecification, context);
15267 	    }
15268 
15269 	    // defer handling of associations
15270 	    // affected types:
15271 	    //
15272 	    //   * bpmn:Activity
15273 	    //   * bpmn:ThrowEvent
15274 	    //   * bpmn:CatchEvent
15275 	    //
15276 	    deferred.push(function() {
15277 	      forEach(flowNode.dataInputAssociations, contextual(handleDataAssociation, context));
15278 	      forEach(flowNode.dataOutputAssociations, contextual(handleDataAssociation, context));
15279 	    });
15280 	  }
15281 
15282 	  function handleSequenceFlow(sequenceFlow, context) {
15283 	    visitIfDi(sequenceFlow, context);
15284 	  }
15285 
15286 	  function handleDataElement(dataObject, context) {
15287 	    visitIfDi(dataObject, context);
15288 	  }
15289 
15290 	  function handleLane(lane, context) {
15291 
15292 	    deferred.push(function() {
15293 
15294 	      var newContext = visitIfDi(lane, context);
15295 
15296 	      if (lane.childLaneSet) {
15297 	        handleLaneSet(lane.childLaneSet, newContext || context);
15298 	      }
15299 
15300 	      wireFlowNodeRefs(lane);
15301 	    });
15302 	  }
15303 
15304 	  function handleLaneSet(laneSet, context) {
15305 	    forEach(laneSet.lanes, contextual(handleLane, context));
15306 	  }
15307 
15308 	  function handleLaneSets(laneSets, context) {
15309 	    forEach(laneSets, contextual(handleLaneSet, context));
15310 	  }
15311 
15312 	  function handleFlowElementsContainer(container, context) {
15313 	    handleFlowElements(container.flowElements, context);
15314 
15315 	    if (container.laneSets) {
15316 	      handleLaneSets(container.laneSets, context);
15317 	    }
15318 	  }
15319 
15320 	  function handleFlowElements(flowElements, context) {
15321 	    forEach(flowElements, function(e) {
15322 	      if (is$2(e, 'bpmn:SequenceFlow')) {
15323 	        deferred.push(function() {
15324 	          handleSequenceFlow(e, context);
15325 	        });
15326 	      } else if (is$2(e, 'bpmn:BoundaryEvent')) {
15327 	        deferred.unshift(function() {
15328 	          handleFlowNode(e, context);
15329 	        });
15330 	      } else if (is$2(e, 'bpmn:FlowNode')) {
15331 	        handleFlowNode(e, context);
15332 	      } else if (is$2(e, 'bpmn:DataObject')) ; else if (is$2(e, 'bpmn:DataStoreReference')) {
15333 	        handleDataElement(e, context);
15334 	      } else if (is$2(e, 'bpmn:DataObjectReference')) {
15335 	        handleDataElement(e, context);
15336 	      } else {
15337 	        logError(
15338 	          translate('unrecognized flowElement {element} in context {context}', {
15339 	            element: elementToString(e),
15340 	            context: (context ? elementToString(context.businessObject) : 'null')
15341 	          }),
15342 	          { element: e, context: context }
15343 	        );
15344 	      }
15345 	    });
15346 	  }
15347 
15348 	  function handleParticipant(participant, context) {
15349 	    var newCtx = visitIfDi(participant, context);
15350 
15351 	    var process = participant.processRef;
15352 	    if (process) {
15353 	      handleProcess(process, newCtx || context);
15354 	    }
15355 	  }
15356 
15357 	  function handleCollaboration(collaboration) {
15358 
15359 	    forEach(collaboration.participants, contextual(handleParticipant));
15360 
15361 	    handleArtifacts(collaboration.artifacts);
15362 
15363 	    // handle message flows latest in the process
15364 	    deferred.push(function() {
15365 	      handleMessageFlows(collaboration.messageFlows);
15366 	    });
15367 	  }
15368 
15369 
15370 	  function wireFlowNodeRefs(lane) {
15371 
15372 	    // wire the virtual flowNodeRefs <-> relationship
15373 	    forEach(lane.flowNodeRef, function(flowNode) {
15374 	      var lanes = flowNode.get('lanes');
15375 
15376 	      if (lanes) {
15377 	        lanes.push(lane);
15378 	      }
15379 	    });
15380 	  }
15381 
15382 	  // API //////////////////////
15383 
15384 	  return {
15385 	    handleDeferred: handleDeferred,
15386 	    handleDefinitions: handleDefinitions,
15387 	    handleSubProcess: handleSubProcess,
15388 	    registerDi: registerDi
15389 	  };
15390 	}
15391 
15392 	/**
15393 	 * The importBpmnDiagram result.
15394 	 *
15395 	 * @typedef {Object} ImportBPMNDiagramResult
15396 	 *
15397 	 * @property {Array<string>} warnings
15398 	 */
15399 
15400 	/**
15401 	* The importBpmnDiagram error.
15402 	*
15403 	* @typedef {Error} ImportBPMNDiagramError
15404 	*
15405 	* @property {Array<string>} warnings
15406 	*/
15407 
15408 	/**
15409 	 * Import the definitions into a diagram.
15410 	 *
15411 	 * Errors and warnings are reported through the specified callback.
15412 	 *
15413 	 * @param  {djs.Diagram} diagram
15414 	 * @param  {ModdleElement<Definitions>} definitions
15415 	 * @param  {ModdleElement<BPMNDiagram>} [bpmnDiagram] the diagram to be rendered
15416 	 * (if not provided, the first one will be rendered)
15417 	 *
15418 	 * Returns {Promise<ImportBPMNDiagramResult, ImportBPMNDiagramError>}
15419 	 */
15420 	function importBpmnDiagram(diagram, definitions, bpmnDiagram) {
15421 
15422 	  var importer,
15423 	      eventBus,
15424 	      translate;
15425 
15426 	  var error,
15427 	      warnings = [];
15428 
15429 	  /**
15430 	   * Walk the diagram semantically, importing (=drawing)
15431 	   * all elements you encounter.
15432 	   *
15433 	   * @param {ModdleElement<Definitions>} definitions
15434 	   * @param {ModdleElement<BPMNDiagram>} bpmnDiagram
15435 	   */
15436 	  function render(definitions, bpmnDiagram) {
15437 
15438 	    var visitor = {
15439 
15440 	      root: function(element) {
15441 	        return importer.add(element);
15442 	      },
15443 
15444 	      element: function(element, parentShape) {
15445 	        return importer.add(element, parentShape);
15446 	      },
15447 
15448 	      error: function(message, context) {
15449 	        warnings.push({ message: message, context: context });
15450 	      }
15451 	    };
15452 
15453 	    var walker = new BpmnTreeWalker(visitor, translate);
15454 
15455 	    // traverse BPMN 2.0 document model,
15456 	    // starting at definitions
15457 	    walker.handleDefinitions(definitions, bpmnDiagram);
15458 	  }
15459 
15460 	  return new Promise(function(resolve, reject) {
15461 	    try {
15462 	      importer = diagram.get('bpmnImporter');
15463 	      eventBus = diagram.get('eventBus');
15464 	      translate = diagram.get('translate');
15465 
15466 	      eventBus.fire('import.render.start', { definitions: definitions });
15467 
15468 	      render(definitions, bpmnDiagram);
15469 
15470 	      eventBus.fire('import.render.complete', {
15471 	        error: error,
15472 	        warnings: warnings
15473 	      });
15474 
15475 	      return resolve({ warnings: warnings });
15476 	    } catch (e) {
15477 
15478 	      e.warnings = warnings;
15479 	      return reject(e);
15480 	    }
15481 	  });
15482 	}
15483 
15484 	// TODO(nikku): remove with future bpmn-js version
15485 
15486 	/**
15487 	 * Wraps APIs to check:
15488 	 *
15489 	 * 1) If a callback is passed -> Warn users about callback deprecation.
15490 	 * 2) If Promise class is implemented in current environment.
15491 	 *
15492 	 * @private
15493 	 */
15494 	function wrapForCompatibility(api) {
15495 
15496 	  return function() {
15497 
15498 	    if (!window.Promise) {
15499 	      throw new Error('Promises is not supported in this environment. Please polyfill Promise.');
15500 	    }
15501 
15502 	    var argLen = arguments.length;
15503 	    if (argLen >= 1 && isFunction(arguments[argLen - 1])) {
15504 
15505 	      var callback = arguments[argLen - 1];
15506 
15507 	      console.warn(new Error(
15508 	        'Passing callbacks to ' + api.name + ' is deprecated and will be removed in a future major release. ' +
15509 	        'Please switch to promises: https://bpmn.io/l/moving-to-promises.html'
15510 	      ));
15511 
15512 	      var argsWithoutCallback = Array.prototype.slice.call(arguments, 0, -1);
15513 
15514 	      api.apply(this, argsWithoutCallback).then(function(result) {
15515 
15516 	        var firstKey = Object.keys(result)[0];
15517 
15518 	        // The APIs we are wrapping all resolve a single item depending on the API.
15519 	        // For instance, importXML resolves { warnings } and saveXML returns { xml }.
15520 	        // That's why we can call the callback with the first item of result.
15521 	        return callback(null, result[firstKey]);
15522 
15523 	        // Passing a second paramter instead of catch because we don't want to
15524 	        // catch errors thrown by callback().
15525 	      }, function(err) {
15526 
15527 	        return callback(err, err.warnings);
15528 	      });
15529 	    } else {
15530 
15531 	      return api.apply(this, arguments);
15532 	    }
15533 	  };
15534 	}
15535 
15536 	/**
15537 	 * This file must not be changed or exchanged.
15538 	 *
15539 	 * @see http://bpmn.io/license for more information.
15540 	 */
15541 
15542 
15543 	// inlined ../../resources/logo.svg
15544 	var BPMNIO_LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14.02 5.57" width="53" height="21" style="vertical-align:middle"><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>';
15545 
15546 	var BPMNIO_IMG = BPMNIO_LOGO_SVG;
15547 
15548 	function css(attrs) {
15549 	  return attrs.join(';');
15550 	}
15551 
15552 	var LINK_STYLES = css([
15553 	  'color: #404040'
15554 	]);
15555 
15556 	var LIGHTBOX_STYLES = css([
15557 	  'z-index: 1001',
15558 	  'position: fixed',
15559 	  'top: 0',
15560 	  'left: 0',
15561 	  'right: 0',
15562 	  'bottom: 0'
15563 	]);
15564 
15565 	var BACKDROP_STYLES = css([
15566 	  'width: 100%',
15567 	  'height: 100%',
15568 	  'background: rgba(40,40,40,0.2)'
15569 	]);
15570 
15571 	var NOTICE_STYLES = css([
15572 	  'position: absolute',
15573 	  'left: 50%',
15574 	  'top: 40%',
15575 	  'transform: translate(-50%)',
15576 	  'width: 260px',
15577 	  'padding: 10px',
15578 	  'background: white',
15579 	  'box-shadow: 0 1px 4px rgba(0,0,0,0.3)',
15580 	  'font-family: Helvetica, Arial, sans-serif',
15581 	  'font-size: 14px',
15582 	  'display: flex',
15583 	  'line-height: 1.3'
15584 	]);
15585 
15586 	var LIGHTBOX_MARKUP =
15587 	  '<div class="bjs-powered-by-lightbox" style="' + LIGHTBOX_STYLES + '">' +
15588 	    '<div class="backdrop" style="' + BACKDROP_STYLES + '"></div>' +
15589 	    '<div class="notice" style="' + NOTICE_STYLES + '">' +
15590 	      '<a href="https://bpmn.io" target="_blank" rel="noopener" style="margin: 15px 20px 15px 10px; align-self: center;' + LINK_STYLES + '">' +
15591 	        BPMNIO_IMG +
15592 	      '</a>' +
15593 	      '<span>' +
15594 	        'Web-based tooling for BPMN, DMN and CMMN diagrams ' +
15595 	        'powered by <a href="https://bpmn.io" target="_blank" rel="noopener">bpmn.io</a>.' +
15596 	      '</span>' +
15597 	    '</div>' +
15598 	  '</div>';
15599 
15600 
15601 	var lightbox;
15602 
15603 	function open() {
15604 
15605 	  if (!lightbox) {
15606 	    lightbox = domify(LIGHTBOX_MARKUP);
15607 
15608 	    delegate.bind(lightbox, '.backdrop', 'click', function(event) {
15609 	      document.body.removeChild(lightbox);
15610 	    });
15611 	  }
15612 
15613 	  document.body.appendChild(lightbox);
15614 	}
15615 
15616 	/**
15617 	 * The code in the <project-logo></project-logo> area
15618 	 * must not be changed.
15619 	 *
15620 	 * @see http://bpmn.io/license for more information.
15621 	 */
15622 
15623 	/**
15624 	 * A base viewer for BPMN 2.0 diagrams.
15625 	 *
15626 	 * Have a look at {@link Viewer}, {@link NavigatedViewer} or {@link Modeler} for
15627 	 * bundles that include actual features.
15628 	 *
15629 	 * @param {Object} [options] configuration options to pass to the viewer
15630 	 * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
15631 	 * @param {string|number} [options.width] the width of the viewer
15632 	 * @param {string|number} [options.height] the height of the viewer
15633 	 * @param {Object} [options.moddleExtensions] extension packages to provide
15634 	 * @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
15635 	 * @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
15636 	 */
15637 	function BaseViewer(options) {
15638 
15639 	  options = assign({}, DEFAULT_OPTIONS, options);
15640 
15641 	  this._moddle = this._createModdle(options);
15642 
15643 	  this._container = this._createContainer(options);
15644 
15645 	  /* <project-logo> */
15646 
15647 	  addProjectLogo(this._container);
15648 
15649 	  /* </project-logo> */
15650 
15651 	  this._init(this._container, this._moddle, options);
15652 	}
15653 
15654 	inherits$1(BaseViewer, Diagram);
15655 
15656 	/**
15657 	* The importXML result.
15658 	*
15659 	* @typedef {Object} ImportXMLResult
15660 	*
15661 	* @property {Array<string>} warnings
15662 	*/
15663 
15664 	/**
15665 	* The importXML error.
15666 	*
15667 	* @typedef {Error} ImportXMLError
15668 	*
15669 	* @property {Array<string>} warnings
15670 	*/
15671 
15672 	/**
15673 	 * Parse and render a BPMN 2.0 diagram.
15674 	 *
15675 	 * Once finished the viewer reports back the result to the
15676 	 * provided callback function with (err, warnings).
15677 	 *
15678 	 * ## Life-Cycle Events
15679 	 *
15680 	 * During import the viewer will fire life-cycle events:
15681 	 *
15682 	 *   * import.parse.start (about to read model from xml)
15683 	 *   * import.parse.complete (model read; may have worked or not)
15684 	 *   * import.render.start (graphical import start)
15685 	 *   * import.render.complete (graphical import finished)
15686 	 *   * import.done (everything done)
15687 	 *
15688 	 * You can use these events to hook into the life-cycle.
15689 	 *
15690 	 * @param {string} xml the BPMN 2.0 xml
15691 	 * @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
15692 	 *
15693 	 * Returns {Promise<ImportXMLResult, ImportXMLError>}
15694 	 */
15695 	BaseViewer.prototype.importXML = wrapForCompatibility(function importXML(xml, bpmnDiagram) {
15696 
15697 	  var self = this;
15698 
15699 	  function ParseCompleteEvent(data) {
15700 
15701 	    var event = self.get('eventBus').createEvent(data);
15702 
15703 	    // TODO(nikku): remove with future bpmn-js version
15704 	    Object.defineProperty(event, 'context', {
15705 	      enumerable: true,
15706 	      get: function() {
15707 
15708 	        console.warn(new Error(
15709 	          'import.parse.complete <context> is deprecated ' +
15710 	          'and will be removed in future library versions'
15711 	        ));
15712 
15713 	        return {
15714 	          warnings: data.warnings,
15715 	          references: data.references,
15716 	          elementsById: data.elementsById
15717 	        };
15718 	      }
15719 	    });
15720 
15721 	    return event;
15722 	  }
15723 
15724 	  return new Promise(function(resolve, reject) {
15725 
15726 	    // hook in pre-parse listeners +
15727 	    // allow xml manipulation
15728 	    xml = self._emit('import.parse.start', { xml: xml }) || xml;
15729 
15730 	    self._moddle.fromXML(xml, 'bpmn:Definitions').then(function(result) {
15731 	      var definitions = result.rootElement;
15732 	      var references = result.references;
15733 	      var parseWarnings = result.warnings;
15734 	      var elementsById = result.elementsById;
15735 
15736 	      // hook in post parse listeners +
15737 	      // allow definitions manipulation
15738 	      definitions = self._emit('import.parse.complete', ParseCompleteEvent({
15739 	        error: null,
15740 	        definitions: definitions,
15741 	        elementsById: elementsById,
15742 	        references: references,
15743 	        warnings: parseWarnings
15744 	      })) || definitions;
15745 
15746 	      self.importDefinitions(definitions, bpmnDiagram).then(function(result) {
15747 	        var allWarnings = [].concat(parseWarnings, result.warnings || []);
15748 
15749 	        self._emit('import.done', { error: null, warnings: allWarnings });
15750 
15751 	        return resolve({ warnings: allWarnings });
15752 	      }).catch(function(err) {
15753 	        var allWarnings = [].concat(parseWarnings, err.warnings || []);
15754 
15755 	        self._emit('import.done', { error: err, warnings: allWarnings });
15756 
15757 	        return reject(addWarningsToError(err, allWarnings));
15758 	      });
15759 	    }).catch(function(err) {
15760 
15761 	      self._emit('import.parse.complete', {
15762 	        error: err
15763 	      });
15764 
15765 	      err = checkValidationError(err);
15766 
15767 	      self._emit('import.done', { error: err, warnings: err.warnings });
15768 
15769 	      return reject(err);
15770 	    });
15771 	  });
15772 	});
15773 
15774 	/**
15775 	* The importDefinitions result.
15776 	*
15777 	* @typedef {Object} ImportDefinitionsResult
15778 	*
15779 	* @property {Array<string>} warnings
15780 	*/
15781 
15782 	/**
15783 	* The importDefinitions error.
15784 	*
15785 	* @typedef {Error} ImportDefinitionsError
15786 	*
15787 	* @property {Array<string>} warnings
15788 	*/
15789 
15790 	/**
15791 	 * Import parsed definitions and render a BPMN 2.0 diagram.
15792 	 *
15793 	 * Once finished the viewer reports back the result to the
15794 	 * provided callback function with (err, warnings).
15795 	 *
15796 	 * ## Life-Cycle Events
15797 	 *
15798 	 * During import the viewer will fire life-cycle events:
15799 	 *
15800 	 *   * import.render.start (graphical import start)
15801 	 *   * import.render.complete (graphical import finished)
15802 	 *
15803 	 * You can use these events to hook into the life-cycle.
15804 	 *
15805 	 * @param {ModdleElement<Definitions>} definitions parsed BPMN 2.0 definitions
15806 	 * @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
15807 	 *
15808 	 * Returns {Promise<ImportDefinitionsResult, ImportDefinitionsError>}
15809 	 */
15810 	BaseViewer.prototype.importDefinitions = wrapForCompatibility(function importDefinitions(definitions, bpmnDiagram) {
15811 
15812 	  var self = this;
15813 
15814 	  return new Promise(function(resolve, reject) {
15815 
15816 	    self._setDefinitions(definitions);
15817 
15818 	    self.open(bpmnDiagram).then(function(result) {
15819 
15820 	      var warnings = result.warnings;
15821 
15822 	      return resolve({ warnings: warnings });
15823 	    }).catch(function(err) {
15824 
15825 	      return reject(err);
15826 	    });
15827 	  });
15828 	});
15829 
15830 	/**
15831 	 * The open result.
15832 	 *
15833 	 * @typedef {Object} OpenResult
15834 	 *
15835 	 * @property {Array<string>} warnings
15836 	 */
15837 
15838 	/**
15839 	* The open error.
15840 	*
15841 	* @typedef {Error} OpenError
15842 	*
15843 	* @property {Array<string>} warnings
15844 	*/
15845 
15846 	/**
15847 	 * Open diagram of previously imported XML.
15848 	 *
15849 	 * Once finished the viewer reports back the result to the
15850 	 * provided callback function with (err, warnings).
15851 	 *
15852 	 * ## Life-Cycle Events
15853 	 *
15854 	 * During switch the viewer will fire life-cycle events:
15855 	 *
15856 	 *   * import.render.start (graphical import start)
15857 	 *   * import.render.complete (graphical import finished)
15858 	 *
15859 	 * You can use these events to hook into the life-cycle.
15860 	 *
15861 	 * @param {string|ModdleElement<BPMNDiagram>} [bpmnDiagramOrId] id or the diagram to open
15862 	 *
15863 	 * Returns {Promise<OpenResult, OpenError>}
15864 	 */
15865 	BaseViewer.prototype.open = wrapForCompatibility(function open(bpmnDiagramOrId) {
15866 
15867 	  var definitions = this._definitions;
15868 	  var bpmnDiagram = bpmnDiagramOrId;
15869 
15870 	  var self = this;
15871 
15872 	  return new Promise(function(resolve, reject) {
15873 	    if (!definitions) {
15874 	      var err1 = new Error('no XML imported');
15875 
15876 	      return reject(addWarningsToError(err1, []));
15877 	    }
15878 
15879 	    if (typeof bpmnDiagramOrId === 'string') {
15880 	      bpmnDiagram = findBPMNDiagram(definitions, bpmnDiagramOrId);
15881 
15882 	      if (!bpmnDiagram) {
15883 	        var err2 = new Error('BPMNDiagram <' + bpmnDiagramOrId + '> not found');
15884 
15885 	        return reject(addWarningsToError(err2, []));
15886 	      }
15887 	    }
15888 
15889 	    // clear existing rendered diagram
15890 	    // catch synchronous exceptions during #clear()
15891 	    try {
15892 	      self.clear();
15893 	    } catch (error) {
15894 
15895 	      return reject(addWarningsToError(error, []));
15896 	    }
15897 
15898 	    // perform graphical import
15899 	    importBpmnDiagram(self, definitions, bpmnDiagram).then(function(result) {
15900 
15901 	      var warnings = result.warnings;
15902 
15903 	      return resolve({ warnings: warnings });
15904 	    }).catch(function(err) {
15905 
15906 	      return reject(err);
15907 	    });
15908 	  });
15909 	});
15910 
15911 	/**
15912 	 * The saveXML result.
15913 	 *
15914 	 * @typedef {Object} SaveXMLResult
15915 	 *
15916 	 * @property {string} xml
15917 	 */
15918 
15919 	/**
15920 	 * Export the currently displayed BPMN 2.0 diagram as
15921 	 * a BPMN 2.0 XML document.
15922 	 *
15923 	 * ## Life-Cycle Events
15924 	 *
15925 	 * During XML saving the viewer will fire life-cycle events:
15926 	 *
15927 	 *   * saveXML.start (before serialization)
15928 	 *   * saveXML.serialized (after xml generation)
15929 	 *   * saveXML.done (everything done)
15930 	 *
15931 	 * You can use these events to hook into the life-cycle.
15932 	 *
15933 	 * @param {Object} [options] export options
15934 	 * @param {boolean} [options.format=false] output formatted XML
15935 	 * @param {boolean} [options.preamble=true] output preamble
15936 	 *
15937 	 * Returns {Promise<SaveXMLResult, Error>}
15938 	 */
15939 	BaseViewer.prototype.saveXML = wrapForCompatibility(function saveXML(options) {
15940 
15941 	  options = options || {};
15942 
15943 	  var self = this;
15944 
15945 	  var definitions = this._definitions;
15946 
15947 	  return new Promise(function(resolve) {
15948 
15949 	    if (!definitions) {
15950 	      return resolve({
15951 	        error: new Error('no definitions loaded')
15952 	      });
15953 	    }
15954 
15955 	    // allow to fiddle around with definitions
15956 	    definitions = self._emit('saveXML.start', {
15957 	      definitions: definitions
15958 	    }) || definitions;
15959 
15960 	    self._moddle.toXML(definitions, options).then(function(result) {
15961 
15962 	      var xml = result.xml;
15963 
15964 	      xml = self._emit('saveXML.serialized', {
15965 	        xml: xml
15966 	      }) || xml;
15967 
15968 	      return resolve({
15969 	        xml: xml
15970 	      });
15971 	    });
15972 	  }).catch(function(error) {
15973 	    return { error: error };
15974 	  }).then(function(result) {
15975 
15976 	    self._emit('saveXML.done', result);
15977 
15978 	    var error = result.error;
15979 
15980 	    if (error) {
15981 	      return Promise.reject(error);
15982 	    }
15983 
15984 	    return result;
15985 	  });
15986 	});
15987 
15988 	/**
15989 	 * The saveSVG result.
15990 	 *
15991 	 * @typedef {Object} SaveSVGResult
15992 	 *
15993 	 * @property {string} svg
15994 	 */
15995 
15996 	/**
15997 	 * Export the currently displayed BPMN 2.0 diagram as
15998 	 * an SVG image.
15999 	 *
16000 	 * ## Life-Cycle Events
16001 	 *
16002 	 * During SVG saving the viewer will fire life-cycle events:
16003 	 *
16004 	 *   * saveSVG.start (before serialization)
16005 	 *   * saveSVG.done (everything done)
16006 	 *
16007 	 * You can use these events to hook into the life-cycle.
16008 	 *
16009 	 * @param {Object} [options]
16010 	 *
16011 	 * Returns {Promise<SaveSVGResult, Error>}
16012 	 */
16013 	BaseViewer.prototype.saveSVG = wrapForCompatibility(function saveSVG(options) {
16014 
16015 	  var self = this;
16016 
16017 	  return new Promise(function(resolve, reject) {
16018 
16019 	    self._emit('saveSVG.start');
16020 
16021 	    var svg, err;
16022 
16023 	    try {
16024 	      var canvas = self.get('canvas');
16025 
16026 	      var contentNode = canvas.getDefaultLayer(),
16027 	          defsNode = query('defs', canvas._svg);
16028 
16029 	      var contents = innerSVG(contentNode),
16030 	          defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
16031 
16032 	      var bbox = contentNode.getBBox();
16033 
16034 	      svg =
16035 	        '<?xml version="1.0" encoding="utf-8"?>\n' +
16036 	        '<!-- created with bpmn-js / http://bpmn.io -->\n' +
16037 	        '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
16038 	        '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
16039 	             'width="' + bbox.width + '" height="' + bbox.height + '" ' +
16040 	             'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
16041 	          defs + contents +
16042 	        '</svg>';
16043 	    } catch (e) {
16044 	      err = e;
16045 	    }
16046 
16047 	    self._emit('saveSVG.done', {
16048 	      error: err,
16049 	      svg: svg
16050 	    });
16051 
16052 	    if (!err) {
16053 	      return resolve({ svg: svg });
16054 	    }
16055 
16056 	    return reject(err);
16057 	  });
16058 	});
16059 
16060 	/**
16061 	 * Get a named diagram service.
16062 	 *
16063 	 * @example
16064 	 *
16065 	 * var elementRegistry = viewer.get('elementRegistry');
16066 	 * var startEventShape = elementRegistry.get('StartEvent_1');
16067 	 *
16068 	 * @param {string} name
16069 	 *
16070 	 * @return {Object} diagram service instance
16071 	 *
16072 	 * @method BaseViewer#get
16073 	 */
16074 
16075 	/**
16076 	 * Invoke a function in the context of this viewer.
16077 	 *
16078 	 * @example
16079 	 *
16080 	 * viewer.invoke(function(elementRegistry) {
16081 	 *   var startEventShape = elementRegistry.get('StartEvent_1');
16082 	 * });
16083 	 *
16084 	 * @param {Function} fn to be invoked
16085 	 *
16086 	 * @return {Object} the functions return value
16087 	 *
16088 	 * @method BaseViewer#invoke
16089 	 */
16090 
16091 
16092 	BaseViewer.prototype._setDefinitions = function(definitions) {
16093 	  this._definitions = definitions;
16094 	};
16095 
16096 	BaseViewer.prototype.getModules = function() {
16097 	  return this._modules;
16098 	};
16099 
16100 	/**
16101 	 * Remove all drawn elements from the viewer.
16102 	 *
16103 	 * After calling this method the viewer can still
16104 	 * be reused for opening another diagram.
16105 	 *
16106 	 * @method BaseViewer#clear
16107 	 */
16108 	BaseViewer.prototype.clear = function() {
16109 	  if (!this.getDefinitions()) {
16110 
16111 	    // no diagram to clear
16112 	    return;
16113 	  }
16114 
16115 	  // remove businessObject#di binding
16116 	  //
16117 	  // this is necessary, as we establish the bindings
16118 	  // in the BpmnTreeWalker (and assume none are given
16119 	  // on reimport)
16120 	  this.get('elementRegistry').forEach(function(element) {
16121 	    var bo = element.businessObject;
16122 
16123 	    if (bo && bo.di) {
16124 	      delete bo.di;
16125 	    }
16126 	  });
16127 
16128 	  // remove drawn elements
16129 	  Diagram.prototype.clear.call(this);
16130 	};
16131 
16132 	/**
16133 	 * Destroy the viewer instance and remove all its
16134 	 * remainders from the document tree.
16135 	 */
16136 	BaseViewer.prototype.destroy = function() {
16137 
16138 	  // diagram destroy
16139 	  Diagram.prototype.destroy.call(this);
16140 
16141 	  // dom detach
16142 	  remove$2(this._container);
16143 	};
16144 
16145 	/**
16146 	 * Register an event listener
16147 	 *
16148 	 * Remove a previously added listener via {@link #off(event, callback)}.
16149 	 *
16150 	 * @param {string} event
16151 	 * @param {number} [priority]
16152 	 * @param {Function} callback
16153 	 * @param {Object} [that]
16154 	 */
16155 	BaseViewer.prototype.on = function(event, priority, callback, target) {
16156 	  return this.get('eventBus').on(event, priority, callback, target);
16157 	};
16158 
16159 	/**
16160 	 * De-register an event listener
16161 	 *
16162 	 * @param {string} event
16163 	 * @param {Function} callback
16164 	 */
16165 	BaseViewer.prototype.off = function(event, callback) {
16166 	  this.get('eventBus').off(event, callback);
16167 	};
16168 
16169 	BaseViewer.prototype.attachTo = function(parentNode) {
16170 
16171 	  if (!parentNode) {
16172 	    throw new Error('parentNode required');
16173 	  }
16174 
16175 	  // ensure we detach from the
16176 	  // previous, old parent
16177 	  this.detach();
16178 
16179 	  // unwrap jQuery if provided
16180 	  if (parentNode.get && parentNode.constructor.prototype.jquery) {
16181 	    parentNode = parentNode.get(0);
16182 	  }
16183 
16184 	  if (typeof parentNode === 'string') {
16185 	    parentNode = query(parentNode);
16186 	  }
16187 
16188 	  parentNode.appendChild(this._container);
16189 
16190 	  this._emit('attach', {});
16191 
16192 	  this.get('canvas').resized();
16193 	};
16194 
16195 	BaseViewer.prototype.getDefinitions = function() {
16196 	  return this._definitions;
16197 	};
16198 
16199 	BaseViewer.prototype.detach = function() {
16200 
16201 	  var container = this._container,
16202 	      parentNode = container.parentNode;
16203 
16204 	  if (!parentNode) {
16205 	    return;
16206 	  }
16207 
16208 	  this._emit('detach', {});
16209 
16210 	  parentNode.removeChild(container);
16211 	};
16212 
16213 	BaseViewer.prototype._init = function(container, moddle, options) {
16214 
16215 	  var baseModules = options.modules || this.getModules(),
16216 	      additionalModules = options.additionalModules || [],
16217 	      staticModules = [
16218 	        {
16219 	          bpmnjs: [ 'value', this ],
16220 	          moddle: [ 'value', moddle ]
16221 	        }
16222 	      ];
16223 
16224 	  var diagramModules = [].concat(staticModules, baseModules, additionalModules);
16225 
16226 	  var diagramOptions = assign(omit(options, [ 'additionalModules' ]), {
16227 	    canvas: assign({}, options.canvas, { container: container }),
16228 	    modules: diagramModules
16229 	  });
16230 
16231 	  // invoke diagram constructor
16232 	  Diagram.call(this, diagramOptions);
16233 
16234 	  if (options && options.container) {
16235 	    this.attachTo(options.container);
16236 	  }
16237 	};
16238 
16239 	/**
16240 	 * Emit an event on the underlying {@link EventBus}
16241 	 *
16242 	 * @param  {string} type
16243 	 * @param  {Object} event
16244 	 *
16245 	 * @return {Object} event processing result (if any)
16246 	 */
16247 	BaseViewer.prototype._emit = function(type, event) {
16248 	  return this.get('eventBus').fire(type, event);
16249 	};
16250 
16251 	BaseViewer.prototype._createContainer = function(options) {
16252 
16253 	  var container = domify('<div class="bjs-container"></div>');
16254 
16255 	  assign(container.style, {
16256 	    width: ensureUnit(options.width),
16257 	    height: ensureUnit(options.height),
16258 	    position: options.position
16259 	  });
16260 
16261 	  return container;
16262 	};
16263 
16264 	BaseViewer.prototype._createModdle = function(options) {
16265 	  var moddleOptions = assign({}, this._moddleExtensions, options.moddleExtensions);
16266 
16267 	  return new simple(moddleOptions);
16268 	};
16269 
16270 	BaseViewer.prototype._modules = [];
16271 
16272 	// helpers ///////////////
16273 
16274 	function addWarningsToError(err, warningsAry) {
16275 	  err.warnings = warningsAry;
16276 	  return err;
16277 	}
16278 
16279 	function checkValidationError(err) {
16280 
16281 	  // check if we can help the user by indicating wrong BPMN 2.0 xml
16282 	  // (in case he or the exporting tool did not get that right)
16283 
16284 	  var pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/;
16285 	  var match = pattern.exec(err.message);
16286 
16287 	  if (match) {
16288 	    err.message =
16289 	      'unparsable content <' + match[1] + '> detected; ' +
16290 	      'this may indicate an invalid BPMN 2.0 diagram file' + match[2];
16291 	  }
16292 
16293 	  return err;
16294 	}
16295 
16296 	var DEFAULT_OPTIONS = {
16297 	  width: '100%',
16298 	  height: '100%',
16299 	  position: 'relative'
16300 	};
16301 
16302 
16303 	/**
16304 	 * Ensure the passed argument is a proper unit (defaulting to px)
16305 	 */
16306 	function ensureUnit(val) {
16307 	  return val + (isNumber(val) ? 'px' : '');
16308 	}
16309 
16310 
16311 	/**
16312 	 * Find BPMNDiagram in definitions by ID
16313 	 *
16314 	 * @param {ModdleElement<Definitions>} definitions
16315 	 * @param {string} diagramId
16316 	 *
16317 	 * @return {ModdleElement<BPMNDiagram>|null}
16318 	 */
16319 	function findBPMNDiagram(definitions, diagramId) {
16320 	  if (!diagramId) {
16321 	    return null;
16322 	  }
16323 
16324 	  return find(definitions.diagrams, function(element) {
16325 	    return element.id === diagramId;
16326 	  }) || null;
16327 	}
16328 
16329 	/**
16330 	 * Adds the project logo to the diagram container as
16331 	 * required by the bpmn.io license.
16332 	 *
16333 	 * @see http://bpmn.io/license
16334 	 *
16335 	 * @param {Element} container
16336 	 */
16337 	function addProjectLogo(container) {
16338 	  var img = BPMNIO_IMG;
16339 
16340 	  var linkMarkup =
16341 	    '<a href="http://bpmn.io" ' +
16342 	       'target="_blank" ' +
16343 	       'class="bjs-powered-by" ' +
16344 	       'title="Powered by bpmn.io" ' +
16345 	       'style="position: absolute; bottom: 15px; right: 15px; z-index: 100; ' + LINK_STYLES + '">' +
16346 	      img +
16347 	    '</a>';
16348 
16349 	  var linkElement = domify(linkMarkup);
16350 
16351 	  container.appendChild(linkElement);
16352 
16353 	  componentEvent.bind(linkElement, 'click', function(event) {
16354 	    open();
16355 
16356 	    event.preventDefault();
16357 	  });
16358 	}
16359 
16360 	/* </project-logo> */
16361 
16362 	/**
16363 	 * A base modeler for BPMN 2.0 diagrams.
16364 	 *
16365 	 * Have a look at {@link Modeler} for a bundle that includes actual features.
16366 	 *
16367 	 * @param {Object} [options] configuration options to pass to the viewer
16368 	 * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
16369 	 * @param {string|number} [options.width] the width of the viewer
16370 	 * @param {string|number} [options.height] the height of the viewer
16371 	 * @param {Object} [options.moddleExtensions] extension packages to provide
16372 	 * @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
16373 	 * @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
16374 	 */
16375 	function BaseModeler(options) {
16376 	  BaseViewer.call(this, options);
16377 
16378 	  // hook ID collection into the modeler
16379 	  this.on('import.parse.complete', function(event) {
16380 	    if (!event.error) {
16381 	      this._collectIds(event.definitions, event.elementsById);
16382 	    }
16383 	  }, this);
16384 
16385 	  this.on('diagram.destroy', function() {
16386 	    this.get('moddle').ids.clear();
16387 	  }, this);
16388 	}
16389 
16390 	inherits$1(BaseModeler, BaseViewer);
16391 
16392 
16393 	/**
16394 	 * Create a moddle instance, attaching ids to it.
16395 	 *
16396 	 * @param {Object} options
16397 	 */
16398 	BaseModeler.prototype._createModdle = function(options) {
16399 	  var moddle = BaseViewer.prototype._createModdle.call(this, options);
16400 
16401 	  // attach ids to moddle to be able to track
16402 	  // and validated ids in the BPMN 2.0 XML document
16403 	  // tree
16404 	  moddle.ids = new Ids([ 32, 36, 1 ]);
16405 
16406 	  return moddle;
16407 	};
16408 
16409 	/**
16410 	 * Collect ids processed during parsing of the
16411 	 * definitions object.
16412 	 *
16413 	 * @param {ModdleElement} definitions
16414 	 * @param {Context} context
16415 	 */
16416 	BaseModeler.prototype._collectIds = function(definitions, elementsById) {
16417 
16418 	  var moddle = definitions.$model,
16419 	      ids = moddle.ids,
16420 	      id;
16421 
16422 	  // remove references from previous import
16423 	  ids.clear();
16424 
16425 	  for (id in elementsById) {
16426 	    ids.claim(id, elementsById[id]);
16427 	  }
16428 	};
16429 
16430 	/**
16431 	 * Is an element of the given BPMN type?
16432 	 *
16433 	 * @param  {djs.model.Base|ModdleElement} element
16434 	 * @param  {string} type
16435 	 *
16436 	 * @return {boolean}
16437 	 */
16438 	function is$1(element, type) {
16439 	  var bo = getBusinessObject(element);
16440 
16441 	  return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
16442 	}
16443 
16444 
16445 	/**
16446 	 * Return the business object for a given element.
16447 	 *
16448 	 * @param  {djs.model.Base|ModdleElement} element
16449 	 *
16450 	 * @return {ModdleElement}
16451 	 */
16452 	function getBusinessObject(element) {
16453 	  return (element && element.businessObject) || element;
16454 	}
16455 
16456 	function isExpanded(element) {
16457 
16458 	  if (is$1(element, 'bpmn:CallActivity')) {
16459 	    return false;
16460 	  }
16461 
16462 	  if (is$1(element, 'bpmn:SubProcess')) {
16463 	    return getBusinessObject(element).di && !!getBusinessObject(element).di.isExpanded;
16464 	  }
16465 
16466 	  if (is$1(element, 'bpmn:Participant')) {
16467 	    return !!getBusinessObject(element).processRef;
16468 	  }
16469 
16470 	  return true;
16471 	}
16472 
16473 	function isInterrupting(element) {
16474 	  return element && getBusinessObject(element).isInterrupting !== false;
16475 	}
16476 
16477 	function isEventSubProcess(element) {
16478 	  return element && !!getBusinessObject(element).triggeredByEvent;
16479 	}
16480 
16481 	function hasEventDefinition$2(element, eventType) {
16482 	  var bo = getBusinessObject(element),
16483 	      hasEventDefinition = false;
16484 
16485 	  if (bo.eventDefinitions) {
16486 	    forEach(bo.eventDefinitions, function(event) {
16487 	      if (is$1(event, eventType)) {
16488 	        hasEventDefinition = true;
16489 	      }
16490 	    });
16491 	  }
16492 
16493 	  return hasEventDefinition;
16494 	}
16495 
16496 	function hasErrorEventDefinition(element) {
16497 	  return hasEventDefinition$2(element, 'bpmn:ErrorEventDefinition');
16498 	}
16499 
16500 	function hasEscalationEventDefinition(element) {
16501 	  return hasEventDefinition$2(element, 'bpmn:EscalationEventDefinition');
16502 	}
16503 
16504 	function hasCompensateEventDefinition(element) {
16505 	  return hasEventDefinition$2(element, 'bpmn:CompensateEventDefinition');
16506 	}
16507 
16508 	function getLabelAttr(semantic) {
16509 	  if (
16510 	    is$1(semantic, 'bpmn:FlowElement') ||
16511 	    is$1(semantic, 'bpmn:Participant') ||
16512 	    is$1(semantic, 'bpmn:Lane') ||
16513 	    is$1(semantic, 'bpmn:SequenceFlow') ||
16514 	    is$1(semantic, 'bpmn:MessageFlow') ||
16515 	    is$1(semantic, 'bpmn:DataInput') ||
16516 	    is$1(semantic, 'bpmn:DataOutput')
16517 	  ) {
16518 	    return 'name';
16519 	  }
16520 
16521 	  if (is$1(semantic, 'bpmn:TextAnnotation')) {
16522 	    return 'text';
16523 	  }
16524 
16525 	  if (is$1(semantic, 'bpmn:Group')) {
16526 	    return 'categoryValueRef';
16527 	  }
16528 	}
16529 
16530 	function getCategoryValue(semantic) {
16531 	  var categoryValueRef = semantic['categoryValueRef'];
16532 
16533 	  if (!categoryValueRef) {
16534 	    return '';
16535 	  }
16536 
16537 
16538 	  return categoryValueRef.value || '';
16539 	}
16540 
16541 	function getLabel(element) {
16542 	  var semantic = element.businessObject,
16543 	      attr = getLabelAttr(semantic);
16544 
16545 	  if (attr) {
16546 
16547 	    if (attr === 'categoryValueRef') {
16548 
16549 	      return getCategoryValue(semantic);
16550 	    }
16551 
16552 	    return semantic[attr] || '';
16553 	  }
16554 	}
16555 
16556 
16557 	function setLabel(element, text, isExternal) {
16558 	  var semantic = element.businessObject,
16559 	      attr = getLabelAttr(semantic);
16560 
16561 	  if (attr) {
16562 
16563 	    if (attr === 'categoryValueRef') {
16564 	      semantic['categoryValueRef'].value = text;
16565 	    } else {
16566 	      semantic[attr] = text;
16567 	    }
16568 
16569 	  }
16570 
16571 	  return element;
16572 	}
16573 
16574 	// element utils //////////////////////
16575 
16576 	/**
16577 	 * Checks if eventDefinition of the given element matches with semantic type.
16578 	 *
16579 	 * @return {boolean} true if element is of the given semantic type
16580 	 */
16581 	function isTypedEvent(event, eventDefinitionType, filter) {
16582 
16583 	  function matches(definition, filter) {
16584 	    return every(filter, function(val, key) {
16585 
16586 	      // we want a == conversion here, to be able to catch
16587 	      // undefined == false and friends
16588 	      /* jshint -W116 */
16589 	      return definition[key] == val;
16590 	    });
16591 	  }
16592 
16593 	  return some(event.eventDefinitions, function(definition) {
16594 	    return definition.$type === eventDefinitionType && matches(event, filter);
16595 	  });
16596 	}
16597 
16598 	function isThrowEvent(event) {
16599 	  return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent');
16600 	}
16601 
16602 	function isCollection(element) {
16603 	  var dataObject = element.dataObjectRef;
16604 
16605 	  return element.isCollection || (dataObject && dataObject.isCollection);
16606 	}
16607 
16608 	function getDi(element) {
16609 	  return element.businessObject.di;
16610 	}
16611 
16612 	function getSemantic(element) {
16613 	  return element.businessObject;
16614 	}
16615 
16616 
16617 	// color access //////////////////////
16618 
16619 	function getFillColor(element, defaultColor) {
16620 	  var di = getDi(element);
16621 
16622 	  return di.get('color:background-color') || di.get('bioc:fill') || defaultColor || 'white';
16623 	}
16624 
16625 	function getStrokeColor$1(element, defaultColor) {
16626 	  var di = getDi(element);
16627 
16628 	  return di.get('color:border-color') || di.get('bioc:stroke') || defaultColor || 'black';
16629 	}
16630 
16631 	function getLabelColor(element, defaultColor, defaultStrokeColor) {
16632 	  var di = getDi(element),
16633 	      label = di.get('label');
16634 
16635 	  return label && label.get('color:color') || defaultColor ||
16636 	    getStrokeColor$1(element, defaultStrokeColor);
16637 	}
16638 
16639 	// cropping path customizations //////////////////////
16640 
16641 	function getCirclePath(shape) {
16642 
16643 	  var cx = shape.x + shape.width / 2,
16644 	      cy = shape.y + shape.height / 2,
16645 	      radius = shape.width / 2;
16646 
16647 	  var circlePath = [
16648 	    ['M', cx, cy],
16649 	    ['m', 0, -radius],
16650 	    ['a', radius, radius, 0, 1, 1, 0, 2 * radius],
16651 	    ['a', radius, radius, 0, 1, 1, 0, -2 * radius],
16652 	    ['z']
16653 	  ];
16654 
16655 	  return componentsToPath(circlePath);
16656 	}
16657 
16658 	function getRoundRectPath(shape, borderRadius) {
16659 
16660 	  var x = shape.x,
16661 	      y = shape.y,
16662 	      width = shape.width,
16663 	      height = shape.height;
16664 
16665 	  var roundRectPath = [
16666 	    ['M', x + borderRadius, y],
16667 	    ['l', width - borderRadius * 2, 0],
16668 	    ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, borderRadius],
16669 	    ['l', 0, height - borderRadius * 2],
16670 	    ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, borderRadius],
16671 	    ['l', borderRadius * 2 - width, 0],
16672 	    ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, -borderRadius],
16673 	    ['l', 0, borderRadius * 2 - height],
16674 	    ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, -borderRadius],
16675 	    ['z']
16676 	  ];
16677 
16678 	  return componentsToPath(roundRectPath);
16679 	}
16680 
16681 	function getDiamondPath(shape) {
16682 
16683 	  var width = shape.width,
16684 	      height = shape.height,
16685 	      x = shape.x,
16686 	      y = shape.y,
16687 	      halfWidth = width / 2,
16688 	      halfHeight = height / 2;
16689 
16690 	  var diamondPath = [
16691 	    ['M', x + halfWidth, y],
16692 	    ['l', halfWidth, halfHeight],
16693 	    ['l', -halfWidth, halfHeight],
16694 	    ['l', -halfWidth, -halfHeight],
16695 	    ['z']
16696 	  ];
16697 
16698 	  return componentsToPath(diamondPath);
16699 	}
16700 
16701 	function getRectPath(shape) {
16702 	  var x = shape.x,
16703 	      y = shape.y,
16704 	      width = shape.width,
16705 	      height = shape.height;
16706 
16707 	  var rectPath = [
16708 	    ['M', x, y],
16709 	    ['l', width, 0],
16710 	    ['l', 0, height],
16711 	    ['l', -width, 0],
16712 	    ['z']
16713 	  ];
16714 
16715 	  return componentsToPath(rectPath);
16716 	}
16717 
16718 	var RENDERER_IDS = new Ids();
16719 
16720 	var TASK_BORDER_RADIUS = 10;
16721 	var INNER_OUTER_DIST = 3;
16722 
16723 	var DEFAULT_FILL_OPACITY = .95,
16724 	    HIGH_FILL_OPACITY = .35;
16725 
16726 	var ELEMENT_LABEL_DISTANCE$1 = 10;
16727 
16728 	function BpmnRenderer(
16729 	    config, eventBus, styles, pathMap,
16730 	    canvas, textRenderer, priority) {
16731 
16732 	  BaseRenderer.call(this, eventBus, priority);
16733 
16734 	  var defaultFillColor = config && config.defaultFillColor,
16735 	      defaultStrokeColor = config && config.defaultStrokeColor,
16736 	      defaultLabelColor = config && config.defaultLabelColor;
16737 
16738 	  var rendererId = RENDERER_IDS.next();
16739 
16740 	  var markers = {};
16741 
16742 	  var computeStyle = styles.computeStyle;
16743 
16744 	  function addMarker(id, options) {
16745 	    var attrs = assign({
16746 	      fill: 'black',
16747 	      strokeWidth: 1,
16748 	      strokeLinecap: 'round',
16749 	      strokeDasharray: 'none'
16750 	    }, options.attrs);
16751 
16752 	    var ref = options.ref || { x: 0, y: 0 };
16753 
16754 	    var scale = options.scale || 1;
16755 
16756 	    // fix for safari / chrome / firefox bug not correctly
16757 	    // resetting stroke dash array
16758 	    if (attrs.strokeDasharray === 'none') {
16759 	      attrs.strokeDasharray = [10000, 1];
16760 	    }
16761 
16762 	    var marker = create$1('marker');
16763 
16764 	    attr(options.element, attrs);
16765 
16766 	    append(marker, options.element);
16767 
16768 	    attr(marker, {
16769 	      id: id,
16770 	      viewBox: '0 0 20 20',
16771 	      refX: ref.x,
16772 	      refY: ref.y,
16773 	      markerWidth: 20 * scale,
16774 	      markerHeight: 20 * scale,
16775 	      orient: 'auto'
16776 	    });
16777 
16778 	    var defs = query('defs', canvas._svg);
16779 
16780 	    if (!defs) {
16781 	      defs = create$1('defs');
16782 
16783 	      append(canvas._svg, defs);
16784 	    }
16785 
16786 	    append(defs, marker);
16787 
16788 	    markers[id] = marker;
16789 	  }
16790 
16791 	  function colorEscape(str) {
16792 
16793 	    // only allow characters and numbers
16794 	    return str.replace(/[^0-9a-zA-z]+/g, '_');
16795 	  }
16796 
16797 	  function marker(type, fill, stroke) {
16798 	    var id = type + '-' + colorEscape(fill) + '-' + colorEscape(stroke) + '-' + rendererId;
16799 
16800 	    if (!markers[id]) {
16801 	      createMarker(id, type, fill, stroke);
16802 	    }
16803 
16804 	    return 'url(#' + id + ')';
16805 	  }
16806 
16807 	  function createMarker(id, type, fill, stroke) {
16808 
16809 	    if (type === 'sequenceflow-end') {
16810 	      var sequenceflowEnd = create$1('path');
16811 	      attr(sequenceflowEnd, { d: 'M 1 5 L 11 10 L 1 15 Z' });
16812 
16813 	      addMarker(id, {
16814 	        element: sequenceflowEnd,
16815 	        ref: { x: 11, y: 10 },
16816 	        scale: 0.5,
16817 	        attrs: {
16818 	          fill: stroke,
16819 	          stroke: stroke
16820 	        }
16821 	      });
16822 	    }
16823 
16824 	    if (type === 'messageflow-start') {
16825 	      var messageflowStart = create$1('circle');
16826 	      attr(messageflowStart, { cx: 6, cy: 6, r: 3.5 });
16827 
16828 	      addMarker(id, {
16829 	        element: messageflowStart,
16830 	        attrs: {
16831 	          fill: fill,
16832 	          stroke: stroke
16833 	        },
16834 	        ref: { x: 6, y: 6 }
16835 	      });
16836 	    }
16837 
16838 	    if (type === 'messageflow-end') {
16839 	      var messageflowEnd = create$1('path');
16840 	      attr(messageflowEnd, { d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z' });
16841 
16842 	      addMarker(id, {
16843 	        element: messageflowEnd,
16844 	        attrs: {
16845 	          fill: fill,
16846 	          stroke: stroke,
16847 	          strokeLinecap: 'butt'
16848 	        },
16849 	        ref: { x: 8.5, y: 5 }
16850 	      });
16851 	    }
16852 
16853 	    if (type === 'association-start') {
16854 	      var associationStart = create$1('path');
16855 	      attr(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
16856 
16857 	      addMarker(id, {
16858 	        element: associationStart,
16859 	        attrs: {
16860 	          fill: 'none',
16861 	          stroke: stroke,
16862 	          strokeWidth: 1.5
16863 	        },
16864 	        ref: { x: 1, y: 10 },
16865 	        scale: 0.5
16866 	      });
16867 	    }
16868 
16869 	    if (type === 'association-end') {
16870 	      var associationEnd = create$1('path');
16871 	      attr(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
16872 
16873 	      addMarker(id, {
16874 	        element: associationEnd,
16875 	        attrs: {
16876 	          fill: 'none',
16877 	          stroke: stroke,
16878 	          strokeWidth: 1.5
16879 	        },
16880 	        ref: { x: 12, y: 10 },
16881 	        scale: 0.5
16882 	      });
16883 	    }
16884 
16885 	    if (type === 'conditional-flow-marker') {
16886 	      var conditionalflowMarker = create$1('path');
16887 	      attr(conditionalflowMarker, { d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z' });
16888 
16889 	      addMarker(id, {
16890 	        element: conditionalflowMarker,
16891 	        attrs: {
16892 	          fill: fill,
16893 	          stroke: stroke
16894 	        },
16895 	        ref: { x: -1, y: 10 },
16896 	        scale: 0.5
16897 	      });
16898 	    }
16899 
16900 	    if (type === 'conditional-default-flow-marker') {
16901 	      var conditionaldefaultflowMarker = create$1('path');
16902 	      attr(conditionaldefaultflowMarker, { d: 'M 6 4 L 10 16' });
16903 
16904 	      addMarker(id, {
16905 	        element: conditionaldefaultflowMarker,
16906 	        attrs: {
16907 	          stroke: stroke
16908 	        },
16909 	        ref: { x: 0, y: 10 },
16910 	        scale: 0.5
16911 	      });
16912 	    }
16913 	  }
16914 
16915 	  function drawCircle(parentGfx, width, height, offset, attrs) {
16916 
16917 	    if (isObject(offset)) {
16918 	      attrs = offset;
16919 	      offset = 0;
16920 	    }
16921 
16922 	    offset = offset || 0;
16923 
16924 	    attrs = computeStyle(attrs, {
16925 	      stroke: 'black',
16926 	      strokeWidth: 2,
16927 	      fill: 'white'
16928 	    });
16929 
16930 	    if (attrs.fill === 'none') {
16931 	      delete attrs.fillOpacity;
16932 	    }
16933 
16934 	    var cx = width / 2,
16935 	        cy = height / 2;
16936 
16937 	    var circle = create$1('circle');
16938 	    attr(circle, {
16939 	      cx: cx,
16940 	      cy: cy,
16941 	      r: Math.round((width + height) / 4 - offset)
16942 	    });
16943 	    attr(circle, attrs);
16944 
16945 	    append(parentGfx, circle);
16946 
16947 	    return circle;
16948 	  }
16949 
16950 	  function drawRect(parentGfx, width, height, r, offset, attrs) {
16951 
16952 	    if (isObject(offset)) {
16953 	      attrs = offset;
16954 	      offset = 0;
16955 	    }
16956 
16957 	    offset = offset || 0;
16958 
16959 	    attrs = computeStyle(attrs, {
16960 	      stroke: 'black',
16961 	      strokeWidth: 2,
16962 	      fill: 'white'
16963 	    });
16964 
16965 	    var rect = create$1('rect');
16966 	    attr(rect, {
16967 	      x: offset,
16968 	      y: offset,
16969 	      width: width - offset * 2,
16970 	      height: height - offset * 2,
16971 	      rx: r,
16972 	      ry: r
16973 	    });
16974 	    attr(rect, attrs);
16975 
16976 	    append(parentGfx, rect);
16977 
16978 	    return rect;
16979 	  }
16980 
16981 	  function drawDiamond(parentGfx, width, height, attrs) {
16982 
16983 	    var x_2 = width / 2;
16984 	    var y_2 = height / 2;
16985 
16986 	    var points = [{ x: x_2, y: 0 }, { x: width, y: y_2 }, { x: x_2, y: height }, { x: 0, y: y_2 }];
16987 
16988 	    var pointsString = points.map(function(point) {
16989 	      return point.x + ',' + point.y;
16990 	    }).join(' ');
16991 
16992 	    attrs = computeStyle(attrs, {
16993 	      stroke: 'black',
16994 	      strokeWidth: 2,
16995 	      fill: 'white'
16996 	    });
16997 
16998 	    var polygon = create$1('polygon');
16999 	    attr(polygon, {
17000 	      points: pointsString
17001 	    });
17002 	    attr(polygon, attrs);
17003 
17004 	    append(parentGfx, polygon);
17005 
17006 	    return polygon;
17007 	  }
17008 
17009 	  function drawLine(parentGfx, waypoints, attrs) {
17010 	    attrs = computeStyle(attrs, [ 'no-fill' ], {
17011 	      stroke: 'black',
17012 	      strokeWidth: 2,
17013 	      fill: 'none'
17014 	    });
17015 
17016 	    var line = createLine(waypoints, attrs);
17017 
17018 	    append(parentGfx, line);
17019 
17020 	    return line;
17021 	  }
17022 
17023 	  function drawPath(parentGfx, d, attrs) {
17024 
17025 	    attrs = computeStyle(attrs, [ 'no-fill' ], {
17026 	      strokeWidth: 2,
17027 	      stroke: 'black'
17028 	    });
17029 
17030 	    var path = create$1('path');
17031 	    attr(path, { d: d });
17032 	    attr(path, attrs);
17033 
17034 	    append(parentGfx, path);
17035 
17036 	    return path;
17037 	  }
17038 
17039 	  function drawMarker(type, parentGfx, path, attrs) {
17040 	    return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
17041 	  }
17042 
17043 	  function as(type) {
17044 	    return function(parentGfx, element) {
17045 	      return handlers[type](parentGfx, element);
17046 	    };
17047 	  }
17048 
17049 	  function renderer(type) {
17050 	    return handlers[type];
17051 	  }
17052 
17053 	  function renderEventContent(element, parentGfx) {
17054 
17055 	    var event = getSemantic(element);
17056 	    var isThrowing = isThrowEvent(event);
17057 
17058 	    if (event.eventDefinitions && event.eventDefinitions.length>1) {
17059 	      if (event.parallelMultiple) {
17060 	        return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing);
17061 	      }
17062 	      else {
17063 	        return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing);
17064 	      }
17065 	    }
17066 
17067 	    if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
17068 	      return renderer('bpmn:MessageEventDefinition')(parentGfx, element, isThrowing);
17069 	    }
17070 
17071 	    if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
17072 	      return renderer('bpmn:TimerEventDefinition')(parentGfx, element, isThrowing);
17073 	    }
17074 
17075 	    if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
17076 	      return renderer('bpmn:ConditionalEventDefinition')(parentGfx, element);
17077 	    }
17078 
17079 	    if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
17080 	      return renderer('bpmn:SignalEventDefinition')(parentGfx, element, isThrowing);
17081 	    }
17082 
17083 	    if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
17084 	      return renderer('bpmn:EscalationEventDefinition')(parentGfx, element, isThrowing);
17085 	    }
17086 
17087 	    if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
17088 	      return renderer('bpmn:LinkEventDefinition')(parentGfx, element, isThrowing);
17089 	    }
17090 
17091 	    if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
17092 	      return renderer('bpmn:ErrorEventDefinition')(parentGfx, element, isThrowing);
17093 	    }
17094 
17095 	    if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
17096 	      return renderer('bpmn:CancelEventDefinition')(parentGfx, element, isThrowing);
17097 	    }
17098 
17099 	    if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
17100 	      return renderer('bpmn:CompensateEventDefinition')(parentGfx, element, isThrowing);
17101 	    }
17102 
17103 	    if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
17104 	      return renderer('bpmn:TerminateEventDefinition')(parentGfx, element, isThrowing);
17105 	    }
17106 
17107 	    return null;
17108 	  }
17109 
17110 	  function renderLabel(parentGfx, label, options) {
17111 
17112 	    options = assign({
17113 	      size: {
17114 	        width: 100
17115 	      }
17116 	    }, options);
17117 
17118 	    var text = textRenderer.createText(label || '', options);
17119 
17120 	    classes(text).add('djs-label');
17121 
17122 	    append(parentGfx, text);
17123 
17124 	    return text;
17125 	  }
17126 
17127 	  function renderEmbeddedLabel(parentGfx, element, align) {
17128 	    var semantic = getSemantic(element);
17129 
17130 	    return renderLabel(parentGfx, semantic.name, {
17131 	      box: element,
17132 	      align: align,
17133 	      padding: 5,
17134 	      style: {
17135 	        fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor)
17136 	      }
17137 	    });
17138 	  }
17139 
17140 	  function renderExternalLabel(parentGfx, element) {
17141 
17142 	    var box = {
17143 	      width: 90,
17144 	      height: 30,
17145 	      x: element.width / 2 + element.x,
17146 	      y: element.height / 2 + element.y
17147 	    };
17148 
17149 	    return renderLabel(parentGfx, getLabel(element), {
17150 	      box: box,
17151 	      fitBox: true,
17152 	      style: assign(
17153 	        {},
17154 	        textRenderer.getExternalStyle(),
17155 	        {
17156 	          fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor)
17157 	        }
17158 	      )
17159 	    });
17160 	  }
17161 
17162 	  function renderLaneLabel(parentGfx, text, element) {
17163 	    var textBox = renderLabel(parentGfx, text, {
17164 	      box: {
17165 	        height: 30,
17166 	        width: element.height
17167 	      },
17168 	      align: 'center-middle',
17169 	      style: {
17170 	        fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor)
17171 	      }
17172 	    });
17173 
17174 	    var top = -1 * element.height;
17175 
17176 	    transform(textBox, 0, -top, 270);
17177 	  }
17178 
17179 	  function createPathFromConnection(connection) {
17180 	    var waypoints = connection.waypoints;
17181 
17182 	    var pathData = 'm  ' + waypoints[0].x + ',' + waypoints[0].y;
17183 	    for (var i = 1; i < waypoints.length; i++) {
17184 	      pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
17185 	    }
17186 	    return pathData;
17187 	  }
17188 
17189 	  var handlers = this.handlers = {
17190 	    'bpmn:Event': function(parentGfx, element, attrs) {
17191 
17192 	      if (!('fillOpacity' in attrs)) {
17193 	        attrs.fillOpacity = DEFAULT_FILL_OPACITY;
17194 	      }
17195 
17196 	      return drawCircle(parentGfx, element.width, element.height, attrs);
17197 	    },
17198 	    'bpmn:StartEvent': function(parentGfx, element) {
17199 	      var attrs = {
17200 	        fill: getFillColor(element, defaultFillColor),
17201 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17202 	      };
17203 
17204 	      var semantic = getSemantic(element);
17205 
17206 	      if (!semantic.isInterrupting) {
17207 	        attrs = {
17208 	          strokeDasharray: '6',
17209 	          strokeLinecap: 'round',
17210 	          fill: getFillColor(element, defaultFillColor),
17211 	          stroke: getStrokeColor$1(element, defaultStrokeColor)
17212 	        };
17213 	      }
17214 
17215 	      var circle = renderer('bpmn:Event')(parentGfx, element, attrs);
17216 
17217 	      renderEventContent(element, parentGfx);
17218 
17219 	      return circle;
17220 	    },
17221 	    'bpmn:MessageEventDefinition': function(parentGfx, element, isThrowing) {
17222 	      var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
17223 	        xScaleFactor: 0.9,
17224 	        yScaleFactor: 0.9,
17225 	        containerWidth: element.width,
17226 	        containerHeight: element.height,
17227 	        position: {
17228 	          mx: 0.235,
17229 	          my: 0.315
17230 	        }
17231 	      });
17232 
17233 	      var fill = isThrowing ? getStrokeColor$1(element, defaultStrokeColor) : getFillColor(element, defaultFillColor);
17234 	      var stroke = isThrowing ? getFillColor(element, defaultFillColor) : getStrokeColor$1(element, defaultStrokeColor);
17235 
17236 	      var messagePath = drawPath(parentGfx, pathData, {
17237 	        strokeWidth: 1,
17238 	        fill: fill,
17239 	        stroke: stroke
17240 	      });
17241 
17242 	      return messagePath;
17243 	    },
17244 	    'bpmn:TimerEventDefinition': function(parentGfx, element) {
17245 	      var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
17246 	        strokeWidth: 2,
17247 	        fill: getFillColor(element, defaultFillColor),
17248 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17249 	      });
17250 
17251 	      var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
17252 	        xScaleFactor: 0.75,
17253 	        yScaleFactor: 0.75,
17254 	        containerWidth: element.width,
17255 	        containerHeight: element.height,
17256 	        position: {
17257 	          mx: 0.5,
17258 	          my: 0.5
17259 	        }
17260 	      });
17261 
17262 	      drawPath(parentGfx, pathData, {
17263 	        strokeWidth: 2,
17264 	        strokeLinecap: 'square',
17265 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17266 	      });
17267 
17268 	      for (var i = 0;i < 12; i++) {
17269 
17270 	        var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
17271 	          xScaleFactor: 0.75,
17272 	          yScaleFactor: 0.75,
17273 	          containerWidth: element.width,
17274 	          containerHeight: element.height,
17275 	          position: {
17276 	            mx: 0.5,
17277 	            my: 0.5
17278 	          }
17279 	        });
17280 
17281 	        var width = element.width / 2;
17282 	        var height = element.height / 2;
17283 
17284 	        drawPath(parentGfx, linePathData, {
17285 	          strokeWidth: 1,
17286 	          strokeLinecap: 'square',
17287 	          transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')',
17288 	          stroke: getStrokeColor$1(element, defaultStrokeColor)
17289 	        });
17290 	      }
17291 
17292 	      return circle;
17293 	    },
17294 	    'bpmn:EscalationEventDefinition': function(parentGfx, event, isThrowing) {
17295 	      var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
17296 	        xScaleFactor: 1,
17297 	        yScaleFactor: 1,
17298 	        containerWidth: event.width,
17299 	        containerHeight: event.height,
17300 	        position: {
17301 	          mx: 0.5,
17302 	          my: 0.2
17303 	        }
17304 	      });
17305 
17306 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17307 
17308 	      return drawPath(parentGfx, pathData, {
17309 	        strokeWidth: 1,
17310 	        fill: fill,
17311 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17312 	      });
17313 	    },
17314 	    'bpmn:ConditionalEventDefinition': function(parentGfx, event) {
17315 	      var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
17316 	        xScaleFactor: 1,
17317 	        yScaleFactor: 1,
17318 	        containerWidth: event.width,
17319 	        containerHeight: event.height,
17320 	        position: {
17321 	          mx: 0.5,
17322 	          my: 0.222
17323 	        }
17324 	      });
17325 
17326 	      return drawPath(parentGfx, pathData, {
17327 	        strokeWidth: 1,
17328 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17329 	      });
17330 	    },
17331 	    'bpmn:LinkEventDefinition': function(parentGfx, event, isThrowing) {
17332 	      var pathData = pathMap.getScaledPath('EVENT_LINK', {
17333 	        xScaleFactor: 1,
17334 	        yScaleFactor: 1,
17335 	        containerWidth: event.width,
17336 	        containerHeight: event.height,
17337 	        position: {
17338 	          mx: 0.57,
17339 	          my: 0.263
17340 	        }
17341 	      });
17342 
17343 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17344 
17345 	      return drawPath(parentGfx, pathData, {
17346 	        strokeWidth: 1,
17347 	        fill: fill,
17348 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17349 	      });
17350 	    },
17351 	    'bpmn:ErrorEventDefinition': function(parentGfx, event, isThrowing) {
17352 	      var pathData = pathMap.getScaledPath('EVENT_ERROR', {
17353 	        xScaleFactor: 1.1,
17354 	        yScaleFactor: 1.1,
17355 	        containerWidth: event.width,
17356 	        containerHeight: event.height,
17357 	        position: {
17358 	          mx: 0.2,
17359 	          my: 0.722
17360 	        }
17361 	      });
17362 
17363 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17364 
17365 	      return drawPath(parentGfx, pathData, {
17366 	        strokeWidth: 1,
17367 	        fill: fill,
17368 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17369 	      });
17370 	    },
17371 	    'bpmn:CancelEventDefinition': function(parentGfx, event, isThrowing) {
17372 	      var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
17373 	        xScaleFactor: 1.0,
17374 	        yScaleFactor: 1.0,
17375 	        containerWidth: event.width,
17376 	        containerHeight: event.height,
17377 	        position: {
17378 	          mx: 0.638,
17379 	          my: -0.055
17380 	        }
17381 	      });
17382 
17383 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17384 
17385 	      var path = drawPath(parentGfx, pathData, {
17386 	        strokeWidth: 1,
17387 	        fill: fill,
17388 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17389 	      });
17390 
17391 	      rotate(path, 45);
17392 
17393 	      return path;
17394 	    },
17395 	    'bpmn:CompensateEventDefinition': function(parentGfx, event, isThrowing) {
17396 	      var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
17397 	        xScaleFactor: 1,
17398 	        yScaleFactor: 1,
17399 	        containerWidth: event.width,
17400 	        containerHeight: event.height,
17401 	        position: {
17402 	          mx: 0.22,
17403 	          my: 0.5
17404 	        }
17405 	      });
17406 
17407 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17408 
17409 	      return drawPath(parentGfx, pathData, {
17410 	        strokeWidth: 1,
17411 	        fill: fill,
17412 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17413 	      });
17414 	    },
17415 	    'bpmn:SignalEventDefinition': function(parentGfx, event, isThrowing) {
17416 	      var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
17417 	        xScaleFactor: 0.9,
17418 	        yScaleFactor: 0.9,
17419 	        containerWidth: event.width,
17420 	        containerHeight: event.height,
17421 	        position: {
17422 	          mx: 0.5,
17423 	          my: 0.2
17424 	        }
17425 	      });
17426 
17427 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17428 
17429 	      return drawPath(parentGfx, pathData, {
17430 	        strokeWidth: 1,
17431 	        fill: fill,
17432 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17433 	      });
17434 	    },
17435 	    'bpmn:MultipleEventDefinition': function(parentGfx, event, isThrowing) {
17436 	      var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
17437 	        xScaleFactor: 1.1,
17438 	        yScaleFactor: 1.1,
17439 	        containerWidth: event.width,
17440 	        containerHeight: event.height,
17441 	        position: {
17442 	          mx: 0.222,
17443 	          my: 0.36
17444 	        }
17445 	      });
17446 
17447 	      var fill = isThrowing ? getStrokeColor$1(event, defaultStrokeColor) : 'none';
17448 
17449 	      return drawPath(parentGfx, pathData, {
17450 	        strokeWidth: 1,
17451 	        fill: fill
17452 	      });
17453 	    },
17454 	    'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event) {
17455 	      var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
17456 	        xScaleFactor: 1.2,
17457 	        yScaleFactor: 1.2,
17458 	        containerWidth: event.width,
17459 	        containerHeight: event.height,
17460 	        position: {
17461 	          mx: 0.458,
17462 	          my: 0.194
17463 	        }
17464 	      });
17465 
17466 	      return drawPath(parentGfx, pathData, {
17467 	        strokeWidth: 1,
17468 	        fill: getStrokeColor$1(event, defaultStrokeColor),
17469 	        stroke: getStrokeColor$1(event, defaultStrokeColor)
17470 	      });
17471 	    },
17472 	    'bpmn:EndEvent': function(parentGfx, element) {
17473 	      var circle = renderer('bpmn:Event')(parentGfx, element, {
17474 	        strokeWidth: 4,
17475 	        fill: getFillColor(element, defaultFillColor),
17476 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17477 	      });
17478 
17479 	      renderEventContent(element, parentGfx);
17480 
17481 	      return circle;
17482 	    },
17483 	    'bpmn:TerminateEventDefinition': function(parentGfx, element) {
17484 	      var circle = drawCircle(parentGfx, element.width, element.height, 8, {
17485 	        strokeWidth: 4,
17486 	        fill: getStrokeColor$1(element, defaultStrokeColor),
17487 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17488 	      });
17489 
17490 	      return circle;
17491 	    },
17492 	    'bpmn:IntermediateEvent': function(parentGfx, element) {
17493 	      var outer = renderer('bpmn:Event')(parentGfx, element, {
17494 	        strokeWidth: 1,
17495 	        fill: getFillColor(element, defaultFillColor),
17496 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17497 	      });
17498 
17499 	      /* inner */
17500 	      drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
17501 	        strokeWidth: 1,
17502 	        fill: getFillColor(element, 'none'),
17503 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17504 	      });
17505 
17506 	      renderEventContent(element, parentGfx);
17507 
17508 	      return outer;
17509 	    },
17510 	    'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
17511 	    'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
17512 
17513 	    'bpmn:Activity': function(parentGfx, element, attrs) {
17514 
17515 	      attrs = attrs || {};
17516 
17517 	      if (!('fillOpacity' in attrs)) {
17518 	        attrs.fillOpacity = DEFAULT_FILL_OPACITY;
17519 	      }
17520 
17521 	      return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs);
17522 	    },
17523 
17524 	    'bpmn:Task': function(parentGfx, element) {
17525 	      var attrs = {
17526 	        fill: getFillColor(element, defaultFillColor),
17527 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17528 	      };
17529 
17530 	      var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
17531 
17532 	      renderEmbeddedLabel(parentGfx, element, 'center-middle');
17533 	      attachTaskMarkers(parentGfx, element);
17534 
17535 	      return rect;
17536 	    },
17537 	    'bpmn:ServiceTask': function(parentGfx, element) {
17538 	      var task = renderer('bpmn:Task')(parentGfx, element);
17539 
17540 	      var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
17541 	        abspos: {
17542 	          x: 12,
17543 	          y: 18
17544 	        }
17545 	      });
17546 
17547 	      /* service bg */ drawPath(parentGfx, pathDataBG, {
17548 	        strokeWidth: 1,
17549 	        fill: getFillColor(element, defaultFillColor),
17550 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17551 	      });
17552 
17553 	      var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
17554 	        abspos: {
17555 	          x: 17.2,
17556 	          y: 18
17557 	        }
17558 	      });
17559 
17560 	      /* service fill */ drawPath(parentGfx, fillPathData, {
17561 	        strokeWidth: 0,
17562 	        fill: getFillColor(element, defaultFillColor)
17563 	      });
17564 
17565 	      var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
17566 	        abspos: {
17567 	          x: 17,
17568 	          y: 22
17569 	        }
17570 	      });
17571 
17572 	      /* service */ drawPath(parentGfx, pathData, {
17573 	        strokeWidth: 1,
17574 	        fill: getFillColor(element, defaultFillColor),
17575 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17576 	      });
17577 
17578 	      return task;
17579 	    },
17580 	    'bpmn:UserTask': function(parentGfx, element) {
17581 	      var task = renderer('bpmn:Task')(parentGfx, element);
17582 
17583 	      var x = 15;
17584 	      var y = 12;
17585 
17586 	      var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
17587 	        abspos: {
17588 	          x: x,
17589 	          y: y
17590 	        }
17591 	      });
17592 
17593 	      /* user path */ drawPath(parentGfx, pathData, {
17594 	        strokeWidth: 0.5,
17595 	        fill: getFillColor(element, defaultFillColor),
17596 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17597 	      });
17598 
17599 	      var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
17600 	        abspos: {
17601 	          x: x,
17602 	          y: y
17603 	        }
17604 	      });
17605 
17606 	      /* user2 path */ drawPath(parentGfx, pathData2, {
17607 	        strokeWidth: 0.5,
17608 	        fill: getFillColor(element, defaultFillColor),
17609 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17610 	      });
17611 
17612 	      var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
17613 	        abspos: {
17614 	          x: x,
17615 	          y: y
17616 	        }
17617 	      });
17618 
17619 	      /* user3 path */ drawPath(parentGfx, pathData3, {
17620 	        strokeWidth: 0.5,
17621 	        fill: getStrokeColor$1(element, defaultStrokeColor),
17622 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17623 	      });
17624 
17625 	      return task;
17626 	    },
17627 	    'bpmn:ManualTask': function(parentGfx, element) {
17628 	      var task = renderer('bpmn:Task')(parentGfx, element);
17629 
17630 	      var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
17631 	        abspos: {
17632 	          x: 17,
17633 	          y: 15
17634 	        }
17635 	      });
17636 
17637 	      /* manual path */ drawPath(parentGfx, pathData, {
17638 	        strokeWidth: 0.5, // 0.25,
17639 	        fill: getFillColor(element, defaultFillColor),
17640 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17641 	      });
17642 
17643 	      return task;
17644 	    },
17645 	    'bpmn:SendTask': function(parentGfx, element) {
17646 	      var task = renderer('bpmn:Task')(parentGfx, element);
17647 
17648 	      var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
17649 	        xScaleFactor: 1,
17650 	        yScaleFactor: 1,
17651 	        containerWidth: 21,
17652 	        containerHeight: 14,
17653 	        position: {
17654 	          mx: 0.285,
17655 	          my: 0.357
17656 	        }
17657 	      });
17658 
17659 	      /* send path */ drawPath(parentGfx, pathData, {
17660 	        strokeWidth: 1,
17661 	        fill: getStrokeColor$1(element, defaultStrokeColor),
17662 	        stroke: getFillColor(element, defaultFillColor)
17663 	      });
17664 
17665 	      return task;
17666 	    },
17667 	    'bpmn:ReceiveTask' : function(parentGfx, element) {
17668 	      var semantic = getSemantic(element);
17669 
17670 	      var task = renderer('bpmn:Task')(parentGfx, element);
17671 	      var pathData;
17672 
17673 	      if (semantic.instantiate) {
17674 	        drawCircle(parentGfx, 28, 28, 20 * 0.22, { strokeWidth: 1 });
17675 
17676 	        pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
17677 	          abspos: {
17678 	            x: 7.77,
17679 	            y: 9.52
17680 	          }
17681 	        });
17682 	      } else {
17683 
17684 	        pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
17685 	          xScaleFactor: 0.9,
17686 	          yScaleFactor: 0.9,
17687 	          containerWidth: 21,
17688 	          containerHeight: 14,
17689 	          position: {
17690 	            mx: 0.3,
17691 	            my: 0.4
17692 	          }
17693 	        });
17694 	      }
17695 
17696 	      /* receive path */ drawPath(parentGfx, pathData, {
17697 	        strokeWidth: 1,
17698 	        fill: getFillColor(element, defaultFillColor),
17699 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17700 	      });
17701 
17702 	      return task;
17703 	    },
17704 	    'bpmn:ScriptTask': function(parentGfx, element) {
17705 	      var task = renderer('bpmn:Task')(parentGfx, element);
17706 
17707 	      var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
17708 	        abspos: {
17709 	          x: 15,
17710 	          y: 20
17711 	        }
17712 	      });
17713 
17714 	      /* script path */ drawPath(parentGfx, pathData, {
17715 	        strokeWidth: 1,
17716 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17717 	      });
17718 
17719 	      return task;
17720 	    },
17721 	    'bpmn:BusinessRuleTask': function(parentGfx, element) {
17722 	      var task = renderer('bpmn:Task')(parentGfx, element);
17723 
17724 	      var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
17725 	        abspos: {
17726 	          x: 8,
17727 	          y: 8
17728 	        }
17729 	      });
17730 
17731 	      var businessHeaderPath = drawPath(parentGfx, headerPathData);
17732 	      attr(businessHeaderPath, {
17733 	        strokeWidth: 1,
17734 	        fill: getFillColor(element, '#aaaaaa'),
17735 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17736 	      });
17737 
17738 	      var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
17739 	        abspos: {
17740 	          x: 8,
17741 	          y: 8
17742 	        }
17743 	      });
17744 
17745 	      var businessPath = drawPath(parentGfx, headerData);
17746 	      attr(businessPath, {
17747 	        strokeWidth: 1,
17748 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17749 	      });
17750 
17751 	      return task;
17752 	    },
17753 	    'bpmn:SubProcess': function(parentGfx, element, attrs) {
17754 	      attrs = assign({
17755 	        fill: getFillColor(element, defaultFillColor),
17756 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17757 	      }, attrs);
17758 
17759 	      var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
17760 
17761 	      var expanded = isExpanded(element);
17762 
17763 	      if (isEventSubProcess(element)) {
17764 	        attr(rect, {
17765 	          strokeDasharray: '1,2'
17766 	        });
17767 	      }
17768 
17769 	      renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle');
17770 
17771 	      if (expanded) {
17772 	        attachTaskMarkers(parentGfx, element);
17773 	      } else {
17774 	        attachTaskMarkers(parentGfx, element, ['SubProcessMarker']);
17775 	      }
17776 
17777 	      return rect;
17778 	    },
17779 	    'bpmn:AdHocSubProcess': function(parentGfx, element) {
17780 	      return renderer('bpmn:SubProcess')(parentGfx, element);
17781 	    },
17782 	    'bpmn:Transaction': function(parentGfx, element) {
17783 	      var outer = renderer('bpmn:SubProcess')(parentGfx, element);
17784 
17785 	      var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
17786 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17787 	      });
17788 
17789 	      /* inner path */ drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
17790 
17791 	      return outer;
17792 	    },
17793 	    'bpmn:CallActivity': function(parentGfx, element) {
17794 	      return renderer('bpmn:SubProcess')(parentGfx, element, {
17795 	        strokeWidth: 5
17796 	      });
17797 	    },
17798 	    'bpmn:Participant': function(parentGfx, element) {
17799 
17800 	      var attrs = {
17801 	        fillOpacity: DEFAULT_FILL_OPACITY,
17802 	        fill: getFillColor(element, defaultFillColor),
17803 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17804 	      };
17805 
17806 	      var lane = renderer('bpmn:Lane')(parentGfx, element, attrs);
17807 
17808 	      var expandedPool = isExpanded(element);
17809 
17810 	      if (expandedPool) {
17811 	        drawLine(parentGfx, [
17812 	          { x: 30, y: 0 },
17813 	          { x: 30, y: element.height }
17814 	        ], {
17815 	          stroke: getStrokeColor$1(element, defaultStrokeColor)
17816 	        });
17817 	        var text = getSemantic(element).name;
17818 	        renderLaneLabel(parentGfx, text, element);
17819 	      } else {
17820 
17821 	        // Collapsed pool draw text inline
17822 	        var text2 = getSemantic(element).name;
17823 	        renderLabel(parentGfx, text2, {
17824 	          box: element, align: 'center-middle',
17825 	          style: {
17826 	            fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor)
17827 	          }
17828 	        });
17829 	      }
17830 
17831 	      var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
17832 
17833 	      if (participantMultiplicity) {
17834 	        renderer('ParticipantMultiplicityMarker')(parentGfx, element);
17835 	      }
17836 
17837 	      return lane;
17838 	    },
17839 	    'bpmn:Lane': function(parentGfx, element, attrs) {
17840 	      var rect = drawRect(parentGfx, element.width, element.height, 0, assign({
17841 	        fill: getFillColor(element, defaultFillColor),
17842 	        fillOpacity: HIGH_FILL_OPACITY,
17843 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17844 	      }, attrs));
17845 
17846 	      var semantic = getSemantic(element);
17847 
17848 	      if (semantic.$type === 'bpmn:Lane') {
17849 	        var text = semantic.name;
17850 	        renderLaneLabel(parentGfx, text, element);
17851 	      }
17852 
17853 	      return rect;
17854 	    },
17855 	    'bpmn:InclusiveGateway': function(parentGfx, element) {
17856 	      var diamond = renderer('bpmn:Gateway')(parentGfx, element);
17857 
17858 	      /* circle path */
17859 	      drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
17860 	        strokeWidth: 2.5,
17861 	        fill: getFillColor(element, defaultFillColor),
17862 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17863 	      });
17864 
17865 	      return diamond;
17866 	    },
17867 	    'bpmn:ExclusiveGateway': function(parentGfx, element) {
17868 	      var diamond = renderer('bpmn:Gateway')(parentGfx, element);
17869 
17870 	      var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
17871 	        xScaleFactor: 0.4,
17872 	        yScaleFactor: 0.4,
17873 	        containerWidth: element.width,
17874 	        containerHeight: element.height,
17875 	        position: {
17876 	          mx: 0.32,
17877 	          my: 0.3
17878 	        }
17879 	      });
17880 
17881 	      if ((getDi(element).isMarkerVisible)) {
17882 	        drawPath(parentGfx, pathData, {
17883 	          strokeWidth: 1,
17884 	          fill: getStrokeColor$1(element, defaultStrokeColor),
17885 	          stroke: getStrokeColor$1(element, defaultStrokeColor)
17886 	        });
17887 	      }
17888 
17889 	      return diamond;
17890 	    },
17891 	    'bpmn:ComplexGateway': function(parentGfx, element) {
17892 	      var diamond = renderer('bpmn:Gateway')(parentGfx, element);
17893 
17894 	      var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
17895 	        xScaleFactor: 0.5,
17896 	        yScaleFactor:0.5,
17897 	        containerWidth: element.width,
17898 	        containerHeight: element.height,
17899 	        position: {
17900 	          mx: 0.46,
17901 	          my: 0.26
17902 	        }
17903 	      });
17904 
17905 	      /* complex path */ drawPath(parentGfx, pathData, {
17906 	        strokeWidth: 1,
17907 	        fill: getStrokeColor$1(element, defaultStrokeColor),
17908 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17909 	      });
17910 
17911 	      return diamond;
17912 	    },
17913 	    'bpmn:ParallelGateway': function(parentGfx, element) {
17914 	      var diamond = renderer('bpmn:Gateway')(parentGfx, element);
17915 
17916 	      var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
17917 	        xScaleFactor: 0.6,
17918 	        yScaleFactor:0.6,
17919 	        containerWidth: element.width,
17920 	        containerHeight: element.height,
17921 	        position: {
17922 	          mx: 0.46,
17923 	          my: 0.2
17924 	        }
17925 	      });
17926 
17927 	      /* parallel path */ drawPath(parentGfx, pathData, {
17928 	        strokeWidth: 1,
17929 	        fill: getStrokeColor$1(element, defaultStrokeColor),
17930 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17931 	      });
17932 
17933 	      return diamond;
17934 	    },
17935 	    'bpmn:EventBasedGateway': function(parentGfx, element) {
17936 
17937 	      var semantic = getSemantic(element);
17938 
17939 	      var diamond = renderer('bpmn:Gateway')(parentGfx, element);
17940 
17941 	      /* outer circle path */ drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
17942 	        strokeWidth: 1,
17943 	        fill: 'none',
17944 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
17945 	      });
17946 
17947 	      var type = semantic.eventGatewayType;
17948 	      var instantiate = !!semantic.instantiate;
17949 
17950 	      function drawEvent() {
17951 
17952 	        var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
17953 	          xScaleFactor: 0.18,
17954 	          yScaleFactor: 0.18,
17955 	          containerWidth: element.width,
17956 	          containerHeight: element.height,
17957 	          position: {
17958 	            mx: 0.36,
17959 	            my: 0.44
17960 	          }
17961 	        });
17962 
17963 	        var attrs = {
17964 	          strokeWidth: 2,
17965 	          fill: getFillColor(element, 'none'),
17966 	          stroke: getStrokeColor$1(element, defaultStrokeColor)
17967 	        };
17968 
17969 	        /* event path */ drawPath(parentGfx, pathData, attrs);
17970 	      }
17971 
17972 	      if (type === 'Parallel') {
17973 
17974 	        var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
17975 	          xScaleFactor: 0.4,
17976 	          yScaleFactor:0.4,
17977 	          containerWidth: element.width,
17978 	          containerHeight: element.height,
17979 	          position: {
17980 	            mx: 0.474,
17981 	            my: 0.296
17982 	          }
17983 	        });
17984 
17985 	        var parallelPath = drawPath(parentGfx, pathData);
17986 	        attr(parallelPath, {
17987 	          strokeWidth: 1,
17988 	          fill: 'none'
17989 	        });
17990 	      } else if (type === 'Exclusive') {
17991 
17992 	        if (!instantiate) {
17993 	          var innerCircle = drawCircle(parentGfx, element.width, element.height, element.height * 0.26);
17994 	          attr(innerCircle, {
17995 	            strokeWidth: 1,
17996 	            fill: 'none',
17997 	            stroke: getStrokeColor$1(element, defaultStrokeColor)
17998 	          });
17999 	        }
18000 
18001 	        drawEvent();
18002 	      }
18003 
18004 
18005 	      return diamond;
18006 	    },
18007 	    'bpmn:Gateway': function(parentGfx, element) {
18008 	      var attrs = {
18009 	        fill: getFillColor(element, defaultFillColor),
18010 	        fillOpacity: DEFAULT_FILL_OPACITY,
18011 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18012 	      };
18013 
18014 	      return drawDiamond(parentGfx, element.width, element.height, attrs);
18015 	    },
18016 	    'bpmn:SequenceFlow': function(parentGfx, element) {
18017 	      var pathData = createPathFromConnection(element);
18018 
18019 	      var fill = getFillColor(element, defaultFillColor),
18020 	          stroke = getStrokeColor$1(element, defaultStrokeColor);
18021 
18022 	      var attrs = {
18023 	        strokeLinejoin: 'round',
18024 	        markerEnd: marker('sequenceflow-end', fill, stroke),
18025 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18026 	      };
18027 
18028 	      var path = drawPath(parentGfx, pathData, attrs);
18029 
18030 	      var sequenceFlow = getSemantic(element);
18031 
18032 	      var source;
18033 
18034 	      if (element.source) {
18035 	        source = element.source.businessObject;
18036 
18037 	        // conditional flow marker
18038 	        if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
18039 	          attr(path, {
18040 	            markerStart: marker('conditional-flow-marker', fill, stroke)
18041 	          });
18042 	        }
18043 
18044 	        // default marker
18045 	        if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
18046 	            source.default === sequenceFlow) {
18047 	          attr(path, {
18048 	            markerStart: marker('conditional-default-flow-marker', fill, stroke)
18049 	          });
18050 	        }
18051 	      }
18052 
18053 	      return path;
18054 	    },
18055 	    'bpmn:Association': function(parentGfx, element, attrs) {
18056 
18057 	      var semantic = getSemantic(element);
18058 
18059 	      var fill = getFillColor(element, defaultFillColor),
18060 	          stroke = getStrokeColor$1(element, defaultStrokeColor);
18061 
18062 	      attrs = assign({
18063 	        strokeDasharray: '0.5, 5',
18064 	        strokeLinecap: 'round',
18065 	        strokeLinejoin: 'round',
18066 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18067 	      }, attrs || {});
18068 
18069 	      if (semantic.associationDirection === 'One' ||
18070 	          semantic.associationDirection === 'Both') {
18071 	        attrs.markerEnd = marker('association-end', fill, stroke);
18072 	      }
18073 
18074 	      if (semantic.associationDirection === 'Both') {
18075 	        attrs.markerStart = marker('association-start', fill, stroke);
18076 	      }
18077 
18078 	      return drawLine(parentGfx, element.waypoints, attrs);
18079 	    },
18080 	    'bpmn:DataInputAssociation': function(parentGfx, element) {
18081 	      var fill = getFillColor(element, defaultFillColor),
18082 	          stroke = getStrokeColor$1(element, defaultStrokeColor);
18083 
18084 	      return renderer('bpmn:Association')(parentGfx, element, {
18085 	        markerEnd: marker('association-end', fill, stroke)
18086 	      });
18087 	    },
18088 	    'bpmn:DataOutputAssociation': function(parentGfx, element) {
18089 	      var fill = getFillColor(element, defaultFillColor),
18090 	          stroke = getStrokeColor$1(element, defaultStrokeColor);
18091 
18092 	      return renderer('bpmn:Association')(parentGfx, element, {
18093 	        markerEnd: marker('association-end', fill, stroke)
18094 	      });
18095 	    },
18096 	    'bpmn:MessageFlow': function(parentGfx, element) {
18097 
18098 	      var semantic = getSemantic(element),
18099 	          di = getDi(element);
18100 
18101 	      var fill = getFillColor(element, defaultFillColor),
18102 	          stroke = getStrokeColor$1(element, defaultStrokeColor);
18103 
18104 	      var pathData = createPathFromConnection(element);
18105 
18106 	      var attrs = {
18107 	        markerEnd: marker('messageflow-end', fill, stroke),
18108 	        markerStart: marker('messageflow-start', fill, stroke),
18109 	        strokeDasharray: '10, 12',
18110 	        strokeLinecap: 'round',
18111 	        strokeLinejoin: 'round',
18112 	        strokeWidth: '1.5px',
18113 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18114 	      };
18115 
18116 	      var path = drawPath(parentGfx, pathData, attrs);
18117 
18118 	      if (semantic.messageRef) {
18119 	        var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
18120 
18121 	        var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
18122 	          abspos: {
18123 	            x: midPoint.x,
18124 	            y: midPoint.y
18125 	          }
18126 	        });
18127 
18128 	        var messageAttrs = { strokeWidth: 1 };
18129 
18130 	        if (di.messageVisibleKind === 'initiating') {
18131 	          messageAttrs.fill = 'white';
18132 	          messageAttrs.stroke = 'black';
18133 	        } else {
18134 	          messageAttrs.fill = '#888';
18135 	          messageAttrs.stroke = 'white';
18136 	        }
18137 
18138 	        var message = drawPath(parentGfx, markerPathData, messageAttrs);
18139 
18140 	        var labelText = semantic.messageRef.name;
18141 	        var label = renderLabel(parentGfx, labelText, {
18142 	          align: 'center-top',
18143 	          fitBox: true,
18144 	          style: {
18145 	            fill: getStrokeColor$1(element, defaultLabelColor)
18146 	          }
18147 	        });
18148 
18149 	        var messageBounds = message.getBBox(),
18150 	            labelBounds = label.getBBox();
18151 
18152 	        var translateX = midPoint.x - labelBounds.width / 2,
18153 	            translateY = midPoint.y + messageBounds.height / 2 + ELEMENT_LABEL_DISTANCE$1;
18154 
18155 	        transform(label, translateX, translateY, 0);
18156 
18157 	      }
18158 
18159 	      return path;
18160 	    },
18161 	    'bpmn:DataObject': function(parentGfx, element) {
18162 	      var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
18163 	        xScaleFactor: 1,
18164 	        yScaleFactor: 1,
18165 	        containerWidth: element.width,
18166 	        containerHeight: element.height,
18167 	        position: {
18168 	          mx: 0.474,
18169 	          my: 0.296
18170 	        }
18171 	      });
18172 
18173 	      var elementObject = drawPath(parentGfx, pathData, {
18174 	        fill: getFillColor(element, defaultFillColor),
18175 	        fillOpacity: DEFAULT_FILL_OPACITY,
18176 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18177 	      });
18178 
18179 	      var semantic = getSemantic(element);
18180 
18181 	      if (isCollection(semantic)) {
18182 	        renderDataItemCollection(parentGfx, element);
18183 	      }
18184 
18185 	      return elementObject;
18186 	    },
18187 	    'bpmn:DataObjectReference': as('bpmn:DataObject'),
18188 	    'bpmn:DataInput': function(parentGfx, element) {
18189 
18190 	      var arrowPathData = pathMap.getRawPath('DATA_ARROW');
18191 
18192 	      // page
18193 	      var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
18194 
18195 	      /* input arrow path */ drawPath(parentGfx, arrowPathData, { strokeWidth: 1 });
18196 
18197 	      return elementObject;
18198 	    },
18199 	    'bpmn:DataOutput': function(parentGfx, element) {
18200 	      var arrowPathData = pathMap.getRawPath('DATA_ARROW');
18201 
18202 	      // page
18203 	      var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
18204 
18205 	      /* output arrow path */ drawPath(parentGfx, arrowPathData, {
18206 	        strokeWidth: 1,
18207 	        fill: 'black'
18208 	      });
18209 
18210 	      return elementObject;
18211 	    },
18212 	    'bpmn:DataStoreReference': function(parentGfx, element) {
18213 	      var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
18214 	        xScaleFactor: 1,
18215 	        yScaleFactor: 1,
18216 	        containerWidth: element.width,
18217 	        containerHeight: element.height,
18218 	        position: {
18219 	          mx: 0,
18220 	          my: 0.133
18221 	        }
18222 	      });
18223 
18224 	      var elementStore = drawPath(parentGfx, DATA_STORE_PATH, {
18225 	        strokeWidth: 2,
18226 	        fill: getFillColor(element, defaultFillColor),
18227 	        fillOpacity: DEFAULT_FILL_OPACITY,
18228 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18229 	      });
18230 
18231 	      return elementStore;
18232 	    },
18233 	    'bpmn:BoundaryEvent': function(parentGfx, element) {
18234 
18235 	      var semantic = getSemantic(element),
18236 	          cancel = semantic.cancelActivity;
18237 
18238 	      var attrs = {
18239 	        strokeWidth: 1,
18240 	        fill: getFillColor(element, defaultFillColor),
18241 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18242 	      };
18243 
18244 	      if (!cancel) {
18245 	        attrs.strokeDasharray = '6';
18246 	        attrs.strokeLinecap = 'round';
18247 	      }
18248 
18249 	      // apply fillOpacity
18250 	      var outerAttrs = assign({}, attrs, {
18251 	        fillOpacity: 1
18252 	      });
18253 
18254 	      // apply no-fill
18255 	      var innerAttrs = assign({}, attrs, {
18256 	        fill: 'none'
18257 	      });
18258 
18259 	      var outer = renderer('bpmn:Event')(parentGfx, element, outerAttrs);
18260 
18261 	      /* inner path */ drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, innerAttrs);
18262 
18263 	      renderEventContent(element, parentGfx);
18264 
18265 	      return outer;
18266 	    },
18267 	    'bpmn:Group': function(parentGfx, element) {
18268 
18269 	      var group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
18270 	        stroke: getStrokeColor$1(element, defaultStrokeColor),
18271 	        strokeWidth: 1,
18272 	        strokeDasharray: '8,3,1,3',
18273 	        fill: 'none',
18274 	        pointerEvents: 'none'
18275 	      });
18276 
18277 	      return group;
18278 	    },
18279 	    'label': function(parentGfx, element) {
18280 	      return renderExternalLabel(parentGfx, element);
18281 	    },
18282 	    'bpmn:TextAnnotation': function(parentGfx, element) {
18283 	      var style = {
18284 	        'fill': 'none',
18285 	        'stroke': 'none'
18286 	      };
18287 
18288 	      var textElement = drawRect(parentGfx, element.width, element.height, 0, 0, style);
18289 
18290 	      var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
18291 	        xScaleFactor: 1,
18292 	        yScaleFactor: 1,
18293 	        containerWidth: element.width,
18294 	        containerHeight: element.height,
18295 	        position: {
18296 	          mx: 0.0,
18297 	          my: 0.0
18298 	        }
18299 	      });
18300 
18301 	      drawPath(parentGfx, textPathData, {
18302 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18303 	      });
18304 
18305 	      var text = getSemantic(element).text || '';
18306 	      renderLabel(parentGfx, text, {
18307 	        box: element,
18308 	        align: 'left-top',
18309 	        padding: 5,
18310 	        style: {
18311 	          fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor)
18312 	        }
18313 	      });
18314 
18315 	      return textElement;
18316 	    },
18317 	    'ParticipantMultiplicityMarker': function(parentGfx, element) {
18318 	      var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
18319 	        xScaleFactor: 1,
18320 	        yScaleFactor: 1,
18321 	        containerWidth: element.width,
18322 	        containerHeight: element.height,
18323 	        position: {
18324 	          mx: ((element.width / 2) / element.width),
18325 	          my: (element.height - 15) / element.height
18326 	        }
18327 	      });
18328 
18329 	      drawMarker('participant-multiplicity', parentGfx, markerPath, {
18330 	        strokeWidth: 2,
18331 	        fill: getFillColor(element, defaultFillColor),
18332 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18333 	      });
18334 	    },
18335 	    'SubProcessMarker': function(parentGfx, element) {
18336 	      var markerRect = drawRect(parentGfx, 14, 14, 0, {
18337 	        strokeWidth: 1,
18338 	        fill: getFillColor(element, defaultFillColor),
18339 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18340 	      });
18341 
18342 	      // Process marker is placed in the middle of the box
18343 	      // therefore fixed values can be used here
18344 	      translate$2(markerRect, element.width / 2 - 7.5, element.height - 20);
18345 
18346 	      var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
18347 	        xScaleFactor: 1.5,
18348 	        yScaleFactor: 1.5,
18349 	        containerWidth: element.width,
18350 	        containerHeight: element.height,
18351 	        position: {
18352 	          mx: (element.width / 2 - 7.5) / element.width,
18353 	          my: (element.height - 20) / element.height
18354 	        }
18355 	      });
18356 
18357 	      drawMarker('sub-process', parentGfx, markerPath, {
18358 	        fill: getFillColor(element, defaultFillColor),
18359 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18360 	      });
18361 	    },
18362 	    'ParallelMarker': function(parentGfx, element, position) {
18363 	      var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
18364 	        xScaleFactor: 1,
18365 	        yScaleFactor: 1,
18366 	        containerWidth: element.width,
18367 	        containerHeight: element.height,
18368 	        position: {
18369 	          mx: ((element.width / 2 + position.parallel) / element.width),
18370 	          my: (element.height - 20) / element.height
18371 	        }
18372 	      });
18373 
18374 	      drawMarker('parallel', parentGfx, markerPath, {
18375 	        fill: getFillColor(element, defaultFillColor),
18376 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18377 	      });
18378 	    },
18379 	    'SequentialMarker': function(parentGfx, element, position) {
18380 	      var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
18381 	        xScaleFactor: 1,
18382 	        yScaleFactor: 1,
18383 	        containerWidth: element.width,
18384 	        containerHeight: element.height,
18385 	        position: {
18386 	          mx: ((element.width / 2 + position.seq) / element.width),
18387 	          my: (element.height - 19) / element.height
18388 	        }
18389 	      });
18390 
18391 	      drawMarker('sequential', parentGfx, markerPath, {
18392 	        fill: getFillColor(element, defaultFillColor),
18393 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18394 	      });
18395 	    },
18396 	    'CompensationMarker': function(parentGfx, element, position) {
18397 	      var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
18398 	        xScaleFactor: 1,
18399 	        yScaleFactor: 1,
18400 	        containerWidth: element.width,
18401 	        containerHeight: element.height,
18402 	        position: {
18403 	          mx: ((element.width / 2 + position.compensation) / element.width),
18404 	          my: (element.height - 13) / element.height
18405 	        }
18406 	      });
18407 
18408 	      drawMarker('compensation', parentGfx, markerMath, {
18409 	        strokeWidth: 1,
18410 	        fill: getFillColor(element, defaultFillColor),
18411 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18412 	      });
18413 	    },
18414 	    'LoopMarker': function(parentGfx, element, position) {
18415 	      var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
18416 	        xScaleFactor: 1,
18417 	        yScaleFactor: 1,
18418 	        containerWidth: element.width,
18419 	        containerHeight: element.height,
18420 	        position: {
18421 	          mx: ((element.width / 2 + position.loop) / element.width),
18422 	          my: (element.height - 7) / element.height
18423 	        }
18424 	      });
18425 
18426 	      drawMarker('loop', parentGfx, markerPath, {
18427 	        strokeWidth: 1,
18428 	        fill: getFillColor(element, defaultFillColor),
18429 	        stroke: getStrokeColor$1(element, defaultStrokeColor),
18430 	        strokeLinecap: 'round',
18431 	        strokeMiterlimit: 0.5
18432 	      });
18433 	    },
18434 	    'AdhocMarker': function(parentGfx, element, position) {
18435 	      var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
18436 	        xScaleFactor: 1,
18437 	        yScaleFactor: 1,
18438 	        containerWidth: element.width,
18439 	        containerHeight: element.height,
18440 	        position: {
18441 	          mx: ((element.width / 2 + position.adhoc) / element.width),
18442 	          my: (element.height - 15) / element.height
18443 	        }
18444 	      });
18445 
18446 	      drawMarker('adhoc', parentGfx, markerPath, {
18447 	        strokeWidth: 1,
18448 	        fill: getStrokeColor$1(element, defaultStrokeColor),
18449 	        stroke: getStrokeColor$1(element, defaultStrokeColor)
18450 	      });
18451 	    }
18452 	  };
18453 
18454 	  function attachTaskMarkers(parentGfx, element, taskMarkers) {
18455 	    var obj = getSemantic(element);
18456 
18457 	    var subprocess = taskMarkers && taskMarkers.indexOf('SubProcessMarker') !== -1;
18458 	    var position;
18459 
18460 	    if (subprocess) {
18461 	      position = {
18462 	        seq: -21,
18463 	        parallel: -22,
18464 	        compensation: -42,
18465 	        loop: -18,
18466 	        adhoc: 10
18467 	      };
18468 	    } else {
18469 	      position = {
18470 	        seq: -3,
18471 	        parallel: -6,
18472 	        compensation: -27,
18473 	        loop: 0,
18474 	        adhoc: 10
18475 	      };
18476 	    }
18477 
18478 	    forEach(taskMarkers, function(marker) {
18479 	      renderer(marker)(parentGfx, element, position);
18480 	    });
18481 
18482 	    if (obj.isForCompensation) {
18483 	      renderer('CompensationMarker')(parentGfx, element, position);
18484 	    }
18485 
18486 	    if (obj.$type === 'bpmn:AdHocSubProcess') {
18487 	      renderer('AdhocMarker')(parentGfx, element, position);
18488 	    }
18489 
18490 	    var loopCharacteristics = obj.loopCharacteristics,
18491 	        isSequential = loopCharacteristics && loopCharacteristics.isSequential;
18492 
18493 	    if (loopCharacteristics) {
18494 
18495 	      if (isSequential === undefined) {
18496 	        renderer('LoopMarker')(parentGfx, element, position);
18497 	      }
18498 
18499 	      if (isSequential === false) {
18500 	        renderer('ParallelMarker')(parentGfx, element, position);
18501 	      }
18502 
18503 	      if (isSequential === true) {
18504 	        renderer('SequentialMarker')(parentGfx, element, position);
18505 	      }
18506 	    }
18507 	  }
18508 
18509 	  function renderDataItemCollection(parentGfx, element) {
18510 
18511 	    var yPosition = (element.height - 18) / element.height;
18512 
18513 	    var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
18514 	      xScaleFactor: 1,
18515 	      yScaleFactor: 1,
18516 	      containerWidth: element.width,
18517 	      containerHeight: element.height,
18518 	      position: {
18519 	        mx: 0.33,
18520 	        my: yPosition
18521 	      }
18522 	    });
18523 
18524 	    /* collection path */ drawPath(parentGfx, pathData, {
18525 	      strokeWidth: 2
18526 	    });
18527 	  }
18528 
18529 
18530 	  // extension API, use at your own risk
18531 	  this._drawPath = drawPath;
18532 
18533 	}
18534 
18535 
18536 	inherits$1(BpmnRenderer, BaseRenderer);
18537 
18538 	BpmnRenderer.$inject = [
18539 	  'config.bpmnRenderer',
18540 	  'eventBus',
18541 	  'styles',
18542 	  'pathMap',
18543 	  'canvas',
18544 	  'textRenderer'
18545 	];
18546 
18547 
18548 	BpmnRenderer.prototype.canRender = function(element) {
18549 	  return is$1(element, 'bpmn:BaseElement');
18550 	};
18551 
18552 	BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
18553 	  var type = element.type;
18554 	  var h = this.handlers[type];
18555 
18556 	  /* jshint -W040 */
18557 	  return h(parentGfx, element);
18558 	};
18559 
18560 	BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
18561 	  var type = element.type;
18562 	  var h = this.handlers[type];
18563 
18564 	  /* jshint -W040 */
18565 	  return h(parentGfx, element);
18566 	};
18567 
18568 	BpmnRenderer.prototype.getShapePath = function(element) {
18569 
18570 	  if (is$1(element, 'bpmn:Event')) {
18571 	    return getCirclePath(element);
18572 	  }
18573 
18574 	  if (is$1(element, 'bpmn:Activity')) {
18575 	    return getRoundRectPath(element, TASK_BORDER_RADIUS);
18576 	  }
18577 
18578 	  if (is$1(element, 'bpmn:Gateway')) {
18579 	    return getDiamondPath(element);
18580 	  }
18581 
18582 	  return getRectPath(element);
18583 	};
18584 
18585 	var DEFAULT_BOX_PADDING = 0;
18586 
18587 	var DEFAULT_LABEL_SIZE$1 = {
18588 	  width: 150,
18589 	  height: 50
18590 	};
18591 
18592 
18593 	function parseAlign(align) {
18594 
18595 	  var parts = align.split('-');
18596 
18597 	  return {
18598 	    horizontal: parts[0] || 'center',
18599 	    vertical: parts[1] || 'top'
18600 	  };
18601 	}
18602 
18603 	function parsePadding(padding) {
18604 
18605 	  if (isObject(padding)) {
18606 	    return assign({ top: 0, left: 0, right: 0, bottom: 0 }, padding);
18607 	  } else {
18608 	    return {
18609 	      top: padding,
18610 	      left: padding,
18611 	      right: padding,
18612 	      bottom: padding
18613 	    };
18614 	  }
18615 	}
18616 
18617 	function getTextBBox(text, fakeText) {
18618 
18619 	  fakeText.textContent = text;
18620 
18621 	  var textBBox;
18622 
18623 	  try {
18624 	    var bbox,
18625 	        emptyLine = text === '';
18626 
18627 	    // add dummy text, when line is empty to
18628 	    // determine correct height
18629 	    fakeText.textContent = emptyLine ? 'dummy' : text;
18630 
18631 	    textBBox = fakeText.getBBox();
18632 
18633 	    // take text rendering related horizontal
18634 	    // padding into account
18635 	    bbox = {
18636 	      width: textBBox.width + textBBox.x * 2,
18637 	      height: textBBox.height
18638 	    };
18639 
18640 	    if (emptyLine) {
18641 
18642 	      // correct width
18643 	      bbox.width = 0;
18644 	    }
18645 
18646 	    return bbox;
18647 	  } catch (e) {
18648 	    return { width: 0, height: 0 };
18649 	  }
18650 	}
18651 
18652 
18653 	/**
18654 	 * Layout the next line and return the layouted element.
18655 	 *
18656 	 * Alters the lines passed.
18657 	 *
18658 	 * @param  {Array<string>} lines
18659 	 * @return {Object} the line descriptor, an object { width, height, text }
18660 	 */
18661 	function layoutNext(lines, maxWidth, fakeText) {
18662 
18663 	  var originalLine = lines.shift(),
18664 	      fitLine = originalLine;
18665 
18666 	  var textBBox;
18667 
18668 	  for (;;) {
18669 	    textBBox = getTextBBox(fitLine, fakeText);
18670 
18671 	    textBBox.width = fitLine ? textBBox.width : 0;
18672 
18673 	    // try to fit
18674 	    if (fitLine === ' ' || fitLine === '' || textBBox.width < Math.round(maxWidth) || fitLine.length < 2) {
18675 	      return fit(lines, fitLine, originalLine, textBBox);
18676 	    }
18677 
18678 	    fitLine = shortenLine(fitLine, textBBox.width, maxWidth);
18679 	  }
18680 	}
18681 
18682 	function fit(lines, fitLine, originalLine, textBBox) {
18683 	  if (fitLine.length < originalLine.length) {
18684 	    var remainder = originalLine.slice(fitLine.length).trim();
18685 
18686 	    lines.unshift(remainder);
18687 	  }
18688 
18689 	  return {
18690 	    width: textBBox.width,
18691 	    height: textBBox.height,
18692 	    text: fitLine
18693 	  };
18694 	}
18695 
18696 	var SOFT_BREAK = '\u00AD';
18697 
18698 
18699 	/**
18700 	 * Shortens a line based on spacing and hyphens.
18701 	 * Returns the shortened result on success.
18702 	 *
18703 	 * @param  {string} line
18704 	 * @param  {number} maxLength the maximum characters of the string
18705 	 * @return {string} the shortened string
18706 	 */
18707 	function semanticShorten(line, maxLength) {
18708 
18709 	  var parts = line.split(/(\s|-|\u00AD)/g),
18710 	      part,
18711 	      shortenedParts = [],
18712 	      length = 0;
18713 
18714 	  // try to shorten via break chars
18715 	  if (parts.length > 1) {
18716 
18717 	    while ((part = parts.shift())) {
18718 	      if (part.length + length < maxLength) {
18719 	        shortenedParts.push(part);
18720 	        length += part.length;
18721 	      } else {
18722 
18723 	        // remove previous part, too if hyphen does not fit anymore
18724 	        if (part === '-' || part === SOFT_BREAK) {
18725 	          shortenedParts.pop();
18726 	        }
18727 
18728 	        break;
18729 	      }
18730 	    }
18731 	  }
18732 
18733 	  var last = shortenedParts[shortenedParts.length - 1];
18734 
18735 	  // translate trailing soft break to actual hyphen
18736 	  if (last && last === SOFT_BREAK) {
18737 	    shortenedParts[shortenedParts.length - 1] = '-';
18738 	  }
18739 
18740 	  return shortenedParts.join('');
18741 	}
18742 
18743 
18744 	function shortenLine(line, width, maxWidth) {
18745 	  var length = Math.max(line.length * (maxWidth / width), 1);
18746 
18747 	  // try to shorten semantically (i.e. based on spaces and hyphens)
18748 	  var shortenedLine = semanticShorten(line, length);
18749 
18750 	  if (!shortenedLine) {
18751 
18752 	    // force shorten by cutting the long word
18753 	    shortenedLine = line.slice(0, Math.max(Math.round(length - 1), 1));
18754 	  }
18755 
18756 	  return shortenedLine;
18757 	}
18758 
18759 
18760 	function getHelperSvg() {
18761 	  var helperSvg = document.getElementById('helper-svg');
18762 
18763 	  if (!helperSvg) {
18764 	    helperSvg = create$1('svg');
18765 
18766 	    attr(helperSvg, {
18767 	      id: 'helper-svg',
18768 	      width: 0,
18769 	      height: 0,
18770 	      style: 'visibility: hidden; position: fixed'
18771 	    });
18772 
18773 	    document.body.appendChild(helperSvg);
18774 	  }
18775 
18776 	  return helperSvg;
18777 	}
18778 
18779 
18780 	/**
18781 	 * Creates a new label utility
18782 	 *
18783 	 * @param {Object} config
18784 	 * @param {Dimensions} config.size
18785 	 * @param {number} config.padding
18786 	 * @param {Object} config.style
18787 	 * @param {string} config.align
18788 	 */
18789 	function Text(config) {
18790 
18791 	  this._config = assign({}, {
18792 	    size: DEFAULT_LABEL_SIZE$1,
18793 	    padding: DEFAULT_BOX_PADDING,
18794 	    style: {},
18795 	    align: 'center-top'
18796 	  }, config || {});
18797 	}
18798 
18799 	/**
18800 	 * Returns the layouted text as an SVG element.
18801 	 *
18802 	 * @param {string} text
18803 	 * @param {Object} options
18804 	 *
18805 	 * @return {SVGElement}
18806 	 */
18807 	Text.prototype.createText = function(text, options) {
18808 	  return this.layoutText(text, options).element;
18809 	};
18810 
18811 	/**
18812 	 * Returns a labels layouted dimensions.
18813 	 *
18814 	 * @param {string} text to layout
18815 	 * @param {Object} options
18816 	 *
18817 	 * @return {Dimensions}
18818 	 */
18819 	Text.prototype.getDimensions = function(text, options) {
18820 	  return this.layoutText(text, options).dimensions;
18821 	};
18822 
18823 	/**
18824 	 * Creates and returns a label and its bounding box.
18825 	 *
18826 	 * @method Text#createText
18827 	 *
18828 	 * @param {string} text the text to render on the label
18829 	 * @param {Object} options
18830 	 * @param {string} options.align how to align in the bounding box.
18831 	 *                               Any of { 'center-middle', 'center-top' },
18832 	 *                               defaults to 'center-top'.
18833 	 * @param {string} options.style style to be applied to the text
18834 	 * @param {boolean} options.fitBox indicates if box will be recalculated to
18835 	 *                                 fit text
18836 	 *
18837 	 * @return {Object} { element, dimensions }
18838 	 */
18839 	Text.prototype.layoutText = function(text, options) {
18840 	  var box = assign({}, this._config.size, options.box),
18841 	      style = assign({}, this._config.style, options.style),
18842 	      align = parseAlign(options.align || this._config.align),
18843 	      padding = parsePadding(options.padding !== undefined ? options.padding : this._config.padding),
18844 	      fitBox = options.fitBox || false;
18845 
18846 	  var lineHeight = getLineHeight(style);
18847 
18848 	  // we split text by lines and normalize
18849 	  // {soft break} + {line break} => { line break }
18850 	  var lines = text.split(/\u00AD?\r?\n/),
18851 	      layouted = [];
18852 
18853 	  var maxWidth = box.width - padding.left - padding.right;
18854 
18855 	  // ensure correct rendering by attaching helper text node to invisible SVG
18856 	  var helperText = create$1('text');
18857 	  attr(helperText, { x: 0, y: 0 });
18858 	  attr(helperText, style);
18859 
18860 	  var helperSvg = getHelperSvg();
18861 
18862 	  append(helperSvg, helperText);
18863 
18864 	  while (lines.length) {
18865 	    layouted.push(layoutNext(lines, maxWidth, helperText));
18866 	  }
18867 
18868 	  if (align.vertical === 'middle') {
18869 	    padding.top = padding.bottom = 0;
18870 	  }
18871 
18872 	  var totalHeight = reduce(layouted, function(sum, line, idx) {
18873 	    return sum + (lineHeight || line.height);
18874 	  }, 0) + padding.top + padding.bottom;
18875 
18876 	  var maxLineWidth = reduce(layouted, function(sum, line, idx) {
18877 	    return line.width > sum ? line.width : sum;
18878 	  }, 0);
18879 
18880 	  // the y position of the next line
18881 	  var y = padding.top;
18882 
18883 	  if (align.vertical === 'middle') {
18884 	    y += (box.height - totalHeight) / 2;
18885 	  }
18886 
18887 	  // magic number initial offset
18888 	  y -= (lineHeight || layouted[0].height) / 4;
18889 
18890 
18891 	  var textElement = create$1('text');
18892 
18893 	  attr(textElement, style);
18894 
18895 	  // layout each line taking into account that parent
18896 	  // shape might resize to fit text size
18897 	  forEach(layouted, function(line) {
18898 
18899 	    var x;
18900 
18901 	    y += (lineHeight || line.height);
18902 
18903 	    switch (align.horizontal) {
18904 	    case 'left':
18905 	      x = padding.left;
18906 	      break;
18907 
18908 	    case 'right':
18909 	      x = ((fitBox ? maxLineWidth : maxWidth)
18910 	        - padding.right - line.width);
18911 	      break;
18912 
18913 	    default:
18914 
18915 	      // aka center
18916 	      x = Math.max((((fitBox ? maxLineWidth : maxWidth)
18917 	        - line.width) / 2 + padding.left), 0);
18918 	    }
18919 
18920 	    var tspan = create$1('tspan');
18921 	    attr(tspan, { x: x, y: y });
18922 
18923 	    tspan.textContent = line.text;
18924 
18925 	    append(textElement, tspan);
18926 	  });
18927 
18928 	  remove$1(helperText);
18929 
18930 	  var dimensions = {
18931 	    width: maxLineWidth,
18932 	    height: totalHeight
18933 	  };
18934 
18935 	  return {
18936 	    dimensions: dimensions,
18937 	    element: textElement
18938 	  };
18939 	};
18940 
18941 
18942 	function getLineHeight(style) {
18943 	  if ('fontSize' in style && 'lineHeight' in style) {
18944 	    return style.lineHeight * parseInt(style.fontSize, 10);
18945 	  }
18946 	}
18947 
18948 	var DEFAULT_FONT_SIZE = 12;
18949 	var LINE_HEIGHT_RATIO = 1.2;
18950 
18951 	var MIN_TEXT_ANNOTATION_HEIGHT = 30;
18952 
18953 
18954 	function TextRenderer(config) {
18955 
18956 	  var defaultStyle = assign({
18957 	    fontFamily: 'Arial, sans-serif',
18958 	    fontSize: DEFAULT_FONT_SIZE,
18959 	    fontWeight: 'normal',
18960 	    lineHeight: LINE_HEIGHT_RATIO
18961 	  }, config && config.defaultStyle || {});
18962 
18963 	  var fontSize = parseInt(defaultStyle.fontSize, 10) - 1;
18964 
18965 	  var externalStyle = assign({}, defaultStyle, {
18966 	    fontSize: fontSize
18967 	  }, config && config.externalStyle || {});
18968 
18969 	  var textUtil = new Text({
18970 	    style: defaultStyle
18971 	  });
18972 
18973 	  /**
18974 	   * Get the new bounds of an externally rendered,
18975 	   * layouted label.
18976 	   *
18977 	   * @param  {Bounds} bounds
18978 	   * @param  {string} text
18979 	   *
18980 	   * @return {Bounds}
18981 	   */
18982 	  this.getExternalLabelBounds = function(bounds, text) {
18983 
18984 	    var layoutedDimensions = textUtil.getDimensions(text, {
18985 	      box: {
18986 	        width: 90,
18987 	        height: 30,
18988 	        x: bounds.width / 2 + bounds.x,
18989 	        y: bounds.height / 2 + bounds.y
18990 	      },
18991 	      style: externalStyle
18992 	    });
18993 
18994 	    // resize label shape to fit label text
18995 	    return {
18996 	      x: Math.round(bounds.x + bounds.width / 2 - layoutedDimensions.width / 2),
18997 	      y: Math.round(bounds.y),
18998 	      width: Math.ceil(layoutedDimensions.width),
18999 	      height: Math.ceil(layoutedDimensions.height)
19000 	    };
19001 
19002 	  };
19003 
19004 	  /**
19005 	   * Get the new bounds of text annotation.
19006 	   *
19007 	   * @param  {Bounds} bounds
19008 	   * @param  {string} text
19009 	   *
19010 	   * @return {Bounds}
19011 	   */
19012 	  this.getTextAnnotationBounds = function(bounds, text) {
19013 
19014 	    var layoutedDimensions = textUtil.getDimensions(text, {
19015 	      box: bounds,
19016 	      style: defaultStyle,
19017 	      align: 'left-top',
19018 	      padding: 5
19019 	    });
19020 
19021 	    return {
19022 	      x: bounds.x,
19023 	      y: bounds.y,
19024 	      width: bounds.width,
19025 	      height: Math.max(MIN_TEXT_ANNOTATION_HEIGHT, Math.round(layoutedDimensions.height))
19026 	    };
19027 	  };
19028 
19029 	  /**
19030 	   * Create a layouted text element.
19031 	   *
19032 	   * @param {string} text
19033 	   * @param {Object} [options]
19034 	   *
19035 	   * @return {SVGElement} rendered text
19036 	   */
19037 	  this.createText = function(text, options) {
19038 	    return textUtil.createText(text, options || {});
19039 	  };
19040 
19041 	  /**
19042 	   * Get default text style.
19043 	   */
19044 	  this.getDefaultStyle = function() {
19045 	    return defaultStyle;
19046 	  };
19047 
19048 	  /**
19049 	   * Get the external text style.
19050 	   */
19051 	  this.getExternalStyle = function() {
19052 	    return externalStyle;
19053 	  };
19054 
19055 	}
19056 
19057 	TextRenderer.$inject = [
19058 	  'config.textRenderer'
19059 	];
19060 
19061 	/**
19062 	 * Map containing SVG paths needed by BpmnRenderer.
19063 	 */
19064 
19065 	function PathMap() {
19066 
19067 	  /**
19068 	   * Contains a map of path elements
19069 	   *
19070 	   * <h1>Path definition</h1>
19071 	   * A parameterized path is defined like this:
19072 	   * <pre>
19073 	   * 'GATEWAY_PARALLEL': {
19074 	   *   d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
19075 	          '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
19076 	   *   height: 17.5,
19077 	   *   width:  17.5,
19078 	   *   heightElements: [2.5, 7.5],
19079 	   *   widthElements: [2.5, 7.5]
19080 	   * }
19081 	   * </pre>
19082 	   * <p>It's important to specify a correct <b>height and width</b> for the path as the scaling
19083 	   * is based on the ratio between the specified height and width in this object and the
19084 	   * height and width that is set as scale target (Note x,y coordinates will be scaled with
19085 	   * individual ratios).</p>
19086 	   * <p>The '<b>heightElements</b>' and '<b>widthElements</b>' array must contain the values that will be scaled.
19087 	   * The scaling is based on the computed ratios.
19088 	   * Coordinates on the y axis should be in the <b>heightElement</b>'s array, they will be scaled using
19089 	   * the computed ratio coefficient.
19090 	   * In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets.
19091 	   *   <ul>
19092 	   *    <li>The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....</li>
19093 	   *    <li>The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....</li>
19094 	   *   </ul>
19095 	   *   The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index.
19096 	   * </p>
19097 	   */
19098 	  this.pathMap = {
19099 	    'EVENT_MESSAGE': {
19100 	      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}',
19101 	      height: 36,
19102 	      width:  36,
19103 	      heightElements: [6, 14],
19104 	      widthElements: [10.5, 21]
19105 	    },
19106 	    'EVENT_SIGNAL': {
19107 	      d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x1},0 Z',
19108 	      height: 36,
19109 	      width: 36,
19110 	      heightElements: [18],
19111 	      widthElements: [10, 20]
19112 	    },
19113 	    'EVENT_ESCALATION': {
19114 	      d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x0},-{e.y1} l -{e.x0},{e.y1} Z',
19115 	      height: 36,
19116 	      width: 36,
19117 	      heightElements: [20, 7],
19118 	      widthElements: [8]
19119 	    },
19120 	    'EVENT_CONDITIONAL': {
19121 	      d: 'M {e.x0},{e.y0} l {e.x1},0 l 0,{e.y2} l -{e.x1},0 Z ' +
19122 	         'M {e.x2},{e.y3} l {e.x0},0 ' +
19123 	         'M {e.x2},{e.y4} l {e.x0},0 ' +
19124 	         'M {e.x2},{e.y5} l {e.x0},0 ' +
19125 	         'M {e.x2},{e.y6} l {e.x0},0 ' +
19126 	         'M {e.x2},{e.y7} l {e.x0},0 ' +
19127 	         'M {e.x2},{e.y8} l {e.x0},0 ',
19128 	      height: 36,
19129 	      width:  36,
19130 	      heightElements: [8.5, 14.5, 18, 11.5, 14.5, 17.5, 20.5, 23.5, 26.5],
19131 	      widthElements:  [10.5, 14.5, 12.5]
19132 	    },
19133 	    'EVENT_LINK': {
19134 	      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',
19135 	      height: 36,
19136 	      width: 36,
19137 	      heightElements: [4.4375, 6.75, 7.8125],
19138 	      widthElements: [9.84375, 13.5]
19139 	    },
19140 	    'EVENT_ERROR': {
19141 	      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',
19142 	      height: 36,
19143 	      width: 36,
19144 	      heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714],
19145 	      widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636]
19146 	    },
19147 	    'EVENT_CANCEL_45': {
19148 	      d: 'm {mx},{my} -{e.x1},0 0,{e.x0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
19149 	        '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
19150 	      height: 36,
19151 	      width: 36,
19152 	      heightElements: [4.75, 8.5],
19153 	      widthElements: [4.75, 8.5]
19154 	    },
19155 	    'EVENT_COMPENSATION': {
19156 	      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',
19157 	      height: 36,
19158 	      width: 36,
19159 	      heightElements: [6.5, 13, 0.4, 6.1],
19160 	      widthElements: [9, 9.3, 8.7]
19161 	    },
19162 	    'EVENT_TIMER_WH': {
19163 	      d: 'M {mx},{my} l {e.x0},-{e.y0} m -{e.x0},{e.y0} l {e.x1},{e.y1} ',
19164 	      height: 36,
19165 	      width:  36,
19166 	      heightElements: [10, 2],
19167 	      widthElements: [3, 7]
19168 	    },
19169 	    'EVENT_TIMER_LINE': {
19170 	      d:  'M {mx},{my} ' +
19171 	          'm {e.x0},{e.y0} l -{e.x1},{e.y1} ',
19172 	      height: 36,
19173 	      width:  36,
19174 	      heightElements: [10, 3],
19175 	      widthElements: [0, 0]
19176 	    },
19177 	    'EVENT_MULTIPLE': {
19178 	      d:'m {mx},{my} {e.x1},-{e.y0} {e.x1},{e.y0} -{e.x0},{e.y1} -{e.x2},0 z',
19179 	      height: 36,
19180 	      width:  36,
19181 	      heightElements: [6.28099, 12.56199],
19182 	      widthElements: [3.1405, 9.42149, 12.56198]
19183 	    },
19184 	    'EVENT_PARALLEL_MULTIPLE': {
19185 	      d:'m {mx},{my} {e.x0},0 0,{e.y1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
19186 	        '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
19187 	      height: 36,
19188 	      width:  36,
19189 	      heightElements: [2.56228, 7.68683],
19190 	      widthElements: [2.56228, 7.68683]
19191 	    },
19192 	    'GATEWAY_EXCLUSIVE': {
19193 	      d:'m {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' +
19194 	                    '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' +
19195 	                    '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z',
19196 	      height: 17.5,
19197 	      width:  17.5,
19198 	      heightElements: [8.5, 6.5312, -6.5312, -8.5],
19199 	      widthElements:  [6.5, -6.5, 3, -3, 5, -5]
19200 	    },
19201 	    'GATEWAY_PARALLEL': {
19202 	      d:'m {mx},{my} 0,{e.y1} -{e.x1},0 0,{e.y0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
19203 	        '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
19204 	      height: 30,
19205 	      width:  30,
19206 	      heightElements: [5, 12.5],
19207 	      widthElements: [5, 12.5]
19208 	    },
19209 	    'GATEWAY_EVENT_BASED': {
19210 	      d:'m {mx},{my} {e.x0},{e.y0} {e.x0},{e.y1} {e.x1},{e.y2} {e.x2},0 z',
19211 	      height: 11,
19212 	      width:  11,
19213 	      heightElements: [-6, 6, 12, -12],
19214 	      widthElements: [9, -3, -12]
19215 	    },
19216 	    'GATEWAY_COMPLEX': {
19217 	      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} ' +
19218 	        '{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} ' +
19219 	        '{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} ' +
19220 	        '-{e.x0},{e.y1} 0,-{e.y0} -{e.x3},0 z',
19221 	      height: 17.125,
19222 	      width:  17.125,
19223 	      heightElements: [4.875, 3.4375, 2.125, 3],
19224 	      widthElements: [3.4375, 2.125, 4.875, 3]
19225 	    },
19226 	    'DATA_OBJECT_PATH': {
19227 	      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',
19228 	      height: 61,
19229 	      width:  51,
19230 	      heightElements: [10, 50, 60],
19231 	      widthElements: [10, 40, 50, 60]
19232 	    },
19233 	    'DATA_OBJECT_COLLECTION_PATH': {
19234 	      d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
19235 	      height: 10,
19236 	      width: 10,
19237 	      heightElements: [],
19238 	      widthElements: []
19239 	    },
19240 	    'DATA_ARROW': {
19241 	      d:'m 5,9 9,0 0,-3 5,5 -5,5 0,-3 -9,0 z',
19242 	      height: 61,
19243 	      width:  51,
19244 	      heightElements: [],
19245 	      widthElements: []
19246 	    },
19247 	    'DATA_STORE': {
19248 	      d:'m  {mx},{my} ' +
19249 	        'l  0,{e.y2} ' +
19250 	        'c  {e.x0},{e.y1} {e.x1},{e.y1}  {e.x2},0 ' +
19251 	        'l  0,-{e.y2} ' +
19252 	        'c -{e.x0},-{e.y1} -{e.x1},-{e.y1} -{e.x2},0' +
19253 	        'c  {e.x0},{e.y1} {e.x1},{e.y1}  {e.x2},0 ' +
19254 	        'm  -{e.x2},{e.y0}' +
19255 	        'c  {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0' +
19256 	        'm  -{e.x2},{e.y0}' +
19257 	        'c  {e.x0},{e.y1} {e.x1},{e.y1}  {e.x2},0',
19258 	      height: 61,
19259 	      width:  61,
19260 	      heightElements: [7, 10, 45],
19261 	      widthElements:  [2, 58, 60]
19262 	    },
19263 	    'TEXT_ANNOTATION': {
19264 	      d: 'm {mx}, {my} m 10,0 l -10,0 l 0,{e.y0} l 10,0',
19265 	      height: 30,
19266 	      width: 10,
19267 	      heightElements: [30],
19268 	      widthElements: [10]
19269 	    },
19270 	    'MARKER_SUB_PROCESS': {
19271 	      d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0',
19272 	      height: 10,
19273 	      width: 10,
19274 	      heightElements: [],
19275 	      widthElements: []
19276 	    },
19277 	    'MARKER_PARALLEL': {
19278 	      d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
19279 	      height: 10,
19280 	      width: 10,
19281 	      heightElements: [],
19282 	      widthElements: []
19283 	    },
19284 	    'MARKER_SEQUENTIAL': {
19285 	      d: 'm{mx},{my} m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0',
19286 	      height: 10,
19287 	      width: 10,
19288 	      heightElements: [],
19289 	      widthElements: []
19290 	    },
19291 	    'MARKER_COMPENSATION': {
19292 	      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',
19293 	      height: 10,
19294 	      width: 21,
19295 	      heightElements: [],
19296 	      widthElements: []
19297 	    },
19298 	    'MARKER_LOOP': {
19299 	      d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' +
19300 	        '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' +
19301 	        '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' +
19302 	        'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902',
19303 	      height: 13.9,
19304 	      width: 13.7,
19305 	      heightElements: [],
19306 	      widthElements: []
19307 	    },
19308 	    'MARKER_ADHOC': {
19309 	      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 ' +
19310 	        '3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' +
19311 	        '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 ' +
19312 	        '-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' +
19313 	        '-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z',
19314 	      height: 4,
19315 	      width: 15,
19316 	      heightElements: [],
19317 	      widthElements: []
19318 	    },
19319 	    'TASK_TYPE_SEND': {
19320 	      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}',
19321 	      height: 14,
19322 	      width:  21,
19323 	      heightElements: [6, 14],
19324 	      widthElements: [10.5, 21]
19325 	    },
19326 	    'TASK_TYPE_SCRIPT': {
19327 	      d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' +
19328 	        'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' +
19329 	        'm -7,-12 l 5,0 ' +
19330 	        'm -4.5,3 l 4.5,0 ' +
19331 	        'm -3,3 l 5,0' +
19332 	        'm -4,3 l 5,0',
19333 	      height: 15,
19334 	      width:  12.6,
19335 	      heightElements: [6, 14],
19336 	      widthElements: [10.5, 21]
19337 	    },
19338 	    'TASK_TYPE_USER_1': {
19339 	      d: 'm {mx},{my} c 0.909,-0.845 1.594,-2.049 1.594,-3.385 0,-2.554 -1.805,-4.62199999 ' +
19340 	        '-4.357,-4.62199999 -2.55199998,0 -4.28799998,2.06799999 -4.28799998,4.62199999 0,1.348 ' +
19341 	        '0.974,2.562 1.89599998,3.405 -0.52899998,0.187 -5.669,2.097 -5.794,4.7560005 v 6.718 ' +
19342 	        'h 17 v -6.718 c 0,-2.2980005 -5.5279996,-4.5950005 -6.0509996,-4.7760005 z' +
19343 	        'm -8,6 l 0,5.5 m 11,0 l 0,-5'
19344 	    },
19345 	    'TASK_TYPE_USER_2': {
19346 	      d: 'm {mx},{my} m 2.162,1.009 c 0,2.4470005 -2.158,4.4310005 -4.821,4.4310005 ' +
19347 	        '-2.66499998,0 -4.822,-1.981 -4.822,-4.4310005 '
19348 	    },
19349 	    'TASK_TYPE_USER_3': {
19350 	      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 ' +
19351 	        '4.124,0.965 -0.098,-0.57 -0.117,-3.79099999 -4.191,-4.13599999 -3.57499998,0.001 ' +
19352 	        '-4.20799998,3.36699999 -4.20699998,4.34799999 z'
19353 	    },
19354 	    'TASK_TYPE_MANUAL': {
19355 	      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 ' +
19356 	        '-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 ' +
19357 	        '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 ' +
19358 	        '-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 ' +
19359 	        '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 ' +
19360 	        '-10.86,-0.003 -11.0829995,-0.003 -0.022,-0.047 -0.045,-0.094 -0.069,-0.139 0.3939995,-0.319 ' +
19361 	        '2.0409995,-1.626 2.4149995,-2.017 0.469,-0.4870005 0.519,-1.1650005 0.162,-1.6040005 -0.414,-0.511 ' +
19362 	        '-0.973,-0.5 -1.48,-0.236 -1.4609995,0.764 -6.5999995,3.6430005 -7.7329995,4.2710005 -0.9,0.499 ' +
19363 	        '-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 ' +
19364 	        '-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 ' +
19365 	        '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 ' +
19366 	        '-5.824,-0.004 -6.04,-0.004 10e-4,-0.084 0.003,-0.586 10e-4,-0.67 z'
19367 	    },
19368 	    'TASK_TYPE_INSTANTIATING_SEND': {
19369 	      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'
19370 	    },
19371 	    'TASK_TYPE_SERVICE': {
19372 	      d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' +
19373 	        '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' +
19374 	        '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' +
19375 	        'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' +
19376 	        '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' +
19377 	        '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' +
19378 	        '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 ' +
19379 	        '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' +
19380 	        'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' +
19381 	        'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' +
19382 	        '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' +
19383 	        'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' +
19384 	        'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
19385 	        '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
19386 	        '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
19387 	    },
19388 	    'TASK_TYPE_SERVICE_FILL': {
19389 	      d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
19390 	        '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
19391 	        '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
19392 	    },
19393 	    'TASK_TYPE_BUSINESS_RULE_HEADER': {
19394 	      d: 'm {mx},{my} 0,4 20,0 0,-4 z'
19395 	    },
19396 	    'TASK_TYPE_BUSINESS_RULE_MAIN': {
19397 	      d: 'm {mx},{my} 0,12 20,0 0,-12 z' +
19398 	        'm 0,8 l 20,0 ' +
19399 	        'm -13,-4 l 0,8'
19400 	    },
19401 	    'MESSAGE_FLOW_MARKER': {
19402 	      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'
19403 	    }
19404 	  };
19405 
19406 	  this.getRawPath = function getRawPath(pathId) {
19407 	    return this.pathMap[pathId].d;
19408 	  };
19409 
19410 	  /**
19411 	   * Scales the path to the given height and width.
19412 	   * <h1>Use case</h1>
19413 	   * <p>Use case is to scale the content of elements (event, gateways) based
19414 	   * on the element bounding box's size.
19415 	   * </p>
19416 	   * <h1>Why not transform</h1>
19417 	   * <p>Scaling a path with transform() will also scale the stroke and IE does not support
19418 	   * the option 'non-scaling-stroke' to prevent this.
19419 	   * Also there are use cases where only some parts of a path should be
19420 	   * scaled.</p>
19421 	   *
19422 	   * @param {string} pathId The ID of the path.
19423 	   * @param {Object} param <p>
19424 	   *   Example param object scales the path to 60% size of the container (data.width, data.height).
19425 	   *   <pre>
19426 	   *   {
19427 	   *     xScaleFactor: 0.6,
19428 	   *     yScaleFactor:0.6,
19429 	   *     containerWidth: data.width,
19430 	   *     containerHeight: data.height,
19431 	   *     position: {
19432 	   *       mx: 0.46,
19433 	   *       my: 0.2,
19434 	   *     }
19435 	   *   }
19436 	   *   </pre>
19437 	   *   <ul>
19438 	   *    <li>targetpathwidth = xScaleFactor * containerWidth</li>
19439 	   *    <li>targetpathheight = yScaleFactor * containerHeight</li>
19440 	   *    <li>Position is used to set the starting coordinate of the path. M is computed:
19441 	    *    <ul>
19442 	    *      <li>position.x * containerWidth</li>
19443 	    *      <li>position.y * containerHeight</li>
19444 	    *    </ul>
19445 	    *    Center of the container <pre> position: {
19446 	   *       mx: 0.5,
19447 	   *       my: 0.5,
19448 	   *     }</pre>
19449 	   *     Upper left corner of the container
19450 	   *     <pre> position: {
19451 	   *       mx: 0.0,
19452 	   *       my: 0.0,
19453 	   *     }</pre>
19454 	   *    </li>
19455 	   *   </ul>
19456 	   * </p>
19457 	   *
19458 	   */
19459 	  this.getScaledPath = function getScaledPath(pathId, param) {
19460 	    var rawPath = this.pathMap[pathId];
19461 
19462 	    // positioning
19463 	    // compute the start point of the path
19464 	    var mx, my;
19465 
19466 	    if (param.abspos) {
19467 	      mx = param.abspos.x;
19468 	      my = param.abspos.y;
19469 	    } else {
19470 	      mx = param.containerWidth * param.position.mx;
19471 	      my = param.containerHeight * param.position.my;
19472 	    }
19473 
19474 	    var coordinates = {}; // map for the scaled coordinates
19475 	    if (param.position) {
19476 
19477 	      // path
19478 	      var heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor;
19479 	      var widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor;
19480 
19481 
19482 	      // Apply height ratio
19483 	      for (var heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) {
19484 	        coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio;
19485 	      }
19486 
19487 	      // Apply width ratio
19488 	      for (var widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) {
19489 	        coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio;
19490 	      }
19491 	    }
19492 
19493 	    // Apply value to raw path
19494 	    var path = format(
19495 	      rawPath.d, {
19496 	        mx: mx,
19497 	        my: my,
19498 	        e: coordinates
19499 	      }
19500 	    );
19501 	    return path;
19502 	  };
19503 	}
19504 
19505 	// helpers //////////////////////
19506 
19507 	// copied and adjusted from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js
19508 	var tokenRegex = /\{([^{}]+)\}/g,
19509 	    objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties
19510 
19511 	function replacer(all, key, obj) {
19512 	  var res = obj;
19513 	  key.replace(objNotationRegex, function(all, name, quote, quotedName, isFunc) {
19514 	    name = name || quotedName;
19515 	    if (res) {
19516 	      if (name in res) {
19517 	        res = res[name];
19518 	      }
19519 	      typeof res == 'function' && isFunc && (res = res());
19520 	    }
19521 	  });
19522 	  res = (res == null || res == obj ? all : res) + '';
19523 
19524 	  return res;
19525 	}
19526 
19527 	function format(str, obj) {
19528 	  return String(str).replace(tokenRegex, function(all, key) {
19529 	    return replacer(all, key, obj);
19530 	  });
19531 	}
19532 
19533 	var DrawModule = {
19534 	  __init__: [ 'bpmnRenderer' ],
19535 	  bpmnRenderer: [ 'type', BpmnRenderer ],
19536 	  textRenderer: [ 'type', TextRenderer ],
19537 	  pathMap: [ 'type', PathMap ]
19538 	};
19539 
19540 	/**
19541 	 * A simple translation stub to be used for multi-language support
19542 	 * in diagrams. Can be easily replaced with a more sophisticated
19543 	 * solution.
19544 	 *
19545 	 * @example
19546 	 *
19547 	 * // use it inside any diagram component by injecting `translate`.
19548 	 *
19549 	 * function MyService(translate) {
19550 	 *   alert(translate('HELLO {you}', { you: 'You!' }));
19551 	 * }
19552 	 *
19553 	 * @param {string} template to interpolate
19554 	 * @param {Object} [replacements] a map with substitutes
19555 	 *
19556 	 * @return {string} the translated string
19557 	 */
19558 	function translate$1(template, replacements) {
19559 
19560 	  replacements = replacements || {};
19561 
19562 	  return template.replace(/{([^}]+)}/g, function(_, key) {
19563 	    return replacements[key] || '{' + key + '}';
19564 	  });
19565 	}
19566 
19567 	var translate = {
19568 	  translate: [ 'value', translate$1 ]
19569 	};
19570 
19571 	var DEFAULT_LABEL_SIZE = {
19572 	  width: 90,
19573 	  height: 20
19574 	};
19575 
19576 	var FLOW_LABEL_INDENT = 15;
19577 
19578 
19579 	/**
19580 	 * Returns true if the given semantic has an external label
19581 	 *
19582 	 * @param {BpmnElement} semantic
19583 	 * @return {boolean} true if has label
19584 	 */
19585 	function isLabelExternal(semantic) {
19586 	  return is$1(semantic, 'bpmn:Event') ||
19587 	         is$1(semantic, 'bpmn:Gateway') ||
19588 	         is$1(semantic, 'bpmn:DataStoreReference') ||
19589 	         is$1(semantic, 'bpmn:DataObjectReference') ||
19590 	         is$1(semantic, 'bpmn:DataInput') ||
19591 	         is$1(semantic, 'bpmn:DataOutput') ||
19592 	         is$1(semantic, 'bpmn:SequenceFlow') ||
19593 	         is$1(semantic, 'bpmn:MessageFlow') ||
19594 	         is$1(semantic, 'bpmn:Group');
19595 	}
19596 
19597 	/**
19598 	 * Returns true if the given element has an external label
19599 	 *
19600 	 * @param {djs.model.shape} element
19601 	 * @return {boolean} true if has label
19602 	 */
19603 	function hasExternalLabel(element) {
19604 	  return isLabel$6(element.label);
19605 	}
19606 
19607 	/**
19608 	 * Get the position for sequence flow labels
19609 	 *
19610 	 * @param  {Array<Point>} waypoints
19611 	 * @return {Point} the label position
19612 	 */
19613 	function getFlowLabelPosition(waypoints) {
19614 
19615 	  // get the waypoints mid
19616 	  var mid = waypoints.length / 2 - 1;
19617 
19618 	  var first = waypoints[Math.floor(mid)];
19619 	  var second = waypoints[Math.ceil(mid + 0.01)];
19620 
19621 	  // get position
19622 	  var position = getWaypointsMid(waypoints);
19623 
19624 	  // calculate angle
19625 	  var angle = Math.atan((second.y - first.y) / (second.x - first.x));
19626 
19627 	  var x = position.x,
19628 	      y = position.y;
19629 
19630 	  if (Math.abs(angle) < Math.PI / 2) {
19631 	    y -= FLOW_LABEL_INDENT;
19632 	  } else {
19633 	    x += FLOW_LABEL_INDENT;
19634 	  }
19635 
19636 	  return { x: x, y: y };
19637 	}
19638 
19639 
19640 	/**
19641 	 * Get the middle of a number of waypoints
19642 	 *
19643 	 * @param  {Array<Point>} waypoints
19644 	 * @return {Point} the mid point
19645 	 */
19646 	function getWaypointsMid(waypoints) {
19647 
19648 	  var mid = waypoints.length / 2 - 1;
19649 
19650 	  var first = waypoints[Math.floor(mid)];
19651 	  var second = waypoints[Math.ceil(mid + 0.01)];
19652 
19653 	  return {
19654 	    x: first.x + (second.x - first.x) / 2,
19655 	    y: first.y + (second.y - first.y) / 2
19656 	  };
19657 	}
19658 
19659 
19660 	function getExternalLabelMid(element) {
19661 
19662 	  if (element.waypoints) {
19663 	    return getFlowLabelPosition(element.waypoints);
19664 	  } else if (is$1(element, 'bpmn:Group')) {
19665 	    return {
19666 	      x: element.x + element.width / 2,
19667 	      y: element.y + DEFAULT_LABEL_SIZE.height / 2
19668 	    };
19669 	  } else {
19670 	    return {
19671 	      x: element.x + element.width / 2,
19672 	      y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
19673 	    };
19674 	  }
19675 	}
19676 
19677 
19678 	/**
19679 	 * Returns the bounds of an elements label, parsed from the elements DI or
19680 	 * generated from its bounds.
19681 	 *
19682 	 * @param {BpmnElement} semantic
19683 	 * @param {djs.model.Base} element
19684 	 */
19685 	function getExternalLabelBounds(semantic, element) {
19686 
19687 	  var mid,
19688 	      size,
19689 	      bounds,
19690 	      di = semantic.di,
19691 	      label = di.label;
19692 
19693 	  if (label && label.bounds) {
19694 	    bounds = label.bounds;
19695 
19696 	    size = {
19697 	      width: Math.max(DEFAULT_LABEL_SIZE.width, bounds.width),
19698 	      height: bounds.height
19699 	    };
19700 
19701 	    mid = {
19702 	      x: bounds.x + bounds.width / 2,
19703 	      y: bounds.y + bounds.height / 2
19704 	    };
19705 	  } else {
19706 
19707 	    mid = getExternalLabelMid(element);
19708 
19709 	    size = DEFAULT_LABEL_SIZE;
19710 	  }
19711 
19712 	  return assign({
19713 	    x: mid.x - size.width / 2,
19714 	    y: mid.y - size.height / 2
19715 	  }, size);
19716 	}
19717 
19718 	function isLabel$6(element) {
19719 	  return element && !!element.labelTarget;
19720 	}
19721 
19722 	function elementData(semantic, attrs) {
19723 	  return assign({
19724 	    id: semantic.id,
19725 	    type: semantic.$type,
19726 	    businessObject: semantic
19727 	  }, attrs);
19728 	}
19729 
19730 	function getWaypoints(bo, source, target) {
19731 
19732 	  var waypoints = bo.di.waypoint;
19733 
19734 	  if (!waypoints || waypoints.length < 2) {
19735 	    return [ getMid(source), getMid(target) ];
19736 	  }
19737 
19738 	  return waypoints.map(function(p) {
19739 	    return { x: p.x, y: p.y };
19740 	  });
19741 	}
19742 
19743 	function notYetDrawn(translate, semantic, refSemantic, property) {
19744 	  return new Error(translate('element {element} referenced by {referenced}#{property} not yet drawn', {
19745 	    element: elementToString(refSemantic),
19746 	    referenced: elementToString(semantic),
19747 	    property: property
19748 	  }));
19749 	}
19750 
19751 
19752 	/**
19753 	 * An importer that adds bpmn elements to the canvas
19754 	 *
19755 	 * @param {EventBus} eventBus
19756 	 * @param {Canvas} canvas
19757 	 * @param {ElementFactory} elementFactory
19758 	 * @param {ElementRegistry} elementRegistry
19759 	 * @param {Function} translate
19760 	 * @param {TextRenderer} textRenderer
19761 	 */
19762 	function BpmnImporter(
19763 	    eventBus, canvas, elementFactory,
19764 	    elementRegistry, translate, textRenderer) {
19765 
19766 	  this._eventBus = eventBus;
19767 	  this._canvas = canvas;
19768 	  this._elementFactory = elementFactory;
19769 	  this._elementRegistry = elementRegistry;
19770 	  this._translate = translate;
19771 	  this._textRenderer = textRenderer;
19772 	}
19773 
19774 	BpmnImporter.$inject = [
19775 	  'eventBus',
19776 	  'canvas',
19777 	  'elementFactory',
19778 	  'elementRegistry',
19779 	  'translate',
19780 	  'textRenderer'
19781 	];
19782 
19783 
19784 	/**
19785 	 * Add bpmn element (semantic) to the canvas onto the
19786 	 * specified parent shape.
19787 	 */
19788 	BpmnImporter.prototype.add = function(semantic, parentElement) {
19789 
19790 	  var di = semantic.di,
19791 	      element,
19792 	      translate = this._translate,
19793 	      hidden;
19794 
19795 	  var parentIndex;
19796 
19797 	  // ROOT ELEMENT
19798 	  // handle the special case that we deal with a
19799 	  // invisible root element (process or collaboration)
19800 	  if (is$1(di, 'bpmndi:BPMNPlane')) {
19801 
19802 	    // add a virtual element (not being drawn)
19803 	    element = this._elementFactory.createRoot(elementData(semantic));
19804 
19805 	    this._canvas.setRootElement(element);
19806 	  }
19807 
19808 	  // SHAPE
19809 	  else if (is$1(di, 'bpmndi:BPMNShape')) {
19810 
19811 	    var collapsed = !isExpanded(semantic),
19812 	        isFrame = isFrameElement(semantic);
19813 	    hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
19814 
19815 	    var bounds = semantic.di.bounds;
19816 
19817 	    element = this._elementFactory.createShape(elementData(semantic, {
19818 	      collapsed: collapsed,
19819 	      hidden: hidden,
19820 	      x: Math.round(bounds.x),
19821 	      y: Math.round(bounds.y),
19822 	      width: Math.round(bounds.width),
19823 	      height: Math.round(bounds.height),
19824 	      isFrame: isFrame
19825 	    }));
19826 
19827 	    if (is$1(semantic, 'bpmn:BoundaryEvent')) {
19828 	      this._attachBoundary(semantic, element);
19829 	    }
19830 
19831 	    // insert lanes behind other flow nodes (cf. #727)
19832 	    if (is$1(semantic, 'bpmn:Lane')) {
19833 	      parentIndex = 0;
19834 	    }
19835 
19836 	    if (is$1(semantic, 'bpmn:DataStoreReference')) {
19837 
19838 	      // check whether data store is inside our outside of its semantic parent
19839 	      if (!isPointInsideBBox$1(parentElement, getMid(bounds))) {
19840 	        parentElement = this._canvas.getRootElement();
19841 	      }
19842 	    }
19843 
19844 	    this._canvas.addShape(element, parentElement, parentIndex);
19845 	  }
19846 
19847 	  // CONNECTION
19848 	  else if (is$1(di, 'bpmndi:BPMNEdge')) {
19849 
19850 	    var source = this._getSource(semantic),
19851 	        target = this._getTarget(semantic);
19852 
19853 	    hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
19854 
19855 	    element = this._elementFactory.createConnection(elementData(semantic, {
19856 	      hidden: hidden,
19857 	      source: source,
19858 	      target: target,
19859 	      waypoints: getWaypoints(semantic, source, target)
19860 	    }));
19861 
19862 	    if (is$1(semantic, 'bpmn:DataAssociation')) {
19863 
19864 	      // render always on top; this ensures DataAssociations
19865 	      // are rendered correctly across different "hacks" people
19866 	      // love to model such as cross participant / sub process
19867 	      // associations
19868 	      parentElement = null;
19869 	    }
19870 
19871 	    // insert sequence flows behind other flow nodes (cf. #727)
19872 	    if (is$1(semantic, 'bpmn:SequenceFlow')) {
19873 	      parentIndex = 0;
19874 	    }
19875 
19876 	    this._canvas.addConnection(element, parentElement, parentIndex);
19877 	  } else {
19878 	    throw new Error(translate('unknown di {di} for element {semantic}', {
19879 	      di: elementToString(di),
19880 	      semantic: elementToString(semantic)
19881 	    }));
19882 	  }
19883 
19884 	  // (optional) LABEL
19885 	  if (isLabelExternal(semantic) && getLabel(element)) {
19886 	    this.addLabel(semantic, element);
19887 	  }
19888 
19889 
19890 	  this._eventBus.fire('bpmnElement.added', { element: element });
19891 
19892 	  return element;
19893 	};
19894 
19895 
19896 	/**
19897 	 * Attach the boundary element to the given host
19898 	 *
19899 	 * @param {ModdleElement} boundarySemantic
19900 	 * @param {djs.model.Base} boundaryElement
19901 	 */
19902 	BpmnImporter.prototype._attachBoundary = function(boundarySemantic, boundaryElement) {
19903 	  var translate = this._translate;
19904 	  var hostSemantic = boundarySemantic.attachedToRef;
19905 
19906 	  if (!hostSemantic) {
19907 	    throw new Error(translate('missing {semantic}#attachedToRef', {
19908 	      semantic: elementToString(boundarySemantic)
19909 	    }));
19910 	  }
19911 
19912 	  var host = this._elementRegistry.get(hostSemantic.id),
19913 	      attachers = host && host.attachers;
19914 
19915 	  if (!host) {
19916 	    throw notYetDrawn(translate, boundarySemantic, hostSemantic, 'attachedToRef');
19917 	  }
19918 
19919 	  // wire element.host <> host.attachers
19920 	  boundaryElement.host = host;
19921 
19922 	  if (!attachers) {
19923 	    host.attachers = attachers = [];
19924 	  }
19925 
19926 	  if (attachers.indexOf(boundaryElement) === -1) {
19927 	    attachers.push(boundaryElement);
19928 	  }
19929 	};
19930 
19931 
19932 	/**
19933 	 * add label for an element
19934 	 */
19935 	BpmnImporter.prototype.addLabel = function(semantic, element) {
19936 	  var bounds,
19937 	      text,
19938 	      label;
19939 
19940 	  bounds = getExternalLabelBounds(semantic, element);
19941 
19942 	  text = getLabel(element);
19943 
19944 	  if (text) {
19945 
19946 	    // get corrected bounds from actual layouted text
19947 	    bounds = this._textRenderer.getExternalLabelBounds(bounds, text);
19948 	  }
19949 
19950 	  label = this._elementFactory.createLabel(elementData(semantic, {
19951 	    id: semantic.id + '_label',
19952 	    labelTarget: element,
19953 	    type: 'label',
19954 	    hidden: element.hidden || !getLabel(element),
19955 	    x: Math.round(bounds.x),
19956 	    y: Math.round(bounds.y),
19957 	    width: Math.round(bounds.width),
19958 	    height: Math.round(bounds.height)
19959 	  }));
19960 
19961 	  return this._canvas.addShape(label, element.parent);
19962 	};
19963 
19964 	/**
19965 	 * Return the drawn connection end based on the given side.
19966 	 *
19967 	 * @throws {Error} if the end is not yet drawn
19968 	 */
19969 	BpmnImporter.prototype._getEnd = function(semantic, side) {
19970 
19971 	  var element,
19972 	      refSemantic,
19973 	      type = semantic.$type,
19974 	      translate = this._translate;
19975 
19976 	  refSemantic = semantic[side + 'Ref'];
19977 
19978 	  // handle mysterious isMany DataAssociation#sourceRef
19979 	  if (side === 'source' && type === 'bpmn:DataInputAssociation') {
19980 	    refSemantic = refSemantic && refSemantic[0];
19981 	  }
19982 
19983 	  // fix source / target for DataInputAssociation / DataOutputAssociation
19984 	  if (side === 'source' && type === 'bpmn:DataOutputAssociation' ||
19985 	      side === 'target' && type === 'bpmn:DataInputAssociation') {
19986 
19987 	    refSemantic = semantic.$parent;
19988 	  }
19989 
19990 	  element = refSemantic && this._getElement(refSemantic);
19991 
19992 	  if (element) {
19993 	    return element;
19994 	  }
19995 
19996 	  if (refSemantic) {
19997 	    throw notYetDrawn(translate, semantic, refSemantic, side + 'Ref');
19998 	  } else {
19999 	    throw new Error(translate('{semantic}#{side} Ref not specified', {
20000 	      semantic: elementToString(semantic),
20001 	      side: side
20002 	    }));
20003 	  }
20004 	};
20005 
20006 	BpmnImporter.prototype._getSource = function(semantic) {
20007 	  return this._getEnd(semantic, 'source');
20008 	};
20009 
20010 	BpmnImporter.prototype._getTarget = function(semantic) {
20011 	  return this._getEnd(semantic, 'target');
20012 	};
20013 
20014 
20015 	BpmnImporter.prototype._getElement = function(semantic) {
20016 	  return this._elementRegistry.get(semantic.id);
20017 	};
20018 
20019 
20020 	// helpers ////////////////////
20021 
20022 	function isPointInsideBBox$1(bbox, point) {
20023 	  var x = point.x,
20024 	      y = point.y;
20025 
20026 	  return x >= bbox.x &&
20027 	    x <= bbox.x + bbox.width &&
20028 	    y >= bbox.y &&
20029 	    y <= bbox.y + bbox.height;
20030 	}
20031 
20032 	function isFrameElement(semantic) {
20033 	  return is$1(semantic, 'bpmn:Group');
20034 	}
20035 
20036 	var ImportModule = {
20037 	  __depends__: [
20038 	    translate
20039 	  ],
20040 	  bpmnImporter: [ 'type', BpmnImporter ]
20041 	};
20042 
20043 	var CoreModule = {
20044 	  __depends__: [
20045 	    DrawModule,
20046 	    ImportModule
20047 	  ]
20048 	};
20049 
20050 	function __stopPropagation(event) {
20051 	  if (!event || typeof event.stopPropagation !== 'function') {
20052 	    return;
20053 	  }
20054 
20055 	  event.stopPropagation();
20056 	}
20057 
20058 
20059 	function getOriginal$1(event) {
20060 	  return event.originalEvent || event.srcEvent;
20061 	}
20062 
20063 
20064 	function stopPropagation$1(event, immediate) {
20065 	  __stopPropagation(event);
20066 	  __stopPropagation(getOriginal$1(event));
20067 	}
20068 
20069 
20070 	function toPoint(event) {
20071 
20072 	  if (event.pointers && event.pointers.length) {
20073 	    event = event.pointers[0];
20074 	  }
20075 
20076 	  if (event.touches && event.touches.length) {
20077 	    event = event.touches[0];
20078 	  }
20079 
20080 	  return event ? {
20081 	    x: event.clientX,
20082 	    y: event.clientY
20083 	  } : null;
20084 	}
20085 
20086 	function isMac() {
20087 	  return (/mac/i).test(navigator.platform);
20088 	}
20089 
20090 	function isButton(event, button) {
20091 	  return (getOriginal$1(event) || event).button === button;
20092 	}
20093 
20094 	function isPrimaryButton(event) {
20095 
20096 	  // button === 0 -> left áka primary mouse button
20097 	  return isButton(event, 0);
20098 	}
20099 
20100 	function isAuxiliaryButton(event) {
20101 
20102 	  // button === 1 -> auxiliary áka wheel button
20103 	  return isButton(event, 1);
20104 	}
20105 
20106 	function hasPrimaryModifier(event) {
20107 	  var originalEvent = getOriginal$1(event) || event;
20108 
20109 	  if (!isPrimaryButton(event)) {
20110 	    return false;
20111 	  }
20112 
20113 	  // Use cmd as primary modifier key for mac OS
20114 	  if (isMac()) {
20115 	    return originalEvent.metaKey;
20116 	  } else {
20117 	    return originalEvent.ctrlKey;
20118 	  }
20119 	}
20120 
20121 
20122 	function hasSecondaryModifier(event) {
20123 	  var originalEvent = getOriginal$1(event) || event;
20124 
20125 	  return isPrimaryButton(event) && originalEvent.shiftKey;
20126 	}
20127 
20128 	function allowAll(event) { return true; }
20129 
20130 	function allowPrimaryAndAuxiliary(event) {
20131 	  return isPrimaryButton(event) || isAuxiliaryButton(event);
20132 	}
20133 
20134 	var LOW_PRIORITY$m = 500;
20135 
20136 
20137 	/**
20138 	 * A plugin that provides interaction events for diagram elements.
20139 	 *
20140 	 * It emits the following events:
20141 	 *
20142 	 *   * element.click
20143 	 *   * element.contextmenu
20144 	 *   * element.dblclick
20145 	 *   * element.hover
20146 	 *   * element.mousedown
20147 	 *   * element.mousemove
20148 	 *   * element.mouseup
20149 	 *   * element.out
20150 	 *
20151 	 * Each event is a tuple { element, gfx, originalEvent }.
20152 	 *
20153 	 * Canceling the event via Event#preventDefault()
20154 	 * prevents the original DOM operation.
20155 	 *
20156 	 * @param {EventBus} eventBus
20157 	 */
20158 	function InteractionEvents(eventBus, elementRegistry, styles) {
20159 
20160 	  var self = this;
20161 
20162 	  /**
20163 	   * Fire an interaction event.
20164 	   *
20165 	   * @param {string} type local event name, e.g. element.click.
20166 	   * @param {DOMEvent} event native event
20167 	   * @param {djs.model.Base} [element] the diagram element to emit the event on;
20168 	   *                                   defaults to the event target
20169 	   */
20170 	  function fire(type, event, element) {
20171 
20172 	    if (isIgnored(type, event)) {
20173 	      return;
20174 	    }
20175 
20176 	    var target, gfx, returnValue;
20177 
20178 	    if (!element) {
20179 	      target = event.delegateTarget || event.target;
20180 
20181 	      if (target) {
20182 	        gfx = target;
20183 	        element = elementRegistry.get(gfx);
20184 	      }
20185 	    } else {
20186 	      gfx = elementRegistry.getGraphics(element);
20187 	    }
20188 
20189 	    if (!gfx || !element) {
20190 	      return;
20191 	    }
20192 
20193 	    returnValue = eventBus.fire(type, {
20194 	      element: element,
20195 	      gfx: gfx,
20196 	      originalEvent: event
20197 	    });
20198 
20199 	    if (returnValue === false) {
20200 	      event.stopPropagation();
20201 	      event.preventDefault();
20202 	    }
20203 	  }
20204 
20205 	  // TODO(nikku): document this
20206 	  var handlers = {};
20207 
20208 	  function mouseHandler(localEventName) {
20209 	    return handlers[localEventName];
20210 	  }
20211 
20212 	  function isIgnored(localEventName, event) {
20213 
20214 	    var filter = ignoredFilters[localEventName] || isPrimaryButton;
20215 
20216 	    // only react on left mouse button interactions
20217 	    // except for interaction events that are enabled
20218 	    // for secundary mouse button
20219 	    return !filter(event);
20220 	  }
20221 
20222 	  var bindings = {
20223 	    click: 'element.click',
20224 	    contextmenu: 'element.contextmenu',
20225 	    dblclick: 'element.dblclick',
20226 	    mousedown: 'element.mousedown',
20227 	    mousemove: 'element.mousemove',
20228 	    mouseover: 'element.hover',
20229 	    mouseout: 'element.out',
20230 	    mouseup: 'element.mouseup',
20231 	  };
20232 
20233 	  var ignoredFilters = {
20234 	    'element.contextmenu': allowAll,
20235 	    'element.mousedown': allowPrimaryAndAuxiliary,
20236 	    'element.mouseup': allowPrimaryAndAuxiliary,
20237 	    'element.click': allowPrimaryAndAuxiliary,
20238 	    'element.dblclick': allowPrimaryAndAuxiliary
20239 	  };
20240 
20241 
20242 	  // manual event trigger //////////
20243 
20244 	  /**
20245 	   * Trigger an interaction event (based on a native dom event)
20246 	   * on the target shape or connection.
20247 	   *
20248 	   * @param {string} eventName the name of the triggered DOM event
20249 	   * @param {MouseEvent} event
20250 	   * @param {djs.model.Base} targetElement
20251 	   */
20252 	  function triggerMouseEvent(eventName, event, targetElement) {
20253 
20254 	    // i.e. element.mousedown...
20255 	    var localEventName = bindings[eventName];
20256 
20257 	    if (!localEventName) {
20258 	      throw new Error('unmapped DOM event name <' + eventName + '>');
20259 	    }
20260 
20261 	    return fire(localEventName, event, targetElement);
20262 	  }
20263 
20264 
20265 	  var ELEMENT_SELECTOR = 'svg, .djs-element';
20266 
20267 	  // event handling ///////
20268 
20269 	  function registerEvent(node, event, localEvent, ignoredFilter) {
20270 
20271 	    var handler = handlers[localEvent] = function(event) {
20272 	      fire(localEvent, event);
20273 	    };
20274 
20275 	    if (ignoredFilter) {
20276 	      ignoredFilters[localEvent] = ignoredFilter;
20277 	    }
20278 
20279 	    handler.$delegate = delegate.bind(node, ELEMENT_SELECTOR, event, handler);
20280 	  }
20281 
20282 	  function unregisterEvent(node, event, localEvent) {
20283 
20284 	    var handler = mouseHandler(localEvent);
20285 
20286 	    if (!handler) {
20287 	      return;
20288 	    }
20289 
20290 	    delegate.unbind(node, event, handler.$delegate);
20291 	  }
20292 
20293 	  function registerEvents(svg) {
20294 	    forEach(bindings, function(val, key) {
20295 	      registerEvent(svg, key, val);
20296 	    });
20297 	  }
20298 
20299 	  function unregisterEvents(svg) {
20300 	    forEach(bindings, function(val, key) {
20301 	      unregisterEvent(svg, key, val);
20302 	    });
20303 	  }
20304 
20305 	  eventBus.on('canvas.destroy', function(event) {
20306 	    unregisterEvents(event.svg);
20307 	  });
20308 
20309 	  eventBus.on('canvas.init', function(event) {
20310 	    registerEvents(event.svg);
20311 	  });
20312 
20313 
20314 	  // hit box updating ////////////////
20315 
20316 	  eventBus.on([ 'shape.added', 'connection.added' ], function(event) {
20317 	    var element = event.element,
20318 	        gfx = event.gfx;
20319 
20320 	    eventBus.fire('interactionEvents.createHit', { element: element, gfx: gfx });
20321 	  });
20322 
20323 	  // Update djs-hit on change.
20324 	  // A low priortity is necessary, because djs-hit of labels has to be updated
20325 	  // after the label bounds have been updated in the renderer.
20326 	  eventBus.on([
20327 	    'shape.changed',
20328 	    'connection.changed'
20329 	  ], LOW_PRIORITY$m, function(event) {
20330 
20331 	    var element = event.element,
20332 	        gfx = event.gfx;
20333 
20334 	    eventBus.fire('interactionEvents.updateHit', { element: element, gfx: gfx });
20335 	  });
20336 
20337 	  eventBus.on('interactionEvents.createHit', LOW_PRIORITY$m, function(event) {
20338 	    var element = event.element,
20339 	        gfx = event.gfx;
20340 
20341 	    self.createDefaultHit(element, gfx);
20342 	  });
20343 
20344 	  eventBus.on('interactionEvents.updateHit', function(event) {
20345 	    var element = event.element,
20346 	        gfx = event.gfx;
20347 
20348 	    self.updateDefaultHit(element, gfx);
20349 	  });
20350 
20351 
20352 	  // hit styles ////////////
20353 
20354 	  var STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-stroke');
20355 
20356 	  var CLICK_STROKE_HIT_STYLE = createHitStyle('djs-hit djs-hit-click-stroke');
20357 
20358 	  var ALL_HIT_STYLE = createHitStyle('djs-hit djs-hit-all');
20359 
20360 	  var HIT_TYPES = {
20361 	    'all': ALL_HIT_STYLE,
20362 	    'click-stroke': CLICK_STROKE_HIT_STYLE,
20363 	    'stroke': STROKE_HIT_STYLE
20364 	  };
20365 
20366 	  function createHitStyle(classNames, attrs) {
20367 
20368 	    attrs = assign({
20369 	      stroke: 'white',
20370 	      strokeWidth: 15
20371 	    }, attrs || {});
20372 
20373 	    return styles.cls(classNames, [ 'no-fill', 'no-border' ], attrs);
20374 	  }
20375 
20376 
20377 	  // style helpers ///////////////
20378 
20379 	  function applyStyle(hit, type) {
20380 
20381 	    var attrs = HIT_TYPES[type];
20382 
20383 	    if (!attrs) {
20384 	      throw new Error('invalid hit type <' + type + '>');
20385 	    }
20386 
20387 	    attr(hit, attrs);
20388 
20389 	    return hit;
20390 	  }
20391 
20392 	  function appendHit(gfx, hit) {
20393 	    append(gfx, hit);
20394 	  }
20395 
20396 
20397 	  // API
20398 
20399 	  /**
20400 	   * Remove hints on the given graphics.
20401 	   *
20402 	   * @param {SVGElement} gfx
20403 	   */
20404 	  this.removeHits = function(gfx) {
20405 	    var hits = all('.djs-hit', gfx);
20406 
20407 	    forEach(hits, remove$1);
20408 	  };
20409 
20410 	  /**
20411 	   * Create default hit for the given element.
20412 	   *
20413 	   * @param {djs.model.Base} element
20414 	   * @param {SVGElement} gfx
20415 	   *
20416 	   * @return {SVGElement} created hit
20417 	   */
20418 	  this.createDefaultHit = function(element, gfx) {
20419 	    var waypoints = element.waypoints,
20420 	        isFrame = element.isFrame,
20421 	        boxType;
20422 
20423 	    if (waypoints) {
20424 	      return this.createWaypointsHit(gfx, waypoints);
20425 	    } else {
20426 
20427 	      boxType = isFrame ? 'stroke' : 'all';
20428 
20429 	      return this.createBoxHit(gfx, boxType, {
20430 	        width: element.width,
20431 	        height: element.height
20432 	      });
20433 	    }
20434 	  };
20435 
20436 	  /**
20437 	   * Create hits for the given waypoints.
20438 	   *
20439 	   * @param {SVGElement} gfx
20440 	   * @param {Array<Point>} waypoints
20441 	   *
20442 	   * @return {SVGElement}
20443 	   */
20444 	  this.createWaypointsHit = function(gfx, waypoints) {
20445 
20446 	    var hit = createLine(waypoints);
20447 
20448 	    applyStyle(hit, 'stroke');
20449 
20450 	    appendHit(gfx, hit);
20451 
20452 	    return hit;
20453 	  };
20454 
20455 	  /**
20456 	   * Create hits for a box.
20457 	   *
20458 	   * @param {SVGElement} gfx
20459 	   * @param {string} hitType
20460 	   * @param {Object} attrs
20461 	   *
20462 	   * @return {SVGElement}
20463 	   */
20464 	  this.createBoxHit = function(gfx, type, attrs) {
20465 
20466 	    attrs = assign({
20467 	      x: 0,
20468 	      y: 0
20469 	    }, attrs);
20470 
20471 	    var hit = create$1('rect');
20472 
20473 	    applyStyle(hit, type);
20474 
20475 	    attr(hit, attrs);
20476 
20477 	    appendHit(gfx, hit);
20478 
20479 	    return hit;
20480 	  };
20481 
20482 	  /**
20483 	   * Update default hit of the element.
20484 	   *
20485 	   * @param  {djs.model.Base} element
20486 	   * @param  {SVGElement} gfx
20487 	   *
20488 	   * @return {SVGElement} updated hit
20489 	   */
20490 	  this.updateDefaultHit = function(element, gfx) {
20491 
20492 	    var hit = query('.djs-hit', gfx);
20493 
20494 	    if (!hit) {
20495 	      return;
20496 	    }
20497 
20498 	    if (element.waypoints) {
20499 	      updateLine(hit, element.waypoints);
20500 	    } else {
20501 	      attr(hit, {
20502 	        width: element.width,
20503 	        height: element.height
20504 	      });
20505 	    }
20506 
20507 	    return hit;
20508 	  };
20509 
20510 	  this.fire = fire;
20511 
20512 	  this.triggerMouseEvent = triggerMouseEvent;
20513 
20514 	  this.mouseHandler = mouseHandler;
20515 
20516 	  this.registerEvent = registerEvent;
20517 	  this.unregisterEvent = unregisterEvent;
20518 	}
20519 
20520 
20521 	InteractionEvents.$inject = [
20522 	  'eventBus',
20523 	  'elementRegistry',
20524 	  'styles'
20525 	];
20526 
20527 
20528 	/**
20529 	 * An event indicating that the mouse hovered over an element
20530 	 *
20531 	 * @event element.hover
20532 	 *
20533 	 * @type {Object}
20534 	 * @property {djs.model.Base} element
20535 	 * @property {SVGElement} gfx
20536 	 * @property {Event} originalEvent
20537 	 */
20538 
20539 	/**
20540 	 * An event indicating that the mouse has left an element
20541 	 *
20542 	 * @event element.out
20543 	 *
20544 	 * @type {Object}
20545 	 * @property {djs.model.Base} element
20546 	 * @property {SVGElement} gfx
20547 	 * @property {Event} originalEvent
20548 	 */
20549 
20550 	/**
20551 	 * An event indicating that the mouse has clicked an element
20552 	 *
20553 	 * @event element.click
20554 	 *
20555 	 * @type {Object}
20556 	 * @property {djs.model.Base} element
20557 	 * @property {SVGElement} gfx
20558 	 * @property {Event} originalEvent
20559 	 */
20560 
20561 	/**
20562 	 * An event indicating that the mouse has double clicked an element
20563 	 *
20564 	 * @event element.dblclick
20565 	 *
20566 	 * @type {Object}
20567 	 * @property {djs.model.Base} element
20568 	 * @property {SVGElement} gfx
20569 	 * @property {Event} originalEvent
20570 	 */
20571 
20572 	/**
20573 	 * An event indicating that the mouse has gone down on an element.
20574 	 *
20575 	 * @event element.mousedown
20576 	 *
20577 	 * @type {Object}
20578 	 * @property {djs.model.Base} element
20579 	 * @property {SVGElement} gfx
20580 	 * @property {Event} originalEvent
20581 	 */
20582 
20583 	/**
20584 	 * An event indicating that the mouse has gone up on an element.
20585 	 *
20586 	 * @event element.mouseup
20587 	 *
20588 	 * @type {Object}
20589 	 * @property {djs.model.Base} element
20590 	 * @property {SVGElement} gfx
20591 	 * @property {Event} originalEvent
20592 	 */
20593 
20594 	/**
20595 	 * An event indicating that the context menu action is triggered
20596 	 * via mouse or touch controls.
20597 	 *
20598 	 * @event element.contextmenu
20599 	 *
20600 	 * @type {Object}
20601 	 * @property {djs.model.Base} element
20602 	 * @property {SVGElement} gfx
20603 	 * @property {Event} originalEvent
20604 	 */
20605 
20606 	var InteractionEventsModule$1 = {
20607 	  __init__: [ 'interactionEvents' ],
20608 	  interactionEvents: [ 'type', InteractionEvents ]
20609 	};
20610 
20611 	var LOW_PRIORITY$l = 500;
20612 
20613 
20614 	/**
20615 	 * @class
20616 	 *
20617 	 * A plugin that adds an outline to shapes and connections that may be activated and styled
20618 	 * via CSS classes.
20619 	 *
20620 	 * @param {EventBus} eventBus
20621 	 * @param {Styles} styles
20622 	 * @param {ElementRegistry} elementRegistry
20623 	 */
20624 	function Outline(eventBus, styles, elementRegistry) {
20625 
20626 	  this.offset = 6;
20627 
20628 	  var OUTLINE_STYLE = styles.cls('djs-outline', [ 'no-fill' ]);
20629 
20630 	  var self = this;
20631 
20632 	  function createOutline(gfx, bounds) {
20633 	    var outline = create$1('rect');
20634 
20635 	    attr(outline, assign({
20636 	      x: 10,
20637 	      y: 10,
20638 	      width: 100,
20639 	      height: 100
20640 	    }, OUTLINE_STYLE));
20641 
20642 	    append(gfx, outline);
20643 
20644 	    return outline;
20645 	  }
20646 
20647 	  // A low priortity is necessary, because outlines of labels have to be updated
20648 	  // after the label bounds have been updated in the renderer.
20649 	  eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$l, function(event) {
20650 	    var element = event.element,
20651 	        gfx = event.gfx;
20652 
20653 	    var outline = query('.djs-outline', gfx);
20654 
20655 	    if (!outline) {
20656 	      outline = createOutline(gfx);
20657 	    }
20658 
20659 	    self.updateShapeOutline(outline, element);
20660 	  });
20661 
20662 	  eventBus.on([ 'connection.added', 'connection.changed' ], function(event) {
20663 	    var element = event.element,
20664 	        gfx = event.gfx;
20665 
20666 	    var outline = query('.djs-outline', gfx);
20667 
20668 	    if (!outline) {
20669 	      outline = createOutline(gfx);
20670 	    }
20671 
20672 	    self.updateConnectionOutline(outline, element);
20673 	  });
20674 	}
20675 
20676 
20677 	/**
20678 	 * Updates the outline of a shape respecting the dimension of the
20679 	 * element and an outline offset.
20680 	 *
20681 	 * @param  {SVGElement} outline
20682 	 * @param  {djs.model.Base} element
20683 	 */
20684 	Outline.prototype.updateShapeOutline = function(outline, element) {
20685 
20686 	  attr(outline, {
20687 	    x: -this.offset,
20688 	    y: -this.offset,
20689 	    width: element.width + this.offset * 2,
20690 	    height: element.height + this.offset * 2
20691 	  });
20692 
20693 	};
20694 
20695 
20696 	/**
20697 	 * Updates the outline of a connection respecting the bounding box of
20698 	 * the connection and an outline offset.
20699 	 *
20700 	 * @param  {SVGElement} outline
20701 	 * @param  {djs.model.Base} element
20702 	 */
20703 	Outline.prototype.updateConnectionOutline = function(outline, connection) {
20704 
20705 	  var bbox = getBBox(connection);
20706 
20707 	  attr(outline, {
20708 	    x: bbox.x - this.offset,
20709 	    y: bbox.y - this.offset,
20710 	    width: bbox.width + this.offset * 2,
20711 	    height: bbox.height + this.offset * 2
20712 	  });
20713 
20714 	};
20715 
20716 
20717 	Outline.$inject = ['eventBus', 'styles', 'elementRegistry'];
20718 
20719 	var OutlineModule = {
20720 	  __init__: [ 'outline' ],
20721 	  outline: [ 'type', Outline ]
20722 	};
20723 
20724 	/**
20725 	 * A service that offers the current selection in a diagram.
20726 	 * Offers the api to control the selection, too.
20727 	 *
20728 	 * @class
20729 	 *
20730 	 * @param {EventBus} eventBus the event bus
20731 	 */
20732 	function Selection(eventBus, canvas) {
20733 
20734 	  this._eventBus = eventBus;
20735 	  this._canvas = canvas;
20736 
20737 	  this._selectedElements = [];
20738 
20739 	  var self = this;
20740 
20741 	  eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
20742 	    var element = e.element;
20743 	    self.deselect(element);
20744 	  });
20745 
20746 	  eventBus.on([ 'diagram.clear', 'plane.set' ], function(e) {
20747 	    self.select(null);
20748 	  });
20749 	}
20750 
20751 	Selection.$inject = [ 'eventBus', 'canvas' ];
20752 
20753 
20754 	Selection.prototype.deselect = function(element) {
20755 	  var selectedElements = this._selectedElements;
20756 
20757 	  var idx = selectedElements.indexOf(element);
20758 
20759 	  if (idx !== -1) {
20760 	    var oldSelection = selectedElements.slice();
20761 
20762 	    selectedElements.splice(idx, 1);
20763 
20764 	    this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
20765 	  }
20766 	};
20767 
20768 
20769 	Selection.prototype.get = function() {
20770 	  return this._selectedElements;
20771 	};
20772 
20773 	Selection.prototype.isSelected = function(element) {
20774 	  return this._selectedElements.indexOf(element) !== -1;
20775 	};
20776 
20777 
20778 	/**
20779 	 * This method selects one or more elements on the diagram.
20780 	 *
20781 	 * By passing an additional add parameter you can decide whether or not the element(s)
20782 	 * should be added to the already existing selection or not.
20783 	 *
20784 	 * @method Selection#select
20785 	 *
20786 	 * @param  {Object|Object[]} elements element or array of elements to be selected
20787 	 * @param  {boolean} [add] whether the element(s) should be appended to the current selection, defaults to false
20788 	 */
20789 	Selection.prototype.select = function(elements, add) {
20790 	  var selectedElements = this._selectedElements,
20791 	      oldSelection = selectedElements.slice();
20792 
20793 	  if (!isArray$2(elements)) {
20794 	    elements = elements ? [ elements ] : [];
20795 	  }
20796 
20797 	  var canvas = this._canvas;
20798 
20799 	  elements = elements.filter(function(element) {
20800 	    var plane = canvas.findPlane(element);
20801 
20802 	    return plane === canvas.getActivePlane();
20803 	  });
20804 
20805 	  // selection may be cleared by passing an empty array or null
20806 	  // to the method
20807 	  if (add) {
20808 	    forEach(elements, function(element) {
20809 	      if (selectedElements.indexOf(element) !== -1) {
20810 
20811 	        // already selected
20812 	        return;
20813 	      } else {
20814 	        selectedElements.push(element);
20815 	      }
20816 	    });
20817 	  } else {
20818 	    this._selectedElements = selectedElements = elements.slice();
20819 	  }
20820 
20821 	  this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
20822 	};
20823 
20824 	var MARKER_HOVER = 'hover',
20825 	    MARKER_SELECTED = 'selected';
20826 
20827 
20828 	/**
20829 	 * A plugin that adds a visible selection UI to shapes and connections
20830 	 * by appending the <code>hover</code> and <code>selected</code> classes to them.
20831 	 *
20832 	 * @class
20833 	 *
20834 	 * Makes elements selectable, too.
20835 	 *
20836 	 * @param {EventBus} events
20837 	 * @param {SelectionService} selection
20838 	 * @param {Canvas} canvas
20839 	 */
20840 	function SelectionVisuals(events, canvas, selection, styles) {
20841 
20842 	  this._multiSelectionBox = null;
20843 
20844 	  function addMarker(e, cls) {
20845 	    canvas.addMarker(e, cls);
20846 	  }
20847 
20848 	  function removeMarker(e, cls) {
20849 	    canvas.removeMarker(e, cls);
20850 	  }
20851 
20852 	  events.on('element.hover', function(event) {
20853 	    addMarker(event.element, MARKER_HOVER);
20854 	  });
20855 
20856 	  events.on('element.out', function(event) {
20857 	    removeMarker(event.element, MARKER_HOVER);
20858 	  });
20859 
20860 	  events.on('selection.changed', function(event) {
20861 
20862 	    function deselect(s) {
20863 	      removeMarker(s, MARKER_SELECTED);
20864 	    }
20865 
20866 	    function select(s) {
20867 	      addMarker(s, MARKER_SELECTED);
20868 	    }
20869 
20870 	    var oldSelection = event.oldSelection,
20871 	        newSelection = event.newSelection;
20872 
20873 	    forEach(oldSelection, function(e) {
20874 	      if (newSelection.indexOf(e) === -1) {
20875 	        deselect(e);
20876 	      }
20877 	    });
20878 
20879 	    forEach(newSelection, function(e) {
20880 	      if (oldSelection.indexOf(e) === -1) {
20881 	        select(e);
20882 	      }
20883 	    });
20884 	  });
20885 	}
20886 
20887 	SelectionVisuals.$inject = [
20888 	  'eventBus',
20889 	  'canvas',
20890 	  'selection',
20891 	  'styles'
20892 	];
20893 
20894 	function SelectionBehavior(eventBus, selection, canvas, elementRegistry) {
20895 
20896 	  // Select elements on create
20897 	  eventBus.on('create.end', 500, function(event) {
20898 	    var context = event.context,
20899 	        canExecute = context.canExecute,
20900 	        elements = context.elements,
20901 	        hints = context.hints || {},
20902 	        autoSelect = hints.autoSelect;
20903 
20904 	    if (canExecute) {
20905 	      if (autoSelect === false) {
20906 
20907 	        // Select no elements
20908 	        return;
20909 	      }
20910 
20911 	      if (isArray$2(autoSelect)) {
20912 	        selection.select(autoSelect);
20913 	      } else {
20914 
20915 	        // Select all elements by default
20916 	        selection.select(elements.filter(isShown));
20917 	      }
20918 	    }
20919 	  });
20920 
20921 	  // Select connection targets on connect
20922 	  eventBus.on('connect.end', 500, function(event) {
20923 	    var context = event.context,
20924 	        canExecute = context.canExecute,
20925 	        hover = context.hover;
20926 
20927 	    if (canExecute && hover) {
20928 	      selection.select(hover);
20929 	    }
20930 	  });
20931 
20932 	  // Select shapes on move
20933 	  eventBus.on('shape.move.end', 500, function(event) {
20934 	    var previousSelection = event.previousSelection || [];
20935 
20936 	    var shape = elementRegistry.get(event.context.shape.id);
20937 
20938 	    // Always select main shape on move
20939 	    var isSelected = find(previousSelection, function(selectedShape) {
20940 	      return shape.id === selectedShape.id;
20941 	    });
20942 
20943 	    if (!isSelected) {
20944 	      selection.select(shape);
20945 	    }
20946 	  });
20947 
20948 	  // Select elements on click
20949 	  eventBus.on('element.click', function(event) {
20950 
20951 	    if (!isPrimaryButton(event)) {
20952 	      return;
20953 	    }
20954 
20955 	    var element = event.element;
20956 
20957 	    if (element === canvas.getRootElement()) {
20958 	      element = null;
20959 	    }
20960 
20961 	    var isSelected = selection.isSelected(element),
20962 	        isMultiSelect = selection.get().length > 1;
20963 
20964 	    // Add to selection if CTRL or SHIFT pressed
20965 	    var add = hasPrimaryModifier(event) || hasSecondaryModifier(event);
20966 
20967 	    if (isSelected && isMultiSelect) {
20968 	      if (add) {
20969 
20970 	        // Deselect element
20971 	        return selection.deselect(element);
20972 	      } else {
20973 
20974 	        // Select element only
20975 	        return selection.select(element);
20976 	      }
20977 	    } else if (!isSelected) {
20978 
20979 	      // Select element
20980 	      selection.select(element, add);
20981 	    } else {
20982 
20983 	      // Deselect element
20984 	      selection.deselect(element);
20985 	    }
20986 	  });
20987 	}
20988 
20989 	SelectionBehavior.$inject = [
20990 	  'eventBus',
20991 	  'selection',
20992 	  'canvas',
20993 	  'elementRegistry'
20994 	];
20995 
20996 
20997 	function isShown(element) {
20998 	  return !element.hidden;
20999 	}
21000 
21001 	var SelectionModule = {
21002 	  __init__: [ 'selectionVisuals', 'selectionBehavior' ],
21003 	  __depends__: [
21004 	    InteractionEventsModule$1,
21005 	    OutlineModule
21006 	  ],
21007 	  selection: [ 'type', Selection ],
21008 	  selectionVisuals: [ 'type', SelectionVisuals ],
21009 	  selectionBehavior: [ 'type', SelectionBehavior ]
21010 	};
21011 
21012 	/**
21013 	 * Util that provides unique IDs.
21014 	 *
21015 	 * @class djs.util.IdGenerator
21016 	 * @constructor
21017 	 * @memberOf djs.util
21018 	 *
21019 	 * The ids can be customized via a given prefix and contain a random value to avoid collisions.
21020 	 *
21021 	 * @param {string} prefix a prefix to prepend to generated ids (for better readability)
21022 	 */
21023 	function IdGenerator(prefix) {
21024 
21025 	  this._counter = 0;
21026 	  this._prefix = (prefix ? prefix + '-' : '') + Math.floor(Math.random() * 1000000000) + '-';
21027 	}
21028 
21029 	/**
21030 	 * Returns a next unique ID.
21031 	 *
21032 	 * @method djs.util.IdGenerator#next
21033 	 *
21034 	 * @returns {string} the id
21035 	 */
21036 	IdGenerator.prototype.next = function() {
21037 	  return this._prefix + (++this._counter);
21038 	};
21039 
21040 	// document wide unique overlay ids
21041 	var ids$1 = new IdGenerator('ov');
21042 
21043 	var LOW_PRIORITY$k = 500;
21044 
21045 
21046 	/**
21047 	 * A service that allows users to attach overlays to diagram elements.
21048 	 *
21049 	 * The overlay service will take care of overlay positioning during updates.
21050 	 *
21051 	 * @example
21052 	 *
21053 	 * // add a pink badge on the top left of the shape
21054 	 * overlays.add(someShape, {
21055 	 *   position: {
21056 	 *     top: -5,
21057 	 *     left: -5
21058 	 *   },
21059 	 *   html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
21060 	 * });
21061 	 *
21062 	 * // or add via shape id
21063 	 *
21064 	 * overlays.add('some-element-id', {
21065 	 *   position: {
21066 	 *     top: -5,
21067 	 *     left: -5
21068 	 *   }
21069 	 *   html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
21070 	 * });
21071 	 *
21072 	 * // or add with optional type
21073 	 *
21074 	 * overlays.add(someShape, 'badge', {
21075 	 *   position: {
21076 	 *     top: -5,
21077 	 *     left: -5
21078 	 *   }
21079 	 *   html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
21080 	 * });
21081 	 *
21082 	 *
21083 	 * // remove an overlay
21084 	 *
21085 	 * var id = overlays.add(...);
21086 	 * overlays.remove(id);
21087 	 *
21088 	 *
21089 	 * You may configure overlay defaults during tool by providing a `config` module
21090 	 * with `overlays.defaults` as an entry:
21091 	 *
21092 	 * {
21093 	 *   overlays: {
21094 	 *     defaults: {
21095 	 *       show: {
21096 	 *         minZoom: 0.7,
21097 	 *         maxZoom: 5.0
21098 	 *       },
21099 	 *       scale: {
21100 	 *         min: 1
21101 	 *       }
21102 	 *     }
21103 	 * }
21104 	 *
21105 	 * @param {Object} config
21106 	 * @param {EventBus} eventBus
21107 	 * @param {Canvas} canvas
21108 	 * @param {ElementRegistry} elementRegistry
21109 	 */
21110 	function Overlays(config, eventBus, canvas, elementRegistry) {
21111 
21112 	  this._eventBus = eventBus;
21113 	  this._canvas = canvas;
21114 	  this._elementRegistry = elementRegistry;
21115 
21116 	  this._ids = ids$1;
21117 
21118 	  this._overlayDefaults = assign({
21119 
21120 	    // no show constraints
21121 	    show: null,
21122 
21123 	    // always scale
21124 	    scale: true
21125 	  }, config && config.defaults);
21126 
21127 	  /**
21128 	   * Mapping overlayId -> overlay
21129 	   */
21130 	  this._overlays = {};
21131 
21132 	  /**
21133 	   * Mapping elementId -> overlay container
21134 	   */
21135 	  this._overlayContainers = [];
21136 
21137 	  // root html element for all overlays
21138 	  this._overlayRoot = createRoot$1(canvas.getContainer());
21139 
21140 	  this._init();
21141 	}
21142 
21143 
21144 	Overlays.$inject = [
21145 	  'config.overlays',
21146 	  'eventBus',
21147 	  'canvas',
21148 	  'elementRegistry'
21149 	];
21150 
21151 
21152 	/**
21153 	 * Returns the overlay with the specified id or a list of overlays
21154 	 * for an element with a given type.
21155 	 *
21156 	 * @example
21157 	 *
21158 	 * // return the single overlay with the given id
21159 	 * overlays.get('some-id');
21160 	 *
21161 	 * // return all overlays for the shape
21162 	 * overlays.get({ element: someShape });
21163 	 *
21164 	 * // return all overlays on shape with type 'badge'
21165 	 * overlays.get({ element: someShape, type: 'badge' });
21166 	 *
21167 	 * // shape can also be specified as id
21168 	 * overlays.get({ element: 'element-id', type: 'badge' });
21169 	 *
21170 	 *
21171 	 * @param {Object} search
21172 	 * @param {string} [search.id]
21173 	 * @param {string|djs.model.Base} [search.element]
21174 	 * @param {string} [search.type]
21175 	 *
21176 	 * @return {Object|Array<Object>} the overlay(s)
21177 	 */
21178 	Overlays.prototype.get = function(search) {
21179 
21180 	  if (isString(search)) {
21181 	    search = { id: search };
21182 	  }
21183 
21184 	  if (isString(search.element)) {
21185 	    search.element = this._elementRegistry.get(search.element);
21186 	  }
21187 
21188 	  if (search.element) {
21189 	    var container = this._getOverlayContainer(search.element, true);
21190 
21191 	    // return a list of overlays when searching by element (+type)
21192 	    if (container) {
21193 	      return search.type ? filter(container.overlays, matchPattern({ type: search.type })) : container.overlays.slice();
21194 	    } else {
21195 	      return [];
21196 	    }
21197 	  } else
21198 	  if (search.type) {
21199 	    return filter(this._overlays, matchPattern({ type: search.type }));
21200 	  } else {
21201 
21202 	    // return single element when searching by id
21203 	    return search.id ? this._overlays[search.id] : null;
21204 	  }
21205 	};
21206 
21207 	/**
21208 	 * Adds a HTML overlay to an element.
21209 	 *
21210 	 * @param {string|djs.model.Base}   element   attach overlay to this shape
21211 	 * @param {string}                  [type]    optional type to assign to the overlay
21212 	 * @param {Object}                  overlay   the overlay configuration
21213 	 *
21214 	 * @param {string|DOMElement}       overlay.html                 html element to use as an overlay
21215 	 * @param {Object}                  [overlay.show]               show configuration
21216 	 * @param {number}                  [overlay.show.minZoom]       minimal zoom level to show the overlay
21217 	 * @param {number}                  [overlay.show.maxZoom]       maximum zoom level to show the overlay
21218 	 * @param {Object}                  overlay.position             where to attach the overlay
21219 	 * @param {number}                  [overlay.position.left]      relative to element bbox left attachment
21220 	 * @param {number}                  [overlay.position.top]       relative to element bbox top attachment
21221 	 * @param {number}                  [overlay.position.bottom]    relative to element bbox bottom attachment
21222 	 * @param {number}                  [overlay.position.right]     relative to element bbox right attachment
21223 	 * @param {boolean|Object}          [overlay.scale=true]         false to preserve the same size regardless of
21224 	 *                                                               diagram zoom
21225 	 * @param {number}                  [overlay.scale.min]
21226 	 * @param {number}                  [overlay.scale.max]
21227 	 *
21228 	 * @return {string}                 id that may be used to reference the overlay for update or removal
21229 	 */
21230 	Overlays.prototype.add = function(element, type, overlay) {
21231 
21232 	  if (isObject(type)) {
21233 	    overlay = type;
21234 	    type = null;
21235 	  }
21236 
21237 	  if (!element.id) {
21238 	    element = this._elementRegistry.get(element);
21239 	  }
21240 
21241 	  if (!overlay.position) {
21242 	    throw new Error('must specifiy overlay position');
21243 	  }
21244 
21245 	  if (!overlay.html) {
21246 	    throw new Error('must specifiy overlay html');
21247 	  }
21248 
21249 	  if (!element) {
21250 	    throw new Error('invalid element specified');
21251 	  }
21252 
21253 	  var id = this._ids.next();
21254 
21255 	  overlay = assign({}, this._overlayDefaults, overlay, {
21256 	    id: id,
21257 	    type: type,
21258 	    element: element,
21259 	    html: overlay.html
21260 	  });
21261 
21262 	  this._addOverlay(overlay);
21263 
21264 	  return id;
21265 	};
21266 
21267 
21268 	/**
21269 	 * Remove an overlay with the given id or all overlays matching the given filter.
21270 	 *
21271 	 * @see Overlays#get for filter options.
21272 	 *
21273 	 * @param {string} [id]
21274 	 * @param {Object} [filter]
21275 	 */
21276 	Overlays.prototype.remove = function(filter) {
21277 
21278 	  var overlays = this.get(filter) || [];
21279 
21280 	  if (!isArray$2(overlays)) {
21281 	    overlays = [ overlays ];
21282 	  }
21283 
21284 	  var self = this;
21285 
21286 	  forEach(overlays, function(overlay) {
21287 
21288 	    var container = self._getOverlayContainer(overlay.element, true);
21289 
21290 	    if (overlay) {
21291 	      remove$2(overlay.html);
21292 	      remove$2(overlay.htmlContainer);
21293 
21294 	      delete overlay.htmlContainer;
21295 	      delete overlay.element;
21296 
21297 	      delete self._overlays[overlay.id];
21298 	    }
21299 
21300 	    if (container) {
21301 	      var idx = container.overlays.indexOf(overlay);
21302 	      if (idx !== -1) {
21303 	        container.overlays.splice(idx, 1);
21304 	      }
21305 	    }
21306 	  });
21307 
21308 	};
21309 
21310 
21311 	Overlays.prototype.show = function() {
21312 	  setVisible$1(this._overlayRoot);
21313 	};
21314 
21315 
21316 	Overlays.prototype.hide = function() {
21317 	  setVisible$1(this._overlayRoot, false);
21318 	};
21319 
21320 	Overlays.prototype.clear = function() {
21321 	  this._overlays = {};
21322 
21323 	  this._overlayContainers = [];
21324 
21325 	  clear$1(this._overlayRoot);
21326 	};
21327 
21328 	Overlays.prototype._updateOverlayContainer = function(container) {
21329 	  var element = container.element,
21330 	      html = container.html;
21331 
21332 	  // update container left,top according to the elements x,y coordinates
21333 	  // this ensures we can attach child elements relative to this container
21334 
21335 	  var x = element.x,
21336 	      y = element.y;
21337 
21338 	  if (element.waypoints) {
21339 	    var bbox = getBBox(element);
21340 	    x = bbox.x;
21341 	    y = bbox.y;
21342 	  }
21343 
21344 	  setPosition$1(html, x, y);
21345 
21346 	  attr$1(container.html, 'data-container-id', element.id);
21347 	};
21348 
21349 
21350 	Overlays.prototype._updateOverlay = function(overlay) {
21351 
21352 	  var position = overlay.position,
21353 	      htmlContainer = overlay.htmlContainer,
21354 	      element = overlay.element;
21355 
21356 	  // update overlay html relative to shape because
21357 	  // it is already positioned on the element
21358 
21359 	  // update relative
21360 	  var left = position.left,
21361 	      top = position.top;
21362 
21363 	  if (position.right !== undefined) {
21364 
21365 	    var width;
21366 
21367 	    if (element.waypoints) {
21368 	      width = getBBox(element).width;
21369 	    } else {
21370 	      width = element.width;
21371 	    }
21372 
21373 	    left = position.right * -1 + width;
21374 	  }
21375 
21376 	  if (position.bottom !== undefined) {
21377 
21378 	    var height;
21379 
21380 	    if (element.waypoints) {
21381 	      height = getBBox(element).height;
21382 	    } else {
21383 	      height = element.height;
21384 	    }
21385 
21386 	    top = position.bottom * -1 + height;
21387 	  }
21388 
21389 	  setPosition$1(htmlContainer, left || 0, top || 0);
21390 	};
21391 
21392 
21393 	Overlays.prototype._createOverlayContainer = function(element) {
21394 	  var html = domify('<div class="djs-overlays" style="position: absolute" />');
21395 
21396 	  this._overlayRoot.appendChild(html);
21397 
21398 	  var container = {
21399 	    html: html,
21400 	    element: element,
21401 	    overlays: []
21402 	  };
21403 
21404 	  this._updateOverlayContainer(container);
21405 
21406 	  this._overlayContainers.push(container);
21407 
21408 	  return container;
21409 	};
21410 
21411 
21412 	Overlays.prototype._updateRoot = function(viewbox) {
21413 	  var scale = viewbox.scale || 1;
21414 
21415 	  var matrix = 'matrix(' +
21416 	  [
21417 	    scale,
21418 	    0,
21419 	    0,
21420 	    scale,
21421 	    -1 * viewbox.x * scale,
21422 	    -1 * viewbox.y * scale
21423 	  ].join(',') +
21424 	  ')';
21425 
21426 	  setTransform$1(this._overlayRoot, matrix);
21427 	};
21428 
21429 
21430 	Overlays.prototype._getOverlayContainer = function(element, raw) {
21431 	  var container = find(this._overlayContainers, function(c) {
21432 	    return c.element === element;
21433 	  });
21434 
21435 
21436 	  if (!container && !raw) {
21437 	    return this._createOverlayContainer(element);
21438 	  }
21439 
21440 	  return container;
21441 	};
21442 
21443 
21444 	Overlays.prototype._addOverlay = function(overlay) {
21445 
21446 	  var id = overlay.id,
21447 	      element = overlay.element,
21448 	      html = overlay.html,
21449 	      htmlContainer,
21450 	      overlayContainer;
21451 
21452 	  // unwrap jquery (for those who need it)
21453 	  if (html.get && html.constructor.prototype.jquery) {
21454 	    html = html.get(0);
21455 	  }
21456 
21457 	  // create proper html elements from
21458 	  // overlay HTML strings
21459 	  if (isString(html)) {
21460 	    html = domify(html);
21461 	  }
21462 
21463 	  overlayContainer = this._getOverlayContainer(element);
21464 
21465 	  htmlContainer = domify('<div class="djs-overlay" data-overlay-id="' + id + '" style="position: absolute">');
21466 
21467 	  htmlContainer.appendChild(html);
21468 
21469 	  if (overlay.type) {
21470 	    classes$1(htmlContainer).add('djs-overlay-' + overlay.type);
21471 	  }
21472 
21473 	  var plane = this._canvas.findPlane(element);
21474 	  var activePlane = this._canvas.getActivePlane();
21475 	  overlay.plane = plane;
21476 	  if (plane !== activePlane) {
21477 	    setVisible$1(htmlContainer, false);
21478 	  }
21479 
21480 	  overlay.htmlContainer = htmlContainer;
21481 
21482 	  overlayContainer.overlays.push(overlay);
21483 	  overlayContainer.html.appendChild(htmlContainer);
21484 
21485 	  this._overlays[id] = overlay;
21486 
21487 	  this._updateOverlay(overlay);
21488 	  this._updateOverlayVisibilty(overlay, this._canvas.viewbox());
21489 	};
21490 
21491 
21492 	Overlays.prototype._updateOverlayVisibilty = function(overlay, viewbox) {
21493 	  var show = overlay.show,
21494 	      minZoom = show && show.minZoom,
21495 	      maxZoom = show && show.maxZoom,
21496 	      htmlContainer = overlay.htmlContainer,
21497 	      visible = true;
21498 
21499 	  if (show) {
21500 	    if (
21501 	      (isDefined(minZoom) && minZoom > viewbox.scale) ||
21502 	      (isDefined(maxZoom) && maxZoom < viewbox.scale)
21503 	    ) {
21504 	      visible = false;
21505 	    }
21506 
21507 	    setVisible$1(htmlContainer, visible);
21508 	  }
21509 
21510 	  this._updateOverlayScale(overlay, viewbox);
21511 	};
21512 
21513 
21514 	Overlays.prototype._updateOverlayScale = function(overlay, viewbox) {
21515 	  var shouldScale = overlay.scale,
21516 	      minScale,
21517 	      maxScale,
21518 	      htmlContainer = overlay.htmlContainer;
21519 
21520 	  var scale, transform = '';
21521 
21522 	  if (shouldScale !== true) {
21523 
21524 	    if (shouldScale === false) {
21525 	      minScale = 1;
21526 	      maxScale = 1;
21527 	    } else {
21528 	      minScale = shouldScale.min;
21529 	      maxScale = shouldScale.max;
21530 	    }
21531 
21532 	    if (isDefined(minScale) && viewbox.scale < minScale) {
21533 	      scale = (1 / viewbox.scale || 1) * minScale;
21534 	    }
21535 
21536 	    if (isDefined(maxScale) && viewbox.scale > maxScale) {
21537 	      scale = (1 / viewbox.scale || 1) * maxScale;
21538 	    }
21539 	  }
21540 
21541 	  if (isDefined(scale)) {
21542 	    transform = 'scale(' + scale + ',' + scale + ')';
21543 	  }
21544 
21545 	  setTransform$1(htmlContainer, transform);
21546 	};
21547 
21548 
21549 	Overlays.prototype._updateOverlaysVisibilty = function(viewbox) {
21550 
21551 	  var self = this;
21552 
21553 	  forEach(this._overlays, function(overlay) {
21554 	    self._updateOverlayVisibilty(overlay, viewbox);
21555 	  });
21556 	};
21557 
21558 
21559 	Overlays.prototype._init = function() {
21560 
21561 	  var eventBus = this._eventBus;
21562 
21563 	  var self = this;
21564 
21565 
21566 	  // scroll/zoom integration
21567 
21568 	  function updateViewbox(viewbox) {
21569 	    self._updateRoot(viewbox);
21570 	    self._updateOverlaysVisibilty(viewbox);
21571 
21572 	    self.show();
21573 	  }
21574 
21575 	  eventBus.on('canvas.viewbox.changing', function(event) {
21576 	    self.hide();
21577 	  });
21578 
21579 	  eventBus.on('canvas.viewbox.changed', function(event) {
21580 	    updateViewbox(event.viewbox);
21581 	  });
21582 
21583 
21584 	  // remove integration
21585 
21586 	  eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
21587 	    var element = e.element;
21588 	    var overlays = self.get({ element: element });
21589 
21590 	    forEach(overlays, function(o) {
21591 	      self.remove(o.id);
21592 	    });
21593 
21594 	    var container = self._getOverlayContainer(element);
21595 
21596 	    if (container) {
21597 	      remove$2(container.html);
21598 	      var i = self._overlayContainers.indexOf(container);
21599 	      if (i !== -1) {
21600 	        self._overlayContainers.splice(i, 1);
21601 	      }
21602 	    }
21603 	  });
21604 
21605 
21606 	  // move integration
21607 
21608 	  eventBus.on('element.changed', LOW_PRIORITY$k, function(e) {
21609 	    var element = e.element;
21610 
21611 	    var container = self._getOverlayContainer(element, true);
21612 
21613 	    if (container) {
21614 	      forEach(container.overlays, function(overlay) {
21615 	        self._updateOverlay(overlay);
21616 	      });
21617 
21618 	      self._updateOverlayContainer(container);
21619 	    }
21620 	  });
21621 
21622 
21623 	  // marker integration, simply add them on the overlays as classes, too.
21624 
21625 	  eventBus.on('element.marker.update', function(e) {
21626 	    var container = self._getOverlayContainer(e.element, true);
21627 	    if (container) {
21628 	      classes$1(container.html)[e.add ? 'add' : 'remove'](e.marker);
21629 	    }
21630 	  });
21631 
21632 
21633 	  eventBus.on('plane.set', function(e) {
21634 	    forEach(self._overlays, function(el) {
21635 	      setVisible$1(el.htmlContainer, el.plane === e.plane);
21636 	    });
21637 	  });
21638 
21639 	  // clear overlays with diagram
21640 
21641 	  eventBus.on('diagram.clear', this.clear, this);
21642 	};
21643 
21644 
21645 
21646 	// helpers /////////////////////////////
21647 
21648 	function createRoot$1(parentNode) {
21649 	  var root = domify(
21650 	    '<div class="djs-overlay-container" style="position: absolute; width: 0; height: 0;" />'
21651 	  );
21652 
21653 	  parentNode.insertBefore(root, parentNode.firstChild);
21654 
21655 	  return root;
21656 	}
21657 
21658 	function setPosition$1(el, x, y) {
21659 	  assign(el.style, { left: x + 'px', top: y + 'px' });
21660 	}
21661 
21662 	function setVisible$1(el, visible) {
21663 	  el.style.display = visible === false ? 'none' : '';
21664 	}
21665 
21666 	function setTransform$1(el, transform) {
21667 
21668 	  el.style['transform-origin'] = 'top left';
21669 
21670 	  [ '', '-ms-', '-webkit-' ].forEach(function(prefix) {
21671 	    el.style[prefix + 'transform'] = transform;
21672 	  });
21673 	}
21674 
21675 	var OverlaysModule = {
21676 	  __init__: [ 'overlays' ],
21677 	  overlays: [ 'type', Overlays ]
21678 	};
21679 
21680 	/**
21681 	 * A viewer for BPMN 2.0 diagrams.
21682 	 *
21683 	 * Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include
21684 	 * additional features.
21685 	 *
21686 	 *
21687 	 * ## Extending the Viewer
21688 	 *
21689 	 * In order to extend the viewer pass extension modules to bootstrap via the
21690 	 * `additionalModules` option. An extension module is an object that exposes
21691 	 * named services.
21692 	 *
21693 	 * The following example depicts the integration of a simple
21694 	 * logging component that integrates with interaction events:
21695 	 *
21696 	 *
21697 	 * ```javascript
21698 	 *
21699 	 * // logging component
21700 	 * function InteractionLogger(eventBus) {
21701 	 *   eventBus.on('element.hover', function(event) {
21702 	 *     console.log()
21703 	 *   })
21704 	 * }
21705 	 *
21706 	 * InteractionLogger.$inject = [ 'eventBus' ]; // minification save
21707 	 *
21708 	 * // extension module
21709 	 * var extensionModule = {
21710 	 *   __init__: [ 'interactionLogger' ],
21711 	 *   interactionLogger: [ 'type', InteractionLogger ]
21712 	 * };
21713 	 *
21714 	 * // extend the viewer
21715 	 * var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] });
21716 	 * bpmnViewer.importXML(...);
21717 	 * ```
21718 	 *
21719 	 * @param {Object} [options] configuration options to pass to the viewer
21720 	 * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
21721 	 * @param {string|number} [options.width] the width of the viewer
21722 	 * @param {string|number} [options.height] the height of the viewer
21723 	 * @param {Object} [options.moddleExtensions] extension packages to provide
21724 	 * @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
21725 	 * @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
21726 	 */
21727 	function Viewer(options) {
21728 	  BaseViewer.call(this, options);
21729 	}
21730 
21731 	inherits$1(Viewer, BaseViewer);
21732 
21733 	// modules the viewer is composed of
21734 	Viewer.prototype._modules = [
21735 	  CoreModule,
21736 	  translate,
21737 	  SelectionModule,
21738 	  OverlaysModule
21739 	];
21740 
21741 	// default moddle extensions the viewer is composed of
21742 	Viewer.prototype._moddleExtensions = {};
21743 
21744 	/**
21745 	 * Returns true if event was triggered with any modifier
21746 	 * @param {KeyboardEvent} event
21747 	 */
21748 	function hasModifier(event) {
21749 	  return (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey);
21750 	}
21751 
21752 	/**
21753 	 * @param {KeyboardEvent} event
21754 	 */
21755 	function isCmd(event) {
21756 
21757 	  // ensure we don't react to AltGr
21758 	  // (mapped to CTRL + ALT)
21759 	  if (event.altKey) {
21760 	    return false;
21761 	  }
21762 
21763 	  return event.ctrlKey || event.metaKey;
21764 	}
21765 
21766 	/**
21767 	 * Checks if key pressed is one of provided keys.
21768 	 *
21769 	 * @param {string|Array<string>} keys
21770 	 * @param {KeyboardEvent} event
21771 	 */
21772 	function isKey(keys, event) {
21773 	  keys = isArray$2(keys) ? keys : [ keys ];
21774 
21775 	  return keys.indexOf(event.key) !== -1 || keys.indexOf(event.keyCode) !== -1;
21776 	}
21777 
21778 	/**
21779 	 * @param {KeyboardEvent} event
21780 	 */
21781 	function isShift(event) {
21782 	  return event.shiftKey;
21783 	}
21784 
21785 	var KEYDOWN_EVENT = 'keyboard.keydown',
21786 	    KEYUP_EVENT = 'keyboard.keyup';
21787 
21788 	var HANDLE_MODIFIER_ATTRIBUTE = 'input-handle-modified-keys';
21789 
21790 	var DEFAULT_PRIORITY$4 = 1000;
21791 
21792 	/**
21793 	 * A keyboard abstraction that may be activated and
21794 	 * deactivated by users at will, consuming key events
21795 	 * and triggering diagram actions.
21796 	 *
21797 	 * For keys pressed down, keyboard fires `keyboard.keydown` event.
21798 	 * The event context contains one field which is `KeyboardEvent` event.
21799 	 *
21800 	 * The implementation fires the following key events that allow
21801 	 * other components to hook into key handling:
21802 	 *
21803 	 *  - keyboard.bind
21804 	 *  - keyboard.unbind
21805 	 *  - keyboard.init
21806 	 *  - keyboard.destroy
21807 	 *
21808 	 * All events contain one field which is node.
21809 	 *
21810 	 * A default binding for the keyboard may be specified via the
21811 	 * `keyboard.bindTo` configuration option.
21812 	 *
21813 	 * @param {Config} config
21814 	 * @param {EventBus} eventBus
21815 	 */
21816 	function Keyboard(config, eventBus) {
21817 	  var self = this;
21818 
21819 	  this._config = config || {};
21820 	  this._eventBus = eventBus;
21821 
21822 	  this._keydownHandler = this._keydownHandler.bind(this);
21823 	  this._keyupHandler = this._keyupHandler.bind(this);
21824 
21825 	  // properly clean dom registrations
21826 	  eventBus.on('diagram.destroy', function() {
21827 	    self._fire('destroy');
21828 
21829 	    self.unbind();
21830 	  });
21831 
21832 	  eventBus.on('diagram.init', function() {
21833 	    self._fire('init');
21834 	  });
21835 
21836 	  eventBus.on('attach', function() {
21837 	    if (config && config.bindTo) {
21838 	      self.bind(config.bindTo);
21839 	    }
21840 	  });
21841 
21842 	  eventBus.on('detach', function() {
21843 	    self.unbind();
21844 	  });
21845 	}
21846 
21847 	Keyboard.$inject = [
21848 	  'config.keyboard',
21849 	  'eventBus'
21850 	];
21851 
21852 	Keyboard.prototype._keydownHandler = function(event) {
21853 	  this._keyHandler(event, KEYDOWN_EVENT);
21854 	};
21855 
21856 	Keyboard.prototype._keyupHandler = function(event) {
21857 	  this._keyHandler(event, KEYUP_EVENT);
21858 	};
21859 
21860 	Keyboard.prototype._keyHandler = function(event, type) {
21861 	  var eventBusResult;
21862 
21863 	  if (this._isEventIgnored(event)) {
21864 	    return;
21865 	  }
21866 
21867 	  var context = {
21868 	    keyEvent: event
21869 	  };
21870 
21871 	  eventBusResult = this._eventBus.fire(type || KEYDOWN_EVENT, context);
21872 
21873 	  if (eventBusResult) {
21874 	    event.preventDefault();
21875 	  }
21876 	};
21877 
21878 	Keyboard.prototype._isEventIgnored = function(event) {
21879 	  return isInput(event.target) && this._isModifiedKeyIgnored(event);
21880 	};
21881 
21882 	Keyboard.prototype._isModifiedKeyIgnored = function(event) {
21883 	  if (!isCmd(event)) {
21884 	    return true;
21885 	  }
21886 
21887 	  var allowedModifiers = this._getAllowedModifiers(event.target);
21888 	  return !allowedModifiers.includes(event.key);
21889 	};
21890 
21891 	Keyboard.prototype._getAllowedModifiers = function(element) {
21892 	  var modifierContainer = closest(element, '[' + HANDLE_MODIFIER_ATTRIBUTE + ']', true);
21893 
21894 	  if (!modifierContainer || (this._node && !this._node.contains(modifierContainer))) {
21895 	    return [];
21896 	  }
21897 
21898 	  return modifierContainer.getAttribute(HANDLE_MODIFIER_ATTRIBUTE).split(',');
21899 	};
21900 
21901 	Keyboard.prototype.bind = function(node) {
21902 
21903 	  // make sure that the keyboard is only bound once to the DOM
21904 	  this.unbind();
21905 
21906 	  this._node = node;
21907 
21908 	  // bind key events
21909 	  componentEvent.bind(node, 'keydown', this._keydownHandler, true);
21910 	  componentEvent.bind(node, 'keyup', this._keyupHandler, true);
21911 
21912 	  this._fire('bind');
21913 	};
21914 
21915 	Keyboard.prototype.getBinding = function() {
21916 	  return this._node;
21917 	};
21918 
21919 	Keyboard.prototype.unbind = function() {
21920 	  var node = this._node;
21921 
21922 	  if (node) {
21923 	    this._fire('unbind');
21924 
21925 	    // unbind key events
21926 	    componentEvent.unbind(node, 'keydown', this._keydownHandler, true);
21927 	    componentEvent.unbind(node, 'keyup', this._keyupHandler, true);
21928 	  }
21929 
21930 	  this._node = null;
21931 	};
21932 
21933 	Keyboard.prototype._fire = function(event) {
21934 	  this._eventBus.fire('keyboard.' + event, { node: this._node });
21935 	};
21936 
21937 	/**
21938 	 * Add a listener function that is notified with `KeyboardEvent` whenever
21939 	 * the keyboard is bound and the user presses a key. If no priority is
21940 	 * provided, the default value of 1000 is used.
21941 	 *
21942 	 * @param {number} [priority]
21943 	 * @param {Function} listener
21944 	 * @param {string} type
21945 	 */
21946 	Keyboard.prototype.addListener = function(priority, listener, type) {
21947 	  if (isFunction(priority)) {
21948 	    type = listener;
21949 	    listener = priority;
21950 	    priority = DEFAULT_PRIORITY$4;
21951 	  }
21952 
21953 	  this._eventBus.on(type || KEYDOWN_EVENT, priority, listener);
21954 	};
21955 
21956 	Keyboard.prototype.removeListener = function(listener, type) {
21957 	  this._eventBus.off(type || KEYDOWN_EVENT, listener);
21958 	};
21959 
21960 	Keyboard.prototype.hasModifier = hasModifier;
21961 	Keyboard.prototype.isCmd = isCmd;
21962 	Keyboard.prototype.isShift = isShift;
21963 	Keyboard.prototype.isKey = isKey;
21964 
21965 
21966 
21967 	// helpers ///////
21968 
21969 	function isInput(target) {
21970 	  return target && (matchesSelector(target, 'input, textarea') || target.contentEditable === 'true');
21971 	}
21972 
21973 	var LOW_PRIORITY$j = 500;
21974 
21975 	var KEYCODE_C = 67;
21976 	var KEYCODE_V = 86;
21977 	var KEYCODE_Y = 89;
21978 	var KEYCODE_Z = 90;
21979 
21980 	var KEYS_COPY = ['c', 'C', KEYCODE_C ];
21981 	var KEYS_PASTE = [ 'v', 'V', KEYCODE_V ];
21982 	var KEYS_REDO = [ 'y', 'Y', KEYCODE_Y ];
21983 	var KEYS_UNDO = [ 'z', 'Z', KEYCODE_Z ];
21984 
21985 
21986 	/**
21987 	 * Adds default keyboard bindings.
21988 	 *
21989 	 * This does not pull in any features will bind only actions that
21990 	 * have previously been registered against the editorActions component.
21991 	 *
21992 	 * @param {EventBus} eventBus
21993 	 * @param {Keyboard} keyboard
21994 	 */
21995 	function KeyboardBindings(eventBus, keyboard) {
21996 
21997 	  var self = this;
21998 
21999 	  eventBus.on('editorActions.init', LOW_PRIORITY$j, function(event) {
22000 
22001 	    var editorActions = event.editorActions;
22002 
22003 	    self.registerBindings(keyboard, editorActions);
22004 	  });
22005 	}
22006 
22007 	KeyboardBindings.$inject = [
22008 	  'eventBus',
22009 	  'keyboard'
22010 	];
22011 
22012 
22013 	/**
22014 	 * Register available keyboard bindings.
22015 	 *
22016 	 * @param {Keyboard} keyboard
22017 	 * @param {EditorActions} editorActions
22018 	 */
22019 	KeyboardBindings.prototype.registerBindings = function(keyboard, editorActions) {
22020 
22021 	  /**
22022 	   * Add keyboard binding if respective editor action
22023 	   * is registered.
22024 	   *
22025 	   * @param {string} action name
22026 	   * @param {Function} fn that implements the key binding
22027 	   */
22028 	  function addListener(action, fn) {
22029 
22030 	    if (editorActions.isRegistered(action)) {
22031 	      keyboard.addListener(fn);
22032 	    }
22033 	  }
22034 
22035 
22036 	  // undo
22037 	  // (CTRL|CMD) + Z
22038 	  addListener('undo', function(context) {
22039 
22040 	    var event = context.keyEvent;
22041 
22042 	    if (isCmd(event) && !isShift(event) && isKey(KEYS_UNDO, event)) {
22043 	      editorActions.trigger('undo');
22044 
22045 	      return true;
22046 	    }
22047 	  });
22048 
22049 	  // redo
22050 	  // CTRL + Y
22051 	  // CMD + SHIFT + Z
22052 	  addListener('redo', function(context) {
22053 
22054 	    var event = context.keyEvent;
22055 
22056 	    if (isCmd(event) && (isKey(KEYS_REDO, event) || (isKey(KEYS_UNDO, event) && isShift(event)))) {
22057 	      editorActions.trigger('redo');
22058 
22059 	      return true;
22060 	    }
22061 	  });
22062 
22063 	  // copy
22064 	  // CTRL/CMD + C
22065 	  addListener('copy', function(context) {
22066 
22067 	    var event = context.keyEvent;
22068 
22069 	    if (isCmd(event) && isKey(KEYS_COPY, event)) {
22070 	      editorActions.trigger('copy');
22071 
22072 	      return true;
22073 	    }
22074 	  });
22075 
22076 	  // paste
22077 	  // CTRL/CMD + V
22078 	  addListener('paste', function(context) {
22079 
22080 	    var event = context.keyEvent;
22081 
22082 	    if (isCmd(event) && isKey(KEYS_PASTE, event)) {
22083 	      editorActions.trigger('paste');
22084 
22085 	      return true;
22086 	    }
22087 	  });
22088 
22089 	  // zoom in one step
22090 	  // CTRL/CMD + +
22091 	  addListener('stepZoom', function(context) {
22092 
22093 	    var event = context.keyEvent;
22094 
22095 	    // quirk: it has to be triggered by `=` as well to work on international keyboard layout
22096 	    // cf: https://github.com/bpmn-io/bpmn-js/issues/1362#issuecomment-722989754
22097 	    if (isKey([ '+', 'Add', '=' ], event) && isCmd(event)) {
22098 	      editorActions.trigger('stepZoom', { value: 1 });
22099 
22100 	      return true;
22101 	    }
22102 	  });
22103 
22104 	  // zoom out one step
22105 	  // CTRL + -
22106 	  addListener('stepZoom', function(context) {
22107 
22108 	    var event = context.keyEvent;
22109 
22110 	    if (isKey([ '-', 'Subtract' ], event) && isCmd(event)) {
22111 	      editorActions.trigger('stepZoom', { value: -1 });
22112 
22113 	      return true;
22114 	    }
22115 	  });
22116 
22117 	  // zoom to the default level
22118 	  // CTRL + 0
22119 	  addListener('zoom', function(context) {
22120 
22121 	    var event = context.keyEvent;
22122 
22123 	    if (isKey('0', event) && isCmd(event)) {
22124 	      editorActions.trigger('zoom', { value: 1 });
22125 
22126 	      return true;
22127 	    }
22128 	  });
22129 
22130 	  // delete selected element
22131 	  // DEL
22132 	  addListener('removeSelection', function(context) {
22133 
22134 	    var event = context.keyEvent;
22135 
22136 	    if (isKey(['Backspace', 'Delete', 'Del' ], event)) {
22137 	      editorActions.trigger('removeSelection');
22138 
22139 	      return true;
22140 	    }
22141 	  });
22142 	};
22143 
22144 	var KeyboardModule$1 = {
22145 	  __init__: [ 'keyboard', 'keyboardBindings' ],
22146 	  keyboard: [ 'type', Keyboard ],
22147 	  keyboardBindings: [ 'type', KeyboardBindings ]
22148 	};
22149 
22150 	var DEFAULT_CONFIG$1 = {
22151 	  moveSpeed: 50,
22152 	  moveSpeedAccelerated: 200
22153 	};
22154 
22155 
22156 	/**
22157 	 * A feature that allows users to move the canvas using the keyboard.
22158 	 *
22159 	 * @param {Object} config
22160 	 * @param {number} [config.moveSpeed=50]
22161 	 * @param {number} [config.moveSpeedAccelerated=200]
22162 	 * @param {Keyboard} keyboard
22163 	 * @param {Canvas} canvas
22164 	 */
22165 	function KeyboardMove(
22166 	    config,
22167 	    keyboard,
22168 	    canvas
22169 	) {
22170 
22171 	  var self = this;
22172 
22173 	  this._config = assign({}, DEFAULT_CONFIG$1, config || {});
22174 
22175 	  keyboard.addListener(arrowsListener);
22176 
22177 
22178 	  function arrowsListener(context) {
22179 
22180 	    var event = context.keyEvent,
22181 	        config = self._config;
22182 
22183 	    if (!keyboard.isCmd(event)) {
22184 	      return;
22185 	    }
22186 
22187 	    if (keyboard.isKey([
22188 	      'ArrowLeft', 'Left',
22189 	      'ArrowUp', 'Up',
22190 	      'ArrowDown', 'Down',
22191 	      'ArrowRight', 'Right'
22192 	    ], event)) {
22193 
22194 	      var speed = (
22195 	        keyboard.isShift(event) ?
22196 	          config.moveSpeedAccelerated :
22197 	          config.moveSpeed
22198 	      );
22199 
22200 	      var direction;
22201 
22202 	      switch (event.key) {
22203 	      case 'ArrowLeft':
22204 	      case 'Left':
22205 	        direction = 'left';
22206 	        break;
22207 	      case 'ArrowUp':
22208 	      case 'Up':
22209 	        direction = 'up';
22210 	        break;
22211 	      case 'ArrowRight':
22212 	      case 'Right':
22213 	        direction = 'right';
22214 	        break;
22215 	      case 'ArrowDown':
22216 	      case 'Down':
22217 	        direction = 'down';
22218 	        break;
22219 	      }
22220 
22221 	      self.moveCanvas({
22222 	        speed: speed,
22223 	        direction: direction
22224 	      });
22225 
22226 	      return true;
22227 	    }
22228 	  }
22229 
22230 	  this.moveCanvas = function(opts) {
22231 
22232 	    var dx = 0,
22233 	        dy = 0,
22234 	        speed = opts.speed;
22235 
22236 	    var actualSpeed = speed / Math.min(Math.sqrt(canvas.viewbox().scale), 1);
22237 
22238 	    switch (opts.direction) {
22239 	    case 'left': // Left
22240 	      dx = actualSpeed;
22241 	      break;
22242 	    case 'up': // Up
22243 	      dy = actualSpeed;
22244 	      break;
22245 	    case 'right': // Right
22246 	      dx = -actualSpeed;
22247 	      break;
22248 	    case 'down': // Down
22249 	      dy = -actualSpeed;
22250 	      break;
22251 	    }
22252 
22253 	    canvas.scroll({
22254 	      dx: dx,
22255 	      dy: dy
22256 	    });
22257 	  };
22258 
22259 	}
22260 
22261 
22262 	KeyboardMove.$inject = [
22263 	  'config.keyboardMove',
22264 	  'keyboard',
22265 	  'canvas'
22266 	];
22267 
22268 	var KeyboardMoveModule = {
22269 	  __depends__: [
22270 	    KeyboardModule$1
22271 	  ],
22272 	  __init__: [ 'keyboardMove' ],
22273 	  keyboardMove: [ 'type', KeyboardMove ]
22274 	};
22275 
22276 	var CURSOR_CLS_PATTERN = /^djs-cursor-.*$/;
22277 
22278 
22279 	function set(mode) {
22280 	  var classes = classes$1(document.body);
22281 
22282 	  classes.removeMatching(CURSOR_CLS_PATTERN);
22283 
22284 	  if (mode) {
22285 	    classes.add('djs-cursor-' + mode);
22286 	  }
22287 	}
22288 
22289 	function unset() {
22290 	  set(null);
22291 	}
22292 
22293 	var TRAP_PRIORITY = 5000;
22294 
22295 	/**
22296 	 * Installs a click trap that prevents a ghost click following a dragging operation.
22297 	 *
22298 	 * @return {Function} a function to immediately remove the installed trap.
22299 	 */
22300 	function install(eventBus, eventName) {
22301 
22302 	  eventName = eventName || 'element.click';
22303 
22304 	  function trap() {
22305 	    return false;
22306 	  }
22307 
22308 	  eventBus.once(eventName, TRAP_PRIORITY, trap);
22309 
22310 	  return function() {
22311 	    eventBus.off(eventName, trap);
22312 	  };
22313 	}
22314 
22315 	function center(bounds) {
22316 	  return {
22317 	    x: bounds.x + (bounds.width / 2),
22318 	    y: bounds.y + (bounds.height / 2)
22319 	  };
22320 	}
22321 
22322 
22323 	function delta(a, b) {
22324 	  return {
22325 	    x: a.x - b.x,
22326 	    y: a.y - b.y
22327 	  };
22328 	}
22329 
22330 	var THRESHOLD$1 = 15;
22331 
22332 
22333 	/**
22334 	 * Move the canvas via mouse.
22335 	 *
22336 	 * @param {EventBus} eventBus
22337 	 * @param {Canvas} canvas
22338 	 */
22339 	function MoveCanvas(eventBus, canvas) {
22340 
22341 	  var context;
22342 
22343 
22344 	  // listen for move on element mouse down;
22345 	  // allow others to hook into the event before us though
22346 	  // (dragging / element moving will do this)
22347 	  eventBus.on('element.mousedown', 500, function(e) {
22348 	    return handleStart(e.originalEvent);
22349 	  });
22350 
22351 
22352 	  function handleMove(event) {
22353 
22354 	    var start = context.start,
22355 	        button = context.button,
22356 	        position = toPoint(event),
22357 	        delta$1 = delta(position, start);
22358 
22359 	    if (!context.dragging && length(delta$1) > THRESHOLD$1) {
22360 	      context.dragging = true;
22361 
22362 	      if (button === 0) {
22363 	        install(eventBus);
22364 	      }
22365 
22366 	      set('grab');
22367 	    }
22368 
22369 	    if (context.dragging) {
22370 
22371 	      var lastPosition = context.last || context.start;
22372 
22373 	      delta$1 = delta(position, lastPosition);
22374 
22375 	      canvas.scroll({
22376 	        dx: delta$1.x,
22377 	        dy: delta$1.y
22378 	      });
22379 
22380 	      context.last = position;
22381 	    }
22382 
22383 	    // prevent select
22384 	    event.preventDefault();
22385 	  }
22386 
22387 
22388 	  function handleEnd(event) {
22389 	    componentEvent.unbind(document, 'mousemove', handleMove);
22390 	    componentEvent.unbind(document, 'mouseup', handleEnd);
22391 
22392 	    context = null;
22393 
22394 	    unset();
22395 	  }
22396 
22397 	  function handleStart(event) {
22398 
22399 	    // event is already handled by '.djs-draggable'
22400 	    if (closest(event.target, '.djs-draggable')) {
22401 	      return;
22402 	    }
22403 
22404 	    var button = event.button;
22405 
22406 	    // reject right mouse button or modifier key
22407 	    if (button >= 2 || event.ctrlKey || event.shiftKey || event.altKey) {
22408 	      return;
22409 	    }
22410 
22411 	    context = {
22412 	      button: button,
22413 	      start: toPoint(event)
22414 	    };
22415 
22416 	    componentEvent.bind(document, 'mousemove', handleMove);
22417 	    componentEvent.bind(document, 'mouseup', handleEnd);
22418 
22419 	    // we've handled the event
22420 	    return true;
22421 	  }
22422 
22423 	  this.isActive = function() {
22424 	    return !!context;
22425 	  };
22426 
22427 	}
22428 
22429 
22430 	MoveCanvas.$inject = [
22431 	  'eventBus',
22432 	  'canvas'
22433 	];
22434 
22435 
22436 
22437 	// helpers ///////
22438 
22439 	function length(point) {
22440 	  return Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
22441 	}
22442 
22443 	var MoveCanvasModule = {
22444 	  __init__: [ 'moveCanvas' ],
22445 	  moveCanvas: [ 'type', MoveCanvas ]
22446 	};
22447 
22448 	/**
22449 	 * Get the logarithm of x with base 10
22450 	 * @param  {Integer} value
22451 	 */
22452 	function log10(x) {
22453 	  return Math.log(x) / Math.log(10);
22454 	}
22455 
22456 	/**
22457 	 * Get step size for given range and number of steps.
22458 	 *
22459 	 * @param {Object} range
22460 	 * @param {number} range.min
22461 	 * @param {number} range.max
22462 	 */
22463 	function getStepSize(range, steps) {
22464 
22465 	  var minLinearRange = log10(range.min),
22466 	      maxLinearRange = log10(range.max);
22467 
22468 	  var absoluteLinearRange = Math.abs(minLinearRange) + Math.abs(maxLinearRange);
22469 
22470 	  return absoluteLinearRange / steps;
22471 	}
22472 
22473 	function cap(range, scale) {
22474 	  return Math.max(range.min, Math.min(range.max, scale));
22475 	}
22476 
22477 	var sign = Math.sign || function(n) {
22478 	  return n >= 0 ? 1 : -1;
22479 	};
22480 
22481 	var RANGE = { min: 0.2, max: 4 },
22482 	    NUM_STEPS = 10;
22483 
22484 	var DELTA_THRESHOLD = 0.1;
22485 
22486 	var DEFAULT_SCALE = 0.75;
22487 
22488 	/**
22489 	 * An implementation of zooming and scrolling within the
22490 	 * {@link Canvas} via the mouse wheel.
22491 	 *
22492 	 * Mouse wheel zooming / scrolling may be disabled using
22493 	 * the {@link toggle(enabled)} method.
22494 	 *
22495 	 * @param {Object} [config]
22496 	 * @param {boolean} [config.enabled=true] default enabled state
22497 	 * @param {number} [config.scale=.75] scroll sensivity
22498 	 * @param {EventBus} eventBus
22499 	 * @param {Canvas} canvas
22500 	 */
22501 	function ZoomScroll(config, eventBus, canvas) {
22502 
22503 	  config = config || {};
22504 
22505 	  this._enabled = false;
22506 
22507 	  this._canvas = canvas;
22508 	  this._container = canvas._container;
22509 
22510 	  this._handleWheel = bind$2(this._handleWheel, this);
22511 
22512 	  this._totalDelta = 0;
22513 	  this._scale = config.scale || DEFAULT_SCALE;
22514 
22515 	  var self = this;
22516 
22517 	  eventBus.on('canvas.init', function(e) {
22518 	    self._init(config.enabled !== false);
22519 	  });
22520 	}
22521 
22522 	ZoomScroll.$inject = [
22523 	  'config.zoomScroll',
22524 	  'eventBus',
22525 	  'canvas'
22526 	];
22527 
22528 	ZoomScroll.prototype.scroll = function scroll(delta) {
22529 	  this._canvas.scroll(delta);
22530 	};
22531 
22532 
22533 	ZoomScroll.prototype.reset = function reset() {
22534 	  this._canvas.zoom('fit-viewport');
22535 	};
22536 
22537 	/**
22538 	 * Zoom depending on delta.
22539 	 *
22540 	 * @param {number} delta
22541 	 * @param {Object} position
22542 	 */
22543 	ZoomScroll.prototype.zoom = function zoom(delta, position) {
22544 
22545 	  // zoom with half the step size of stepZoom
22546 	  var stepSize = getStepSize(RANGE, NUM_STEPS * 2);
22547 
22548 	  // add until threshold reached
22549 	  this._totalDelta += delta;
22550 
22551 	  if (Math.abs(this._totalDelta) > DELTA_THRESHOLD) {
22552 	    this._zoom(delta, position, stepSize);
22553 
22554 	    // reset
22555 	    this._totalDelta = 0;
22556 	  }
22557 	};
22558 
22559 
22560 	ZoomScroll.prototype._handleWheel = function handleWheel(event) {
22561 
22562 	  // event is already handled by '.djs-scrollable'
22563 	  if (closest(event.target, '.djs-scrollable', true)) {
22564 	    return;
22565 	  }
22566 
22567 	  var element = this._container;
22568 
22569 	  event.preventDefault();
22570 
22571 	  // pinch to zoom is mapped to wheel + ctrlKey = true
22572 	  // in modern browsers (!)
22573 
22574 	  var isZoom = event.ctrlKey;
22575 
22576 	  var isHorizontalScroll = event.shiftKey;
22577 
22578 	  var factor = -1 * this._scale,
22579 	      delta;
22580 
22581 	  if (isZoom) {
22582 	    factor *= event.deltaMode === 0 ? 0.020 : 0.32;
22583 	  } else {
22584 	    factor *= event.deltaMode === 0 ? 1.0 : 16.0;
22585 	  }
22586 
22587 	  if (isZoom) {
22588 	    var elementRect = element.getBoundingClientRect();
22589 
22590 	    var offset = {
22591 	      x: event.clientX - elementRect.left,
22592 	      y: event.clientY - elementRect.top
22593 	    };
22594 
22595 	    delta = (
22596 	      Math.sqrt(
22597 	        Math.pow(event.deltaY, 2) +
22598 	        Math.pow(event.deltaX, 2)
22599 	      ) * sign(event.deltaY) * factor
22600 	    );
22601 
22602 	    // zoom in relative to diagram {x,y} coordinates
22603 	    this.zoom(delta, offset);
22604 	  } else {
22605 
22606 	    if (isHorizontalScroll) {
22607 	      delta = {
22608 	        dx: factor * event.deltaY,
22609 	        dy: 0
22610 	      };
22611 	    } else {
22612 	      delta = {
22613 	        dx: factor * event.deltaX,
22614 	        dy: factor * event.deltaY
22615 	      };
22616 	    }
22617 
22618 	    this.scroll(delta);
22619 	  }
22620 	};
22621 
22622 	/**
22623 	 * Zoom with fixed step size.
22624 	 *
22625 	 * @param {number} delta - Zoom delta (1 for zooming in, -1 for out).
22626 	 * @param {Object} position
22627 	 */
22628 	ZoomScroll.prototype.stepZoom = function stepZoom(delta, position) {
22629 
22630 	  var stepSize = getStepSize(RANGE, NUM_STEPS);
22631 
22632 	  this._zoom(delta, position, stepSize);
22633 	};
22634 
22635 
22636 	/**
22637 	 * Zoom in/out given a step size.
22638 	 *
22639 	 * @param {number} delta
22640 	 * @param {Object} position
22641 	 * @param {number} stepSize
22642 	 */
22643 	ZoomScroll.prototype._zoom = function(delta, position, stepSize) {
22644 	  var canvas = this._canvas;
22645 
22646 	  var direction = delta > 0 ? 1 : -1;
22647 
22648 	  var currentLinearZoomLevel = log10(canvas.zoom());
22649 
22650 	  // snap to a proximate zoom step
22651 	  var newLinearZoomLevel = Math.round(currentLinearZoomLevel / stepSize) * stepSize;
22652 
22653 	  // increase or decrease one zoom step in the given direction
22654 	  newLinearZoomLevel += stepSize * direction;
22655 
22656 	  // calculate the absolute logarithmic zoom level based on the linear zoom level
22657 	  // (e.g. 2 for an absolute x2 zoom)
22658 	  var newLogZoomLevel = Math.pow(10, newLinearZoomLevel);
22659 
22660 	  canvas.zoom(cap(RANGE, newLogZoomLevel), position);
22661 	};
22662 
22663 
22664 	/**
22665 	 * Toggle the zoom scroll ability via mouse wheel.
22666 	 *
22667 	 * @param  {boolean} [newEnabled] new enabled state
22668 	 */
22669 	ZoomScroll.prototype.toggle = function toggle(newEnabled) {
22670 
22671 	  var element = this._container;
22672 	  var handleWheel = this._handleWheel;
22673 
22674 	  var oldEnabled = this._enabled;
22675 
22676 	  if (typeof newEnabled === 'undefined') {
22677 	    newEnabled = !oldEnabled;
22678 	  }
22679 
22680 	  // only react on actual changes
22681 	  if (oldEnabled !== newEnabled) {
22682 
22683 	    // add or remove wheel listener based on
22684 	    // changed enabled state
22685 	    componentEvent[newEnabled ? 'bind' : 'unbind'](element, 'wheel', handleWheel, false);
22686 	  }
22687 
22688 	  this._enabled = newEnabled;
22689 
22690 	  return newEnabled;
22691 	};
22692 
22693 
22694 	ZoomScroll.prototype._init = function(newEnabled) {
22695 	  this.toggle(newEnabled);
22696 	};
22697 
22698 	var ZoomScrollModule = {
22699 	  __init__: [ 'zoomScroll' ],
22700 	  zoomScroll: [ 'type', ZoomScroll ]
22701 	};
22702 
22703 	/**
22704 	 * A viewer that includes mouse navigation facilities
22705 	 *
22706 	 * @param {Object} options
22707 	 */
22708 	function NavigatedViewer(options) {
22709 	  Viewer.call(this, options);
22710 	}
22711 
22712 	inherits$1(NavigatedViewer, Viewer);
22713 
22714 
22715 	NavigatedViewer.prototype._navigationModules = [
22716 	  KeyboardMoveModule,
22717 	  MoveCanvasModule,
22718 	  ZoomScrollModule
22719 	];
22720 
22721 	NavigatedViewer.prototype._modules = [].concat(
22722 	  Viewer.prototype._modules,
22723 	  NavigatedViewer.prototype._navigationModules
22724 	);
22725 
22726 	var hammer = {exports: {}};
22727 
22728 	/*! Hammer.JS - v2.0.7 - 2016-04-22
22729 	 * http://hammerjs.github.io/
22730 	 *
22731 	 * Copyright (c) 2016 Jorik Tangelder;
22732 	 * Licensed under the MIT license */
22733 
22734 	(function (module) {
22735 	(function(window, document, exportName, undefined$1) {
22736 
22737 	var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
22738 	var TEST_ELEMENT = document.createElement('div');
22739 
22740 	var TYPE_FUNCTION = 'function';
22741 
22742 	var round = Math.round;
22743 	var abs = Math.abs;
22744 	var now = Date.now;
22745 
22746 	/**
22747 	 * set a timeout with a given scope
22748 	 * @param {Function} fn
22749 	 * @param {Number} timeout
22750 	 * @param {Object} context
22751 	 * @returns {number}
22752 	 */
22753 	function setTimeoutContext(fn, timeout, context) {
22754 	    return setTimeout(bindFn(fn, context), timeout);
22755 	}
22756 
22757 	/**
22758 	 * if the argument is an array, we want to execute the fn on each entry
22759 	 * if it aint an array we don't want to do a thing.
22760 	 * this is used by all the methods that accept a single and array argument.
22761 	 * @param {*|Array} arg
22762 	 * @param {String} fn
22763 	 * @param {Object} [context]
22764 	 * @returns {Boolean}
22765 	 */
22766 	function invokeArrayArg(arg, fn, context) {
22767 	    if (Array.isArray(arg)) {
22768 	        each(arg, context[fn], context);
22769 	        return true;
22770 	    }
22771 	    return false;
22772 	}
22773 
22774 	/**
22775 	 * walk objects and arrays
22776 	 * @param {Object} obj
22777 	 * @param {Function} iterator
22778 	 * @param {Object} context
22779 	 */
22780 	function each(obj, iterator, context) {
22781 	    var i;
22782 
22783 	    if (!obj) {
22784 	        return;
22785 	    }
22786 
22787 	    if (obj.forEach) {
22788 	        obj.forEach(iterator, context);
22789 	    } else if (obj.length !== undefined$1) {
22790 	        i = 0;
22791 	        while (i < obj.length) {
22792 	            iterator.call(context, obj[i], i, obj);
22793 	            i++;
22794 	        }
22795 	    } else {
22796 	        for (i in obj) {
22797 	            obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
22798 	        }
22799 	    }
22800 	}
22801 
22802 	/**
22803 	 * wrap a method with a deprecation warning and stack trace
22804 	 * @param {Function} method
22805 	 * @param {String} name
22806 	 * @param {String} message
22807 	 * @returns {Function} A new function wrapping the supplied method.
22808 	 */
22809 	function deprecate(method, name, message) {
22810 	    var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
22811 	    return function() {
22812 	        var e = new Error('get-stack-trace');
22813 	        var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
22814 	            .replace(/^\s+at\s+/gm, '')
22815 	            .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
22816 
22817 	        var log = window.console && (window.console.warn || window.console.log);
22818 	        if (log) {
22819 	            log.call(window.console, deprecationMessage, stack);
22820 	        }
22821 	        return method.apply(this, arguments);
22822 	    };
22823 	}
22824 
22825 	/**
22826 	 * extend object.
22827 	 * means that properties in dest will be overwritten by the ones in src.
22828 	 * @param {Object} target
22829 	 * @param {...Object} objects_to_assign
22830 	 * @returns {Object} target
22831 	 */
22832 	var assign;
22833 	if (typeof Object.assign !== 'function') {
22834 	    assign = function assign(target) {
22835 	        if (target === undefined$1 || target === null) {
22836 	            throw new TypeError('Cannot convert undefined or null to object');
22837 	        }
22838 
22839 	        var output = Object(target);
22840 	        for (var index = 1; index < arguments.length; index++) {
22841 	            var source = arguments[index];
22842 	            if (source !== undefined$1 && source !== null) {
22843 	                for (var nextKey in source) {
22844 	                    if (source.hasOwnProperty(nextKey)) {
22845 	                        output[nextKey] = source[nextKey];
22846 	                    }
22847 	                }
22848 	            }
22849 	        }
22850 	        return output;
22851 	    };
22852 	} else {
22853 	    assign = Object.assign;
22854 	}
22855 
22856 	/**
22857 	 * extend object.
22858 	 * means that properties in dest will be overwritten by the ones in src.
22859 	 * @param {Object} dest
22860 	 * @param {Object} src
22861 	 * @param {Boolean} [merge=false]
22862 	 * @returns {Object} dest
22863 	 */
22864 	var extend = deprecate(function extend(dest, src, merge) {
22865 	    var keys = Object.keys(src);
22866 	    var i = 0;
22867 	    while (i < keys.length) {
22868 	        if (!merge || (merge && dest[keys[i]] === undefined$1)) {
22869 	            dest[keys[i]] = src[keys[i]];
22870 	        }
22871 	        i++;
22872 	    }
22873 	    return dest;
22874 	}, 'extend', 'Use `assign`.');
22875 
22876 	/**
22877 	 * merge the values from src in the dest.
22878 	 * means that properties that exist in dest will not be overwritten by src
22879 	 * @param {Object} dest
22880 	 * @param {Object} src
22881 	 * @returns {Object} dest
22882 	 */
22883 	var merge = deprecate(function merge(dest, src) {
22884 	    return extend(dest, src, true);
22885 	}, 'merge', 'Use `assign`.');
22886 
22887 	/**
22888 	 * simple class inheritance
22889 	 * @param {Function} child
22890 	 * @param {Function} base
22891 	 * @param {Object} [properties]
22892 	 */
22893 	function inherit(child, base, properties) {
22894 	    var baseP = base.prototype,
22895 	        childP;
22896 
22897 	    childP = child.prototype = Object.create(baseP);
22898 	    childP.constructor = child;
22899 	    childP._super = baseP;
22900 
22901 	    if (properties) {
22902 	        assign(childP, properties);
22903 	    }
22904 	}
22905 
22906 	/**
22907 	 * simple function bind
22908 	 * @param {Function} fn
22909 	 * @param {Object} context
22910 	 * @returns {Function}
22911 	 */
22912 	function bindFn(fn, context) {
22913 	    return function boundFn() {
22914 	        return fn.apply(context, arguments);
22915 	    };
22916 	}
22917 
22918 	/**
22919 	 * let a boolean value also be a function that must return a boolean
22920 	 * this first item in args will be used as the context
22921 	 * @param {Boolean|Function} val
22922 	 * @param {Array} [args]
22923 	 * @returns {Boolean}
22924 	 */
22925 	function boolOrFn(val, args) {
22926 	    if (typeof val == TYPE_FUNCTION) {
22927 	        return val.apply(args ? args[0] || undefined$1 : undefined$1, args);
22928 	    }
22929 	    return val;
22930 	}
22931 
22932 	/**
22933 	 * use the val2 when val1 is undefined
22934 	 * @param {*} val1
22935 	 * @param {*} val2
22936 	 * @returns {*}
22937 	 */
22938 	function ifUndefined(val1, val2) {
22939 	    return (val1 === undefined$1) ? val2 : val1;
22940 	}
22941 
22942 	/**
22943 	 * addEventListener with multiple events at once
22944 	 * @param {EventTarget} target
22945 	 * @param {String} types
22946 	 * @param {Function} handler
22947 	 */
22948 	function addEventListeners(target, types, handler) {
22949 	    each(splitStr(types), function(type) {
22950 	        target.addEventListener(type, handler, false);
22951 	    });
22952 	}
22953 
22954 	/**
22955 	 * removeEventListener with multiple events at once
22956 	 * @param {EventTarget} target
22957 	 * @param {String} types
22958 	 * @param {Function} handler
22959 	 */
22960 	function removeEventListeners(target, types, handler) {
22961 	    each(splitStr(types), function(type) {
22962 	        target.removeEventListener(type, handler, false);
22963 	    });
22964 	}
22965 
22966 	/**
22967 	 * find if a node is in the given parent
22968 	 * @method hasParent
22969 	 * @param {HTMLElement} node
22970 	 * @param {HTMLElement} parent
22971 	 * @return {Boolean} found
22972 	 */
22973 	function hasParent(node, parent) {
22974 	    while (node) {
22975 	        if (node == parent) {
22976 	            return true;
22977 	        }
22978 	        node = node.parentNode;
22979 	    }
22980 	    return false;
22981 	}
22982 
22983 	/**
22984 	 * small indexOf wrapper
22985 	 * @param {String} str
22986 	 * @param {String} find
22987 	 * @returns {Boolean} found
22988 	 */
22989 	function inStr(str, find) {
22990 	    return str.indexOf(find) > -1;
22991 	}
22992 
22993 	/**
22994 	 * split string on whitespace
22995 	 * @param {String} str
22996 	 * @returns {Array} words
22997 	 */
22998 	function splitStr(str) {
22999 	    return str.trim().split(/\s+/g);
23000 	}
23001 
23002 	/**
23003 	 * find if a array contains the object using indexOf or a simple polyFill
23004 	 * @param {Array} src
23005 	 * @param {String} find
23006 	 * @param {String} [findByKey]
23007 	 * @return {Boolean|Number} false when not found, or the index
23008 	 */
23009 	function inArray(src, find, findByKey) {
23010 	    if (src.indexOf && !findByKey) {
23011 	        return src.indexOf(find);
23012 	    } else {
23013 	        var i = 0;
23014 	        while (i < src.length) {
23015 	            if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
23016 	                return i;
23017 	            }
23018 	            i++;
23019 	        }
23020 	        return -1;
23021 	    }
23022 	}
23023 
23024 	/**
23025 	 * convert array-like objects to real arrays
23026 	 * @param {Object} obj
23027 	 * @returns {Array}
23028 	 */
23029 	function toArray(obj) {
23030 	    return Array.prototype.slice.call(obj, 0);
23031 	}
23032 
23033 	/**
23034 	 * unique array with objects based on a key (like 'id') or just by the array's value
23035 	 * @param {Array} src [{id:1},{id:2},{id:1}]
23036 	 * @param {String} [key]
23037 	 * @param {Boolean} [sort=False]
23038 	 * @returns {Array} [{id:1},{id:2}]
23039 	 */
23040 	function uniqueArray(src, key, sort) {
23041 	    var results = [];
23042 	    var values = [];
23043 	    var i = 0;
23044 
23045 	    while (i < src.length) {
23046 	        var val = key ? src[i][key] : src[i];
23047 	        if (inArray(values, val) < 0) {
23048 	            results.push(src[i]);
23049 	        }
23050 	        values[i] = val;
23051 	        i++;
23052 	    }
23053 
23054 	    if (sort) {
23055 	        if (!key) {
23056 	            results = results.sort();
23057 	        } else {
23058 	            results = results.sort(function sortUniqueArray(a, b) {
23059 	                return a[key] > b[key];
23060 	            });
23061 	        }
23062 	    }
23063 
23064 	    return results;
23065 	}
23066 
23067 	/**
23068 	 * get the prefixed property
23069 	 * @param {Object} obj
23070 	 * @param {String} property
23071 	 * @returns {String|Undefined} prefixed
23072 	 */
23073 	function prefixed(obj, property) {
23074 	    var prefix, prop;
23075 	    var camelProp = property[0].toUpperCase() + property.slice(1);
23076 
23077 	    var i = 0;
23078 	    while (i < VENDOR_PREFIXES.length) {
23079 	        prefix = VENDOR_PREFIXES[i];
23080 	        prop = (prefix) ? prefix + camelProp : property;
23081 
23082 	        if (prop in obj) {
23083 	            return prop;
23084 	        }
23085 	        i++;
23086 	    }
23087 	    return undefined$1;
23088 	}
23089 
23090 	/**
23091 	 * get a unique id
23092 	 * @returns {number} uniqueId
23093 	 */
23094 	var _uniqueId = 1;
23095 	function uniqueId() {
23096 	    return _uniqueId++;
23097 	}
23098 
23099 	/**
23100 	 * get the window object of an element
23101 	 * @param {HTMLElement} element
23102 	 * @returns {DocumentView|Window}
23103 	 */
23104 	function getWindowForElement(element) {
23105 	    var doc = element.ownerDocument || element;
23106 	    return (doc.defaultView || doc.parentWindow || window);
23107 	}
23108 
23109 	var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
23110 
23111 	var SUPPORT_TOUCH = ('ontouchstart' in window);
23112 	var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined$1;
23113 	var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
23114 
23115 	var INPUT_TYPE_TOUCH = 'touch';
23116 	var INPUT_TYPE_PEN = 'pen';
23117 	var INPUT_TYPE_MOUSE = 'mouse';
23118 	var INPUT_TYPE_KINECT = 'kinect';
23119 
23120 	var COMPUTE_INTERVAL = 25;
23121 
23122 	var INPUT_START = 1;
23123 	var INPUT_MOVE = 2;
23124 	var INPUT_END = 4;
23125 	var INPUT_CANCEL = 8;
23126 
23127 	var DIRECTION_NONE = 1;
23128 	var DIRECTION_LEFT = 2;
23129 	var DIRECTION_RIGHT = 4;
23130 	var DIRECTION_UP = 8;
23131 	var DIRECTION_DOWN = 16;
23132 
23133 	var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
23134 	var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
23135 	var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
23136 
23137 	var PROPS_XY = ['x', 'y'];
23138 	var PROPS_CLIENT_XY = ['clientX', 'clientY'];
23139 
23140 	/**
23141 	 * create new input type manager
23142 	 * @param {Manager} manager
23143 	 * @param {Function} callback
23144 	 * @returns {Input}
23145 	 * @constructor
23146 	 */
23147 	function Input(manager, callback) {
23148 	    var self = this;
23149 	    this.manager = manager;
23150 	    this.callback = callback;
23151 	    this.element = manager.element;
23152 	    this.target = manager.options.inputTarget;
23153 
23154 	    // smaller wrapper around the handler, for the scope and the enabled state of the manager,
23155 	    // so when disabled the input events are completely bypassed.
23156 	    this.domHandler = function(ev) {
23157 	        if (boolOrFn(manager.options.enable, [manager])) {
23158 	            self.handler(ev);
23159 	        }
23160 	    };
23161 
23162 	    this.init();
23163 
23164 	}
23165 
23166 	Input.prototype = {
23167 	    /**
23168 	     * should handle the inputEvent data and trigger the callback
23169 	     * @virtual
23170 	     */
23171 	    handler: function() { },
23172 
23173 	    /**
23174 	     * bind the events
23175 	     */
23176 	    init: function() {
23177 	        this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
23178 	        this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
23179 	        this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
23180 	    },
23181 
23182 	    /**
23183 	     * unbind the events
23184 	     */
23185 	    destroy: function() {
23186 	        this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
23187 	        this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
23188 	        this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
23189 	    }
23190 	};
23191 
23192 	/**
23193 	 * create new input type manager
23194 	 * called by the Manager constructor
23195 	 * @param {Hammer} manager
23196 	 * @returns {Input}
23197 	 */
23198 	function createInputInstance(manager) {
23199 	    var Type;
23200 	    var inputClass = manager.options.inputClass;
23201 
23202 	    if (inputClass) {
23203 	        Type = inputClass;
23204 	    } else if (SUPPORT_POINTER_EVENTS) {
23205 	        Type = PointerEventInput;
23206 	    } else if (SUPPORT_ONLY_TOUCH) {
23207 	        Type = TouchInput;
23208 	    } else if (!SUPPORT_TOUCH) {
23209 	        Type = MouseInput;
23210 	    } else {
23211 	        Type = TouchMouseInput;
23212 	    }
23213 	    return new (Type)(manager, inputHandler);
23214 	}
23215 
23216 	/**
23217 	 * handle input events
23218 	 * @param {Manager} manager
23219 	 * @param {String} eventType
23220 	 * @param {Object} input
23221 	 */
23222 	function inputHandler(manager, eventType, input) {
23223 	    var pointersLen = input.pointers.length;
23224 	    var changedPointersLen = input.changedPointers.length;
23225 	    var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
23226 	    var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
23227 
23228 	    input.isFirst = !!isFirst;
23229 	    input.isFinal = !!isFinal;
23230 
23231 	    if (isFirst) {
23232 	        manager.session = {};
23233 	    }
23234 
23235 	    // source event is the normalized value of the domEvents
23236 	    // like 'touchstart, mouseup, pointerdown'
23237 	    input.eventType = eventType;
23238 
23239 	    // compute scale, rotation etc
23240 	    computeInputData(manager, input);
23241 
23242 	    // emit secret event
23243 	    manager.emit('hammer.input', input);
23244 
23245 	    manager.recognize(input);
23246 	    manager.session.prevInput = input;
23247 	}
23248 
23249 	/**
23250 	 * extend the data with some usable properties like scale, rotate, velocity etc
23251 	 * @param {Object} manager
23252 	 * @param {Object} input
23253 	 */
23254 	function computeInputData(manager, input) {
23255 	    var session = manager.session;
23256 	    var pointers = input.pointers;
23257 	    var pointersLength = pointers.length;
23258 
23259 	    // store the first input to calculate the distance and direction
23260 	    if (!session.firstInput) {
23261 	        session.firstInput = simpleCloneInputData(input);
23262 	    }
23263 
23264 	    // to compute scale and rotation we need to store the multiple touches
23265 	    if (pointersLength > 1 && !session.firstMultiple) {
23266 	        session.firstMultiple = simpleCloneInputData(input);
23267 	    } else if (pointersLength === 1) {
23268 	        session.firstMultiple = false;
23269 	    }
23270 
23271 	    var firstInput = session.firstInput;
23272 	    var firstMultiple = session.firstMultiple;
23273 	    var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
23274 
23275 	    var center = input.center = getCenter(pointers);
23276 	    input.timeStamp = now();
23277 	    input.deltaTime = input.timeStamp - firstInput.timeStamp;
23278 
23279 	    input.angle = getAngle(offsetCenter, center);
23280 	    input.distance = getDistance(offsetCenter, center);
23281 
23282 	    computeDeltaXY(session, input);
23283 	    input.offsetDirection = getDirection(input.deltaX, input.deltaY);
23284 
23285 	    var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
23286 	    input.overallVelocityX = overallVelocity.x;
23287 	    input.overallVelocityY = overallVelocity.y;
23288 	    input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
23289 
23290 	    input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
23291 	    input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
23292 
23293 	    input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
23294 	        session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
23295 
23296 	    computeIntervalInputData(session, input);
23297 
23298 	    // find the correct target
23299 	    var target = manager.element;
23300 	    if (hasParent(input.srcEvent.target, target)) {
23301 	        target = input.srcEvent.target;
23302 	    }
23303 	    input.target = target;
23304 	}
23305 
23306 	function computeDeltaXY(session, input) {
23307 	    var center = input.center;
23308 	    var offset = session.offsetDelta || {};
23309 	    var prevDelta = session.prevDelta || {};
23310 	    var prevInput = session.prevInput || {};
23311 
23312 	    if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
23313 	        prevDelta = session.prevDelta = {
23314 	            x: prevInput.deltaX || 0,
23315 	            y: prevInput.deltaY || 0
23316 	        };
23317 
23318 	        offset = session.offsetDelta = {
23319 	            x: center.x,
23320 	            y: center.y
23321 	        };
23322 	    }
23323 
23324 	    input.deltaX = prevDelta.x + (center.x - offset.x);
23325 	    input.deltaY = prevDelta.y + (center.y - offset.y);
23326 	}
23327 
23328 	/**
23329 	 * velocity is calculated every x ms
23330 	 * @param {Object} session
23331 	 * @param {Object} input
23332 	 */
23333 	function computeIntervalInputData(session, input) {
23334 	    var last = session.lastInterval || input,
23335 	        deltaTime = input.timeStamp - last.timeStamp,
23336 	        velocity, velocityX, velocityY, direction;
23337 
23338 	    if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined$1)) {
23339 	        var deltaX = input.deltaX - last.deltaX;
23340 	        var deltaY = input.deltaY - last.deltaY;
23341 
23342 	        var v = getVelocity(deltaTime, deltaX, deltaY);
23343 	        velocityX = v.x;
23344 	        velocityY = v.y;
23345 	        velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
23346 	        direction = getDirection(deltaX, deltaY);
23347 
23348 	        session.lastInterval = input;
23349 	    } else {
23350 	        // use latest velocity info if it doesn't overtake a minimum period
23351 	        velocity = last.velocity;
23352 	        velocityX = last.velocityX;
23353 	        velocityY = last.velocityY;
23354 	        direction = last.direction;
23355 	    }
23356 
23357 	    input.velocity = velocity;
23358 	    input.velocityX = velocityX;
23359 	    input.velocityY = velocityY;
23360 	    input.direction = direction;
23361 	}
23362 
23363 	/**
23364 	 * create a simple clone from the input used for storage of firstInput and firstMultiple
23365 	 * @param {Object} input
23366 	 * @returns {Object} clonedInputData
23367 	 */
23368 	function simpleCloneInputData(input) {
23369 	    // make a simple copy of the pointers because we will get a reference if we don't
23370 	    // we only need clientXY for the calculations
23371 	    var pointers = [];
23372 	    var i = 0;
23373 	    while (i < input.pointers.length) {
23374 	        pointers[i] = {
23375 	            clientX: round(input.pointers[i].clientX),
23376 	            clientY: round(input.pointers[i].clientY)
23377 	        };
23378 	        i++;
23379 	    }
23380 
23381 	    return {
23382 	        timeStamp: now(),
23383 	        pointers: pointers,
23384 	        center: getCenter(pointers),
23385 	        deltaX: input.deltaX,
23386 	        deltaY: input.deltaY
23387 	    };
23388 	}
23389 
23390 	/**
23391 	 * get the center of all the pointers
23392 	 * @param {Array} pointers
23393 	 * @return {Object} center contains `x` and `y` properties
23394 	 */
23395 	function getCenter(pointers) {
23396 	    var pointersLength = pointers.length;
23397 
23398 	    // no need to loop when only one touch
23399 	    if (pointersLength === 1) {
23400 	        return {
23401 	            x: round(pointers[0].clientX),
23402 	            y: round(pointers[0].clientY)
23403 	        };
23404 	    }
23405 
23406 	    var x = 0, y = 0, i = 0;
23407 	    while (i < pointersLength) {
23408 	        x += pointers[i].clientX;
23409 	        y += pointers[i].clientY;
23410 	        i++;
23411 	    }
23412 
23413 	    return {
23414 	        x: round(x / pointersLength),
23415 	        y: round(y / pointersLength)
23416 	    };
23417 	}
23418 
23419 	/**
23420 	 * calculate the velocity between two points. unit is in px per ms.
23421 	 * @param {Number} deltaTime
23422 	 * @param {Number} x
23423 	 * @param {Number} y
23424 	 * @return {Object} velocity `x` and `y`
23425 	 */
23426 	function getVelocity(deltaTime, x, y) {
23427 	    return {
23428 	        x: x / deltaTime || 0,
23429 	        y: y / deltaTime || 0
23430 	    };
23431 	}
23432 
23433 	/**
23434 	 * get the direction between two points
23435 	 * @param {Number} x
23436 	 * @param {Number} y
23437 	 * @return {Number} direction
23438 	 */
23439 	function getDirection(x, y) {
23440 	    if (x === y) {
23441 	        return DIRECTION_NONE;
23442 	    }
23443 
23444 	    if (abs(x) >= abs(y)) {
23445 	        return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
23446 	    }
23447 	    return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
23448 	}
23449 
23450 	/**
23451 	 * calculate the absolute distance between two points
23452 	 * @param {Object} p1 {x, y}
23453 	 * @param {Object} p2 {x, y}
23454 	 * @param {Array} [props] containing x and y keys
23455 	 * @return {Number} distance
23456 	 */
23457 	function getDistance(p1, p2, props) {
23458 	    if (!props) {
23459 	        props = PROPS_XY;
23460 	    }
23461 	    var x = p2[props[0]] - p1[props[0]],
23462 	        y = p2[props[1]] - p1[props[1]];
23463 
23464 	    return Math.sqrt((x * x) + (y * y));
23465 	}
23466 
23467 	/**
23468 	 * calculate the angle between two coordinates
23469 	 * @param {Object} p1
23470 	 * @param {Object} p2
23471 	 * @param {Array} [props] containing x and y keys
23472 	 * @return {Number} angle
23473 	 */
23474 	function getAngle(p1, p2, props) {
23475 	    if (!props) {
23476 	        props = PROPS_XY;
23477 	    }
23478 	    var x = p2[props[0]] - p1[props[0]],
23479 	        y = p2[props[1]] - p1[props[1]];
23480 	    return Math.atan2(y, x) * 180 / Math.PI;
23481 	}
23482 
23483 	/**
23484 	 * calculate the rotation degrees between two pointersets
23485 	 * @param {Array} start array of pointers
23486 	 * @param {Array} end array of pointers
23487 	 * @return {Number} rotation
23488 	 */
23489 	function getRotation(start, end) {
23490 	    return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
23491 	}
23492 
23493 	/**
23494 	 * calculate the scale factor between two pointersets
23495 	 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
23496 	 * @param {Array} start array of pointers
23497 	 * @param {Array} end array of pointers
23498 	 * @return {Number} scale
23499 	 */
23500 	function getScale(start, end) {
23501 	    return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
23502 	}
23503 
23504 	var MOUSE_INPUT_MAP = {
23505 	    mousedown: INPUT_START,
23506 	    mousemove: INPUT_MOVE,
23507 	    mouseup: INPUT_END
23508 	};
23509 
23510 	var MOUSE_ELEMENT_EVENTS = 'mousedown';
23511 	var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
23512 
23513 	/**
23514 	 * Mouse events input
23515 	 * @constructor
23516 	 * @extends Input
23517 	 */
23518 	function MouseInput() {
23519 	    this.evEl = MOUSE_ELEMENT_EVENTS;
23520 	    this.evWin = MOUSE_WINDOW_EVENTS;
23521 
23522 	    this.pressed = false; // mousedown state
23523 
23524 	    Input.apply(this, arguments);
23525 	}
23526 
23527 	inherit(MouseInput, Input, {
23528 	    /**
23529 	     * handle mouse events
23530 	     * @param {Object} ev
23531 	     */
23532 	    handler: function MEhandler(ev) {
23533 	        var eventType = MOUSE_INPUT_MAP[ev.type];
23534 
23535 	        // on start we want to have the left mouse button down
23536 	        if (eventType & INPUT_START && ev.button === 0) {
23537 	            this.pressed = true;
23538 	        }
23539 
23540 	        if (eventType & INPUT_MOVE && ev.which !== 1) {
23541 	            eventType = INPUT_END;
23542 	        }
23543 
23544 	        // mouse must be down
23545 	        if (!this.pressed) {
23546 	            return;
23547 	        }
23548 
23549 	        if (eventType & INPUT_END) {
23550 	            this.pressed = false;
23551 	        }
23552 
23553 	        this.callback(this.manager, eventType, {
23554 	            pointers: [ev],
23555 	            changedPointers: [ev],
23556 	            pointerType: INPUT_TYPE_MOUSE,
23557 	            srcEvent: ev
23558 	        });
23559 	    }
23560 	});
23561 
23562 	var POINTER_INPUT_MAP = {
23563 	    pointerdown: INPUT_START,
23564 	    pointermove: INPUT_MOVE,
23565 	    pointerup: INPUT_END,
23566 	    pointercancel: INPUT_CANCEL,
23567 	    pointerout: INPUT_CANCEL
23568 	};
23569 
23570 	// in IE10 the pointer types is defined as an enum
23571 	var IE10_POINTER_TYPE_ENUM = {
23572 	    2: INPUT_TYPE_TOUCH,
23573 	    3: INPUT_TYPE_PEN,
23574 	    4: INPUT_TYPE_MOUSE,
23575 	    5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
23576 	};
23577 
23578 	var POINTER_ELEMENT_EVENTS = 'pointerdown';
23579 	var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
23580 
23581 	// IE10 has prefixed support, and case-sensitive
23582 	if (window.MSPointerEvent && !window.PointerEvent) {
23583 	    POINTER_ELEMENT_EVENTS = 'MSPointerDown';
23584 	    POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
23585 	}
23586 
23587 	/**
23588 	 * Pointer events input
23589 	 * @constructor
23590 	 * @extends Input
23591 	 */
23592 	function PointerEventInput() {
23593 	    this.evEl = POINTER_ELEMENT_EVENTS;
23594 	    this.evWin = POINTER_WINDOW_EVENTS;
23595 
23596 	    Input.apply(this, arguments);
23597 
23598 	    this.store = (this.manager.session.pointerEvents = []);
23599 	}
23600 
23601 	inherit(PointerEventInput, Input, {
23602 	    /**
23603 	     * handle mouse events
23604 	     * @param {Object} ev
23605 	     */
23606 	    handler: function PEhandler(ev) {
23607 	        var store = this.store;
23608 	        var removePointer = false;
23609 
23610 	        var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
23611 	        var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
23612 	        var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
23613 
23614 	        var isTouch = (pointerType == INPUT_TYPE_TOUCH);
23615 
23616 	        // get index of the event in the store
23617 	        var storeIndex = inArray(store, ev.pointerId, 'pointerId');
23618 
23619 	        // start and mouse must be down
23620 	        if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
23621 	            if (storeIndex < 0) {
23622 	                store.push(ev);
23623 	                storeIndex = store.length - 1;
23624 	            }
23625 	        } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
23626 	            removePointer = true;
23627 	        }
23628 
23629 	        // it not found, so the pointer hasn't been down (so it's probably a hover)
23630 	        if (storeIndex < 0) {
23631 	            return;
23632 	        }
23633 
23634 	        // update the event in the store
23635 	        store[storeIndex] = ev;
23636 
23637 	        this.callback(this.manager, eventType, {
23638 	            pointers: store,
23639 	            changedPointers: [ev],
23640 	            pointerType: pointerType,
23641 	            srcEvent: ev
23642 	        });
23643 
23644 	        if (removePointer) {
23645 	            // remove from the store
23646 	            store.splice(storeIndex, 1);
23647 	        }
23648 	    }
23649 	});
23650 
23651 	var SINGLE_TOUCH_INPUT_MAP = {
23652 	    touchstart: INPUT_START,
23653 	    touchmove: INPUT_MOVE,
23654 	    touchend: INPUT_END,
23655 	    touchcancel: INPUT_CANCEL
23656 	};
23657 
23658 	var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
23659 	var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
23660 
23661 	/**
23662 	 * Touch events input
23663 	 * @constructor
23664 	 * @extends Input
23665 	 */
23666 	function SingleTouchInput() {
23667 	    this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
23668 	    this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
23669 	    this.started = false;
23670 
23671 	    Input.apply(this, arguments);
23672 	}
23673 
23674 	inherit(SingleTouchInput, Input, {
23675 	    handler: function TEhandler(ev) {
23676 	        var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
23677 
23678 	        // should we handle the touch events?
23679 	        if (type === INPUT_START) {
23680 	            this.started = true;
23681 	        }
23682 
23683 	        if (!this.started) {
23684 	            return;
23685 	        }
23686 
23687 	        var touches = normalizeSingleTouches.call(this, ev, type);
23688 
23689 	        // when done, reset the started state
23690 	        if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
23691 	            this.started = false;
23692 	        }
23693 
23694 	        this.callback(this.manager, type, {
23695 	            pointers: touches[0],
23696 	            changedPointers: touches[1],
23697 	            pointerType: INPUT_TYPE_TOUCH,
23698 	            srcEvent: ev
23699 	        });
23700 	    }
23701 	});
23702 
23703 	/**
23704 	 * @this {TouchInput}
23705 	 * @param {Object} ev
23706 	 * @param {Number} type flag
23707 	 * @returns {undefined|Array} [all, changed]
23708 	 */
23709 	function normalizeSingleTouches(ev, type) {
23710 	    var all = toArray(ev.touches);
23711 	    var changed = toArray(ev.changedTouches);
23712 
23713 	    if (type & (INPUT_END | INPUT_CANCEL)) {
23714 	        all = uniqueArray(all.concat(changed), 'identifier', true);
23715 	    }
23716 
23717 	    return [all, changed];
23718 	}
23719 
23720 	var TOUCH_INPUT_MAP = {
23721 	    touchstart: INPUT_START,
23722 	    touchmove: INPUT_MOVE,
23723 	    touchend: INPUT_END,
23724 	    touchcancel: INPUT_CANCEL
23725 	};
23726 
23727 	var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
23728 
23729 	/**
23730 	 * Multi-user touch events input
23731 	 * @constructor
23732 	 * @extends Input
23733 	 */
23734 	function TouchInput() {
23735 	    this.evTarget = TOUCH_TARGET_EVENTS;
23736 	    this.targetIds = {};
23737 
23738 	    Input.apply(this, arguments);
23739 	}
23740 
23741 	inherit(TouchInput, Input, {
23742 	    handler: function MTEhandler(ev) {
23743 	        var type = TOUCH_INPUT_MAP[ev.type];
23744 	        var touches = getTouches.call(this, ev, type);
23745 	        if (!touches) {
23746 	            return;
23747 	        }
23748 
23749 	        this.callback(this.manager, type, {
23750 	            pointers: touches[0],
23751 	            changedPointers: touches[1],
23752 	            pointerType: INPUT_TYPE_TOUCH,
23753 	            srcEvent: ev
23754 	        });
23755 	    }
23756 	});
23757 
23758 	/**
23759 	 * @this {TouchInput}
23760 	 * @param {Object} ev
23761 	 * @param {Number} type flag
23762 	 * @returns {undefined|Array} [all, changed]
23763 	 */
23764 	function getTouches(ev, type) {
23765 	    var allTouches = toArray(ev.touches);
23766 	    var targetIds = this.targetIds;
23767 
23768 	    // when there is only one touch, the process can be simplified
23769 	    if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
23770 	        targetIds[allTouches[0].identifier] = true;
23771 	        return [allTouches, allTouches];
23772 	    }
23773 
23774 	    var i,
23775 	        targetTouches,
23776 	        changedTouches = toArray(ev.changedTouches),
23777 	        changedTargetTouches = [],
23778 	        target = this.target;
23779 
23780 	    // get target touches from touches
23781 	    targetTouches = allTouches.filter(function(touch) {
23782 	        return hasParent(touch.target, target);
23783 	    });
23784 
23785 	    // collect touches
23786 	    if (type === INPUT_START) {
23787 	        i = 0;
23788 	        while (i < targetTouches.length) {
23789 	            targetIds[targetTouches[i].identifier] = true;
23790 	            i++;
23791 	        }
23792 	    }
23793 
23794 	    // filter changed touches to only contain touches that exist in the collected target ids
23795 	    i = 0;
23796 	    while (i < changedTouches.length) {
23797 	        if (targetIds[changedTouches[i].identifier]) {
23798 	            changedTargetTouches.push(changedTouches[i]);
23799 	        }
23800 
23801 	        // cleanup removed touches
23802 	        if (type & (INPUT_END | INPUT_CANCEL)) {
23803 	            delete targetIds[changedTouches[i].identifier];
23804 	        }
23805 	        i++;
23806 	    }
23807 
23808 	    if (!changedTargetTouches.length) {
23809 	        return;
23810 	    }
23811 
23812 	    return [
23813 	        // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
23814 	        uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
23815 	        changedTargetTouches
23816 	    ];
23817 	}
23818 
23819 	/**
23820 	 * Combined touch and mouse input
23821 	 *
23822 	 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
23823 	 * This because touch devices also emit mouse events while doing a touch.
23824 	 *
23825 	 * @constructor
23826 	 * @extends Input
23827 	 */
23828 
23829 	var DEDUP_TIMEOUT = 2500;
23830 	var DEDUP_DISTANCE = 25;
23831 
23832 	function TouchMouseInput() {
23833 	    Input.apply(this, arguments);
23834 
23835 	    var handler = bindFn(this.handler, this);
23836 	    this.touch = new TouchInput(this.manager, handler);
23837 	    this.mouse = new MouseInput(this.manager, handler);
23838 
23839 	    this.primaryTouch = null;
23840 	    this.lastTouches = [];
23841 	}
23842 
23843 	inherit(TouchMouseInput, Input, {
23844 	    /**
23845 	     * handle mouse and touch events
23846 	     * @param {Hammer} manager
23847 	     * @param {String} inputEvent
23848 	     * @param {Object} inputData
23849 	     */
23850 	    handler: function TMEhandler(manager, inputEvent, inputData) {
23851 	        var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
23852 	            isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
23853 
23854 	        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
23855 	            return;
23856 	        }
23857 
23858 	        // when we're in a touch event, record touches to  de-dupe synthetic mouse event
23859 	        if (isTouch) {
23860 	            recordTouches.call(this, inputEvent, inputData);
23861 	        } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
23862 	            return;
23863 	        }
23864 
23865 	        this.callback(manager, inputEvent, inputData);
23866 	    },
23867 
23868 	    /**
23869 	     * remove the event listeners
23870 	     */
23871 	    destroy: function destroy() {
23872 	        this.touch.destroy();
23873 	        this.mouse.destroy();
23874 	    }
23875 	});
23876 
23877 	function recordTouches(eventType, eventData) {
23878 	    if (eventType & INPUT_START) {
23879 	        this.primaryTouch = eventData.changedPointers[0].identifier;
23880 	        setLastTouch.call(this, eventData);
23881 	    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
23882 	        setLastTouch.call(this, eventData);
23883 	    }
23884 	}
23885 
23886 	function setLastTouch(eventData) {
23887 	    var touch = eventData.changedPointers[0];
23888 
23889 	    if (touch.identifier === this.primaryTouch) {
23890 	        var lastTouch = {x: touch.clientX, y: touch.clientY};
23891 	        this.lastTouches.push(lastTouch);
23892 	        var lts = this.lastTouches;
23893 	        var removeLastTouch = function() {
23894 	            var i = lts.indexOf(lastTouch);
23895 	            if (i > -1) {
23896 	                lts.splice(i, 1);
23897 	            }
23898 	        };
23899 	        setTimeout(removeLastTouch, DEDUP_TIMEOUT);
23900 	    }
23901 	}
23902 
23903 	function isSyntheticEvent(eventData) {
23904 	    var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
23905 	    for (var i = 0; i < this.lastTouches.length; i++) {
23906 	        var t = this.lastTouches[i];
23907 	        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
23908 	        if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
23909 	            return true;
23910 	        }
23911 	    }
23912 	    return false;
23913 	}
23914 
23915 	var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
23916 	var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined$1;
23917 
23918 	// magical touchAction value
23919 	var TOUCH_ACTION_COMPUTE = 'compute';
23920 	var TOUCH_ACTION_AUTO = 'auto';
23921 	var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
23922 	var TOUCH_ACTION_NONE = 'none';
23923 	var TOUCH_ACTION_PAN_X = 'pan-x';
23924 	var TOUCH_ACTION_PAN_Y = 'pan-y';
23925 	var TOUCH_ACTION_MAP = getTouchActionProps();
23926 
23927 	/**
23928 	 * Touch Action
23929 	 * sets the touchAction property or uses the js alternative
23930 	 * @param {Manager} manager
23931 	 * @param {String} value
23932 	 * @constructor
23933 	 */
23934 	function TouchAction(manager, value) {
23935 	    this.manager = manager;
23936 	    this.set(value);
23937 	}
23938 
23939 	TouchAction.prototype = {
23940 	    /**
23941 	     * set the touchAction value on the element or enable the polyfill
23942 	     * @param {String} value
23943 	     */
23944 	    set: function(value) {
23945 	        // find out the touch-action by the event handlers
23946 	        if (value == TOUCH_ACTION_COMPUTE) {
23947 	            value = this.compute();
23948 	        }
23949 
23950 	        if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
23951 	            this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
23952 	        }
23953 	        this.actions = value.toLowerCase().trim();
23954 	    },
23955 
23956 	    /**
23957 	     * just re-set the touchAction value
23958 	     */
23959 	    update: function() {
23960 	        this.set(this.manager.options.touchAction);
23961 	    },
23962 
23963 	    /**
23964 	     * compute the value for the touchAction property based on the recognizer's settings
23965 	     * @returns {String} value
23966 	     */
23967 	    compute: function() {
23968 	        var actions = [];
23969 	        each(this.manager.recognizers, function(recognizer) {
23970 	            if (boolOrFn(recognizer.options.enable, [recognizer])) {
23971 	                actions = actions.concat(recognizer.getTouchAction());
23972 	            }
23973 	        });
23974 	        return cleanTouchActions(actions.join(' '));
23975 	    },
23976 
23977 	    /**
23978 	     * this method is called on each input cycle and provides the preventing of the browser behavior
23979 	     * @param {Object} input
23980 	     */
23981 	    preventDefaults: function(input) {
23982 	        var srcEvent = input.srcEvent;
23983 	        var direction = input.offsetDirection;
23984 
23985 	        // if the touch action did prevented once this session
23986 	        if (this.manager.session.prevented) {
23987 	            srcEvent.preventDefault();
23988 	            return;
23989 	        }
23990 
23991 	        var actions = this.actions;
23992 	        var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
23993 	        var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
23994 	        var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
23995 
23996 	        if (hasNone) {
23997 	            //do not prevent defaults if this is a tap gesture
23998 
23999 	            var isTapPointer = input.pointers.length === 1;
24000 	            var isTapMovement = input.distance < 2;
24001 	            var isTapTouchTime = input.deltaTime < 250;
24002 
24003 	            if (isTapPointer && isTapMovement && isTapTouchTime) {
24004 	                return;
24005 	            }
24006 	        }
24007 
24008 	        if (hasPanX && hasPanY) {
24009 	            // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
24010 	            return;
24011 	        }
24012 
24013 	        if (hasNone ||
24014 	            (hasPanY && direction & DIRECTION_HORIZONTAL) ||
24015 	            (hasPanX && direction & DIRECTION_VERTICAL)) {
24016 	            return this.preventSrc(srcEvent);
24017 	        }
24018 	    },
24019 
24020 	    /**
24021 	     * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
24022 	     * @param {Object} srcEvent
24023 	     */
24024 	    preventSrc: function(srcEvent) {
24025 	        this.manager.session.prevented = true;
24026 	        srcEvent.preventDefault();
24027 	    }
24028 	};
24029 
24030 	/**
24031 	 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
24032 	 * @param {String} actions
24033 	 * @returns {*}
24034 	 */
24035 	function cleanTouchActions(actions) {
24036 	    // none
24037 	    if (inStr(actions, TOUCH_ACTION_NONE)) {
24038 	        return TOUCH_ACTION_NONE;
24039 	    }
24040 
24041 	    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
24042 	    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
24043 
24044 	    // if both pan-x and pan-y are set (different recognizers
24045 	    // for different directions, e.g. horizontal pan but vertical swipe?)
24046 	    // we need none (as otherwise with pan-x pan-y combined none of these
24047 	    // recognizers will work, since the browser would handle all panning
24048 	    if (hasPanX && hasPanY) {
24049 	        return TOUCH_ACTION_NONE;
24050 	    }
24051 
24052 	    // pan-x OR pan-y
24053 	    if (hasPanX || hasPanY) {
24054 	        return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
24055 	    }
24056 
24057 	    // manipulation
24058 	    if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
24059 	        return TOUCH_ACTION_MANIPULATION;
24060 	    }
24061 
24062 	    return TOUCH_ACTION_AUTO;
24063 	}
24064 
24065 	function getTouchActionProps() {
24066 	    if (!NATIVE_TOUCH_ACTION) {
24067 	        return false;
24068 	    }
24069 	    var touchMap = {};
24070 	    var cssSupports = window.CSS && window.CSS.supports;
24071 	    ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
24072 
24073 	        // If css.supports is not supported but there is native touch-action assume it supports
24074 	        // all values. This is the case for IE 10 and 11.
24075 	        touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
24076 	    });
24077 	    return touchMap;
24078 	}
24079 
24080 	/**
24081 	 * Recognizer flow explained; *
24082 	 * All recognizers have the initial state of POSSIBLE when a input session starts.
24083 	 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
24084 	 * Example session for mouse-input: mousedown -> mousemove -> mouseup
24085 	 *
24086 	 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
24087 	 * which determines with state it should be.
24088 	 *
24089 	 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
24090 	 * POSSIBLE to give it another change on the next cycle.
24091 	 *
24092 	 *               Possible
24093 	 *                  |
24094 	 *            +-----+---------------+
24095 	 *            |                     |
24096 	 *      +-----+-----+               |
24097 	 *      |           |               |
24098 	 *   Failed      Cancelled          |
24099 	 *                          +-------+------+
24100 	 *                          |              |
24101 	 *                      Recognized       Began
24102 	 *                                         |
24103 	 *                                      Changed
24104 	 *                                         |
24105 	 *                                  Ended/Recognized
24106 	 */
24107 	var STATE_POSSIBLE = 1;
24108 	var STATE_BEGAN = 2;
24109 	var STATE_CHANGED = 4;
24110 	var STATE_ENDED = 8;
24111 	var STATE_RECOGNIZED = STATE_ENDED;
24112 	var STATE_CANCELLED = 16;
24113 	var STATE_FAILED = 32;
24114 
24115 	/**
24116 	 * Recognizer
24117 	 * Every recognizer needs to extend from this class.
24118 	 * @constructor
24119 	 * @param {Object} options
24120 	 */
24121 	function Recognizer(options) {
24122 	    this.options = assign({}, this.defaults, options || {});
24123 
24124 	    this.id = uniqueId();
24125 
24126 	    this.manager = null;
24127 
24128 	    // default is enable true
24129 	    this.options.enable = ifUndefined(this.options.enable, true);
24130 
24131 	    this.state = STATE_POSSIBLE;
24132 
24133 	    this.simultaneous = {};
24134 	    this.requireFail = [];
24135 	}
24136 
24137 	Recognizer.prototype = {
24138 	    /**
24139 	     * @virtual
24140 	     * @type {Object}
24141 	     */
24142 	    defaults: {},
24143 
24144 	    /**
24145 	     * set options
24146 	     * @param {Object} options
24147 	     * @return {Recognizer}
24148 	     */
24149 	    set: function(options) {
24150 	        assign(this.options, options);
24151 
24152 	        // also update the touchAction, in case something changed about the directions/enabled state
24153 	        this.manager && this.manager.touchAction.update();
24154 	        return this;
24155 	    },
24156 
24157 	    /**
24158 	     * recognize simultaneous with an other recognizer.
24159 	     * @param {Recognizer} otherRecognizer
24160 	     * @returns {Recognizer} this
24161 	     */
24162 	    recognizeWith: function(otherRecognizer) {
24163 	        if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
24164 	            return this;
24165 	        }
24166 
24167 	        var simultaneous = this.simultaneous;
24168 	        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
24169 	        if (!simultaneous[otherRecognizer.id]) {
24170 	            simultaneous[otherRecognizer.id] = otherRecognizer;
24171 	            otherRecognizer.recognizeWith(this);
24172 	        }
24173 	        return this;
24174 	    },
24175 
24176 	    /**
24177 	     * drop the simultaneous link. it doesnt remove the link on the other recognizer.
24178 	     * @param {Recognizer} otherRecognizer
24179 	     * @returns {Recognizer} this
24180 	     */
24181 	    dropRecognizeWith: function(otherRecognizer) {
24182 	        if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
24183 	            return this;
24184 	        }
24185 
24186 	        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
24187 	        delete this.simultaneous[otherRecognizer.id];
24188 	        return this;
24189 	    },
24190 
24191 	    /**
24192 	     * recognizer can only run when an other is failing
24193 	     * @param {Recognizer} otherRecognizer
24194 	     * @returns {Recognizer} this
24195 	     */
24196 	    requireFailure: function(otherRecognizer) {
24197 	        if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
24198 	            return this;
24199 	        }
24200 
24201 	        var requireFail = this.requireFail;
24202 	        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
24203 	        if (inArray(requireFail, otherRecognizer) === -1) {
24204 	            requireFail.push(otherRecognizer);
24205 	            otherRecognizer.requireFailure(this);
24206 	        }
24207 	        return this;
24208 	    },
24209 
24210 	    /**
24211 	     * drop the requireFailure link. it does not remove the link on the other recognizer.
24212 	     * @param {Recognizer} otherRecognizer
24213 	     * @returns {Recognizer} this
24214 	     */
24215 	    dropRequireFailure: function(otherRecognizer) {
24216 	        if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
24217 	            return this;
24218 	        }
24219 
24220 	        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
24221 	        var index = inArray(this.requireFail, otherRecognizer);
24222 	        if (index > -1) {
24223 	            this.requireFail.splice(index, 1);
24224 	        }
24225 	        return this;
24226 	    },
24227 
24228 	    /**
24229 	     * has require failures boolean
24230 	     * @returns {boolean}
24231 	     */
24232 	    hasRequireFailures: function() {
24233 	        return this.requireFail.length > 0;
24234 	    },
24235 
24236 	    /**
24237 	     * if the recognizer can recognize simultaneous with an other recognizer
24238 	     * @param {Recognizer} otherRecognizer
24239 	     * @returns {Boolean}
24240 	     */
24241 	    canRecognizeWith: function(otherRecognizer) {
24242 	        return !!this.simultaneous[otherRecognizer.id];
24243 	    },
24244 
24245 	    /**
24246 	     * You should use `tryEmit` instead of `emit` directly to check
24247 	     * that all the needed recognizers has failed before emitting.
24248 	     * @param {Object} input
24249 	     */
24250 	    emit: function(input) {
24251 	        var self = this;
24252 	        var state = this.state;
24253 
24254 	        function emit(event) {
24255 	            self.manager.emit(event, input);
24256 	        }
24257 
24258 	        // 'panstart' and 'panmove'
24259 	        if (state < STATE_ENDED) {
24260 	            emit(self.options.event + stateStr(state));
24261 	        }
24262 
24263 	        emit(self.options.event); // simple 'eventName' events
24264 
24265 	        if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
24266 	            emit(input.additionalEvent);
24267 	        }
24268 
24269 	        // panend and pancancel
24270 	        if (state >= STATE_ENDED) {
24271 	            emit(self.options.event + stateStr(state));
24272 	        }
24273 	    },
24274 
24275 	    /**
24276 	     * Check that all the require failure recognizers has failed,
24277 	     * if true, it emits a gesture event,
24278 	     * otherwise, setup the state to FAILED.
24279 	     * @param {Object} input
24280 	     */
24281 	    tryEmit: function(input) {
24282 	        if (this.canEmit()) {
24283 	            return this.emit(input);
24284 	        }
24285 	        // it's failing anyway
24286 	        this.state = STATE_FAILED;
24287 	    },
24288 
24289 	    /**
24290 	     * can we emit?
24291 	     * @returns {boolean}
24292 	     */
24293 	    canEmit: function() {
24294 	        var i = 0;
24295 	        while (i < this.requireFail.length) {
24296 	            if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
24297 	                return false;
24298 	            }
24299 	            i++;
24300 	        }
24301 	        return true;
24302 	    },
24303 
24304 	    /**
24305 	     * update the recognizer
24306 	     * @param {Object} inputData
24307 	     */
24308 	    recognize: function(inputData) {
24309 	        // make a new copy of the inputData
24310 	        // so we can change the inputData without messing up the other recognizers
24311 	        var inputDataClone = assign({}, inputData);
24312 
24313 	        // is is enabled and allow recognizing?
24314 	        if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
24315 	            this.reset();
24316 	            this.state = STATE_FAILED;
24317 	            return;
24318 	        }
24319 
24320 	        // reset when we've reached the end
24321 	        if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
24322 	            this.state = STATE_POSSIBLE;
24323 	        }
24324 
24325 	        this.state = this.process(inputDataClone);
24326 
24327 	        // the recognizer has recognized a gesture
24328 	        // so trigger an event
24329 	        if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
24330 	            this.tryEmit(inputDataClone);
24331 	        }
24332 	    },
24333 
24334 	    /**
24335 	     * return the state of the recognizer
24336 	     * the actual recognizing happens in this method
24337 	     * @virtual
24338 	     * @param {Object} inputData
24339 	     * @returns {Const} STATE
24340 	     */
24341 	    process: function(inputData) { }, // jshint ignore:line
24342 
24343 	    /**
24344 	     * return the preferred touch-action
24345 	     * @virtual
24346 	     * @returns {Array}
24347 	     */
24348 	    getTouchAction: function() { },
24349 
24350 	    /**
24351 	     * called when the gesture isn't allowed to recognize
24352 	     * like when another is being recognized or it is disabled
24353 	     * @virtual
24354 	     */
24355 	    reset: function() { }
24356 	};
24357 
24358 	/**
24359 	 * get a usable string, used as event postfix
24360 	 * @param {Const} state
24361 	 * @returns {String} state
24362 	 */
24363 	function stateStr(state) {
24364 	    if (state & STATE_CANCELLED) {
24365 	        return 'cancel';
24366 	    } else if (state & STATE_ENDED) {
24367 	        return 'end';
24368 	    } else if (state & STATE_CHANGED) {
24369 	        return 'move';
24370 	    } else if (state & STATE_BEGAN) {
24371 	        return 'start';
24372 	    }
24373 	    return '';
24374 	}
24375 
24376 	/**
24377 	 * direction cons to string
24378 	 * @param {Const} direction
24379 	 * @returns {String}
24380 	 */
24381 	function directionStr(direction) {
24382 	    if (direction == DIRECTION_DOWN) {
24383 	        return 'down';
24384 	    } else if (direction == DIRECTION_UP) {
24385 	        return 'up';
24386 	    } else if (direction == DIRECTION_LEFT) {
24387 	        return 'left';
24388 	    } else if (direction == DIRECTION_RIGHT) {
24389 	        return 'right';
24390 	    }
24391 	    return '';
24392 	}
24393 
24394 	/**
24395 	 * get a recognizer by name if it is bound to a manager
24396 	 * @param {Recognizer|String} otherRecognizer
24397 	 * @param {Recognizer} recognizer
24398 	 * @returns {Recognizer}
24399 	 */
24400 	function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
24401 	    var manager = recognizer.manager;
24402 	    if (manager) {
24403 	        return manager.get(otherRecognizer);
24404 	    }
24405 	    return otherRecognizer;
24406 	}
24407 
24408 	/**
24409 	 * This recognizer is just used as a base for the simple attribute recognizers.
24410 	 * @constructor
24411 	 * @extends Recognizer
24412 	 */
24413 	function AttrRecognizer() {
24414 	    Recognizer.apply(this, arguments);
24415 	}
24416 
24417 	inherit(AttrRecognizer, Recognizer, {
24418 	    /**
24419 	     * @namespace
24420 	     * @memberof AttrRecognizer
24421 	     */
24422 	    defaults: {
24423 	        /**
24424 	         * @type {Number}
24425 	         * @default 1
24426 	         */
24427 	        pointers: 1
24428 	    },
24429 
24430 	    /**
24431 	     * Used to check if it the recognizer receives valid input, like input.distance > 10.
24432 	     * @memberof AttrRecognizer
24433 	     * @param {Object} input
24434 	     * @returns {Boolean} recognized
24435 	     */
24436 	    attrTest: function(input) {
24437 	        var optionPointers = this.options.pointers;
24438 	        return optionPointers === 0 || input.pointers.length === optionPointers;
24439 	    },
24440 
24441 	    /**
24442 	     * Process the input and return the state for the recognizer
24443 	     * @memberof AttrRecognizer
24444 	     * @param {Object} input
24445 	     * @returns {*} State
24446 	     */
24447 	    process: function(input) {
24448 	        var state = this.state;
24449 	        var eventType = input.eventType;
24450 
24451 	        var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
24452 	        var isValid = this.attrTest(input);
24453 
24454 	        // on cancel input and we've recognized before, return STATE_CANCELLED
24455 	        if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
24456 	            return state | STATE_CANCELLED;
24457 	        } else if (isRecognized || isValid) {
24458 	            if (eventType & INPUT_END) {
24459 	                return state | STATE_ENDED;
24460 	            } else if (!(state & STATE_BEGAN)) {
24461 	                return STATE_BEGAN;
24462 	            }
24463 	            return state | STATE_CHANGED;
24464 	        }
24465 	        return STATE_FAILED;
24466 	    }
24467 	});
24468 
24469 	/**
24470 	 * Pan
24471 	 * Recognized when the pointer is down and moved in the allowed direction.
24472 	 * @constructor
24473 	 * @extends AttrRecognizer
24474 	 */
24475 	function PanRecognizer() {
24476 	    AttrRecognizer.apply(this, arguments);
24477 
24478 	    this.pX = null;
24479 	    this.pY = null;
24480 	}
24481 
24482 	inherit(PanRecognizer, AttrRecognizer, {
24483 	    /**
24484 	     * @namespace
24485 	     * @memberof PanRecognizer
24486 	     */
24487 	    defaults: {
24488 	        event: 'pan',
24489 	        threshold: 10,
24490 	        pointers: 1,
24491 	        direction: DIRECTION_ALL
24492 	    },
24493 
24494 	    getTouchAction: function() {
24495 	        var direction = this.options.direction;
24496 	        var actions = [];
24497 	        if (direction & DIRECTION_HORIZONTAL) {
24498 	            actions.push(TOUCH_ACTION_PAN_Y);
24499 	        }
24500 	        if (direction & DIRECTION_VERTICAL) {
24501 	            actions.push(TOUCH_ACTION_PAN_X);
24502 	        }
24503 	        return actions;
24504 	    },
24505 
24506 	    directionTest: function(input) {
24507 	        var options = this.options;
24508 	        var hasMoved = true;
24509 	        var distance = input.distance;
24510 	        var direction = input.direction;
24511 	        var x = input.deltaX;
24512 	        var y = input.deltaY;
24513 
24514 	        // lock to axis?
24515 	        if (!(direction & options.direction)) {
24516 	            if (options.direction & DIRECTION_HORIZONTAL) {
24517 	                direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
24518 	                hasMoved = x != this.pX;
24519 	                distance = Math.abs(input.deltaX);
24520 	            } else {
24521 	                direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
24522 	                hasMoved = y != this.pY;
24523 	                distance = Math.abs(input.deltaY);
24524 	            }
24525 	        }
24526 	        input.direction = direction;
24527 	        return hasMoved && distance > options.threshold && direction & options.direction;
24528 	    },
24529 
24530 	    attrTest: function(input) {
24531 	        return AttrRecognizer.prototype.attrTest.call(this, input) &&
24532 	            (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
24533 	    },
24534 
24535 	    emit: function(input) {
24536 
24537 	        this.pX = input.deltaX;
24538 	        this.pY = input.deltaY;
24539 
24540 	        var direction = directionStr(input.direction);
24541 
24542 	        if (direction) {
24543 	            input.additionalEvent = this.options.event + direction;
24544 	        }
24545 	        this._super.emit.call(this, input);
24546 	    }
24547 	});
24548 
24549 	/**
24550 	 * Pinch
24551 	 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
24552 	 * @constructor
24553 	 * @extends AttrRecognizer
24554 	 */
24555 	function PinchRecognizer() {
24556 	    AttrRecognizer.apply(this, arguments);
24557 	}
24558 
24559 	inherit(PinchRecognizer, AttrRecognizer, {
24560 	    /**
24561 	     * @namespace
24562 	     * @memberof PinchRecognizer
24563 	     */
24564 	    defaults: {
24565 	        event: 'pinch',
24566 	        threshold: 0,
24567 	        pointers: 2
24568 	    },
24569 
24570 	    getTouchAction: function() {
24571 	        return [TOUCH_ACTION_NONE];
24572 	    },
24573 
24574 	    attrTest: function(input) {
24575 	        return this._super.attrTest.call(this, input) &&
24576 	            (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
24577 	    },
24578 
24579 	    emit: function(input) {
24580 	        if (input.scale !== 1) {
24581 	            var inOut = input.scale < 1 ? 'in' : 'out';
24582 	            input.additionalEvent = this.options.event + inOut;
24583 	        }
24584 	        this._super.emit.call(this, input);
24585 	    }
24586 	});
24587 
24588 	/**
24589 	 * Press
24590 	 * Recognized when the pointer is down for x ms without any movement.
24591 	 * @constructor
24592 	 * @extends Recognizer
24593 	 */
24594 	function PressRecognizer() {
24595 	    Recognizer.apply(this, arguments);
24596 
24597 	    this._timer = null;
24598 	    this._input = null;
24599 	}
24600 
24601 	inherit(PressRecognizer, Recognizer, {
24602 	    /**
24603 	     * @namespace
24604 	     * @memberof PressRecognizer
24605 	     */
24606 	    defaults: {
24607 	        event: 'press',
24608 	        pointers: 1,
24609 	        time: 251, // minimal time of the pointer to be pressed
24610 	        threshold: 9 // a minimal movement is ok, but keep it low
24611 	    },
24612 
24613 	    getTouchAction: function() {
24614 	        return [TOUCH_ACTION_AUTO];
24615 	    },
24616 
24617 	    process: function(input) {
24618 	        var options = this.options;
24619 	        var validPointers = input.pointers.length === options.pointers;
24620 	        var validMovement = input.distance < options.threshold;
24621 	        var validTime = input.deltaTime > options.time;
24622 
24623 	        this._input = input;
24624 
24625 	        // we only allow little movement
24626 	        // and we've reached an end event, so a tap is possible
24627 	        if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
24628 	            this.reset();
24629 	        } else if (input.eventType & INPUT_START) {
24630 	            this.reset();
24631 	            this._timer = setTimeoutContext(function() {
24632 	                this.state = STATE_RECOGNIZED;
24633 	                this.tryEmit();
24634 	            }, options.time, this);
24635 	        } else if (input.eventType & INPUT_END) {
24636 	            return STATE_RECOGNIZED;
24637 	        }
24638 	        return STATE_FAILED;
24639 	    },
24640 
24641 	    reset: function() {
24642 	        clearTimeout(this._timer);
24643 	    },
24644 
24645 	    emit: function(input) {
24646 	        if (this.state !== STATE_RECOGNIZED) {
24647 	            return;
24648 	        }
24649 
24650 	        if (input && (input.eventType & INPUT_END)) {
24651 	            this.manager.emit(this.options.event + 'up', input);
24652 	        } else {
24653 	            this._input.timeStamp = now();
24654 	            this.manager.emit(this.options.event, this._input);
24655 	        }
24656 	    }
24657 	});
24658 
24659 	/**
24660 	 * Rotate
24661 	 * Recognized when two or more pointer are moving in a circular motion.
24662 	 * @constructor
24663 	 * @extends AttrRecognizer
24664 	 */
24665 	function RotateRecognizer() {
24666 	    AttrRecognizer.apply(this, arguments);
24667 	}
24668 
24669 	inherit(RotateRecognizer, AttrRecognizer, {
24670 	    /**
24671 	     * @namespace
24672 	     * @memberof RotateRecognizer
24673 	     */
24674 	    defaults: {
24675 	        event: 'rotate',
24676 	        threshold: 0,
24677 	        pointers: 2
24678 	    },
24679 
24680 	    getTouchAction: function() {
24681 	        return [TOUCH_ACTION_NONE];
24682 	    },
24683 
24684 	    attrTest: function(input) {
24685 	        return this._super.attrTest.call(this, input) &&
24686 	            (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
24687 	    }
24688 	});
24689 
24690 	/**
24691 	 * Swipe
24692 	 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
24693 	 * @constructor
24694 	 * @extends AttrRecognizer
24695 	 */
24696 	function SwipeRecognizer() {
24697 	    AttrRecognizer.apply(this, arguments);
24698 	}
24699 
24700 	inherit(SwipeRecognizer, AttrRecognizer, {
24701 	    /**
24702 	     * @namespace
24703 	     * @memberof SwipeRecognizer
24704 	     */
24705 	    defaults: {
24706 	        event: 'swipe',
24707 	        threshold: 10,
24708 	        velocity: 0.3,
24709 	        direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
24710 	        pointers: 1
24711 	    },
24712 
24713 	    getTouchAction: function() {
24714 	        return PanRecognizer.prototype.getTouchAction.call(this);
24715 	    },
24716 
24717 	    attrTest: function(input) {
24718 	        var direction = this.options.direction;
24719 	        var velocity;
24720 
24721 	        if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
24722 	            velocity = input.overallVelocity;
24723 	        } else if (direction & DIRECTION_HORIZONTAL) {
24724 	            velocity = input.overallVelocityX;
24725 	        } else if (direction & DIRECTION_VERTICAL) {
24726 	            velocity = input.overallVelocityY;
24727 	        }
24728 
24729 	        return this._super.attrTest.call(this, input) &&
24730 	            direction & input.offsetDirection &&
24731 	            input.distance > this.options.threshold &&
24732 	            input.maxPointers == this.options.pointers &&
24733 	            abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
24734 	    },
24735 
24736 	    emit: function(input) {
24737 	        var direction = directionStr(input.offsetDirection);
24738 	        if (direction) {
24739 	            this.manager.emit(this.options.event + direction, input);
24740 	        }
24741 
24742 	        this.manager.emit(this.options.event, input);
24743 	    }
24744 	});
24745 
24746 	/**
24747 	 * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
24748 	 * between the given interval and position. The delay option can be used to recognize multi-taps without firing
24749 	 * a single tap.
24750 	 *
24751 	 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
24752 	 * multi-taps being recognized.
24753 	 * @constructor
24754 	 * @extends Recognizer
24755 	 */
24756 	function TapRecognizer() {
24757 	    Recognizer.apply(this, arguments);
24758 
24759 	    // previous time and center,
24760 	    // used for tap counting
24761 	    this.pTime = false;
24762 	    this.pCenter = false;
24763 
24764 	    this._timer = null;
24765 	    this._input = null;
24766 	    this.count = 0;
24767 	}
24768 
24769 	inherit(TapRecognizer, Recognizer, {
24770 	    /**
24771 	     * @namespace
24772 	     * @memberof PinchRecognizer
24773 	     */
24774 	    defaults: {
24775 	        event: 'tap',
24776 	        pointers: 1,
24777 	        taps: 1,
24778 	        interval: 300, // max time between the multi-tap taps
24779 	        time: 250, // max time of the pointer to be down (like finger on the screen)
24780 	        threshold: 9, // a minimal movement is ok, but keep it low
24781 	        posThreshold: 10 // a multi-tap can be a bit off the initial position
24782 	    },
24783 
24784 	    getTouchAction: function() {
24785 	        return [TOUCH_ACTION_MANIPULATION];
24786 	    },
24787 
24788 	    process: function(input) {
24789 	        var options = this.options;
24790 
24791 	        var validPointers = input.pointers.length === options.pointers;
24792 	        var validMovement = input.distance < options.threshold;
24793 	        var validTouchTime = input.deltaTime < options.time;
24794 
24795 	        this.reset();
24796 
24797 	        if ((input.eventType & INPUT_START) && (this.count === 0)) {
24798 	            return this.failTimeout();
24799 	        }
24800 
24801 	        // we only allow little movement
24802 	        // and we've reached an end event, so a tap is possible
24803 	        if (validMovement && validTouchTime && validPointers) {
24804 	            if (input.eventType != INPUT_END) {
24805 	                return this.failTimeout();
24806 	            }
24807 
24808 	            var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
24809 	            var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
24810 
24811 	            this.pTime = input.timeStamp;
24812 	            this.pCenter = input.center;
24813 
24814 	            if (!validMultiTap || !validInterval) {
24815 	                this.count = 1;
24816 	            } else {
24817 	                this.count += 1;
24818 	            }
24819 
24820 	            this._input = input;
24821 
24822 	            // if tap count matches we have recognized it,
24823 	            // else it has began recognizing...
24824 	            var tapCount = this.count % options.taps;
24825 	            if (tapCount === 0) {
24826 	                // no failing requirements, immediately trigger the tap event
24827 	                // or wait as long as the multitap interval to trigger
24828 	                if (!this.hasRequireFailures()) {
24829 	                    return STATE_RECOGNIZED;
24830 	                } else {
24831 	                    this._timer = setTimeoutContext(function() {
24832 	                        this.state = STATE_RECOGNIZED;
24833 	                        this.tryEmit();
24834 	                    }, options.interval, this);
24835 	                    return STATE_BEGAN;
24836 	                }
24837 	            }
24838 	        }
24839 	        return STATE_FAILED;
24840 	    },
24841 
24842 	    failTimeout: function() {
24843 	        this._timer = setTimeoutContext(function() {
24844 	            this.state = STATE_FAILED;
24845 	        }, this.options.interval, this);
24846 	        return STATE_FAILED;
24847 	    },
24848 
24849 	    reset: function() {
24850 	        clearTimeout(this._timer);
24851 	    },
24852 
24853 	    emit: function() {
24854 	        if (this.state == STATE_RECOGNIZED) {
24855 	            this._input.tapCount = this.count;
24856 	            this.manager.emit(this.options.event, this._input);
24857 	        }
24858 	    }
24859 	});
24860 
24861 	/**
24862 	 * Simple way to create a manager with a default set of recognizers.
24863 	 * @param {HTMLElement} element
24864 	 * @param {Object} [options]
24865 	 * @constructor
24866 	 */
24867 	function Hammer(element, options) {
24868 	    options = options || {};
24869 	    options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
24870 	    return new Manager(element, options);
24871 	}
24872 
24873 	/**
24874 	 * @const {string}
24875 	 */
24876 	Hammer.VERSION = '2.0.7';
24877 
24878 	/**
24879 	 * default settings
24880 	 * @namespace
24881 	 */
24882 	Hammer.defaults = {
24883 	    /**
24884 	     * set if DOM events are being triggered.
24885 	     * But this is slower and unused by simple implementations, so disabled by default.
24886 	     * @type {Boolean}
24887 	     * @default false
24888 	     */
24889 	    domEvents: false,
24890 
24891 	    /**
24892 	     * The value for the touchAction property/fallback.
24893 	     * When set to `compute` it will magically set the correct value based on the added recognizers.
24894 	     * @type {String}
24895 	     * @default compute
24896 	     */
24897 	    touchAction: TOUCH_ACTION_COMPUTE,
24898 
24899 	    /**
24900 	     * @type {Boolean}
24901 	     * @default true
24902 	     */
24903 	    enable: true,
24904 
24905 	    /**
24906 	     * EXPERIMENTAL FEATURE -- can be removed/changed
24907 	     * Change the parent input target element.
24908 	     * If Null, then it is being set the to main element.
24909 	     * @type {Null|EventTarget}
24910 	     * @default null
24911 	     */
24912 	    inputTarget: null,
24913 
24914 	    /**
24915 	     * force an input class
24916 	     * @type {Null|Function}
24917 	     * @default null
24918 	     */
24919 	    inputClass: null,
24920 
24921 	    /**
24922 	     * Default recognizer setup when calling `Hammer()`
24923 	     * When creating a new Manager these will be skipped.
24924 	     * @type {Array}
24925 	     */
24926 	    preset: [
24927 	        // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
24928 	        [RotateRecognizer, {enable: false}],
24929 	        [PinchRecognizer, {enable: false}, ['rotate']],
24930 	        [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
24931 	        [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
24932 	        [TapRecognizer],
24933 	        [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
24934 	        [PressRecognizer]
24935 	    ],
24936 
24937 	    /**
24938 	     * Some CSS properties can be used to improve the working of Hammer.
24939 	     * Add them to this method and they will be set when creating a new Manager.
24940 	     * @namespace
24941 	     */
24942 	    cssProps: {
24943 	        /**
24944 	         * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
24945 	         * @type {String}
24946 	         * @default 'none'
24947 	         */
24948 	        userSelect: 'none',
24949 
24950 	        /**
24951 	         * Disable the Windows Phone grippers when pressing an element.
24952 	         * @type {String}
24953 	         * @default 'none'
24954 	         */
24955 	        touchSelect: 'none',
24956 
24957 	        /**
24958 	         * Disables the default callout shown when you touch and hold a touch target.
24959 	         * On iOS, when you touch and hold a touch target such as a link, Safari displays
24960 	         * a callout containing information about the link. This property allows you to disable that callout.
24961 	         * @type {String}
24962 	         * @default 'none'
24963 	         */
24964 	        touchCallout: 'none',
24965 
24966 	        /**
24967 	         * Specifies whether zooming is enabled. Used by IE10>
24968 	         * @type {String}
24969 	         * @default 'none'
24970 	         */
24971 	        contentZooming: 'none',
24972 
24973 	        /**
24974 	         * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
24975 	         * @type {String}
24976 	         * @default 'none'
24977 	         */
24978 	        userDrag: 'none',
24979 
24980 	        /**
24981 	         * Overrides the highlight color shown when the user taps a link or a JavaScript
24982 	         * clickable element in iOS. This property obeys the alpha value, if specified.
24983 	         * @type {String}
24984 	         * @default 'rgba(0,0,0,0)'
24985 	         */
24986 	        tapHighlightColor: 'rgba(0,0,0,0)'
24987 	    }
24988 	};
24989 
24990 	var STOP = 1;
24991 	var FORCED_STOP = 2;
24992 
24993 	/**
24994 	 * Manager
24995 	 * @param {HTMLElement} element
24996 	 * @param {Object} [options]
24997 	 * @constructor
24998 	 */
24999 	function Manager(element, options) {
25000 	    this.options = assign({}, Hammer.defaults, options || {});
25001 
25002 	    this.options.inputTarget = this.options.inputTarget || element;
25003 
25004 	    this.handlers = {};
25005 	    this.session = {};
25006 	    this.recognizers = [];
25007 	    this.oldCssProps = {};
25008 
25009 	    this.element = element;
25010 	    this.input = createInputInstance(this);
25011 	    this.touchAction = new TouchAction(this, this.options.touchAction);
25012 
25013 	    toggleCssProps(this, true);
25014 
25015 	    each(this.options.recognizers, function(item) {
25016 	        var recognizer = this.add(new (item[0])(item[1]));
25017 	        item[2] && recognizer.recognizeWith(item[2]);
25018 	        item[3] && recognizer.requireFailure(item[3]);
25019 	    }, this);
25020 	}
25021 
25022 	Manager.prototype = {
25023 	    /**
25024 	     * set options
25025 	     * @param {Object} options
25026 	     * @returns {Manager}
25027 	     */
25028 	    set: function(options) {
25029 	        assign(this.options, options);
25030 
25031 	        // Options that need a little more setup
25032 	        if (options.touchAction) {
25033 	            this.touchAction.update();
25034 	        }
25035 	        if (options.inputTarget) {
25036 	            // Clean up existing event listeners and reinitialize
25037 	            this.input.destroy();
25038 	            this.input.target = options.inputTarget;
25039 	            this.input.init();
25040 	        }
25041 	        return this;
25042 	    },
25043 
25044 	    /**
25045 	     * stop recognizing for this session.
25046 	     * This session will be discarded, when a new [input]start event is fired.
25047 	     * When forced, the recognizer cycle is stopped immediately.
25048 	     * @param {Boolean} [force]
25049 	     */
25050 	    stop: function(force) {
25051 	        this.session.stopped = force ? FORCED_STOP : STOP;
25052 	    },
25053 
25054 	    /**
25055 	     * run the recognizers!
25056 	     * called by the inputHandler function on every movement of the pointers (touches)
25057 	     * it walks through all the recognizers and tries to detect the gesture that is being made
25058 	     * @param {Object} inputData
25059 	     */
25060 	    recognize: function(inputData) {
25061 	        var session = this.session;
25062 	        if (session.stopped) {
25063 	            return;
25064 	        }
25065 
25066 	        // run the touch-action polyfill
25067 	        this.touchAction.preventDefaults(inputData);
25068 
25069 	        var recognizer;
25070 	        var recognizers = this.recognizers;
25071 
25072 	        // this holds the recognizer that is being recognized.
25073 	        // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
25074 	        // if no recognizer is detecting a thing, it is set to `null`
25075 	        var curRecognizer = session.curRecognizer;
25076 
25077 	        // reset when the last recognizer is recognized
25078 	        // or when we're in a new session
25079 	        if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
25080 	            curRecognizer = session.curRecognizer = null;
25081 	        }
25082 
25083 	        var i = 0;
25084 	        while (i < recognizers.length) {
25085 	            recognizer = recognizers[i];
25086 
25087 	            // find out if we are allowed try to recognize the input for this one.
25088 	            // 1.   allow if the session is NOT forced stopped (see the .stop() method)
25089 	            // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
25090 	            //      that is being recognized.
25091 	            // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
25092 	            //      this can be setup with the `recognizeWith()` method on the recognizer.
25093 	            if (session.stopped !== FORCED_STOP && ( // 1
25094 	                    !curRecognizer || recognizer == curRecognizer || // 2
25095 	                    recognizer.canRecognizeWith(curRecognizer))) { // 3
25096 	                recognizer.recognize(inputData);
25097 	            } else {
25098 	                recognizer.reset();
25099 	            }
25100 
25101 	            // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
25102 	            // current active recognizer. but only if we don't already have an active recognizer
25103 	            if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
25104 	                curRecognizer = session.curRecognizer = recognizer;
25105 	            }
25106 	            i++;
25107 	        }
25108 	    },
25109 
25110 	    /**
25111 	     * get a recognizer by its event name.
25112 	     * @param {Recognizer|String} recognizer
25113 	     * @returns {Recognizer|Null}
25114 	     */
25115 	    get: function(recognizer) {
25116 	        if (recognizer instanceof Recognizer) {
25117 	            return recognizer;
25118 	        }
25119 
25120 	        var recognizers = this.recognizers;
25121 	        for (var i = 0; i < recognizers.length; i++) {
25122 	            if (recognizers[i].options.event == recognizer) {
25123 	                return recognizers[i];
25124 	            }
25125 	        }
25126 	        return null;
25127 	    },
25128 
25129 	    /**
25130 	     * add a recognizer to the manager
25131 	     * existing recognizers with the same event name will be removed
25132 	     * @param {Recognizer} recognizer
25133 	     * @returns {Recognizer|Manager}
25134 	     */
25135 	    add: function(recognizer) {
25136 	        if (invokeArrayArg(recognizer, 'add', this)) {
25137 	            return this;
25138 	        }
25139 
25140 	        // remove existing
25141 	        var existing = this.get(recognizer.options.event);
25142 	        if (existing) {
25143 	            this.remove(existing);
25144 	        }
25145 
25146 	        this.recognizers.push(recognizer);
25147 	        recognizer.manager = this;
25148 
25149 	        this.touchAction.update();
25150 	        return recognizer;
25151 	    },
25152 
25153 	    /**
25154 	     * remove a recognizer by name or instance
25155 	     * @param {Recognizer|String} recognizer
25156 	     * @returns {Manager}
25157 	     */
25158 	    remove: function(recognizer) {
25159 	        if (invokeArrayArg(recognizer, 'remove', this)) {
25160 	            return this;
25161 	        }
25162 
25163 	        recognizer = this.get(recognizer);
25164 
25165 	        // let's make sure this recognizer exists
25166 	        if (recognizer) {
25167 	            var recognizers = this.recognizers;
25168 	            var index = inArray(recognizers, recognizer);
25169 
25170 	            if (index !== -1) {
25171 	                recognizers.splice(index, 1);
25172 	                this.touchAction.update();
25173 	            }
25174 	        }
25175 
25176 	        return this;
25177 	    },
25178 
25179 	    /**
25180 	     * bind event
25181 	     * @param {String} events
25182 	     * @param {Function} handler
25183 	     * @returns {EventEmitter} this
25184 	     */
25185 	    on: function(events, handler) {
25186 	        if (events === undefined$1) {
25187 	            return;
25188 	        }
25189 	        if (handler === undefined$1) {
25190 	            return;
25191 	        }
25192 
25193 	        var handlers = this.handlers;
25194 	        each(splitStr(events), function(event) {
25195 	            handlers[event] = handlers[event] || [];
25196 	            handlers[event].push(handler);
25197 	        });
25198 	        return this;
25199 	    },
25200 
25201 	    /**
25202 	     * unbind event, leave emit blank to remove all handlers
25203 	     * @param {String} events
25204 	     * @param {Function} [handler]
25205 	     * @returns {EventEmitter} this
25206 	     */
25207 	    off: function(events, handler) {
25208 	        if (events === undefined$1) {
25209 	            return;
25210 	        }
25211 
25212 	        var handlers = this.handlers;
25213 	        each(splitStr(events), function(event) {
25214 	            if (!handler) {
25215 	                delete handlers[event];
25216 	            } else {
25217 	                handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
25218 	            }
25219 	        });
25220 	        return this;
25221 	    },
25222 
25223 	    /**
25224 	     * emit event to the listeners
25225 	     * @param {String} event
25226 	     * @param {Object} data
25227 	     */
25228 	    emit: function(event, data) {
25229 	        // we also want to trigger dom events
25230 	        if (this.options.domEvents) {
25231 	            triggerDomEvent(event, data);
25232 	        }
25233 
25234 	        // no handlers, so skip it all
25235 	        var handlers = this.handlers[event] && this.handlers[event].slice();
25236 	        if (!handlers || !handlers.length) {
25237 	            return;
25238 	        }
25239 
25240 	        data.type = event;
25241 	        data.preventDefault = function() {
25242 	            data.srcEvent.preventDefault();
25243 	        };
25244 
25245 	        var i = 0;
25246 	        while (i < handlers.length) {
25247 	            handlers[i](data);
25248 	            i++;
25249 	        }
25250 	    },
25251 
25252 	    /**
25253 	     * destroy the manager and unbinds all events
25254 	     * it doesn't unbind dom events, that is the user own responsibility
25255 	     */
25256 	    destroy: function() {
25257 	        this.element && toggleCssProps(this, false);
25258 
25259 	        this.handlers = {};
25260 	        this.session = {};
25261 	        this.input.destroy();
25262 	        this.element = null;
25263 	    }
25264 	};
25265 
25266 	/**
25267 	 * add/remove the css properties as defined in manager.options.cssProps
25268 	 * @param {Manager} manager
25269 	 * @param {Boolean} add
25270 	 */
25271 	function toggleCssProps(manager, add) {
25272 	    var element = manager.element;
25273 	    if (!element.style) {
25274 	        return;
25275 	    }
25276 	    var prop;
25277 	    each(manager.options.cssProps, function(value, name) {
25278 	        prop = prefixed(element.style, name);
25279 	        if (add) {
25280 	            manager.oldCssProps[prop] = element.style[prop];
25281 	            element.style[prop] = value;
25282 	        } else {
25283 	            element.style[prop] = manager.oldCssProps[prop] || '';
25284 	        }
25285 	    });
25286 	    if (!add) {
25287 	        manager.oldCssProps = {};
25288 	    }
25289 	}
25290 
25291 	/**
25292 	 * trigger dom event
25293 	 * @param {String} event
25294 	 * @param {Object} data
25295 	 */
25296 	function triggerDomEvent(event, data) {
25297 	    var gestureEvent = document.createEvent('Event');
25298 	    gestureEvent.initEvent(event, true, true);
25299 	    gestureEvent.gesture = data;
25300 	    data.target.dispatchEvent(gestureEvent);
25301 	}
25302 
25303 	assign(Hammer, {
25304 	    INPUT_START: INPUT_START,
25305 	    INPUT_MOVE: INPUT_MOVE,
25306 	    INPUT_END: INPUT_END,
25307 	    INPUT_CANCEL: INPUT_CANCEL,
25308 
25309 	    STATE_POSSIBLE: STATE_POSSIBLE,
25310 	    STATE_BEGAN: STATE_BEGAN,
25311 	    STATE_CHANGED: STATE_CHANGED,
25312 	    STATE_ENDED: STATE_ENDED,
25313 	    STATE_RECOGNIZED: STATE_RECOGNIZED,
25314 	    STATE_CANCELLED: STATE_CANCELLED,
25315 	    STATE_FAILED: STATE_FAILED,
25316 
25317 	    DIRECTION_NONE: DIRECTION_NONE,
25318 	    DIRECTION_LEFT: DIRECTION_LEFT,
25319 	    DIRECTION_RIGHT: DIRECTION_RIGHT,
25320 	    DIRECTION_UP: DIRECTION_UP,
25321 	    DIRECTION_DOWN: DIRECTION_DOWN,
25322 	    DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
25323 	    DIRECTION_VERTICAL: DIRECTION_VERTICAL,
25324 	    DIRECTION_ALL: DIRECTION_ALL,
25325 
25326 	    Manager: Manager,
25327 	    Input: Input,
25328 	    TouchAction: TouchAction,
25329 
25330 	    TouchInput: TouchInput,
25331 	    MouseInput: MouseInput,
25332 	    PointerEventInput: PointerEventInput,
25333 	    TouchMouseInput: TouchMouseInput,
25334 	    SingleTouchInput: SingleTouchInput,
25335 
25336 	    Recognizer: Recognizer,
25337 	    AttrRecognizer: AttrRecognizer,
25338 	    Tap: TapRecognizer,
25339 	    Pan: PanRecognizer,
25340 	    Swipe: SwipeRecognizer,
25341 	    Pinch: PinchRecognizer,
25342 	    Rotate: RotateRecognizer,
25343 	    Press: PressRecognizer,
25344 
25345 	    on: addEventListeners,
25346 	    off: removeEventListeners,
25347 	    each: each,
25348 	    merge: merge,
25349 	    extend: extend,
25350 	    assign: assign,
25351 	    inherit: inherit,
25352 	    bindFn: bindFn,
25353 	    prefixed: prefixed
25354 	});
25355 
25356 	// this prevents errors when Hammer is loaded in the presence of an AMD
25357 	//  style loader but by script tag, not by the loader.
25358 	var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
25359 	freeGlobal.Hammer = Hammer;
25360 
25361 	if (typeof undefined$1 === 'function' && undefined$1.amd) {
25362 	    undefined$1(function() {
25363 	        return Hammer;
25364 	    });
25365 	} else if (module.exports) {
25366 	    module.exports = Hammer;
25367 	} else {
25368 	    window[exportName] = Hammer;
25369 	}
25370 
25371 	})(window, document, 'Hammer');
25372 	}(hammer));
25373 
25374 	var Hammer = hammer.exports;
25375 
25376 	var MIN_ZOOM = 0.2,
25377 	    MAX_ZOOM = 4;
25378 
25379 	var mouseEvents = [
25380 	  'mousedown',
25381 	  'mouseup',
25382 	  'mouseover',
25383 	  'mouseout',
25384 	  'click',
25385 	  'dblclick'
25386 	];
25387 
25388 	function get(service, injector) {
25389 	  return injector.get(service, false);
25390 	}
25391 
25392 	function stopEvent(event) {
25393 
25394 	  event.preventDefault();
25395 
25396 	  if (typeof event.stopPropagation === 'function') {
25397 	    event.stopPropagation();
25398 	  } else if (event.srcEvent && typeof event.srcEvent.stopPropagation === 'function') {
25399 
25400 	    // iPhone & iPad
25401 	    event.srcEvent.stopPropagation();
25402 	  }
25403 
25404 	  if (typeof event.stopImmediatePropagation === 'function') {
25405 	    event.stopImmediatePropagation();
25406 	  }
25407 	}
25408 
25409 
25410 	function createTouchRecognizer(node) {
25411 
25412 	  function stopMouse(event) {
25413 
25414 	    forEach(mouseEvents, function(e) {
25415 	      componentEvent.bind(node, e, stopEvent, true);
25416 	    });
25417 	  }
25418 
25419 	  function allowMouse(event) {
25420 	    setTimeout(function() {
25421 	      forEach(mouseEvents, function(e) {
25422 	        componentEvent.unbind(node, e, stopEvent, true);
25423 	      });
25424 	    }, 500);
25425 	  }
25426 
25427 	  componentEvent.bind(node, 'touchstart', stopMouse, true);
25428 	  componentEvent.bind(node, 'touchend', allowMouse, true);
25429 	  componentEvent.bind(node, 'touchcancel', allowMouse, true);
25430 
25431 	  // A touch event recognizer that handles
25432 	  // touch events only (we know, we can already handle
25433 	  // mouse events out of the box)
25434 
25435 	  var recognizer = new Hammer.Manager(node, {
25436 	    inputClass: Hammer.TouchInput,
25437 	    recognizers: [],
25438 	    domEvents: true
25439 	  });
25440 
25441 
25442 	  var tap = new Hammer.Tap();
25443 	  var pan = new Hammer.Pan({ threshold: 10 });
25444 	  var press = new Hammer.Press();
25445 	  var pinch = new Hammer.Pinch();
25446 
25447 	  var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });
25448 
25449 	  pinch.requireFailure(pan);
25450 	  pinch.requireFailure(press);
25451 
25452 	  recognizer.add([ pan, press, pinch, doubleTap, tap ]);
25453 
25454 	  recognizer.reset = function(force) {
25455 	    var recognizers = this.recognizers,
25456 	        session = this.session;
25457 
25458 	    if (session.stopped) {
25459 	      return;
25460 	    }
25461 
25462 	    recognizer.stop(force);
25463 
25464 	    setTimeout(function() {
25465 	      var i, r;
25466 	      for (i = 0; (r = recognizers[i]); i++) {
25467 	        r.reset();
25468 	        r.state = 8; // FAILED STATE
25469 	      }
25470 
25471 	      session.curRecognizer = null;
25472 	    }, 0);
25473 	  };
25474 
25475 	  recognizer.on('hammer.input', function(event) {
25476 	    if (event.srcEvent.defaultPrevented) {
25477 	      recognizer.reset(true);
25478 	    }
25479 	  });
25480 
25481 	  return recognizer;
25482 	}
25483 
25484 	/**
25485 	 * A plugin that provides touch events for elements.
25486 	 *
25487 	 * @param {EventBus} eventBus
25488 	 * @param {InteractionEvents} interactionEvents
25489 	 */
25490 	function TouchInteractionEvents(
25491 	    injector, canvas, eventBus,
25492 	    elementRegistry, interactionEvents) {
25493 
25494 	  // optional integrations
25495 	  var dragging = get('dragging', injector),
25496 	      move = get('move', injector),
25497 	      contextPad = get('contextPad', injector),
25498 	      palette = get('palette', injector);
25499 
25500 	  // the touch recognizer
25501 	  var recognizer;
25502 
25503 	  function handler(type) {
25504 
25505 	    return function(event) {
25506 
25507 	      interactionEvents.fire(type, event);
25508 	    };
25509 	  }
25510 
25511 	  function getGfx(target) {
25512 	    var node = closest(target, 'svg, .djs-element', true);
25513 	    return node;
25514 	  }
25515 
25516 	  function initEvents(svg) {
25517 
25518 	    // touch recognizer
25519 	    recognizer = createTouchRecognizer(svg);
25520 
25521 	    recognizer.on('doubletap', handler('element.dblclick'));
25522 
25523 	    recognizer.on('tap', handler('element.click'));
25524 
25525 	    function startGrabCanvas(event) {
25526 
25527 	      var lx = 0, ly = 0;
25528 
25529 	      function update(e) {
25530 
25531 	        var dx = e.deltaX - lx,
25532 	            dy = e.deltaY - ly;
25533 
25534 	        canvas.scroll({ dx: dx, dy: dy });
25535 
25536 	        lx = e.deltaX;
25537 	        ly = e.deltaY;
25538 	      }
25539 
25540 	      function end(e) {
25541 	        recognizer.off('panmove', update);
25542 	        recognizer.off('panend', end);
25543 	        recognizer.off('pancancel', end);
25544 	      }
25545 
25546 	      recognizer.on('panmove', update);
25547 	      recognizer.on('panend', end);
25548 	      recognizer.on('pancancel', end);
25549 	    }
25550 
25551 	    function startGrab(event) {
25552 
25553 	      var gfx = getGfx(event.target),
25554 	          element = gfx && elementRegistry.get(gfx);
25555 
25556 	      // recognizer
25557 	      if (move && canvas.getRootElement() !== element) {
25558 	        return move.start(event, element, true);
25559 	      } else {
25560 	        startGrabCanvas();
25561 	      }
25562 	    }
25563 
25564 	    function startZoom(e) {
25565 
25566 	      var zoom = canvas.zoom(),
25567 	          mid = e.center;
25568 
25569 	      function update(e) {
25570 
25571 	        var ratio = 1 - (1 - e.scale) / 1.50,
25572 	            newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, ratio * zoom));
25573 
25574 	        canvas.zoom(newZoom, mid);
25575 
25576 	        stopEvent(e);
25577 	      }
25578 
25579 	      function end(e) {
25580 	        recognizer.off('pinchmove', update);
25581 	        recognizer.off('pinchend', end);
25582 	        recognizer.off('pinchcancel', end);
25583 
25584 	        recognizer.reset(true);
25585 	      }
25586 
25587 	      recognizer.on('pinchmove', update);
25588 	      recognizer.on('pinchend', end);
25589 	      recognizer.on('pinchcancel', end);
25590 	    }
25591 
25592 	    recognizer.on('panstart', startGrab);
25593 	    recognizer.on('press', startGrab);
25594 
25595 	    recognizer.on('pinchstart', startZoom);
25596 	  }
25597 
25598 	  if (dragging) {
25599 
25600 	    // simulate hover during dragging
25601 	    eventBus.on('drag.move', function(event) {
25602 
25603 	      var originalEvent = event.originalEvent;
25604 
25605 	      if (!originalEvent || originalEvent instanceof MouseEvent) {
25606 	        return;
25607 	      }
25608 
25609 	      var position = toPoint(originalEvent);
25610 
25611 	      // this gets really expensive ...
25612 	      var node = document.elementFromPoint(position.x, position.y),
25613 	          gfx = getGfx(node),
25614 	          element = gfx && elementRegistry.get(gfx);
25615 
25616 	      if (element !== event.hover) {
25617 	        if (event.hover) {
25618 	          dragging.out(event);
25619 	        }
25620 
25621 	        if (element) {
25622 	          dragging.hover({ element: element, gfx: gfx });
25623 
25624 	          event.hover = element;
25625 	          event.hoverGfx = gfx;
25626 	        }
25627 	      }
25628 	    });
25629 	  }
25630 
25631 	  if (contextPad) {
25632 
25633 	    eventBus.on('contextPad.create', function(event) {
25634 	      var node = event.pad.html;
25635 
25636 	      // touch recognizer
25637 	      var padRecognizer = createTouchRecognizer(node);
25638 
25639 	      padRecognizer.on('panstart', function(event) {
25640 	        contextPad.trigger('dragstart', event, true);
25641 	      });
25642 
25643 	      padRecognizer.on('press', function(event) {
25644 	        contextPad.trigger('dragstart', event, true);
25645 	      });
25646 
25647 	      padRecognizer.on('tap', function(event) {
25648 	        contextPad.trigger('click', event);
25649 	      });
25650 	    });
25651 	  }
25652 
25653 	  if (palette) {
25654 	    eventBus.on('palette.create', function(event) {
25655 	      var node = event.container;
25656 
25657 	      // touch recognizer
25658 	      var padRecognizer = createTouchRecognizer(node);
25659 
25660 	      padRecognizer.on('panstart', function(event) {
25661 	        palette.trigger('dragstart', event, true);
25662 	      });
25663 
25664 	      padRecognizer.on('press', function(event) {
25665 	        palette.trigger('dragstart', event, true);
25666 	      });
25667 
25668 	      padRecognizer.on('tap', function(event) {
25669 	        palette.trigger('click', event);
25670 	      });
25671 	    });
25672 	  }
25673 
25674 	  eventBus.on('canvas.init', function(event) {
25675 	    initEvents(event.svg);
25676 	  });
25677 	}
25678 
25679 
25680 	TouchInteractionEvents.$inject = [
25681 	  'injector',
25682 	  'canvas',
25683 	  'eventBus',
25684 	  'elementRegistry',
25685 	  'interactionEvents',
25686 	  'touchFix'
25687 	];
25688 
25689 	function TouchFix(canvas, eventBus) {
25690 
25691 	  var self = this;
25692 
25693 	  eventBus.on('canvas.init', function(e) {
25694 	    self.addBBoxMarker(e.svg);
25695 	  });
25696 	}
25697 
25698 	TouchFix.$inject = [ 'canvas', 'eventBus' ];
25699 
25700 
25701 	/**
25702 	 * Safari mobile (iOS 7) does not fire touchstart event in <SVG> element
25703 	 * if there is no shape between 0,0 and viewport elements origin.
25704 	 *
25705 	 * So touchstart event is only fired when the <g class="viewport"> element was hit.
25706 	 * Putting an element over and below the 'viewport' fixes that behavior.
25707 	 */
25708 	TouchFix.prototype.addBBoxMarker = function(svg) {
25709 
25710 	  var markerStyle = {
25711 	    fill: 'none',
25712 	    class: 'outer-bound-marker'
25713 	  };
25714 
25715 	  var rect1 = create$1('rect');
25716 	  attr(rect1, {
25717 	    x: -10000,
25718 	    y: 10000,
25719 	    width: 10,
25720 	    height: 10
25721 	  });
25722 	  attr(rect1, markerStyle);
25723 
25724 	  append(svg, rect1);
25725 
25726 	  var rect2 = create$1('rect');
25727 	  attr(rect2, {
25728 	    x: 10000,
25729 	    y: 10000,
25730 	    width: 10,
25731 	    height: 10
25732 	  });
25733 	  attr(rect2, markerStyle);
25734 
25735 	  append(svg, rect2);
25736 	};
25737 
25738 	var TouchModule$1 = {
25739 	  __depends__: [ InteractionEventsModule$1 ],
25740 	  __init__: [ 'touchInteractionEvents' ],
25741 	  touchInteractionEvents: [ 'type', TouchInteractionEvents ],
25742 	  touchFix: [ 'type', TouchFix ]
25743 	};
25744 
25745 	var TouchModule = {
25746 	  __depends__: [
25747 	    TouchModule$1
25748 	  ]
25749 	};
25750 
25751 	function last(arr) {
25752 	  return arr && arr[arr.length - 1];
25753 	}
25754 
25755 	function sortTopOrMiddle(element) {
25756 	  return element.y;
25757 	}
25758 
25759 	function sortLeftOrCenter(element) {
25760 	  return element.x;
25761 	}
25762 
25763 	/**
25764 	 * Sorting functions for different types of alignment
25765 	 *
25766 	 * @type {Object}
25767 	 *
25768 	 * @return {Function}
25769 	 */
25770 	var ALIGNMENT_SORTING = {
25771 	  left: sortLeftOrCenter,
25772 	  center: sortLeftOrCenter,
25773 	  right: function(element) {
25774 	    return element.x + element.width;
25775 	  },
25776 	  top: sortTopOrMiddle,
25777 	  middle: sortTopOrMiddle,
25778 	  bottom: function(element) {
25779 	    return element.y + element.height;
25780 	  }
25781 	};
25782 
25783 
25784 	function AlignElements$1(modeling) {
25785 	  this._modeling = modeling;
25786 	}
25787 
25788 	AlignElements$1.$inject = [ 'modeling' ];
25789 
25790 
25791 	/**
25792 	 * Get the relevant "axis" and "dimension" related to the current type of alignment
25793 	 *
25794 	 * @param  {string} type left|right|center|top|bottom|middle
25795 	 *
25796 	 * @return {Object} { axis, dimension }
25797 	 */
25798 	AlignElements$1.prototype._getOrientationDetails = function(type) {
25799 	  var vertical = [ 'top', 'bottom', 'middle' ],
25800 	      axis = 'x',
25801 	      dimension = 'width';
25802 
25803 	  if (vertical.indexOf(type) !== -1) {
25804 	    axis = 'y';
25805 	    dimension = 'height';
25806 	  }
25807 
25808 	  return {
25809 	    axis: axis,
25810 	    dimension: dimension
25811 	  };
25812 	};
25813 
25814 	AlignElements$1.prototype._isType = function(type, types) {
25815 	  return types.indexOf(type) !== -1;
25816 	};
25817 
25818 	/**
25819 	 * Get a point on the relevant axis where elements should align to
25820 	 *
25821 	 * @param  {string} type left|right|center|top|bottom|middle
25822 	 * @param  {Array} sortedElements
25823 	 *
25824 	 * @return {Object}
25825 	 */
25826 	AlignElements$1.prototype._alignmentPosition = function(type, sortedElements) {
25827 	  var orientation = this._getOrientationDetails(type),
25828 	      axis = orientation.axis,
25829 	      dimension = orientation.dimension,
25830 	      alignment = {},
25831 	      centers = {},
25832 	      hasSharedCenters = false,
25833 	      centeredElements,
25834 	      firstElement,
25835 	      lastElement;
25836 
25837 	  function getMiddleOrTop(first, last) {
25838 	    return Math.round((first[axis] + last[axis] + last[dimension]) / 2);
25839 	  }
25840 
25841 	  if (this._isType(type, [ 'left', 'top' ])) {
25842 	    alignment[type] = sortedElements[0][axis];
25843 
25844 	  } else if (this._isType(type, [ 'right', 'bottom' ])) {
25845 	    lastElement = last(sortedElements);
25846 
25847 	    alignment[type] = lastElement[axis] + lastElement[dimension];
25848 
25849 	  } else if (this._isType(type, [ 'center', 'middle' ])) {
25850 
25851 	    // check if there is a center shared by more than one shape
25852 	    // if not, just take the middle of the range
25853 	    forEach(sortedElements, function(element) {
25854 	      var center = element[axis] + Math.round(element[dimension] / 2);
25855 
25856 	      if (centers[center]) {
25857 	        centers[center].elements.push(element);
25858 	      } else {
25859 	        centers[center] = {
25860 	          elements: [ element ],
25861 	          center: center
25862 	        };
25863 	      }
25864 	    });
25865 
25866 	    centeredElements = sortBy(centers, function(center) {
25867 	      if (center.elements.length > 1) {
25868 	        hasSharedCenters = true;
25869 	      }
25870 
25871 	      return center.elements.length;
25872 	    });
25873 
25874 	    if (hasSharedCenters) {
25875 	      alignment[type] = last(centeredElements).center;
25876 
25877 	      return alignment;
25878 	    }
25879 
25880 	    firstElement = sortedElements[0];
25881 
25882 	    sortedElements = sortBy(sortedElements, function(element) {
25883 	      return element[axis] + element[dimension];
25884 	    });
25885 
25886 	    lastElement = last(sortedElements);
25887 
25888 	    alignment[type] = getMiddleOrTop(firstElement, lastElement);
25889 	  }
25890 
25891 	  return alignment;
25892 	};
25893 
25894 	/**
25895 	 * Executes the alignment of a selection of elements
25896 	 *
25897 	 * @param  {Array} elements
25898 	 * @param  {string} type left|right|center|top|bottom|middle
25899 	 */
25900 	AlignElements$1.prototype.trigger = function(elements, type) {
25901 	  var modeling = this._modeling;
25902 
25903 	  var filteredElements = filter(elements, function(element) {
25904 	    return !(element.waypoints || element.host || element.labelTarget);
25905 	  });
25906 
25907 	  if (filteredElements.length < 2) {
25908 	    return;
25909 	  }
25910 
25911 	  var sortFn = ALIGNMENT_SORTING[type];
25912 
25913 	  var sortedElements = sortBy(filteredElements, sortFn);
25914 
25915 	  var alignment = this._alignmentPosition(type, sortedElements);
25916 
25917 	  modeling.alignElements(sortedElements, alignment);
25918 	};
25919 
25920 	var AlignElementsModule = {
25921 	  __init__: [ 'alignElements' ],
25922 	  alignElements: [ 'type', AlignElements$1 ]
25923 	};
25924 
25925 	// padding to detect element placement
25926 	var PLACEMENT_DETECTION_PAD = 10;
25927 
25928 	var DEFAULT_DISTANCE = 50;
25929 
25930 	var DEFAULT_MAX_DISTANCE = 250;
25931 
25932 
25933 	/**
25934 	 * Get free position starting from given position.
25935 	 *
25936 	 * @param {djs.model.Shape} source
25937 	 * @param {djs.model.Shape} element
25938 	 * @param {Point} position
25939 	 * @param {Function} getNextPosition
25940 	 *
25941 	 * @return {Point}
25942 	 */
25943 	function findFreePosition(source, element, position, getNextPosition) {
25944 	  var connectedAtPosition;
25945 
25946 	  while ((connectedAtPosition = getConnectedAtPosition(source, position, element))) {
25947 	    position = getNextPosition(element, position, connectedAtPosition);
25948 	  }
25949 
25950 	  return position;
25951 	}
25952 
25953 	/**
25954 	 * Returns function that returns next position.
25955 	 *
25956 	 * @param {Object} nextPositionDirection
25957 	 * @param {Object} [nextPositionDirection.x]
25958 	 * @param {Object} [nextPositionDirection.y]
25959 	 *
25960 	 * @returns {Function}
25961 	 */
25962 	function generateGetNextPosition(nextPositionDirection) {
25963 	  return function(element, previousPosition, connectedAtPosition) {
25964 	    var nextPosition = {
25965 	      x: previousPosition.x,
25966 	      y: previousPosition.y
25967 	    };
25968 
25969 	    [ 'x', 'y' ].forEach(function(axis) {
25970 
25971 	      var nextPositionDirectionForAxis = nextPositionDirection[ axis ];
25972 
25973 	      if (!nextPositionDirectionForAxis) {
25974 	        return;
25975 	      }
25976 
25977 	      var dimension = axis === 'x' ? 'width' : 'height';
25978 
25979 	      var margin = nextPositionDirectionForAxis.margin,
25980 	          minDistance = nextPositionDirectionForAxis.minDistance;
25981 
25982 	      if (margin < 0) {
25983 	        nextPosition[ axis ] = Math.min(
25984 	          connectedAtPosition[ axis ] + margin - element[ dimension ] / 2,
25985 	          previousPosition[ axis ] - minDistance + margin
25986 	        );
25987 	      } else {
25988 	        nextPosition[ axis ] = Math.max(
25989 	          connectedAtPosition[ axis ] + connectedAtPosition[ dimension ] + margin + element[ dimension ] / 2,
25990 	          previousPosition[ axis ] + minDistance + margin
25991 	        );
25992 	      }
25993 	    });
25994 
25995 	    return nextPosition;
25996 	  };
25997 	}
25998 
25999 	/**
26000 	 * Return target at given position, if defined.
26001 	 *
26002 	 * This takes connected elements from host and attachers
26003 	 * into account, too.
26004 	 */
26005 	function getConnectedAtPosition(source, position, element) {
26006 
26007 	  var bounds = {
26008 	    x: position.x - (element.width / 2),
26009 	    y: position.y - (element.height / 2),
26010 	    width: element.width,
26011 	    height: element.height
26012 	  };
26013 
26014 	  var closure = getAutoPlaceClosure(source);
26015 
26016 	  return find(closure, function(target) {
26017 
26018 	    if (target === element) {
26019 	      return false;
26020 	    }
26021 
26022 	    var orientation = getOrientation(target, bounds, PLACEMENT_DETECTION_PAD);
26023 
26024 	    return orientation === 'intersect';
26025 	  });
26026 	}
26027 
26028 	/**
26029 	* Compute optimal distance between source and target based on existing connections to and from source.
26030 	* Assumes left-to-right and top-to-down modeling.
26031 	*
26032 	* @param {djs.model.Shape} source
26033 	* @param {Object} [hints]
26034 	* @param {number} [hints.defaultDistance]
26035 	* @param {string} [hints.direction]
26036 	* @param {Function} [hints.filter]
26037 	* @param {Function} [hints.getWeight]
26038 	* @param {number} [hints.maxDistance]
26039 	* @param {string} [hints.reference]
26040 	*
26041 	* @return {number}
26042 	*/
26043 	function getConnectedDistance(source, hints) {
26044 	  if (!hints) {
26045 	    hints = {};
26046 	  }
26047 
26048 	  // targets > sources by default
26049 	  function getDefaultWeight(connection) {
26050 	    return connection.source === source ? 1 : -1;
26051 	  }
26052 
26053 	  var defaultDistance = hints.defaultDistance || DEFAULT_DISTANCE,
26054 	      direction = hints.direction || 'e',
26055 	      filter = hints.filter,
26056 	      getWeight = hints.getWeight || getDefaultWeight,
26057 	      maxDistance = hints.maxDistance || DEFAULT_MAX_DISTANCE,
26058 	      reference = hints.reference || 'start';
26059 
26060 	  if (!filter) {
26061 	    filter = noneFilter;
26062 	  }
26063 
26064 	  function getDistance(a, b) {
26065 	    if (direction === 'n') {
26066 	      if (reference === 'start') {
26067 	        return asTRBL(a).top - asTRBL(b).bottom;
26068 	      } else if (reference === 'center') {
26069 	        return asTRBL(a).top - getMid(b).y;
26070 	      } else {
26071 	        return asTRBL(a).top - asTRBL(b).top;
26072 	      }
26073 	    } else if (direction === 'w') {
26074 	      if (reference === 'start') {
26075 	        return asTRBL(a).left - asTRBL(b).right;
26076 	      } else if (reference === 'center') {
26077 	        return asTRBL(a).left - getMid(b).x;
26078 	      } else {
26079 	        return asTRBL(a).left - asTRBL(b).left;
26080 	      }
26081 	    } else if (direction === 's') {
26082 	      if (reference === 'start') {
26083 	        return asTRBL(b).top - asTRBL(a).bottom;
26084 	      } else if (reference === 'center') {
26085 	        return getMid(b).y - asTRBL(a).bottom;
26086 	      } else {
26087 	        return asTRBL(b).bottom - asTRBL(a).bottom;
26088 	      }
26089 	    } else {
26090 	      if (reference === 'start') {
26091 	        return asTRBL(b).left - asTRBL(a).right;
26092 	      } else if (reference === 'center') {
26093 	        return getMid(b).x - asTRBL(a).right;
26094 	      } else {
26095 	        return asTRBL(b).right - asTRBL(a).right;
26096 	      }
26097 	    }
26098 	  }
26099 
26100 	  var sourcesDistances = source.incoming
26101 	    .filter(filter)
26102 	    .map(function(connection) {
26103 	      var weight = getWeight(connection);
26104 
26105 	      var distance = weight < 0
26106 	        ? getDistance(connection.source, source)
26107 	        : getDistance(source, connection.source);
26108 
26109 	      return {
26110 	        id: connection.source.id,
26111 	        distance: distance,
26112 	        weight: weight
26113 	      };
26114 	    });
26115 
26116 	  var targetsDistances = source.outgoing
26117 	    .filter(filter)
26118 	    .map(function(connection) {
26119 	      var weight = getWeight(connection);
26120 
26121 	      var distance = weight > 0
26122 	        ? getDistance(source, connection.target)
26123 	        : getDistance(connection.target, source);
26124 
26125 	      return {
26126 	        id: connection.target.id,
26127 	        distance: distance,
26128 	        weight: weight
26129 	      };
26130 	    });
26131 
26132 	  var distances = sourcesDistances.concat(targetsDistances).reduce(function(accumulator, currentValue) {
26133 	    accumulator[ currentValue.id + '__weight_' + currentValue.weight ] = currentValue;
26134 
26135 	    return accumulator;
26136 	  }, {});
26137 
26138 	  var distancesGrouped = reduce(distances, function(accumulator, currentValue) {
26139 	    var distance = currentValue.distance,
26140 	        weight = currentValue.weight;
26141 
26142 	    if (distance < 0 || distance > maxDistance) {
26143 	      return accumulator;
26144 	    }
26145 
26146 	    if (!accumulator[ String(distance) ]) {
26147 	      accumulator[ String(distance) ] = 0;
26148 	    }
26149 
26150 	    accumulator[ String(distance) ] += 1 * weight;
26151 
26152 	    if (!accumulator.distance || accumulator[ accumulator.distance ] < accumulator[ String(distance) ]) {
26153 	      accumulator.distance = distance;
26154 	    }
26155 
26156 	    return accumulator;
26157 	  }, {});
26158 
26159 	  return distancesGrouped.distance || defaultDistance;
26160 	}
26161 
26162 	/**
26163 	 * Returns all connected elements around the given source.
26164 	 *
26165 	 * This includes:
26166 	 *
26167 	 *   - connected elements
26168 	 *   - host connected elements
26169 	 *   - attachers connected elements
26170 	 *
26171 	 * @param  {djs.model.Shape} source
26172 	 *
26173 	 * @return {Array<djs.model.Shape>}
26174 	 */
26175 	function getAutoPlaceClosure(source) {
26176 
26177 	  var allConnected = getConnected(source);
26178 
26179 	  if (source.host) {
26180 	    allConnected = allConnected.concat(getConnected(source.host));
26181 	  }
26182 
26183 	  if (source.attachers) {
26184 	    allConnected = allConnected.concat(source.attachers.reduce(function(shapes, attacher) {
26185 	      return shapes.concat(getConnected(attacher));
26186 	    }, []));
26187 	  }
26188 
26189 	  return allConnected;
26190 	}
26191 
26192 	function getConnected(element) {
26193 	  return getTargets(element).concat(getSources(element));
26194 	}
26195 
26196 	function getSources(shape) {
26197 	  return shape.incoming.map(function(connection) {
26198 	    return connection.source;
26199 	  });
26200 	}
26201 
26202 	function getTargets(shape) {
26203 	  return shape.outgoing.map(function(connection) {
26204 	    return connection.target;
26205 	  });
26206 	}
26207 
26208 	function noneFilter() {
26209 	  return true;
26210 	}
26211 
26212 	var LOW_PRIORITY$i = 100;
26213 
26214 
26215 	/**
26216 	 * A service that places elements connected to existing ones
26217 	 * to an appropriate position in an _automated_ fashion.
26218 	 *
26219 	 * @param {EventBus} eventBus
26220 	 * @param {Modeling} modeling
26221 	 */
26222 	function AutoPlace$1(eventBus, modeling, canvas) {
26223 
26224 	  eventBus.on('autoPlace', LOW_PRIORITY$i, function(context) {
26225 	    var shape = context.shape,
26226 	        source = context.source;
26227 
26228 	    return getNewShapePosition$1(source, shape);
26229 	  });
26230 
26231 	  eventBus.on('autoPlace.end', function(event) {
26232 	    canvas.scrollToElement(event.shape);
26233 	  });
26234 
26235 	  /**
26236 	   * Append shape to source at appropriate position.
26237 	   *
26238 	   * @param {djs.model.Shape} source
26239 	   * @param {djs.model.Shape} shape
26240 	   *
26241 	   * @return {djs.model.Shape} appended shape
26242 	   */
26243 	  this.append = function(source, shape, hints) {
26244 
26245 	    eventBus.fire('autoPlace.start', {
26246 	      source: source,
26247 	      shape: shape
26248 	    });
26249 
26250 	    // allow others to provide the position
26251 	    var position = eventBus.fire('autoPlace', {
26252 	      source: source,
26253 	      shape: shape
26254 	    });
26255 
26256 	    var newShape = modeling.appendShape(source, shape, position, source.parent, hints);
26257 
26258 	    eventBus.fire('autoPlace.end', {
26259 	      source: source,
26260 	      shape: newShape
26261 	    });
26262 
26263 	    return newShape;
26264 	  };
26265 
26266 	}
26267 
26268 	AutoPlace$1.$inject = [
26269 	  'eventBus',
26270 	  'modeling',
26271 	  'canvas'
26272 	];
26273 
26274 	// helpers //////////
26275 
26276 	/**
26277 	 * Find the new position for the target element to
26278 	 * connect to source.
26279 	 *
26280 	 * @param  {djs.model.Shape} source
26281 	 * @param  {djs.model.Shape} element
26282 	 * @param  {Object} [hints]
26283 	 * @param  {Object} [hints.defaultDistance]
26284 	 *
26285 	 * @returns {Point}
26286 	 */
26287 	function getNewShapePosition$1(source, element, hints) {
26288 	  if (!hints) {
26289 	    hints = {};
26290 	  }
26291 
26292 	  var distance = hints.defaultDistance || DEFAULT_DISTANCE;
26293 
26294 	  var sourceMid = getMid(source),
26295 	      sourceTrbl = asTRBL(source);
26296 
26297 	  // simply put element right next to source
26298 	  return {
26299 	    x: sourceTrbl.right + distance + element.width / 2,
26300 	    y: sourceMid.y
26301 	  };
26302 	}
26303 
26304 	/**
26305 	 * Select element after auto placement.
26306 	 *
26307 	 * @param {EventBus} eventBus
26308 	 * @param {Selection} selection
26309 	 */
26310 	function AutoPlaceSelectionBehavior(eventBus, selection) {
26311 
26312 	  eventBus.on('autoPlace.end', 500, function(e) {
26313 	    selection.select(e.shape);
26314 	  });
26315 
26316 	}
26317 
26318 	AutoPlaceSelectionBehavior.$inject = [
26319 	  'eventBus',
26320 	  'selection'
26321 	];
26322 
26323 	var AutoPlaceModule$1 = {
26324 	  __init__: [ 'autoPlaceSelectionBehavior' ],
26325 	  autoPlace: [ 'type', AutoPlace$1 ],
26326 	  autoPlaceSelectionBehavior: [ 'type', AutoPlaceSelectionBehavior ]
26327 	};
26328 
26329 	/**
26330 	 * Return true if element has any of the given types.
26331 	 *
26332 	 * @param {djs.model.Base} element
26333 	 * @param {Array<string>} types
26334 	 *
26335 	 * @return {boolean}
26336 	 */
26337 	function isAny(element, types) {
26338 	  return some(types, function(t) {
26339 	    return is$1(element, t);
26340 	  });
26341 	}
26342 
26343 
26344 	/**
26345 	 * Return the parent of the element with any of the given types.
26346 	 *
26347 	 * @param {djs.model.Base} element
26348 	 * @param {string|Array<string>} anyType
26349 	 *
26350 	 * @return {djs.model.Base}
26351 	 */
26352 	function getParent(element, anyType) {
26353 
26354 	  if (typeof anyType === 'string') {
26355 	    anyType = [ anyType ];
26356 	  }
26357 
26358 	  while ((element = element.parent)) {
26359 	    if (isAny(element, anyType)) {
26360 	      return element;
26361 	    }
26362 	  }
26363 
26364 	  return null;
26365 	}
26366 
26367 	/**
26368 	 * Find the new position for the target element to
26369 	 * connect to source.
26370 	 *
26371 	 * @param  {djs.model.Shape} source
26372 	 * @param  {djs.model.Shape} element
26373 	 *
26374 	 * @return {Point}
26375 	 */
26376 	function getNewShapePosition(source, element) {
26377 
26378 	  if (is$1(element, 'bpmn:TextAnnotation')) {
26379 	    return getTextAnnotationPosition(source, element);
26380 	  }
26381 
26382 	  if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
26383 	    return getDataElementPosition(source, element);
26384 	  }
26385 
26386 	  if (is$1(element, 'bpmn:FlowNode')) {
26387 	    return getFlowNodePosition(source, element);
26388 	  }
26389 	}
26390 
26391 	/**
26392 	 * Always try to place element right of source;
26393 	 * compute actual distance from previous nodes in flow.
26394 	 */
26395 	function getFlowNodePosition(source, element) {
26396 
26397 	  var sourceTrbl = asTRBL(source);
26398 	  var sourceMid = getMid(source);
26399 
26400 	  var horizontalDistance = getConnectedDistance(source, {
26401 	    filter: function(connection) {
26402 	      return is$1(connection, 'bpmn:SequenceFlow');
26403 	    }
26404 	  });
26405 
26406 	  var margin = 30,
26407 	      minDistance = 80,
26408 	      orientation = 'left';
26409 
26410 	  if (is$1(source, 'bpmn:BoundaryEvent')) {
26411 	    orientation = getOrientation(source, source.host, -25);
26412 
26413 	    if (orientation.indexOf('top') !== -1) {
26414 	      margin *= -1;
26415 	    }
26416 	  }
26417 
26418 	  var position = {
26419 	    x: sourceTrbl.right + horizontalDistance + element.width / 2,
26420 	    y: sourceMid.y + getVerticalDistance(orientation, minDistance)
26421 	  };
26422 
26423 	  var nextPositionDirection = {
26424 	    y: {
26425 	      margin: margin,
26426 	      minDistance: minDistance
26427 	    }
26428 	  };
26429 
26430 	  return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
26431 	}
26432 
26433 
26434 	function getVerticalDistance(orientation, minDistance) {
26435 	  if (orientation.indexOf('top') != -1) {
26436 	    return -1 * minDistance;
26437 	  } else if (orientation.indexOf('bottom') != -1) {
26438 	    return minDistance;
26439 	  } else {
26440 	    return 0;
26441 	  }
26442 	}
26443 
26444 
26445 	/**
26446 	 * Always try to place text annotations top right of source.
26447 	 */
26448 	function getTextAnnotationPosition(source, element) {
26449 
26450 	  var sourceTrbl = asTRBL(source);
26451 
26452 	  var position = {
26453 	    x: sourceTrbl.right + element.width / 2,
26454 	    y: sourceTrbl.top - 50 - element.height / 2
26455 	  };
26456 
26457 	  var nextPositionDirection = {
26458 	    y: {
26459 	      margin: -30,
26460 	      minDistance: 20
26461 	    }
26462 	  };
26463 
26464 	  return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
26465 	}
26466 
26467 
26468 	/**
26469 	 * Always put element bottom right of source.
26470 	 */
26471 	function getDataElementPosition(source, element) {
26472 
26473 	  var sourceTrbl = asTRBL(source);
26474 
26475 	  var position = {
26476 	    x: sourceTrbl.right - 10 + element.width / 2,
26477 	    y: sourceTrbl.bottom + 40 + element.width / 2
26478 	  };
26479 
26480 	  var nextPositionDirection = {
26481 	    x: {
26482 	      margin: 30,
26483 	      minDistance: 30
26484 	    }
26485 	  };
26486 
26487 	  return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
26488 	}
26489 
26490 	/**
26491 	 * BPMN auto-place behavior.
26492 	 *
26493 	 * @param {EventBus} eventBus
26494 	 */
26495 	function AutoPlace(eventBus) {
26496 	  eventBus.on('autoPlace', function(context) {
26497 	    var shape = context.shape,
26498 	        source = context.source;
26499 
26500 	    return getNewShapePosition(source, shape);
26501 	  });
26502 	}
26503 
26504 	AutoPlace.$inject = [ 'eventBus' ];
26505 
26506 	var AutoPlaceModule = {
26507 	  __depends__: [ AutoPlaceModule$1 ],
26508 	  __init__: [ 'bpmnAutoPlace' ],
26509 	  bpmnAutoPlace: [ 'type', AutoPlace ]
26510 	};
26511 
26512 	var DEFAULT_PRIORITY$3 = 1000;
26513 
26514 	/**
26515 	 * A utility that can be used to plug-in into the command execution for
26516 	 * extension and/or validation.
26517 	 *
26518 	 * @param {EventBus} eventBus
26519 	 *
26520 	 * @example
26521 	 *
26522 	 * import inherits from 'inherits';
26523 	 *
26524 	 * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
26525 	 *
26526 	 * function CommandLogger(eventBus) {
26527 	 *   CommandInterceptor.call(this, eventBus);
26528 	 *
26529 	 *   this.preExecute(function(event) {
26530 	 *     console.log('command pre-execute', event);
26531 	 *   });
26532 	 * }
26533 	 *
26534 	 * inherits(CommandLogger, CommandInterceptor);
26535 	 *
26536 	 */
26537 	function CommandInterceptor(eventBus) {
26538 	  this._eventBus = eventBus;
26539 	}
26540 
26541 	CommandInterceptor.$inject = [ 'eventBus' ];
26542 
26543 	function unwrapEvent(fn, that) {
26544 	  return function(event) {
26545 	    return fn.call(that || null, event.context, event.command, event);
26546 	  };
26547 	}
26548 
26549 	/**
26550 	 * Register an interceptor for a command execution
26551 	 *
26552 	 * @param {string|Array<string>} [events] list of commands to register on
26553 	 * @param {string} [hook] command hook, i.e. preExecute, executed to listen on
26554 	 * @param {number} [priority] the priority on which to hook into the execution
26555 	 * @param {Function} handlerFn interceptor to be invoked with (event)
26556 	 * @param {boolean} unwrap if true, unwrap the event and pass (context, command, event) to the
26557 	 *                          listener instead
26558 	 * @param {Object} [that] Pass context (`this`) to the handler function
26559 	 */
26560 	CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) {
26561 
26562 	  if (isFunction(hook) || isNumber(hook)) {
26563 	    that = unwrap;
26564 	    unwrap = handlerFn;
26565 	    handlerFn = priority;
26566 	    priority = hook;
26567 	    hook = null;
26568 	  }
26569 
26570 	  if (isFunction(priority)) {
26571 	    that = unwrap;
26572 	    unwrap = handlerFn;
26573 	    handlerFn = priority;
26574 	    priority = DEFAULT_PRIORITY$3;
26575 	  }
26576 
26577 	  if (isObject(unwrap)) {
26578 	    that = unwrap;
26579 	    unwrap = false;
26580 	  }
26581 
26582 	  if (!isFunction(handlerFn)) {
26583 	    throw new Error('handlerFn must be a function');
26584 	  }
26585 
26586 	  if (!isArray$2(events)) {
26587 	    events = [ events ];
26588 	  }
26589 
26590 	  var eventBus = this._eventBus;
26591 
26592 	  forEach(events, function(event) {
26593 
26594 	    // concat commandStack(.event)?(.hook)?
26595 	    var fullEvent = [ 'commandStack', event, hook ].filter(function(e) { return e; }).join('.');
26596 
26597 	    eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
26598 	  });
26599 	};
26600 
26601 
26602 	var hooks = [
26603 	  'canExecute',
26604 	  'preExecute',
26605 	  'preExecuted',
26606 	  'execute',
26607 	  'executed',
26608 	  'postExecute',
26609 	  'postExecuted',
26610 	  'revert',
26611 	  'reverted'
26612 	];
26613 
26614 	/*
26615 	 * Install hook shortcuts
26616 	 *
26617 	 * This will generate the CommandInterceptor#(preExecute|...|reverted) methods
26618 	 * which will in term forward to CommandInterceptor#on.
26619 	 */
26620 	forEach(hooks, function(hook) {
26621 
26622 	  /**
26623 	   * {canExecute|preExecute|preExecuted|execute|executed|postExecute|postExecuted|revert|reverted}
26624 	   *
26625 	   * A named hook for plugging into the command execution
26626 	   *
26627 	   * @param {string|Array<string>} [events] list of commands to register on
26628 	   * @param {number} [priority] the priority on which to hook into the execution
26629 	   * @param {Function} handlerFn interceptor to be invoked with (event)
26630 	   * @param {boolean} [unwrap=false] if true, unwrap the event and pass (context, command, event) to the
26631 	   *                          listener instead
26632 	   * @param {Object} [that] Pass context (`this`) to the handler function
26633 	   */
26634 	  CommandInterceptor.prototype[hook] = function(events, priority, handlerFn, unwrap, that) {
26635 
26636 	    if (isFunction(events) || isNumber(events)) {
26637 	      that = unwrap;
26638 	      unwrap = handlerFn;
26639 	      handlerFn = priority;
26640 	      priority = events;
26641 	      events = null;
26642 	    }
26643 
26644 	    this.on(events, hook, priority, handlerFn, unwrap, that);
26645 	  };
26646 	});
26647 
26648 	/**
26649 	 * An auto resize component that takes care of expanding a parent element
26650 	 * if child elements are created or moved close the parents edge.
26651 	 *
26652 	 * @param {EventBus} eventBus
26653 	 * @param {ElementRegistry} elementRegistry
26654 	 * @param {Modeling} modeling
26655 	 * @param {Rules} rules
26656 	 */
26657 	function AutoResize(eventBus, elementRegistry, modeling, rules) {
26658 
26659 	  CommandInterceptor.call(this, eventBus);
26660 
26661 	  this._elementRegistry = elementRegistry;
26662 	  this._modeling = modeling;
26663 	  this._rules = rules;
26664 
26665 	  var self = this;
26666 
26667 	  this.postExecuted([ 'shape.create' ], function(event) {
26668 	    var context = event.context,
26669 	        hints = context.hints || {},
26670 	        shape = context.shape,
26671 	        parent = context.parent || context.newParent;
26672 
26673 	    if (hints.autoResize === false) {
26674 	      return;
26675 	    }
26676 
26677 	    self._expand([ shape ], parent);
26678 	  });
26679 
26680 	  this.postExecuted([ 'elements.move' ], function(event) {
26681 	    var context = event.context,
26682 	        elements = flatten(values(context.closure.topLevel)),
26683 	        hints = context.hints;
26684 
26685 	    var autoResize = hints ? hints.autoResize : true;
26686 
26687 	    if (autoResize === false) {
26688 	      return;
26689 	    }
26690 
26691 	    var expandings = groupBy(elements, function(element) {
26692 	      return element.parent.id;
26693 	    });
26694 
26695 	    forEach(expandings, function(elements, parentId) {
26696 
26697 	      // optionally filter elements to be considered when resizing
26698 	      if (isArray$2(autoResize)) {
26699 	        elements = elements.filter(function(element) {
26700 	          return find(autoResize, matchPattern({ id: element.id }));
26701 	        });
26702 	      }
26703 
26704 	      self._expand(elements, parentId);
26705 	    });
26706 	  });
26707 
26708 	  this.postExecuted([ 'shape.toggleCollapse' ], function(event) {
26709 	    var context = event.context,
26710 	        hints = context.hints,
26711 	        shape = context.shape;
26712 
26713 	    if (hints && hints.autoResize === false) {
26714 	      return;
26715 	    }
26716 
26717 	    if (shape.collapsed) {
26718 	      return;
26719 	    }
26720 
26721 	    self._expand(shape.children || [], shape);
26722 	  });
26723 
26724 	  this.postExecuted([ 'shape.resize' ], function(event) {
26725 	    var context = event.context,
26726 	        hints = context.hints,
26727 	        shape = context.shape,
26728 	        parent = shape.parent;
26729 
26730 	    if (hints && hints.autoResize === false) {
26731 	      return;
26732 	    }
26733 
26734 	    if (parent) {
26735 	      self._expand([ shape ], parent);
26736 	    }
26737 	  });
26738 
26739 	}
26740 
26741 	AutoResize.$inject = [
26742 	  'eventBus',
26743 	  'elementRegistry',
26744 	  'modeling',
26745 	  'rules'
26746 	];
26747 
26748 	inherits$1(AutoResize, CommandInterceptor);
26749 
26750 
26751 	/**
26752 	 * Calculate the new bounds of the target shape, given
26753 	 * a number of elements have been moved or added into the parent.
26754 	 *
26755 	 * This method considers the current size, the added elements as well as
26756 	 * the provided padding for the new bounds.
26757 	 *
26758 	 * @param {Array<djs.model.Shape>} elements
26759 	 * @param {djs.model.Shape} target
26760 	 */
26761 	AutoResize.prototype._getOptimalBounds = function(elements, target) {
26762 
26763 	  var offset = this.getOffset(target),
26764 	      padding = this.getPadding(target);
26765 
26766 	  var elementsTrbl = asTRBL(getBBox(elements)),
26767 	      targetTrbl = asTRBL(target);
26768 
26769 	  var newTrbl = {};
26770 
26771 	  if (elementsTrbl.top - targetTrbl.top < padding.top) {
26772 	    newTrbl.top = elementsTrbl.top - offset.top;
26773 	  }
26774 
26775 	  if (elementsTrbl.left - targetTrbl.left < padding.left) {
26776 	    newTrbl.left = elementsTrbl.left - offset.left;
26777 	  }
26778 
26779 	  if (targetTrbl.right - elementsTrbl.right < padding.right) {
26780 	    newTrbl.right = elementsTrbl.right + offset.right;
26781 	  }
26782 
26783 	  if (targetTrbl.bottom - elementsTrbl.bottom < padding.bottom) {
26784 	    newTrbl.bottom = elementsTrbl.bottom + offset.bottom;
26785 	  }
26786 
26787 	  return asBounds(assign({}, targetTrbl, newTrbl));
26788 	};
26789 
26790 
26791 	/**
26792 	 * Expand the target shape respecting rules, offset and padding
26793 	 *
26794 	 * @param {Array<djs.model.Shape>} elements
26795 	 * @param {djs.model.Shape|string} target|targetId
26796 	 */
26797 	AutoResize.prototype._expand = function(elements, target) {
26798 
26799 	  if (typeof target === 'string') {
26800 	    target = this._elementRegistry.get(target);
26801 	  }
26802 
26803 	  var allowed = this._rules.allowed('element.autoResize', {
26804 	    elements: elements,
26805 	    target: target
26806 	  });
26807 
26808 	  if (!allowed) {
26809 	    return;
26810 	  }
26811 
26812 	  // calculate the new bounds
26813 	  var newBounds = this._getOptimalBounds(elements, target);
26814 
26815 	  if (!boundsChanged$1(newBounds, target)) {
26816 	    return;
26817 	  }
26818 
26819 	  var resizeDirections = getResizeDirections(pick(target, [ 'x', 'y', 'width', 'height' ]), newBounds);
26820 
26821 	  // resize the parent shape
26822 	  this.resize(target, newBounds, {
26823 	    autoResize: resizeDirections
26824 	  });
26825 
26826 	  var parent = target.parent;
26827 
26828 	  // recursively expand parent elements
26829 	  if (parent) {
26830 	    this._expand([ target ], parent);
26831 	  }
26832 	};
26833 
26834 
26835 	/**
26836 	 * Get the amount to expand the given shape in each direction.
26837 	 *
26838 	 * @param {djs.model.Shape} shape
26839 	 *
26840 	 * @return {TRBL}
26841 	 */
26842 	AutoResize.prototype.getOffset = function(shape) {
26843 	  return { top: 60, bottom: 60, left: 100, right: 100 };
26844 	};
26845 
26846 
26847 	/**
26848 	 * Get the activation threshold for each side for which
26849 	 * resize triggers.
26850 	 *
26851 	 * @param {djs.model.Shape} shape
26852 	 *
26853 	 * @return {TRBL}
26854 	 */
26855 	AutoResize.prototype.getPadding = function(shape) {
26856 	  return { top: 2, bottom: 2, left: 15, right: 15 };
26857 	};
26858 
26859 
26860 	/**
26861 	 * Perform the actual resize operation.
26862 	 *
26863 	 * @param {djs.model.Shape} shape
26864 	 * @param {Bounds} newBounds
26865 	 * @param {Object} [hints]
26866 	 * @param {string} [hints.autoResize]
26867 	 */
26868 	AutoResize.prototype.resize = function(shape, newBounds, hints) {
26869 	  this._modeling.resizeShape(shape, newBounds, null, hints);
26870 	};
26871 
26872 
26873 	function boundsChanged$1(newBounds, oldBounds) {
26874 	  return (
26875 	    newBounds.x !== oldBounds.x ||
26876 	    newBounds.y !== oldBounds.y ||
26877 	    newBounds.width !== oldBounds.width ||
26878 	    newBounds.height !== oldBounds.height
26879 	  );
26880 	}
26881 
26882 	/**
26883 	 * Get directions of resize as {n|w|s|e} e.g. "nw".
26884 	 *
26885 	 * @param {Bounds} oldBounds
26886 	 * @param {Bounds} newBounds
26887 	 *
26888 	 * @returns {string} Resize directions as {n|w|s|e}.
26889 	 */
26890 	function getResizeDirections(oldBounds, newBounds) {
26891 	  var directions = '';
26892 
26893 	  oldBounds = asTRBL(oldBounds);
26894 	  newBounds = asTRBL(newBounds);
26895 
26896 	  if (oldBounds.top > newBounds.top) {
26897 	    directions = directions.concat('n');
26898 	  }
26899 
26900 	  if (oldBounds.right < newBounds.right) {
26901 	    directions = directions.concat('w');
26902 	  }
26903 
26904 	  if (oldBounds.bottom < newBounds.bottom) {
26905 	    directions = directions.concat('s');
26906 	  }
26907 
26908 	  if (oldBounds.left > newBounds.left) {
26909 	    directions = directions.concat('e');
26910 	  }
26911 
26912 	  return directions;
26913 	}
26914 
26915 	/**
26916 	 * Sub class of the AutoResize module which implements a BPMN
26917 	 * specific resize function.
26918 	 */
26919 	function BpmnAutoResize(injector) {
26920 
26921 	  injector.invoke(AutoResize, this);
26922 	}
26923 
26924 	BpmnAutoResize.$inject = [
26925 	  'injector'
26926 	];
26927 
26928 	inherits$1(BpmnAutoResize, AutoResize);
26929 
26930 
26931 	/**
26932 	 * Resize shapes and lanes.
26933 	 *
26934 	 * @param {djs.model.Shape} target
26935 	 * @param {Bounds} newBounds
26936 	 * @param {Object} hints
26937 	 */
26938 	BpmnAutoResize.prototype.resize = function(target, newBounds, hints) {
26939 
26940 	  if (is$1(target, 'bpmn:Participant')) {
26941 	    this._modeling.resizeLane(target, newBounds, null, hints);
26942 	  } else {
26943 	    this._modeling.resizeShape(target, newBounds, null, hints);
26944 	  }
26945 	};
26946 
26947 	/**
26948 	 * A basic provider that may be extended to implement modeling rules.
26949 	 *
26950 	 * Extensions should implement the init method to actually add their custom
26951 	 * modeling checks. Checks may be added via the #addRule(action, fn) method.
26952 	 *
26953 	 * @param {EventBus} eventBus
26954 	 */
26955 	function RuleProvider(eventBus) {
26956 	  CommandInterceptor.call(this, eventBus);
26957 
26958 	  this.init();
26959 	}
26960 
26961 	RuleProvider.$inject = [ 'eventBus' ];
26962 
26963 	inherits$1(RuleProvider, CommandInterceptor);
26964 
26965 
26966 	/**
26967 	 * Adds a modeling rule for the given action, implemented through
26968 	 * a callback function.
26969 	 *
26970 	 * The function will receive the modeling specific action context
26971 	 * to perform its check. It must return `false` to disallow the
26972 	 * action from happening or `true` to allow the action.
26973 	 *
26974 	 * A rule provider may pass over the evaluation to lower priority
26975 	 * rules by returning return nothing (or <code>undefined</code>).
26976 	 *
26977 	 * @example
26978 	 *
26979 	 * ResizableRules.prototype.init = function() {
26980 	 *
26981 	 *   \/**
26982 	 *    * Return `true`, `false` or nothing to denote
26983 	 *    * _allowed_, _not allowed_ and _continue evaluating_.
26984 	 *    *\/
26985 	 *   this.addRule('shape.resize', function(context) {
26986 	 *
26987 	 *     var shape = context.shape;
26988 	 *
26989 	 *     if (!context.newBounds) {
26990 	 *       // check general resizability
26991 	 *       if (!shape.resizable) {
26992 	 *         return false;
26993 	 *       }
26994 	 *
26995 	 *       // not returning anything (read: undefined)
26996 	 *       // will continue the evaluation of other rules
26997 	 *       // (with lower priority)
26998 	 *       return;
26999 	 *     } else {
27000 	 *       // element must have minimum size of 10*10 points
27001 	 *       return context.newBounds.width > 10 && context.newBounds.height > 10;
27002 	 *     }
27003 	 *   });
27004 	 * };
27005 	 *
27006 	 * @param {string|Array<string>} actions the identifier for the modeling action to check
27007 	 * @param {number} [priority] the priority at which this rule is being applied
27008 	 * @param {Function} fn the callback function that performs the actual check
27009 	 */
27010 	RuleProvider.prototype.addRule = function(actions, priority, fn) {
27011 
27012 	  var self = this;
27013 
27014 	  if (typeof actions === 'string') {
27015 	    actions = [ actions ];
27016 	  }
27017 
27018 	  actions.forEach(function(action) {
27019 
27020 	    self.canExecute(action, priority, function(context, action, event) {
27021 	      return fn(context);
27022 	    }, true);
27023 	  });
27024 	};
27025 
27026 	/**
27027 	 * Implement this method to add new rules during provider initialization.
27028 	 */
27029 	RuleProvider.prototype.init = function() {};
27030 
27031 	/**
27032 	 * This is a base rule provider for the element.autoResize rule.
27033 	 */
27034 	function AutoResizeProvider(eventBus) {
27035 
27036 	  RuleProvider.call(this, eventBus);
27037 
27038 	  var self = this;
27039 
27040 	  this.addRule('element.autoResize', function(context) {
27041 	    return self.canResize(context.elements, context.target);
27042 	  });
27043 	}
27044 
27045 	AutoResizeProvider.$inject = [ 'eventBus' ];
27046 
27047 	inherits$1(AutoResizeProvider, RuleProvider);
27048 
27049 	/**
27050 	 * Needs to be implemented by sub classes to allow actual auto resize
27051 	 *
27052 	 * @param  {Array<djs.model.Shape>} elements
27053 	 * @param  {djs.model.Shape} target
27054 	 *
27055 	 * @return {boolean}
27056 	 */
27057 	AutoResizeProvider.prototype.canResize = function(elements, target) {
27058 	  return false;
27059 	};
27060 
27061 	/**
27062 	 * This module is a provider for automatically resizing parent BPMN elements
27063 	 */
27064 	function BpmnAutoResizeProvider(eventBus, modeling) {
27065 	  AutoResizeProvider.call(this, eventBus);
27066 
27067 	  this._modeling = modeling;
27068 	}
27069 
27070 	inherits$1(BpmnAutoResizeProvider, AutoResizeProvider);
27071 
27072 	BpmnAutoResizeProvider.$inject = [
27073 	  'eventBus',
27074 	  'modeling'
27075 	];
27076 
27077 
27078 	/**
27079 	 * Check if the given target can be expanded
27080 	 *
27081 	 * @param  {djs.model.Shape} target
27082 	 *
27083 	 * @return {boolean}
27084 	 */
27085 	BpmnAutoResizeProvider.prototype.canResize = function(elements, target) {
27086 
27087 	  if (!is$1(target, 'bpmn:Participant') && !is$1(target, 'bpmn:Lane') && !(is$1(target, 'bpmn:SubProcess'))) {
27088 	    return false;
27089 	  }
27090 
27091 	  var canResize = true;
27092 
27093 	  forEach(elements, function(element) {
27094 
27095 	    if (is$1(element, 'bpmn:Lane') || element.labelTarget) {
27096 	      canResize = false;
27097 	      return;
27098 	    }
27099 	  });
27100 
27101 	  return canResize;
27102 	};
27103 
27104 	var AutoResizeModule = {
27105 	  __init__: [
27106 	    'bpmnAutoResize',
27107 	    'bpmnAutoResizeProvider'
27108 	  ],
27109 	  bpmnAutoResize: [ 'type', BpmnAutoResize ],
27110 	  bpmnAutoResizeProvider: [ 'type', BpmnAutoResizeProvider ]
27111 	};
27112 
27113 	var HIGH_PRIORITY$j = 1500;
27114 
27115 
27116 	/**
27117 	 * Browsers may swallow certain events (hover, out ...) if users are to
27118 	 * fast with the mouse.
27119 	 *
27120 	 * @see http://stackoverflow.com/questions/7448468/why-cant-i-reliably-capture-a-mouseout-event
27121 	 *
27122 	 * The fix implemented in this component ensure that we
27123 	 *
27124 	 * 1) have a hover state after a successful drag.move event
27125 	 * 2) have an out event when dragging leaves an element
27126 	 *
27127 	 * @param {ElementRegistry} elementRegistry
27128 	 * @param {EventBus} eventBus
27129 	 * @param {Injector} injector
27130 	 */
27131 	function HoverFix(elementRegistry, eventBus, injector) {
27132 
27133 	  var self = this;
27134 
27135 	  var dragging = injector.get('dragging', false);
27136 
27137 	  /**
27138 	   * Make sure we are god damn hovering!
27139 	   *
27140 	   * @param {Event} dragging event
27141 	   */
27142 	  function ensureHover(event) {
27143 
27144 	    if (event.hover) {
27145 	      return;
27146 	    }
27147 
27148 	    var originalEvent = event.originalEvent;
27149 
27150 	    var gfx = self._findTargetGfx(originalEvent);
27151 
27152 	    var element = gfx && elementRegistry.get(gfx);
27153 
27154 	    if (gfx && element) {
27155 
27156 	      // 1) cancel current mousemove
27157 	      event.stopPropagation();
27158 
27159 	      // 2) emit fake hover for new target
27160 	      dragging.hover({ element: element, gfx: gfx });
27161 
27162 	      // 3) re-trigger move event
27163 	      dragging.move(originalEvent);
27164 	    }
27165 	  }
27166 
27167 
27168 	  if (dragging) {
27169 
27170 	    /**
27171 	     * We wait for a specific sequence of events before
27172 	     * emitting a fake drag.hover event.
27173 	     *
27174 	     * Event Sequence:
27175 	     *
27176 	     * drag.start
27177 	     * drag.move >> ensure we are hovering
27178 	     */
27179 	    eventBus.on('drag.start', function(event) {
27180 
27181 	      eventBus.once('drag.move', HIGH_PRIORITY$j, function(event) {
27182 
27183 	        ensureHover(event);
27184 
27185 	      });
27186 
27187 	    });
27188 	  }
27189 
27190 
27191 	  /**
27192 	   * We make sure that element.out is always fired, even if the
27193 	   * browser swallows an element.out event.
27194 	   *
27195 	   * Event sequence:
27196 	   *
27197 	   * element.hover
27198 	   * (element.out >> sometimes swallowed)
27199 	   * element.hover >> ensure we fired element.out
27200 	   */
27201 	  (function() {
27202 	    var hoverGfx;
27203 	    var hover;
27204 
27205 	    eventBus.on('element.hover', function(event) {
27206 
27207 	      // (1) remember current hover element
27208 	      hoverGfx = event.gfx;
27209 	      hover = event.element;
27210 	    });
27211 
27212 	    eventBus.on('element.hover', HIGH_PRIORITY$j, function(event) {
27213 
27214 	      // (3) am I on an element still?
27215 	      if (hover) {
27216 
27217 	        // (4) that is a problem, gotta "simulate the out"
27218 	        eventBus.fire('element.out', {
27219 	          element: hover,
27220 	          gfx: hoverGfx
27221 	        });
27222 	      }
27223 
27224 	    });
27225 
27226 	    eventBus.on('element.out', function() {
27227 
27228 	      // (2) unset hover state if we correctly outed us *GG*
27229 	      hoverGfx = null;
27230 	      hover = null;
27231 	    });
27232 
27233 	  })();
27234 
27235 	  this._findTargetGfx = function(event) {
27236 	    var position,
27237 	        target;
27238 
27239 	    if (!(event instanceof MouseEvent)) {
27240 	      return;
27241 	    }
27242 
27243 	    position = toPoint(event);
27244 
27245 	    // damn expensive operation, ouch!
27246 	    target = document.elementFromPoint(position.x, position.y);
27247 
27248 	    return getGfx(target);
27249 	  };
27250 
27251 	}
27252 
27253 	HoverFix.$inject = [
27254 	  'elementRegistry',
27255 	  'eventBus',
27256 	  'injector'
27257 	];
27258 
27259 
27260 	// helpers /////////////////////
27261 
27262 	function getGfx(target) {
27263 	  return closest(target, 'svg, .djs-element', true);
27264 	}
27265 
27266 	var HoverFixModule = {
27267 	  __init__: [
27268 	    'hoverFix'
27269 	  ],
27270 	  hoverFix: [ 'type', HoverFix ],
27271 	};
27272 
27273 	var round$a = Math.round;
27274 
27275 	var DRAG_ACTIVE_CLS = 'djs-drag-active';
27276 
27277 
27278 	function preventDefault$1(event) {
27279 	  event.preventDefault();
27280 	}
27281 
27282 	function isTouchEvent(event) {
27283 
27284 	  // check for TouchEvent being available first
27285 	  // (i.e. not available on desktop Firefox)
27286 	  return typeof TouchEvent !== 'undefined' && event instanceof TouchEvent;
27287 	}
27288 
27289 	function getLength(point) {
27290 	  return Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
27291 	}
27292 
27293 	/**
27294 	 * A helper that fires canvas localized drag events and realizes
27295 	 * the general "drag-and-drop" look and feel.
27296 	 *
27297 	 * Calling {@link Dragging#activate} activates dragging on a canvas.
27298 	 *
27299 	 * It provides the following:
27300 	 *
27301 	 *   * emits life cycle events, namespaced with a prefix assigned
27302 	 *     during dragging activation
27303 	 *   * sets and restores the cursor
27304 	 *   * sets and restores the selection if elements still exist
27305 	 *   * ensures there can be only one drag operation active at a time
27306 	 *
27307 	 * Dragging may be canceled manually by calling {@link Dragging#cancel}
27308 	 * or by pressing ESC.
27309 	 *
27310 	 *
27311 	 * ## Life-cycle events
27312 	 *
27313 	 * Dragging can be in three different states, off, initialized
27314 	 * and active.
27315 	 *
27316 	 * (1) off: no dragging operation is in progress
27317 	 * (2) initialized: a new drag operation got initialized but not yet
27318 	 *                  started (i.e. because of no initial move)
27319 	 * (3) started: dragging is in progress
27320 	 *
27321 	 * Eventually dragging will be off again after a drag operation has
27322 	 * been ended or canceled via user click or ESC key press.
27323 	 *
27324 	 * To indicate transitions between these states dragging emits generic
27325 	 * life-cycle events with the `drag.` prefix _and_ events namespaced
27326 	 * to a prefix choosen by a user during drag initialization.
27327 	 *
27328 	 * The following events are emitted (appropriately prefixed) via
27329 	 * the {@link EventBus}.
27330 	 *
27331 	 * * `init`
27332 	 * * `start`
27333 	 * * `move`
27334 	 * * `end`
27335 	 * * `ended` (dragging already in off state)
27336 	 * * `cancel` (only if previously started)
27337 	 * * `canceled` (dragging already in off state, only if previously started)
27338 	 * * `cleanup`
27339 	 *
27340 	 *
27341 	 * @example
27342 	 *
27343 	 * function MyDragComponent(eventBus, dragging) {
27344 	 *
27345 	 *   eventBus.on('mydrag.start', function(event) {
27346 	 *     console.log('yes, we start dragging');
27347 	 *   });
27348 	 *
27349 	 *   eventBus.on('mydrag.move', function(event) {
27350 	 *     console.log('canvas local coordinates', event.x, event.y, event.dx, event.dy);
27351 	 *
27352 	 *     // local drag data is passed with the event
27353 	 *     event.context.foo; // "BAR"
27354 	 *
27355 	 *     // the original mouse event, too
27356 	 *     event.originalEvent; // MouseEvent(...)
27357 	 *   });
27358 	 *
27359 	 *   eventBus.on('element.click', function(event) {
27360 	 *     dragging.init(event, 'mydrag', {
27361 	 *       cursor: 'grabbing',
27362 	 *       data: {
27363 	 *         context: {
27364 	 *           foo: "BAR"
27365 	 *         }
27366 	 *       }
27367 	 *     });
27368 	 *   });
27369 	 * }
27370 	 */
27371 	function Dragging(eventBus, canvas, selection, elementRegistry) {
27372 
27373 	  var defaultOptions = {
27374 	    threshold: 5,
27375 	    trapClick: true
27376 	  };
27377 
27378 	  // the currently active drag operation
27379 	  // dragging is active as soon as this context exists.
27380 	  //
27381 	  // it is visually _active_ only when a context.active flag is set to true.
27382 	  var context;
27383 
27384 	  /* convert a global event into local coordinates */
27385 	  function toLocalPoint(globalPosition) {
27386 
27387 	    var viewbox = canvas.viewbox();
27388 
27389 	    var clientRect = canvas._container.getBoundingClientRect();
27390 
27391 	    return {
27392 	      x: viewbox.x + (globalPosition.x - clientRect.left) / viewbox.scale,
27393 	      y: viewbox.y + (globalPosition.y - clientRect.top) / viewbox.scale
27394 	    };
27395 	  }
27396 
27397 	  // helpers
27398 
27399 	  function fire(type, dragContext) {
27400 	    dragContext = dragContext || context;
27401 
27402 	    var event = eventBus.createEvent(
27403 	      assign(
27404 	        {},
27405 	        dragContext.payload,
27406 	        dragContext.data,
27407 	        { isTouch: dragContext.isTouch }
27408 	      )
27409 	    );
27410 
27411 	    // default integration
27412 	    if (eventBus.fire('drag.' + type, event) === false) {
27413 	      return false;
27414 	    }
27415 
27416 	    return eventBus.fire(dragContext.prefix + '.' + type, event);
27417 	  }
27418 
27419 	  function restoreSelection(previousSelection) {
27420 	    var existingSelection = previousSelection.filter(function(element) {
27421 	      return elementRegistry.get(element.id);
27422 	    });
27423 
27424 	    existingSelection.length && selection.select(existingSelection);
27425 	  }
27426 
27427 	  // event listeners
27428 
27429 	  function move(event, activate) {
27430 	    var payload = context.payload,
27431 	        displacement = context.displacement;
27432 
27433 	    var globalStart = context.globalStart,
27434 	        globalCurrent = toPoint(event),
27435 	        globalDelta = delta(globalCurrent, globalStart);
27436 
27437 	    var localStart = context.localStart,
27438 	        localCurrent = toLocalPoint(globalCurrent),
27439 	        localDelta = delta(localCurrent, localStart);
27440 
27441 
27442 	    // activate context explicitly or once threshold is reached
27443 	    if (!context.active && (activate || getLength(globalDelta) > context.threshold)) {
27444 
27445 	      // fire start event with original
27446 	      // starting coordinates
27447 
27448 	      assign(payload, {
27449 	        x: round$a(localStart.x + displacement.x),
27450 	        y: round$a(localStart.y + displacement.y),
27451 	        dx: 0,
27452 	        dy: 0
27453 	      }, { originalEvent: event });
27454 
27455 	      if (false === fire('start')) {
27456 	        return cancel();
27457 	      }
27458 
27459 	      context.active = true;
27460 
27461 	      // unset selection and remember old selection
27462 	      // the previous (old) selection will always passed
27463 	      // with the event via the event.previousSelection property
27464 	      if (!context.keepSelection) {
27465 	        payload.previousSelection = selection.get();
27466 	        selection.select(null);
27467 	      }
27468 
27469 	      // allow custom cursor
27470 	      if (context.cursor) {
27471 	        set(context.cursor);
27472 	      }
27473 
27474 	      // indicate dragging via marker on root element
27475 	      canvas.addMarker(canvas.getRootElement(), DRAG_ACTIVE_CLS);
27476 	    }
27477 
27478 	    stopPropagation$1(event);
27479 
27480 	    if (context.active) {
27481 
27482 	      // update payload with actual coordinates
27483 	      assign(payload, {
27484 	        x: round$a(localCurrent.x + displacement.x),
27485 	        y: round$a(localCurrent.y + displacement.y),
27486 	        dx: round$a(localDelta.x),
27487 	        dy: round$a(localDelta.y)
27488 	      }, { originalEvent: event });
27489 
27490 	      // emit move event
27491 	      fire('move');
27492 	    }
27493 	  }
27494 
27495 	  function end(event) {
27496 	    var previousContext,
27497 	        returnValue = true;
27498 
27499 	    if (context.active) {
27500 
27501 	      if (event) {
27502 	        context.payload.originalEvent = event;
27503 
27504 	        // suppress original event (click, ...)
27505 	        // because we just ended a drag operation
27506 	        stopPropagation$1(event);
27507 	      }
27508 
27509 	      // implementations may stop restoring the
27510 	      // original state (selections, ...) by preventing the
27511 	      // end events default action
27512 	      returnValue = fire('end');
27513 	    }
27514 
27515 	    if (returnValue === false) {
27516 	      fire('rejected');
27517 	    }
27518 
27519 	    previousContext = cleanup(returnValue !== true);
27520 
27521 	    // last event to be fired when all drag operations are done
27522 	    // at this point in time no drag operation is in progress anymore
27523 	    fire('ended', previousContext);
27524 	  }
27525 
27526 
27527 	  // cancel active drag operation if the user presses
27528 	  // the ESC key on the keyboard
27529 
27530 	  function checkCancel(event) {
27531 
27532 	    if (event.which === 27) {
27533 	      preventDefault$1(event);
27534 
27535 	      cancel();
27536 	    }
27537 	  }
27538 
27539 
27540 	  // prevent ghost click that might occur after a finished
27541 	  // drag and drop session
27542 
27543 	  function trapClickAndEnd(event) {
27544 
27545 	    var untrap;
27546 
27547 	    // trap the click in case we are part of an active
27548 	    // drag operation. This will effectively prevent
27549 	    // the ghost click that cannot be canceled otherwise.
27550 	    if (context.active) {
27551 
27552 	      untrap = install(eventBus);
27553 
27554 	      // remove trap after minimal delay
27555 	      setTimeout(untrap, 400);
27556 
27557 	      // prevent default action (click)
27558 	      preventDefault$1(event);
27559 	    }
27560 
27561 	    end(event);
27562 	  }
27563 
27564 	  function trapTouch(event) {
27565 	    move(event);
27566 	  }
27567 
27568 	  // update the drag events hover (djs.model.Base) and hoverGfx (Snap<SVGElement>)
27569 	  // properties during hover and out and fire {prefix}.hover and {prefix}.out properties
27570 	  // respectively
27571 
27572 	  function hover(event) {
27573 	    var payload = context.payload;
27574 
27575 	    payload.hoverGfx = event.gfx;
27576 	    payload.hover = event.element;
27577 
27578 	    fire('hover');
27579 	  }
27580 
27581 	  function out(event) {
27582 	    fire('out');
27583 
27584 	    var payload = context.payload;
27585 
27586 	    payload.hoverGfx = null;
27587 	    payload.hover = null;
27588 	  }
27589 
27590 
27591 	  // life-cycle methods
27592 
27593 	  function cancel(restore) {
27594 	    var previousContext;
27595 
27596 	    if (!context) {
27597 	      return;
27598 	    }
27599 
27600 	    var wasActive = context.active;
27601 
27602 	    if (wasActive) {
27603 	      fire('cancel');
27604 	    }
27605 
27606 	    previousContext = cleanup(restore);
27607 
27608 	    if (wasActive) {
27609 
27610 	      // last event to be fired when all drag operations are done
27611 	      // at this point in time no drag operation is in progress anymore
27612 	      fire('canceled', previousContext);
27613 	    }
27614 	  }
27615 
27616 	  function cleanup(restore) {
27617 	    var previousContext,
27618 	        endDrag;
27619 
27620 	    fire('cleanup');
27621 
27622 	    // reset cursor
27623 	    unset();
27624 
27625 	    if (context.trapClick) {
27626 	      endDrag = trapClickAndEnd;
27627 	    } else {
27628 	      endDrag = end;
27629 	    }
27630 
27631 	    // reset dom listeners
27632 	    componentEvent.unbind(document, 'mousemove', move);
27633 
27634 	    componentEvent.unbind(document, 'dragstart', preventDefault$1);
27635 	    componentEvent.unbind(document, 'selectstart', preventDefault$1);
27636 
27637 	    componentEvent.unbind(document, 'mousedown', endDrag, true);
27638 	    componentEvent.unbind(document, 'mouseup', endDrag, true);
27639 
27640 	    componentEvent.unbind(document, 'keyup', checkCancel);
27641 
27642 	    componentEvent.unbind(document, 'touchstart', trapTouch, true);
27643 	    componentEvent.unbind(document, 'touchcancel', cancel, true);
27644 	    componentEvent.unbind(document, 'touchmove', move, true);
27645 	    componentEvent.unbind(document, 'touchend', end, true);
27646 
27647 	    eventBus.off('element.hover', hover);
27648 	    eventBus.off('element.out', out);
27649 
27650 	    // remove drag marker on root element
27651 	    canvas.removeMarker(canvas.getRootElement(), DRAG_ACTIVE_CLS);
27652 
27653 	    // restore selection, unless it has changed
27654 	    var previousSelection = context.payload.previousSelection;
27655 
27656 	    if (restore !== false && previousSelection && !selection.get().length) {
27657 	      restoreSelection(previousSelection);
27658 	    }
27659 
27660 	    previousContext = context;
27661 
27662 	    context = null;
27663 
27664 	    return previousContext;
27665 	  }
27666 
27667 	  /**
27668 	   * Initialize a drag operation.
27669 	   *
27670 	   * If `localPosition` is given, drag events will be emitted
27671 	   * relative to it.
27672 	   *
27673 	   * @param {MouseEvent|TouchEvent} [event]
27674 	   * @param {Point} [localPosition] actual diagram local position this drag operation should start at
27675 	   * @param {string} prefix
27676 	   * @param {Object} [options]
27677 	   */
27678 	  function init(event, relativeTo, prefix, options) {
27679 
27680 	    // only one drag operation may be active, at a time
27681 	    if (context) {
27682 	      cancel(false);
27683 	    }
27684 
27685 	    if (typeof relativeTo === 'string') {
27686 	      options = prefix;
27687 	      prefix = relativeTo;
27688 	      relativeTo = null;
27689 	    }
27690 
27691 	    options = assign({}, defaultOptions, options || {});
27692 
27693 	    var data = options.data || {},
27694 	        originalEvent,
27695 	        globalStart,
27696 	        localStart,
27697 	        endDrag,
27698 	        isTouch;
27699 
27700 	    if (options.trapClick) {
27701 	      endDrag = trapClickAndEnd;
27702 	    } else {
27703 	      endDrag = end;
27704 	    }
27705 
27706 	    if (event) {
27707 	      originalEvent = getOriginal$1(event) || event;
27708 	      globalStart = toPoint(event);
27709 
27710 	      stopPropagation$1(event);
27711 
27712 	      // prevent default browser dragging behavior
27713 	      if (originalEvent.type === 'dragstart') {
27714 	        preventDefault$1(originalEvent);
27715 	      }
27716 	    } else {
27717 	      originalEvent = null;
27718 	      globalStart = { x: 0, y: 0 };
27719 	    }
27720 
27721 	    localStart = toLocalPoint(globalStart);
27722 
27723 	    if (!relativeTo) {
27724 	      relativeTo = localStart;
27725 	    }
27726 
27727 	    isTouch = isTouchEvent(originalEvent);
27728 
27729 	    context = assign({
27730 	      prefix: prefix,
27731 	      data: data,
27732 	      payload: {},
27733 	      globalStart: globalStart,
27734 	      displacement: delta(relativeTo, localStart),
27735 	      localStart: localStart,
27736 	      isTouch: isTouch
27737 	    }, options);
27738 
27739 	    // skip dom registration if trigger
27740 	    // is set to manual (during testing)
27741 	    if (!options.manual) {
27742 
27743 	      // add dom listeners
27744 
27745 	      if (isTouch) {
27746 	        componentEvent.bind(document, 'touchstart', trapTouch, true);
27747 	        componentEvent.bind(document, 'touchcancel', cancel, true);
27748 	        componentEvent.bind(document, 'touchmove', move, true);
27749 	        componentEvent.bind(document, 'touchend', end, true);
27750 	      } else {
27751 
27752 	        // assume we use the mouse to interact per default
27753 	        componentEvent.bind(document, 'mousemove', move);
27754 
27755 	        // prevent default browser drag and text selection behavior
27756 	        componentEvent.bind(document, 'dragstart', preventDefault$1);
27757 	        componentEvent.bind(document, 'selectstart', preventDefault$1);
27758 
27759 	        componentEvent.bind(document, 'mousedown', endDrag, true);
27760 	        componentEvent.bind(document, 'mouseup', endDrag, true);
27761 	      }
27762 
27763 	      componentEvent.bind(document, 'keyup', checkCancel);
27764 
27765 	      eventBus.on('element.hover', hover);
27766 	      eventBus.on('element.out', out);
27767 	    }
27768 
27769 	    fire('init');
27770 
27771 	    if (options.autoActivate) {
27772 	      move(event, true);
27773 	    }
27774 	  }
27775 
27776 	  // cancel on diagram destruction
27777 	  eventBus.on('diagram.destroy', cancel);
27778 
27779 
27780 	  // API
27781 
27782 	  this.init = init;
27783 	  this.move = move;
27784 	  this.hover = hover;
27785 	  this.out = out;
27786 	  this.end = end;
27787 
27788 	  this.cancel = cancel;
27789 
27790 	  // for introspection
27791 
27792 	  this.context = function() {
27793 	    return context;
27794 	  };
27795 
27796 	  this.setOptions = function(options) {
27797 	    assign(defaultOptions, options);
27798 	  };
27799 	}
27800 
27801 	Dragging.$inject = [
27802 	  'eventBus',
27803 	  'canvas',
27804 	  'selection',
27805 	  'elementRegistry'
27806 	];
27807 
27808 	var DraggingModule = {
27809 	  __depends__: [
27810 	    HoverFixModule,
27811 	    SelectionModule,
27812 	  ],
27813 	  dragging: [ 'type', Dragging ],
27814 	};
27815 
27816 	/**
27817 	 * Initiates canvas scrolling if current cursor point is close to a border.
27818 	 * Cancelled when current point moves back inside the scrolling borders
27819 	 * or cancelled manually.
27820 	 *
27821 	 * Default options :
27822 	 *   scrollThresholdIn: [ 20, 20, 20, 20 ],
27823 	 *   scrollThresholdOut: [ 0, 0, 0, 0 ],
27824 	 *   scrollRepeatTimeout: 15,
27825 	 *   scrollStep: 10
27826 	 *
27827 	 * Threshold order:
27828 	 *   [ left, top, right, bottom ]
27829 	 */
27830 	function AutoScroll(config, eventBus, canvas) {
27831 
27832 	  this._canvas = canvas;
27833 
27834 	  this._opts = assign({
27835 	    scrollThresholdIn: [ 20, 20, 20, 20 ],
27836 	    scrollThresholdOut: [ 0, 0, 0, 0 ],
27837 	    scrollRepeatTimeout: 15,
27838 	    scrollStep: 10
27839 	  }, config);
27840 
27841 	  var self = this;
27842 
27843 	  eventBus.on('drag.move', function(e) {
27844 	    var point = self._toBorderPoint(e);
27845 
27846 	    self.startScroll(point);
27847 	  });
27848 
27849 	  eventBus.on([ 'drag.cleanup' ], function() {
27850 	    self.stopScroll();
27851 	  });
27852 	}
27853 
27854 	AutoScroll.$inject = [
27855 	  'config.autoScroll',
27856 	  'eventBus',
27857 	  'canvas'
27858 	];
27859 
27860 
27861 	/**
27862 	 * Starts scrolling loop.
27863 	 * Point is given in global scale in canvas container box plane.
27864 	 *
27865 	 * @param  {Object} point { x: X, y: Y }
27866 	 */
27867 	AutoScroll.prototype.startScroll = function(point) {
27868 
27869 	  var canvas = this._canvas;
27870 	  var opts = this._opts;
27871 	  var self = this;
27872 
27873 	  var clientRect = canvas.getContainer().getBoundingClientRect();
27874 
27875 	  var diff = [
27876 	    point.x,
27877 	    point.y,
27878 	    clientRect.width - point.x,
27879 	    clientRect.height - point.y
27880 	  ];
27881 
27882 	  this.stopScroll();
27883 
27884 	  var dx = 0,
27885 	      dy = 0;
27886 
27887 	  for (var i = 0; i < 4; i++) {
27888 	    if (between(diff[i], opts.scrollThresholdOut[i], opts.scrollThresholdIn[i])) {
27889 	      if (i === 0) {
27890 	        dx = opts.scrollStep;
27891 	      } else if (i == 1) {
27892 	        dy = opts.scrollStep;
27893 	      } else if (i == 2) {
27894 	        dx = -opts.scrollStep;
27895 	      } else if (i == 3) {
27896 	        dy = -opts.scrollStep;
27897 	      }
27898 	    }
27899 	  }
27900 
27901 	  if (dx !== 0 || dy !== 0) {
27902 	    canvas.scroll({ dx: dx, dy: dy });
27903 
27904 	    this._scrolling = setTimeout(function() {
27905 	      self.startScroll(point);
27906 	    }, opts.scrollRepeatTimeout);
27907 	  }
27908 	};
27909 
27910 	function between(val, start, end) {
27911 	  if (start < val && val < end) {
27912 	    return true;
27913 	  }
27914 
27915 	  return false;
27916 	}
27917 
27918 
27919 	/**
27920 	 * Stops scrolling loop.
27921 	 */
27922 	AutoScroll.prototype.stopScroll = function() {
27923 	  clearTimeout(this._scrolling);
27924 	};
27925 
27926 
27927 	/**
27928 	 * Overrides defaults options.
27929 	 *
27930 	 * @param  {Object} options
27931 	 */
27932 	AutoScroll.prototype.setOptions = function(options) {
27933 	  this._opts = assign({}, this._opts, options);
27934 	};
27935 
27936 
27937 	/**
27938 	 * Converts event to a point in canvas container plane in global scale.
27939 	 *
27940 	 * @param  {Event} event
27941 	 * @return {Point}
27942 	 */
27943 	AutoScroll.prototype._toBorderPoint = function(event) {
27944 	  var clientRect = this._canvas._container.getBoundingClientRect();
27945 
27946 	  var globalPosition = toPoint(event.originalEvent);
27947 
27948 	  return {
27949 	    x: globalPosition.x - clientRect.left,
27950 	    y: globalPosition.y - clientRect.top
27951 	  };
27952 	};
27953 
27954 	var AutoScrollModule = {
27955 	  __depends__: [
27956 	    DraggingModule,
27957 	  ],
27958 	  __init__: [ 'autoScroll' ],
27959 	  autoScroll: [ 'type', AutoScroll ]
27960 	};
27961 
27962 	/**
27963 	 * A service that provides rules for certain diagram actions.
27964 	 *
27965 	 * The default implementation will hook into the {@link CommandStack}
27966 	 * to perform the actual rule evaluation. Make sure to provide the
27967 	 * `commandStack` service with this module if you plan to use it.
27968 	 *
27969 	 * Together with this implementation you may use the {@link RuleProvider}
27970 	 * to implement your own rule checkers.
27971 	 *
27972 	 * This module is ment to be easily replaced, thus the tiny foot print.
27973 	 *
27974 	 * @param {Injector} injector
27975 	 */
27976 	function Rules(injector) {
27977 	  this._commandStack = injector.get('commandStack', false);
27978 	}
27979 
27980 	Rules.$inject = [ 'injector' ];
27981 
27982 
27983 	/**
27984 	 * Returns whether or not a given modeling action can be executed
27985 	 * in the specified context.
27986 	 *
27987 	 * This implementation will respond with allow unless anyone
27988 	 * objects.
27989 	 *
27990 	 * @param {string} action the action to be checked
27991 	 * @param {Object} [context] the context to check the action in
27992 	 *
27993 	 * @return {boolean} returns true, false or null depending on whether the
27994 	 *                   operation is allowed, not allowed or should be ignored.
27995 	 */
27996 	Rules.prototype.allowed = function(action, context) {
27997 	  var allowed = true;
27998 
27999 	  var commandStack = this._commandStack;
28000 
28001 	  if (commandStack) {
28002 	    allowed = commandStack.canExecute(action, context);
28003 	  }
28004 
28005 	  // map undefined to true, i.e. no rules
28006 	  return allowed === undefined ? true : allowed;
28007 	};
28008 
28009 	var RulesModule$1 = {
28010 	  __init__: [ 'rules' ],
28011 	  rules: [ 'type', Rules ]
28012 	};
28013 
28014 	var round$9 = Math.round,
28015 	    max$6 = Math.max;
28016 
28017 
28018 	function circlePath(center, r) {
28019 	  var x = center.x,
28020 	      y = center.y;
28021 
28022 	  return [
28023 	    ['M', x, y],
28024 	    ['m', 0, -r],
28025 	    ['a', r, r, 0, 1, 1, 0, 2 * r],
28026 	    ['a', r, r, 0, 1, 1, 0, -2 * r],
28027 	    ['z']
28028 	  ];
28029 	}
28030 
28031 	function linePath(points) {
28032 	  var segments = [];
28033 
28034 	  points.forEach(function(p, idx) {
28035 	    segments.push([ idx === 0 ? 'M' : 'L', p.x, p.y ]);
28036 	  });
28037 
28038 	  return segments;
28039 	}
28040 
28041 
28042 	var INTERSECTION_THRESHOLD$1 = 10;
28043 
28044 	function getBendpointIntersection(waypoints, reference) {
28045 
28046 	  var i, w;
28047 
28048 	  for (i = 0; (w = waypoints[i]); i++) {
28049 
28050 	    if (pointDistance(w, reference) <= INTERSECTION_THRESHOLD$1) {
28051 	      return {
28052 	        point: waypoints[i],
28053 	        bendpoint: true,
28054 	        index: i
28055 	      };
28056 	    }
28057 	  }
28058 
28059 	  return null;
28060 	}
28061 
28062 	function getPathIntersection(waypoints, reference) {
28063 
28064 	  var intersections = intersect(circlePath(reference, INTERSECTION_THRESHOLD$1), linePath(waypoints));
28065 
28066 	  var a = intersections[0],
28067 	      b = intersections[intersections.length - 1],
28068 	      idx;
28069 
28070 	  if (!a) {
28071 
28072 	    // no intersection
28073 	    return null;
28074 	  }
28075 
28076 	  if (a !== b) {
28077 
28078 	    if (a.segment2 !== b.segment2) {
28079 
28080 	      // we use the bendpoint in between both segments
28081 	      // as the intersection point
28082 
28083 	      idx = max$6(a.segment2, b.segment2) - 1;
28084 
28085 	      return {
28086 	        point: waypoints[idx],
28087 	        bendpoint: true,
28088 	        index: idx
28089 	      };
28090 	    }
28091 
28092 	    return {
28093 	      point: {
28094 	        x: (round$9(a.x + b.x) / 2),
28095 	        y: (round$9(a.y + b.y) / 2)
28096 	      },
28097 	      index: a.segment2
28098 	    };
28099 	  }
28100 
28101 	  return {
28102 	    point: {
28103 	      x: round$9(a.x),
28104 	      y: round$9(a.y)
28105 	    },
28106 	    index: a.segment2
28107 	  };
28108 	}
28109 
28110 	/**
28111 	 * Returns the closest point on the connection towards a given reference point.
28112 	 *
28113 	 * @param  {Array<Point>} waypoints
28114 	 * @param  {Point} reference
28115 	 *
28116 	 * @return {Object} intersection data (segment, point)
28117 	 */
28118 	function getApproxIntersection(waypoints, reference) {
28119 	  return getBendpointIntersection(waypoints, reference) || getPathIntersection(waypoints, reference);
28120 	}
28121 
28122 	var BENDPOINT_CLS = 'djs-bendpoint';
28123 	var SEGMENT_DRAGGER_CLS = 'djs-segment-dragger';
28124 
28125 	function toCanvasCoordinates(canvas, event) {
28126 
28127 	  var position = toPoint(event),
28128 	      clientRect = canvas._container.getBoundingClientRect(),
28129 	      offset;
28130 
28131 	  // canvas relative position
28132 
28133 	  offset = {
28134 	    x: clientRect.left,
28135 	    y: clientRect.top
28136 	  };
28137 
28138 	  // update actual event payload with canvas relative measures
28139 
28140 	  var viewbox = canvas.viewbox();
28141 
28142 	  return {
28143 	    x: viewbox.x + (position.x - offset.x) / viewbox.scale,
28144 	    y: viewbox.y + (position.y - offset.y) / viewbox.scale
28145 	  };
28146 	}
28147 
28148 	function getConnectionIntersection(canvas, waypoints, event) {
28149 	  var localPosition = toCanvasCoordinates(canvas, event),
28150 	      intersection = getApproxIntersection(waypoints, localPosition);
28151 
28152 	  return intersection;
28153 	}
28154 
28155 	function addBendpoint(parentGfx, cls) {
28156 	  var groupGfx = create$1('g');
28157 	  classes(groupGfx).add(BENDPOINT_CLS);
28158 
28159 	  append(parentGfx, groupGfx);
28160 
28161 	  var visual = create$1('circle');
28162 	  attr(visual, {
28163 	    cx: 0,
28164 	    cy: 0,
28165 	    r: 4
28166 	  });
28167 	  classes(visual).add('djs-visual');
28168 
28169 	  append(groupGfx, visual);
28170 
28171 	  var hit = create$1('circle');
28172 	  attr(hit, {
28173 	    cx: 0,
28174 	    cy: 0,
28175 	    r: 10
28176 	  });
28177 	  classes(hit).add('djs-hit');
28178 
28179 	  append(groupGfx, hit);
28180 
28181 	  if (cls) {
28182 	    classes(groupGfx).add(cls);
28183 	  }
28184 
28185 	  return groupGfx;
28186 	}
28187 
28188 	function createParallelDragger(parentGfx, segmentStart, segmentEnd, alignment) {
28189 	  var draggerGfx = create$1('g');
28190 
28191 	  append(parentGfx, draggerGfx);
28192 
28193 	  var width = 14,
28194 	      height = 3,
28195 	      padding = 11,
28196 	      hitWidth = calculateHitWidth(segmentStart, segmentEnd, alignment),
28197 	      hitHeight = height + padding;
28198 
28199 	  var visual = create$1('rect');
28200 	  attr(visual, {
28201 	    x: -width / 2,
28202 	    y: -height / 2,
28203 	    width: width,
28204 	    height: height
28205 	  });
28206 	  classes(visual).add('djs-visual');
28207 
28208 	  append(draggerGfx, visual);
28209 
28210 	  var hit = create$1('rect');
28211 	  attr(hit, {
28212 	    x: -hitWidth / 2,
28213 	    y: -hitHeight / 2,
28214 	    width: hitWidth,
28215 	    height: hitHeight
28216 	  });
28217 	  classes(hit).add('djs-hit');
28218 
28219 	  append(draggerGfx, hit);
28220 
28221 	  rotate(draggerGfx, alignment === 'v' ? 90 : 0);
28222 
28223 	  return draggerGfx;
28224 	}
28225 
28226 
28227 	function addSegmentDragger(parentGfx, segmentStart, segmentEnd) {
28228 
28229 	  var groupGfx = create$1('g'),
28230 	      mid = getMidPoint(segmentStart, segmentEnd),
28231 	      alignment = pointsAligned(segmentStart, segmentEnd);
28232 
28233 	  append(parentGfx, groupGfx);
28234 
28235 	  createParallelDragger(groupGfx, segmentStart, segmentEnd, alignment);
28236 
28237 	  classes(groupGfx).add(SEGMENT_DRAGGER_CLS);
28238 	  classes(groupGfx).add(alignment === 'h' ? 'horizontal' : 'vertical');
28239 
28240 	  translate$2(groupGfx, mid.x, mid.y);
28241 
28242 	  return groupGfx;
28243 	}
28244 
28245 	/**
28246 	 * Calculates region for segment move which is 2/3 of the full segment length
28247 	 * @param {number} segmentLength
28248 	 *
28249 	 * @return {number}
28250 	 */
28251 	function calculateSegmentMoveRegion(segmentLength) {
28252 	  return Math.abs(Math.round(segmentLength * 2 / 3));
28253 	}
28254 
28255 	// helper //////////
28256 
28257 	function calculateHitWidth(segmentStart, segmentEnd, alignment) {
28258 	  var segmentLengthXAxis = segmentEnd.x - segmentStart.x,
28259 	      segmentLengthYAxis = segmentEnd.y - segmentStart.y;
28260 
28261 	  return alignment === 'h' ?
28262 	    calculateSegmentMoveRegion(segmentLengthXAxis) :
28263 	    calculateSegmentMoveRegion(segmentLengthYAxis);
28264 	}
28265 
28266 	var css_escape = {exports: {}};
28267 
28268 	/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
28269 
28270 	(function (module, exports) {
28271 	(function(root, factory) {
28272 		// https://github.com/umdjs/umd/blob/master/returnExports.js
28273 		{
28274 			// For Node.js.
28275 			module.exports = factory(root);
28276 		}
28277 	}(typeof commonjsGlobal != 'undefined' ? commonjsGlobal : commonjsGlobal, function(root) {
28278 
28279 		if (root.CSS && root.CSS.escape) {
28280 			return root.CSS.escape;
28281 		}
28282 
28283 		// https://drafts.csswg.org/cssom/#serialize-an-identifier
28284 		var cssEscape = function(value) {
28285 			if (arguments.length == 0) {
28286 				throw new TypeError('`CSS.escape` requires an argument.');
28287 			}
28288 			var string = String(value);
28289 			var length = string.length;
28290 			var index = -1;
28291 			var codeUnit;
28292 			var result = '';
28293 			var firstCodeUnit = string.charCodeAt(0);
28294 			while (++index < length) {
28295 				codeUnit = string.charCodeAt(index);
28296 				// Note: there’s no need to special-case astral symbols, surrogate
28297 				// pairs, or lone surrogates.
28298 
28299 				// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
28300 				// (U+FFFD).
28301 				if (codeUnit == 0x0000) {
28302 					result += '\uFFFD';
28303 					continue;
28304 				}
28305 
28306 				if (
28307 					// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
28308 					// U+007F, […]
28309 					(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
28310 					// If the character is the first character and is in the range [0-9]
28311 					// (U+0030 to U+0039), […]
28312 					(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
28313 					// If the character is the second character and is in the range [0-9]
28314 					// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
28315 					(
28316 						index == 1 &&
28317 						codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
28318 						firstCodeUnit == 0x002D
28319 					)
28320 				) {
28321 					// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
28322 					result += '\\' + codeUnit.toString(16) + ' ';
28323 					continue;
28324 				}
28325 
28326 				if (
28327 					// If the character is the first character and is a `-` (U+002D), and
28328 					// there is no second character, […]
28329 					index == 0 &&
28330 					length == 1 &&
28331 					codeUnit == 0x002D
28332 				) {
28333 					result += '\\' + string.charAt(index);
28334 					continue;
28335 				}
28336 
28337 				// If the character is not handled by one of the above rules and is
28338 				// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
28339 				// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
28340 				// U+005A), or [a-z] (U+0061 to U+007A), […]
28341 				if (
28342 					codeUnit >= 0x0080 ||
28343 					codeUnit == 0x002D ||
28344 					codeUnit == 0x005F ||
28345 					codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
28346 					codeUnit >= 0x0041 && codeUnit <= 0x005A ||
28347 					codeUnit >= 0x0061 && codeUnit <= 0x007A
28348 				) {
28349 					// the character itself
28350 					result += string.charAt(index);
28351 					continue;
28352 				}
28353 
28354 				// Otherwise, the escaped character.
28355 				// https://drafts.csswg.org/cssom/#escape-a-character
28356 				result += '\\' + string.charAt(index);
28357 
28358 			}
28359 			return result;
28360 		};
28361 
28362 		if (!root.CSS) {
28363 			root.CSS = {};
28364 		}
28365 
28366 		root.CSS.escape = cssEscape;
28367 		return cssEscape;
28368 
28369 	}));
28370 	}(css_escape));
28371 
28372 	var cssEscape = css_escape.exports;
28373 
28374 	var HTML_ESCAPE_MAP = {
28375 	  '&': '&amp;',
28376 	  '<': '&lt;',
28377 	  '>': '&gt;',
28378 	  '"': '&quot;',
28379 	  '\'': '&#39;'
28380 	};
28381 
28382 	function escapeHTML(str) {
28383 	  str = '' + str;
28384 
28385 	  return str && str.replace(/[&<>"']/g, function(match) {
28386 	    return HTML_ESCAPE_MAP[match];
28387 	  });
28388 	}
28389 
28390 	/**
28391 	 * A service that adds editable bendpoints to connections.
28392 	 */
28393 	function Bendpoints(
28394 	    eventBus, canvas, interactionEvents,
28395 	    bendpointMove, connectionSegmentMove) {
28396 
28397 	  /**
28398 	   * Returns true if intersection point is inside middle region of segment, adjusted by
28399 	   * optional threshold
28400 	   */
28401 	  function isIntersectionMiddle(intersection, waypoints, treshold) {
28402 	    var idx = intersection.index,
28403 	        p = intersection.point,
28404 	        p0, p1, mid, aligned, xDelta, yDelta;
28405 
28406 	    if (idx <= 0 || intersection.bendpoint) {
28407 	      return false;
28408 	    }
28409 
28410 	    p0 = waypoints[idx - 1];
28411 	    p1 = waypoints[idx];
28412 	    mid = getMidPoint(p0, p1),
28413 	    aligned = pointsAligned(p0, p1);
28414 	    xDelta = Math.abs(p.x - mid.x);
28415 	    yDelta = Math.abs(p.y - mid.y);
28416 
28417 	    return aligned && xDelta <= treshold && yDelta <= treshold;
28418 	  }
28419 
28420 	  /**
28421 	   * Calculates the threshold from a connection's middle which fits the two-third-region
28422 	   */
28423 	  function calculateIntersectionThreshold(connection, intersection) {
28424 	    var waypoints = connection.waypoints,
28425 	        relevantSegment, alignment, segmentLength, threshold;
28426 
28427 	    if (intersection.index <= 0 || intersection.bendpoint) {
28428 	      return null;
28429 	    }
28430 
28431 	    // segment relative to connection intersection
28432 	    relevantSegment = {
28433 	      start: waypoints[intersection.index - 1],
28434 	      end: waypoints[intersection.index]
28435 	    };
28436 
28437 	    alignment = pointsAligned(relevantSegment.start, relevantSegment.end);
28438 
28439 	    if (!alignment) {
28440 	      return null;
28441 	    }
28442 
28443 	    if (alignment === 'h') {
28444 	      segmentLength = relevantSegment.end.x - relevantSegment.start.x;
28445 	    } else {
28446 	      segmentLength = relevantSegment.end.y - relevantSegment.start.y;
28447 	    }
28448 
28449 	    // calculate threshold relative to 2/3 of segment length
28450 	    threshold = calculateSegmentMoveRegion(segmentLength) / 2;
28451 
28452 	    return threshold;
28453 	  }
28454 
28455 	  function activateBendpointMove(event, connection) {
28456 	    var waypoints = connection.waypoints,
28457 	        intersection = getConnectionIntersection(canvas, waypoints, event),
28458 	        threshold;
28459 
28460 	    if (!intersection) {
28461 	      return;
28462 	    }
28463 
28464 	    threshold = calculateIntersectionThreshold(connection, intersection);
28465 
28466 	    if (isIntersectionMiddle(intersection, waypoints, threshold)) {
28467 	      connectionSegmentMove.start(event, connection, intersection.index);
28468 	    } else {
28469 	      bendpointMove.start(event, connection, intersection.index, !intersection.bendpoint);
28470 	    }
28471 
28472 	    // we've handled the event
28473 	    return true;
28474 	  }
28475 
28476 	  function bindInteractionEvents(node, eventName, element) {
28477 
28478 	    componentEvent.bind(node, eventName, function(event) {
28479 	      interactionEvents.triggerMouseEvent(eventName, event, element);
28480 	      event.stopPropagation();
28481 	    });
28482 	  }
28483 
28484 	  function getBendpointsContainer(element, create) {
28485 
28486 	    var layer = canvas.getLayer('overlays'),
28487 	        gfx = query('.djs-bendpoints[data-element-id="' + cssEscape(element.id) + '"]', layer);
28488 
28489 	    if (!gfx && create) {
28490 	      gfx = create$1('g');
28491 	      attr(gfx, { 'data-element-id': element.id });
28492 	      classes(gfx).add('djs-bendpoints');
28493 
28494 	      append(layer, gfx);
28495 
28496 	      bindInteractionEvents(gfx, 'mousedown', element);
28497 	      bindInteractionEvents(gfx, 'click', element);
28498 	      bindInteractionEvents(gfx, 'dblclick', element);
28499 	    }
28500 
28501 	    return gfx;
28502 	  }
28503 
28504 	  function getSegmentDragger(idx, parentGfx) {
28505 	    return query(
28506 	      '.djs-segment-dragger[data-segment-idx="' + idx + '"]',
28507 	      parentGfx
28508 	    );
28509 	  }
28510 
28511 	  function createBendpoints(gfx, connection) {
28512 	    connection.waypoints.forEach(function(p, idx) {
28513 	      var bendpoint = addBendpoint(gfx);
28514 
28515 	      append(gfx, bendpoint);
28516 
28517 	      translate$2(bendpoint, p.x, p.y);
28518 	    });
28519 
28520 	    // add floating bendpoint
28521 	    addBendpoint(gfx, 'floating');
28522 	  }
28523 
28524 	  function createSegmentDraggers(gfx, connection) {
28525 
28526 	    var waypoints = connection.waypoints;
28527 
28528 	    var segmentStart,
28529 	        segmentEnd,
28530 	        segmentDraggerGfx;
28531 
28532 	    for (var i = 1; i < waypoints.length; i++) {
28533 
28534 	      segmentStart = waypoints[i - 1];
28535 	      segmentEnd = waypoints[i];
28536 
28537 	      if (pointsAligned(segmentStart, segmentEnd)) {
28538 	        segmentDraggerGfx = addSegmentDragger(gfx, segmentStart, segmentEnd);
28539 
28540 	        attr(segmentDraggerGfx, { 'data-segment-idx': i });
28541 
28542 	        bindInteractionEvents(segmentDraggerGfx, 'mousemove', connection);
28543 	      }
28544 	    }
28545 	  }
28546 
28547 	  function clearBendpoints(gfx) {
28548 	    forEach(all('.' + BENDPOINT_CLS, gfx), function(node) {
28549 	      remove$1(node);
28550 	    });
28551 	  }
28552 
28553 	  function clearSegmentDraggers(gfx) {
28554 	    forEach(all('.' + SEGMENT_DRAGGER_CLS, gfx), function(node) {
28555 	      remove$1(node);
28556 	    });
28557 	  }
28558 
28559 	  function addHandles(connection) {
28560 
28561 	    var gfx = getBendpointsContainer(connection);
28562 
28563 	    if (!gfx) {
28564 	      gfx = getBendpointsContainer(connection, true);
28565 
28566 	      createBendpoints(gfx, connection);
28567 	      createSegmentDraggers(gfx, connection);
28568 	    }
28569 
28570 	    return gfx;
28571 	  }
28572 
28573 	  function updateHandles(connection) {
28574 
28575 	    var gfx = getBendpointsContainer(connection);
28576 
28577 	    if (gfx) {
28578 	      clearSegmentDraggers(gfx);
28579 	      clearBendpoints(gfx);
28580 	      createSegmentDraggers(gfx, connection);
28581 	      createBendpoints(gfx, connection);
28582 	    }
28583 	  }
28584 
28585 	  function updateFloatingBendpointPosition(parentGfx, intersection) {
28586 	    var floating = query('.floating', parentGfx),
28587 	        point = intersection.point;
28588 
28589 	    if (!floating) {
28590 	      return;
28591 	    }
28592 
28593 	    translate$2(floating, point.x, point.y);
28594 
28595 	  }
28596 
28597 	  function updateSegmentDraggerPosition(parentGfx, intersection, waypoints) {
28598 
28599 	    var draggerGfx = getSegmentDragger(intersection.index, parentGfx),
28600 	        segmentStart = waypoints[intersection.index - 1],
28601 	        segmentEnd = waypoints[intersection.index],
28602 	        point = intersection.point,
28603 	        mid = getMidPoint(segmentStart, segmentEnd),
28604 	        alignment = pointsAligned(segmentStart, segmentEnd),
28605 	        draggerVisual, relativePosition;
28606 
28607 	    if (!draggerGfx) {
28608 	      return;
28609 	    }
28610 
28611 	    draggerVisual = getDraggerVisual(draggerGfx);
28612 
28613 	    relativePosition = {
28614 	      x: point.x - mid.x,
28615 	      y: point.y - mid.y
28616 	    };
28617 
28618 	    if (alignment === 'v') {
28619 
28620 	      // rotate position
28621 	      relativePosition = {
28622 	        x: relativePosition.y,
28623 	        y: relativePosition.x
28624 	      };
28625 	    }
28626 
28627 	    translate$2(draggerVisual, relativePosition.x, relativePosition.y);
28628 	  }
28629 
28630 	  eventBus.on('connection.changed', function(event) {
28631 	    updateHandles(event.element);
28632 	  });
28633 
28634 	  eventBus.on('connection.remove', function(event) {
28635 	    var gfx = getBendpointsContainer(event.element);
28636 
28637 	    if (gfx) {
28638 	      remove$1(gfx);
28639 	    }
28640 	  });
28641 
28642 	  eventBus.on('element.marker.update', function(event) {
28643 
28644 	    var element = event.element,
28645 	        bendpointsGfx;
28646 
28647 	    if (!element.waypoints) {
28648 	      return;
28649 	    }
28650 
28651 	    bendpointsGfx = addHandles(element);
28652 
28653 	    if (event.add) {
28654 	      classes(bendpointsGfx).add(event.marker);
28655 	    } else {
28656 	      classes(bendpointsGfx).remove(event.marker);
28657 	    }
28658 	  });
28659 
28660 	  eventBus.on('element.mousemove', function(event) {
28661 
28662 	    var element = event.element,
28663 	        waypoints = element.waypoints,
28664 	        bendpointsGfx,
28665 	        intersection;
28666 
28667 	    if (waypoints) {
28668 	      bendpointsGfx = getBendpointsContainer(element, true);
28669 
28670 	      intersection = getConnectionIntersection(canvas, waypoints, event.originalEvent);
28671 
28672 	      if (!intersection) {
28673 	        return;
28674 	      }
28675 
28676 	      updateFloatingBendpointPosition(bendpointsGfx, intersection);
28677 
28678 	      if (!intersection.bendpoint) {
28679 	        updateSegmentDraggerPosition(bendpointsGfx, intersection, waypoints);
28680 	      }
28681 
28682 	    }
28683 	  });
28684 
28685 	  eventBus.on('element.mousedown', function(event) {
28686 
28687 	    if (!isPrimaryButton(event)) {
28688 	      return;
28689 	    }
28690 
28691 	    var originalEvent = event.originalEvent,
28692 	        element = event.element;
28693 
28694 	    if (!element.waypoints) {
28695 	      return;
28696 	    }
28697 
28698 	    return activateBendpointMove(originalEvent, element);
28699 	  });
28700 
28701 	  eventBus.on('selection.changed', function(event) {
28702 	    var newSelection = event.newSelection,
28703 	        primary = newSelection[0];
28704 
28705 	    if (primary && primary.waypoints) {
28706 	      addHandles(primary);
28707 	    }
28708 	  });
28709 
28710 	  eventBus.on('element.hover', function(event) {
28711 	    var element = event.element;
28712 
28713 	    if (element.waypoints) {
28714 	      addHandles(element);
28715 	      interactionEvents.registerEvent(event.gfx, 'mousemove', 'element.mousemove');
28716 	    }
28717 	  });
28718 
28719 	  eventBus.on('element.out', function(event) {
28720 	    interactionEvents.unregisterEvent(event.gfx, 'mousemove', 'element.mousemove');
28721 	  });
28722 
28723 	  // update bendpoint container data attribute on element ID change
28724 	  eventBus.on('element.updateId', function(context) {
28725 	    var element = context.element,
28726 	        newId = context.newId;
28727 
28728 	    if (element.waypoints) {
28729 	      var bendpointContainer = getBendpointsContainer(element);
28730 
28731 	      if (bendpointContainer) {
28732 	        attr(bendpointContainer, { 'data-element-id': newId });
28733 	      }
28734 	    }
28735 	  });
28736 
28737 	  // API
28738 
28739 	  this.addHandles = addHandles;
28740 	  this.updateHandles = updateHandles;
28741 	  this.getBendpointsContainer = getBendpointsContainer;
28742 	  this.getSegmentDragger = getSegmentDragger;
28743 	}
28744 
28745 	Bendpoints.$inject = [
28746 	  'eventBus',
28747 	  'canvas',
28748 	  'interactionEvents',
28749 	  'bendpointMove',
28750 	  'connectionSegmentMove'
28751 	];
28752 
28753 
28754 
28755 	// helper /////////////
28756 
28757 	function getDraggerVisual(draggerGfx) {
28758 	  return query('.djs-visual', draggerGfx);
28759 	}
28760 
28761 	var round$8 = Math.round;
28762 
28763 	var RECONNECT_START$1 = 'reconnectStart',
28764 	    RECONNECT_END$1 = 'reconnectEnd',
28765 	    UPDATE_WAYPOINTS$1 = 'updateWaypoints';
28766 
28767 
28768 	/**
28769 	 * Move bendpoints through drag and drop to add/remove bendpoints or reconnect connection.
28770 	 */
28771 	function BendpointMove(injector, eventBus, canvas, dragging, rules, modeling) {
28772 	  this._injector = injector;
28773 
28774 	  this.start = function(event, connection, bendpointIndex, insert) {
28775 	    var gfx = canvas.getGraphics(connection),
28776 	        source = connection.source,
28777 	        target = connection.target,
28778 	        waypoints = connection.waypoints,
28779 	        type;
28780 
28781 	    if (!insert && bendpointIndex === 0) {
28782 	      type = RECONNECT_START$1;
28783 	    } else
28784 	    if (!insert && bendpointIndex === waypoints.length - 1) {
28785 	      type = RECONNECT_END$1;
28786 	    } else {
28787 	      type = UPDATE_WAYPOINTS$1;
28788 	    }
28789 
28790 	    var command = type === UPDATE_WAYPOINTS$1 ? 'connection.updateWaypoints' : 'connection.reconnect';
28791 
28792 	    var allowed = rules.allowed(command, {
28793 	      connection: connection,
28794 	      source: source,
28795 	      target: target
28796 	    });
28797 
28798 	    if (allowed === false) {
28799 	      allowed = rules.allowed(command, {
28800 	        connection: connection,
28801 	        source: target,
28802 	        target: source
28803 	      });
28804 	    }
28805 
28806 	    if (allowed === false) {
28807 	      return;
28808 	    }
28809 
28810 	    dragging.init(event, 'bendpoint.move', {
28811 	      data: {
28812 	        connection: connection,
28813 	        connectionGfx: gfx,
28814 	        context: {
28815 	          allowed: allowed,
28816 	          bendpointIndex: bendpointIndex,
28817 	          connection: connection,
28818 	          source: source,
28819 	          target: target,
28820 	          insert: insert,
28821 	          type: type
28822 	        }
28823 	      }
28824 	    });
28825 	  };
28826 
28827 	  eventBus.on('bendpoint.move.hover', function(event) {
28828 	    var context = event.context,
28829 	        connection = context.connection,
28830 	        source = connection.source,
28831 	        target = connection.target,
28832 	        hover = event.hover,
28833 	        type = context.type;
28834 
28835 	    // cache hover state
28836 	    context.hover = hover;
28837 
28838 	    var allowed;
28839 
28840 	    if (!hover) {
28841 	      return;
28842 	    }
28843 
28844 	    var command = type === UPDATE_WAYPOINTS$1 ? 'connection.updateWaypoints' : 'connection.reconnect';
28845 
28846 	    allowed = context.allowed = rules.allowed(command, {
28847 	      connection: connection,
28848 	      source: type === RECONNECT_START$1 ? hover : source,
28849 	      target: type === RECONNECT_END$1 ? hover : target
28850 	    });
28851 
28852 	    if (allowed) {
28853 	      context.source = type === RECONNECT_START$1 ? hover : source;
28854 	      context.target = type === RECONNECT_END$1 ? hover : target;
28855 
28856 	      return;
28857 	    }
28858 
28859 	    if (allowed === false) {
28860 	      allowed = context.allowed = rules.allowed(command, {
28861 	        connection: connection,
28862 	        source: type === RECONNECT_END$1 ? hover : target,
28863 	        target: type === RECONNECT_START$1 ? hover : source
28864 	      });
28865 	    }
28866 
28867 	    if (allowed) {
28868 	      context.source = type === RECONNECT_END$1 ? hover : target;
28869 	      context.target = type === RECONNECT_START$1 ? hover : source;
28870 	    }
28871 	  });
28872 
28873 	  eventBus.on([ 'bendpoint.move.out', 'bendpoint.move.cleanup' ], function(event) {
28874 	    var context = event.context,
28875 	        type = context.type;
28876 
28877 	    context.hover = null;
28878 	    context.source = null;
28879 	    context.target = null;
28880 
28881 	    if (type !== UPDATE_WAYPOINTS$1) {
28882 	      context.allowed = false;
28883 	    }
28884 	  });
28885 
28886 	  eventBus.on('bendpoint.move.end', function(event) {
28887 	    var context = event.context,
28888 	        allowed = context.allowed,
28889 	        bendpointIndex = context.bendpointIndex,
28890 	        connection = context.connection,
28891 	        insert = context.insert,
28892 	        newWaypoints = connection.waypoints.slice(),
28893 	        source = context.source,
28894 	        target = context.target,
28895 	        type = context.type,
28896 	        hints = context.hints || {};
28897 
28898 	    // ensure integer values (important if zoom level was > 1 during move)
28899 	    var docking = {
28900 	      x: round$8(event.x),
28901 	      y: round$8(event.y)
28902 	    };
28903 
28904 	    if (!allowed) {
28905 	      return false;
28906 	    }
28907 
28908 	    if (type === UPDATE_WAYPOINTS$1) {
28909 	      if (insert) {
28910 
28911 	        // insert new bendpoint
28912 	        newWaypoints.splice(bendpointIndex, 0, docking);
28913 	      } else {
28914 
28915 	        // swap previous waypoint with moved one
28916 	        newWaypoints[bendpointIndex] = docking;
28917 	      }
28918 
28919 	      // pass hints about actual moved bendpoint
28920 	      // useful for connection/label layout
28921 	      hints.bendpointMove = {
28922 	        insert: insert,
28923 	        bendpointIndex: bendpointIndex
28924 	      };
28925 
28926 	      newWaypoints = this.cropWaypoints(connection, newWaypoints);
28927 
28928 	      modeling.updateWaypoints(connection, filterRedundantWaypoints(newWaypoints), hints);
28929 	    } else {
28930 	      if (type === RECONNECT_START$1) {
28931 	        hints.docking = 'source';
28932 
28933 	        if (isReverse$2(context)) {
28934 	          hints.docking = 'target';
28935 
28936 	          hints.newWaypoints = newWaypoints.reverse();
28937 	        }
28938 	      } else if (type === RECONNECT_END$1) {
28939 	        hints.docking = 'target';
28940 
28941 	        if (isReverse$2(context)) {
28942 	          hints.docking = 'source';
28943 
28944 	          hints.newWaypoints = newWaypoints.reverse();
28945 	        }
28946 	      }
28947 
28948 	      modeling.reconnect(connection, source, target, docking, hints);
28949 	    }
28950 	  }, this);
28951 	}
28952 
28953 	BendpointMove.$inject = [
28954 	  'injector',
28955 	  'eventBus',
28956 	  'canvas',
28957 	  'dragging',
28958 	  'rules',
28959 	  'modeling'
28960 	];
28961 
28962 	BendpointMove.prototype.cropWaypoints = function(connection, newWaypoints) {
28963 	  var connectionDocking = this._injector.get('connectionDocking', false);
28964 
28965 	  if (!connectionDocking) {
28966 	    return newWaypoints;
28967 	  }
28968 
28969 	  var waypoints = connection.waypoints;
28970 
28971 	  connection.waypoints = newWaypoints;
28972 
28973 	  connection.waypoints = connectionDocking.getCroppedWaypoints(connection);
28974 
28975 	  newWaypoints = connection.waypoints;
28976 
28977 	  connection.waypoints = waypoints;
28978 
28979 	  return newWaypoints;
28980 	};
28981 
28982 
28983 	// helpers //////////
28984 
28985 	function isReverse$2(context) {
28986 	  var hover = context.hover,
28987 	      source = context.source,
28988 	      target = context.target,
28989 	      type = context.type;
28990 
28991 	  if (type === RECONNECT_START$1) {
28992 	    return hover && target && hover === target && source !== target;
28993 	  }
28994 
28995 	  if (type === RECONNECT_END$1) {
28996 	    return hover && source && hover === source && source !== target;
28997 	  }
28998 	}
28999 
29000 	var RECONNECT_START = 'reconnectStart',
29001 	    RECONNECT_END = 'reconnectEnd',
29002 	    UPDATE_WAYPOINTS = 'updateWaypoints';
29003 
29004 	var MARKER_OK$4 = 'connect-ok',
29005 	    MARKER_NOT_OK$4 = 'connect-not-ok',
29006 	    MARKER_CONNECT_HOVER$1 = 'connect-hover',
29007 	    MARKER_CONNECT_UPDATING$1 = 'djs-updating',
29008 	    MARKER_ELEMENT_HIDDEN = 'djs-element-hidden';
29009 
29010 	var HIGH_PRIORITY$i = 1100;
29011 
29012 	/**
29013 	 * Preview connection while moving bendpoints.
29014 	 */
29015 	function BendpointMovePreview(bendpointMove, injector, eventBus, canvas) {
29016 	  this._injector = injector;
29017 
29018 	  var connectionPreview = injector.get('connectionPreview', false);
29019 
29020 	  eventBus.on('bendpoint.move.start', function(event) {
29021 	    var context = event.context,
29022 	        bendpointIndex = context.bendpointIndex,
29023 	        connection = context.connection,
29024 	        insert = context.insert,
29025 	        waypoints = connection.waypoints,
29026 	        newWaypoints = waypoints.slice();
29027 
29028 	    context.waypoints = waypoints;
29029 
29030 	    if (insert) {
29031 
29032 	      // insert placeholder for new bendpoint
29033 	      newWaypoints.splice(bendpointIndex, 0, { x: event.x, y: event.y });
29034 	    }
29035 
29036 	    connection.waypoints = newWaypoints;
29037 
29038 	    // add dragger gfx
29039 	    var draggerGfx = context.draggerGfx = addBendpoint(canvas.getLayer('overlays'));
29040 
29041 	    classes(draggerGfx).add('djs-dragging');
29042 
29043 	    canvas.addMarker(connection, MARKER_ELEMENT_HIDDEN);
29044 	    canvas.addMarker(connection, MARKER_CONNECT_UPDATING$1);
29045 	  });
29046 
29047 	  eventBus.on('bendpoint.move.hover', function(event) {
29048 	    var context = event.context,
29049 	        allowed = context.allowed,
29050 	        hover = context.hover,
29051 	        type = context.type;
29052 
29053 	    if (hover) {
29054 	      canvas.addMarker(hover, MARKER_CONNECT_HOVER$1);
29055 
29056 	      if (type === UPDATE_WAYPOINTS) {
29057 	        return;
29058 	      }
29059 
29060 	      if (allowed) {
29061 	        canvas.removeMarker(hover, MARKER_NOT_OK$4);
29062 	        canvas.addMarker(hover, MARKER_OK$4);
29063 	      } else if (allowed === false) {
29064 	        canvas.removeMarker(hover, MARKER_OK$4);
29065 	        canvas.addMarker(hover, MARKER_NOT_OK$4);
29066 	      }
29067 	    }
29068 	  });
29069 
29070 	  eventBus.on([
29071 	    'bendpoint.move.out',
29072 	    'bendpoint.move.cleanup'
29073 	  ], HIGH_PRIORITY$i, function(event) {
29074 	    var context = event.context,
29075 	        hover = context.hover,
29076 	        target = context.target;
29077 
29078 	    if (hover) {
29079 	      canvas.removeMarker(hover, MARKER_CONNECT_HOVER$1);
29080 	      canvas.removeMarker(hover, target ? MARKER_OK$4 : MARKER_NOT_OK$4);
29081 	    }
29082 	  });
29083 
29084 	  eventBus.on('bendpoint.move.move', function(event) {
29085 	    var context = event.context,
29086 	        allowed = context.allowed,
29087 	        bendpointIndex = context.bendpointIndex,
29088 	        draggerGfx = context.draggerGfx,
29089 	        hover = context.hover,
29090 	        type = context.type,
29091 	        connection = context.connection,
29092 	        source = connection.source,
29093 	        target = connection.target,
29094 	        newWaypoints = connection.waypoints.slice(),
29095 	        bendpoint = { x: event.x, y: event.y },
29096 	        hints = context.hints || {},
29097 	        drawPreviewHints = {};
29098 
29099 	    if (connectionPreview) {
29100 	      if (hints.connectionStart) {
29101 	        drawPreviewHints.connectionStart = hints.connectionStart;
29102 	      }
29103 
29104 	      if (hints.connectionEnd) {
29105 	        drawPreviewHints.connectionEnd = hints.connectionEnd;
29106 	      }
29107 
29108 
29109 	      if (type === RECONNECT_START) {
29110 	        if (isReverse$2(context)) {
29111 	          drawPreviewHints.connectionEnd = drawPreviewHints.connectionEnd || bendpoint;
29112 
29113 	          drawPreviewHints.source = target;
29114 	          drawPreviewHints.target = hover || source;
29115 
29116 	          newWaypoints = newWaypoints.reverse();
29117 	        } else {
29118 	          drawPreviewHints.connectionStart = drawPreviewHints.connectionStart || bendpoint;
29119 
29120 	          drawPreviewHints.source = hover || source;
29121 	          drawPreviewHints.target = target;
29122 	        }
29123 	      } else if (type === RECONNECT_END) {
29124 	        if (isReverse$2(context)) {
29125 	          drawPreviewHints.connectionStart = drawPreviewHints.connectionStart || bendpoint;
29126 
29127 	          drawPreviewHints.source = hover || target;
29128 	          drawPreviewHints.target = source;
29129 
29130 	          newWaypoints = newWaypoints.reverse();
29131 	        } else {
29132 	          drawPreviewHints.connectionEnd = drawPreviewHints.connectionEnd || bendpoint;
29133 
29134 	          drawPreviewHints.source = source;
29135 	          drawPreviewHints.target = hover || target;
29136 	        }
29137 
29138 	      } else {
29139 	        drawPreviewHints.noCropping = true;
29140 	        drawPreviewHints.noLayout = true;
29141 	        newWaypoints[ bendpointIndex ] = bendpoint;
29142 	      }
29143 
29144 	      if (type === UPDATE_WAYPOINTS) {
29145 	        newWaypoints = bendpointMove.cropWaypoints(connection, newWaypoints);
29146 	      }
29147 
29148 	      drawPreviewHints.waypoints = newWaypoints;
29149 
29150 	      connectionPreview.drawPreview(context, allowed, drawPreviewHints);
29151 	    }
29152 
29153 	    translate$2(draggerGfx, event.x, event.y);
29154 	  }, this);
29155 
29156 	  eventBus.on([
29157 	    'bendpoint.move.end',
29158 	    'bendpoint.move.cancel'
29159 	  ], HIGH_PRIORITY$i, function(event) {
29160 	    var context = event.context,
29161 	        connection = context.connection,
29162 	        draggerGfx = context.draggerGfx,
29163 	        hover = context.hover,
29164 	        target = context.target,
29165 	        waypoints = context.waypoints;
29166 
29167 	    connection.waypoints = waypoints;
29168 
29169 	    // remove dragger gfx
29170 	    remove$1(draggerGfx);
29171 
29172 	    canvas.removeMarker(connection, MARKER_CONNECT_UPDATING$1);
29173 	    canvas.removeMarker(connection, MARKER_ELEMENT_HIDDEN);
29174 
29175 	    if (hover) {
29176 	      canvas.removeMarker(hover, MARKER_OK$4);
29177 	      canvas.removeMarker(hover, target ? MARKER_OK$4 : MARKER_NOT_OK$4);
29178 	    }
29179 
29180 	    if (connectionPreview) {
29181 	      connectionPreview.cleanUp(context);
29182 	    }
29183 	  });
29184 	}
29185 
29186 	BendpointMovePreview.$inject = [
29187 	  'bendpointMove',
29188 	  'injector',
29189 	  'eventBus',
29190 	  'canvas'
29191 	];
29192 
29193 	var MARKER_CONNECT_HOVER = 'connect-hover',
29194 	    MARKER_CONNECT_UPDATING = 'djs-updating';
29195 
29196 
29197 	function axisAdd(point, axis, delta) {
29198 	  return axisSet(point, axis, point[axis] + delta);
29199 	}
29200 
29201 	function axisSet(point, axis, value) {
29202 	  return {
29203 	    x: (axis === 'x' ? value : point.x),
29204 	    y: (axis === 'y' ? value : point.y)
29205 	  };
29206 	}
29207 
29208 	function axisFenced(position, segmentStart, segmentEnd, axis) {
29209 
29210 	  var maxValue = Math.max(segmentStart[axis], segmentEnd[axis]),
29211 	      minValue = Math.min(segmentStart[axis], segmentEnd[axis]);
29212 
29213 	  var padding = 20;
29214 
29215 	  var fencedValue = Math.min(Math.max(minValue + padding, position[axis]), maxValue - padding);
29216 
29217 	  return axisSet(segmentStart, axis, fencedValue);
29218 	}
29219 
29220 	function flipAxis(axis) {
29221 	  return axis === 'x' ? 'y' : 'x';
29222 	}
29223 
29224 	/**
29225 	 * Get the docking point on the given element.
29226 	 *
29227 	 * Compute a reasonable docking, if non exists.
29228 	 *
29229 	 * @param  {Point} point
29230 	 * @param  {djs.model.Shape} referenceElement
29231 	 * @param  {string} moveAxis (x|y)
29232 	 *
29233 	 * @return {Point}
29234 	 */
29235 	function getDocking$2(point, referenceElement, moveAxis) {
29236 
29237 	  var referenceMid,
29238 	      inverseAxis;
29239 
29240 	  if (point.original) {
29241 	    return point.original;
29242 	  } else {
29243 	    referenceMid = getMid(referenceElement);
29244 	    inverseAxis = flipAxis(moveAxis);
29245 
29246 	    return axisSet(point, inverseAxis, referenceMid[inverseAxis]);
29247 	  }
29248 	}
29249 
29250 	/**
29251 	 * A component that implements moving of bendpoints
29252 	 */
29253 	function ConnectionSegmentMove(
29254 	    injector, eventBus, canvas,
29255 	    dragging, graphicsFactory, modeling) {
29256 
29257 	  // optional connection docking integration
29258 	  var connectionDocking = injector.get('connectionDocking', false);
29259 
29260 
29261 	  // API
29262 
29263 	  this.start = function(event, connection, idx) {
29264 
29265 	    var context,
29266 	        gfx = canvas.getGraphics(connection),
29267 	        segmentStartIndex = idx - 1,
29268 	        segmentEndIndex = idx,
29269 	        waypoints = connection.waypoints,
29270 	        segmentStart = waypoints[segmentStartIndex],
29271 	        segmentEnd = waypoints[segmentEndIndex],
29272 	        intersection = getConnectionIntersection(canvas, waypoints, event),
29273 	        direction, axis, dragPosition;
29274 
29275 	    direction = pointsAligned(segmentStart, segmentEnd);
29276 
29277 	    // do not move diagonal connection
29278 	    if (!direction) {
29279 	      return;
29280 	    }
29281 
29282 	    // the axis where we are going to move things
29283 	    axis = direction === 'v' ? 'x' : 'y';
29284 
29285 	    if (segmentStartIndex === 0) {
29286 	      segmentStart = getDocking$2(segmentStart, connection.source, axis);
29287 	    }
29288 
29289 	    if (segmentEndIndex === waypoints.length - 1) {
29290 	      segmentEnd = getDocking$2(segmentEnd, connection.target, axis);
29291 	    }
29292 
29293 	    if (intersection) {
29294 	      dragPosition = intersection.point;
29295 	    } else {
29296 
29297 	      // set to segment center as default
29298 	      dragPosition = {
29299 	        x: (segmentStart.x + segmentEnd.x) / 2,
29300 	        y: (segmentStart.y + segmentEnd.y) / 2
29301 	      };
29302 	    }
29303 
29304 	    context = {
29305 	      connection: connection,
29306 	      segmentStartIndex: segmentStartIndex,
29307 	      segmentEndIndex: segmentEndIndex,
29308 	      segmentStart: segmentStart,
29309 	      segmentEnd: segmentEnd,
29310 	      axis: axis,
29311 	      dragPosition: dragPosition
29312 	    };
29313 
29314 	    dragging.init(event, dragPosition, 'connectionSegment.move', {
29315 	      cursor: axis === 'x' ? 'resize-ew' : 'resize-ns',
29316 	      data: {
29317 	        connection: connection,
29318 	        connectionGfx: gfx,
29319 	        context: context
29320 	      }
29321 	    });
29322 	  };
29323 
29324 	  /**
29325 	   * Crop connection if connection cropping is provided.
29326 	   *
29327 	   * @param {Connection} connection
29328 	   * @param {Array<Point>} newWaypoints
29329 	   *
29330 	   * @return {Array<Point>} cropped connection waypoints
29331 	   */
29332 	  function cropConnection(connection, newWaypoints) {
29333 
29334 	    // crop connection, if docking service is provided only
29335 	    if (!connectionDocking) {
29336 	      return newWaypoints;
29337 	    }
29338 
29339 	    var oldWaypoints = connection.waypoints,
29340 	        croppedWaypoints;
29341 
29342 	    // temporary set new waypoints
29343 	    connection.waypoints = newWaypoints;
29344 
29345 	    croppedWaypoints = connectionDocking.getCroppedWaypoints(connection);
29346 
29347 	    // restore old waypoints
29348 	    connection.waypoints = oldWaypoints;
29349 
29350 	    return croppedWaypoints;
29351 	  }
29352 
29353 	  // DRAGGING IMPLEMENTATION
29354 
29355 	  function redrawConnection(data) {
29356 	    graphicsFactory.update('connection', data.connection, data.connectionGfx);
29357 	  }
29358 
29359 	  function updateDragger(context, segmentOffset, event) {
29360 
29361 	    var newWaypoints = context.newWaypoints,
29362 	        segmentStartIndex = context.segmentStartIndex + segmentOffset,
29363 	        segmentStart = newWaypoints[segmentStartIndex],
29364 	        segmentEndIndex = context.segmentEndIndex + segmentOffset,
29365 	        segmentEnd = newWaypoints[segmentEndIndex],
29366 	        axis = flipAxis(context.axis);
29367 
29368 	    // make sure the dragger does not move
29369 	    // outside the connection
29370 	    var draggerPosition = axisFenced(event, segmentStart, segmentEnd, axis);
29371 
29372 	    // update dragger
29373 	    translate$2(context.draggerGfx, draggerPosition.x, draggerPosition.y);
29374 	  }
29375 
29376 	  /**
29377 	   * Filter waypoints for redundant ones (i.e. on the same axis).
29378 	   * Returns the filtered waypoints and the offset related to the segment move.
29379 	   *
29380 	   * @param {Array<Point>} waypoints
29381 	   * @param {Integer} segmentStartIndex of moved segment start
29382 	   *
29383 	   * @return {Object} { filteredWaypoints, segmentOffset }
29384 	   */
29385 	  function filterRedundantWaypoints(waypoints, segmentStartIndex) {
29386 
29387 	    var segmentOffset = 0;
29388 
29389 	    var filteredWaypoints = waypoints.filter(function(r, idx) {
29390 	      if (pointsOnLine(waypoints[idx - 1], waypoints[idx + 1], r)) {
29391 
29392 	        // remove point and increment offset
29393 	        segmentOffset = idx <= segmentStartIndex ? segmentOffset - 1 : segmentOffset;
29394 	        return false;
29395 	      }
29396 
29397 	      // dont remove point
29398 	      return true;
29399 	    });
29400 
29401 	    return {
29402 	      waypoints: filteredWaypoints,
29403 	      segmentOffset: segmentOffset
29404 	    };
29405 	  }
29406 
29407 	  eventBus.on('connectionSegment.move.start', function(event) {
29408 
29409 	    var context = event.context,
29410 	        connection = event.connection,
29411 	        layer = canvas.getLayer('overlays');
29412 
29413 	    context.originalWaypoints = connection.waypoints.slice();
29414 
29415 	    // add dragger gfx
29416 	    context.draggerGfx = addSegmentDragger(layer, context.segmentStart, context.segmentEnd);
29417 	    classes(context.draggerGfx).add('djs-dragging');
29418 
29419 	    canvas.addMarker(connection, MARKER_CONNECT_UPDATING);
29420 	  });
29421 
29422 	  eventBus.on('connectionSegment.move.move', function(event) {
29423 
29424 	    var context = event.context,
29425 	        connection = context.connection,
29426 	        segmentStartIndex = context.segmentStartIndex,
29427 	        segmentEndIndex = context.segmentEndIndex,
29428 	        segmentStart = context.segmentStart,
29429 	        segmentEnd = context.segmentEnd,
29430 	        axis = context.axis;
29431 
29432 	    var newWaypoints = context.originalWaypoints.slice(),
29433 	        newSegmentStart = axisAdd(segmentStart, axis, event['d' + axis]),
29434 	        newSegmentEnd = axisAdd(segmentEnd, axis, event['d' + axis]);
29435 
29436 	    // original waypoint count and added / removed
29437 	    // from start waypoint delta. We use the later
29438 	    // to retrieve the updated segmentStartIndex / segmentEndIndex
29439 	    var waypointCount = newWaypoints.length,
29440 	        segmentOffset = 0;
29441 
29442 	    // move segment start / end by axis delta
29443 	    newWaypoints[segmentStartIndex] = newSegmentStart;
29444 	    newWaypoints[segmentEndIndex] = newSegmentEnd;
29445 
29446 	    var sourceToSegmentOrientation,
29447 	        targetToSegmentOrientation;
29448 
29449 	    // handle first segment
29450 	    if (segmentStartIndex < 2) {
29451 	      sourceToSegmentOrientation = getOrientation(connection.source, newSegmentStart);
29452 
29453 	      // first bendpoint, remove first segment if intersecting
29454 	      if (segmentStartIndex === 1) {
29455 
29456 	        if (sourceToSegmentOrientation === 'intersect') {
29457 	          newWaypoints.shift();
29458 	          newWaypoints[0] = newSegmentStart;
29459 	          segmentOffset--;
29460 	        }
29461 	      }
29462 
29463 	      // docking point, add segment if not intersecting anymore
29464 	      else {
29465 	        if (sourceToSegmentOrientation !== 'intersect') {
29466 	          newWaypoints.unshift(segmentStart);
29467 	          segmentOffset++;
29468 	        }
29469 	      }
29470 	    }
29471 
29472 	    // handle last segment
29473 	    if (segmentEndIndex > waypointCount - 3) {
29474 	      targetToSegmentOrientation = getOrientation(connection.target, newSegmentEnd);
29475 
29476 	      // last bendpoint, remove last segment if intersecting
29477 	      if (segmentEndIndex === waypointCount - 2) {
29478 
29479 	        if (targetToSegmentOrientation === 'intersect') {
29480 	          newWaypoints.pop();
29481 	          newWaypoints[newWaypoints.length - 1] = newSegmentEnd;
29482 	        }
29483 	      }
29484 
29485 	      // last bendpoint, remove last segment if intersecting
29486 	      else {
29487 	        if (targetToSegmentOrientation !== 'intersect') {
29488 	          newWaypoints.push(segmentEnd);
29489 	        }
29490 	      }
29491 	    }
29492 
29493 	    // update connection waypoints
29494 	    context.newWaypoints = connection.waypoints = cropConnection(connection, newWaypoints);
29495 
29496 	    // update dragger position
29497 	    updateDragger(context, segmentOffset, event);
29498 
29499 	    // save segmentOffset in context
29500 	    context.newSegmentStartIndex = segmentStartIndex + segmentOffset;
29501 
29502 	    // redraw connection
29503 	    redrawConnection(event);
29504 	  });
29505 
29506 	  eventBus.on('connectionSegment.move.hover', function(event) {
29507 
29508 	    event.context.hover = event.hover;
29509 	    canvas.addMarker(event.hover, MARKER_CONNECT_HOVER);
29510 	  });
29511 
29512 	  eventBus.on([
29513 	    'connectionSegment.move.out',
29514 	    'connectionSegment.move.cleanup'
29515 	  ], function(event) {
29516 
29517 	    // remove connect marker
29518 	    // if it was added
29519 	    var hover = event.context.hover;
29520 
29521 	    if (hover) {
29522 	      canvas.removeMarker(hover, MARKER_CONNECT_HOVER);
29523 	    }
29524 	  });
29525 
29526 	  eventBus.on('connectionSegment.move.cleanup', function(event) {
29527 
29528 	    var context = event.context,
29529 	        connection = context.connection;
29530 
29531 	    // remove dragger gfx
29532 	    if (context.draggerGfx) {
29533 	      remove$1(context.draggerGfx);
29534 	    }
29535 
29536 	    canvas.removeMarker(connection, MARKER_CONNECT_UPDATING);
29537 	  });
29538 
29539 	  eventBus.on([
29540 	    'connectionSegment.move.cancel',
29541 	    'connectionSegment.move.end'
29542 	  ], function(event) {
29543 	    var context = event.context,
29544 	        connection = context.connection;
29545 
29546 	    connection.waypoints = context.originalWaypoints;
29547 
29548 	    redrawConnection(event);
29549 	  });
29550 
29551 	  eventBus.on('connectionSegment.move.end', function(event) {
29552 
29553 	    var context = event.context,
29554 	        connection = context.connection,
29555 	        newWaypoints = context.newWaypoints,
29556 	        newSegmentStartIndex = context.newSegmentStartIndex;
29557 
29558 	    // ensure we have actual pixel values bendpoint
29559 	    // coordinates (important when zoom level was > 1 during move)
29560 	    newWaypoints = newWaypoints.map(function(p) {
29561 	      return {
29562 	        original: p.original,
29563 	        x: Math.round(p.x),
29564 	        y: Math.round(p.y)
29565 	      };
29566 	    });
29567 
29568 	    // apply filter redunant waypoints
29569 	    var filtered = filterRedundantWaypoints(newWaypoints, newSegmentStartIndex);
29570 
29571 	    // get filtered waypoints
29572 	    var filteredWaypoints = filtered.waypoints,
29573 	        croppedWaypoints = cropConnection(connection, filteredWaypoints),
29574 	        segmentOffset = filtered.segmentOffset;
29575 
29576 	    var hints = {
29577 	      segmentMove: {
29578 	        segmentStartIndex: context.segmentStartIndex,
29579 	        newSegmentStartIndex: newSegmentStartIndex + segmentOffset
29580 	      }
29581 	    };
29582 
29583 	    modeling.updateWaypoints(connection, croppedWaypoints, hints);
29584 	  });
29585 	}
29586 
29587 	ConnectionSegmentMove.$inject = [
29588 	  'injector',
29589 	  'eventBus',
29590 	  'canvas',
29591 	  'dragging',
29592 	  'graphicsFactory',
29593 	  'modeling'
29594 	];
29595 
29596 	var abs$6 = Math.abs,
29597 	    round$7 = Math.round;
29598 
29599 
29600 	/**
29601 	 * Snap value to a collection of reference values.
29602 	 *
29603 	 * @param  {number} value
29604 	 * @param  {Array<number>} values
29605 	 * @param  {number} [tolerance=10]
29606 	 *
29607 	 * @return {number} the value we snapped to or null, if none snapped
29608 	 */
29609 	function snapTo(value, values, tolerance) {
29610 	  tolerance = tolerance === undefined ? 10 : tolerance;
29611 
29612 	  var idx, snapValue;
29613 
29614 	  for (idx = 0; idx < values.length; idx++) {
29615 	    snapValue = values[idx];
29616 
29617 	    if (abs$6(snapValue - value) <= tolerance) {
29618 	      return snapValue;
29619 	    }
29620 	  }
29621 	}
29622 
29623 
29624 	function topLeft(bounds) {
29625 	  return {
29626 	    x: bounds.x,
29627 	    y: bounds.y
29628 	  };
29629 	}
29630 
29631 	function bottomRight(bounds) {
29632 	  return {
29633 	    x: bounds.x + bounds.width,
29634 	    y: bounds.y + bounds.height
29635 	  };
29636 	}
29637 
29638 	function mid$2(bounds, defaultValue) {
29639 
29640 	  if (!bounds || isNaN(bounds.x) || isNaN(bounds.y)) {
29641 	    return defaultValue;
29642 	  }
29643 
29644 	  return {
29645 	    x: round$7(bounds.x + bounds.width / 2),
29646 	    y: round$7(bounds.y + bounds.height / 2)
29647 	  };
29648 	}
29649 
29650 
29651 	/**
29652 	 * Retrieve the snap state of the given event.
29653 	 *
29654 	 * @param  {Event} event
29655 	 * @param  {string} axis
29656 	 *
29657 	 * @return {boolean} the snapped state
29658 	 *
29659 	 */
29660 	function isSnapped(event, axis) {
29661 	  var snapped = event.snapped;
29662 
29663 	  if (!snapped) {
29664 	    return false;
29665 	  }
29666 
29667 	  if (typeof axis === 'string') {
29668 	    return snapped[axis];
29669 	  }
29670 
29671 	  return snapped.x && snapped.y;
29672 	}
29673 
29674 
29675 	/**
29676 	 * Set the given event as snapped.
29677 	 *
29678 	 * This method may change the x and/or y position of the shape
29679 	 * from the given event!
29680 	 *
29681 	 * @param {Event} event
29682 	 * @param {string} axis
29683 	 * @param {number|boolean} value
29684 	 *
29685 	 * @return {number} old value
29686 	 */
29687 	function setSnapped(event, axis, value) {
29688 	  if (typeof axis !== 'string') {
29689 	    throw new Error('axis must be in [x, y]');
29690 	  }
29691 
29692 	  if (typeof value !== 'number' && value !== false) {
29693 	    throw new Error('value must be Number or false');
29694 	  }
29695 
29696 	  var delta,
29697 	      previousValue = event[axis];
29698 
29699 	  var snapped = event.snapped = (event.snapped || {});
29700 
29701 
29702 	  if (value === false) {
29703 	    snapped[axis] = false;
29704 	  } else {
29705 	    snapped[axis] = true;
29706 
29707 	    delta = value - previousValue;
29708 
29709 	    event[axis] += delta;
29710 	    event['d' + axis] += delta;
29711 	  }
29712 
29713 	  return previousValue;
29714 	}
29715 
29716 	/**
29717 	 * Get children of a shape.
29718 	 *
29719 	 * @param {djs.model.Shape} parent
29720 	 *
29721 	 * @returns {Array<djs.model.Shape|djs.model.Connection>}
29722 	 */
29723 	function getChildren(parent) {
29724 	  return parent.children || [];
29725 	}
29726 
29727 	var abs$5= Math.abs,
29728 	    round$6 = Math.round;
29729 
29730 	var TOLERANCE = 10;
29731 
29732 
29733 	function BendpointSnapping(eventBus) {
29734 
29735 	  function snapTo(values, value) {
29736 
29737 	    if (isArray$2(values)) {
29738 	      var i = values.length;
29739 
29740 	      while (i--) if (abs$5(values[i] - value) <= TOLERANCE) {
29741 	        return values[i];
29742 	      }
29743 	    } else {
29744 	      values = +values;
29745 	      var rem = value % values;
29746 
29747 	      if (rem < TOLERANCE) {
29748 	        return value - rem;
29749 	      }
29750 
29751 	      if (rem > values - TOLERANCE) {
29752 	        return value - rem + values;
29753 	      }
29754 	    }
29755 
29756 	    return value;
29757 	  }
29758 
29759 	  function mid(element) {
29760 	    if (element.width) {
29761 	      return {
29762 	        x: round$6(element.width / 2 + element.x),
29763 	        y: round$6(element.height / 2 + element.y)
29764 	      };
29765 	    }
29766 	  }
29767 
29768 	  // connection segment snapping //////////////////////
29769 
29770 	  function getConnectionSegmentSnaps(context) {
29771 
29772 	    var snapPoints = context.snapPoints,
29773 	        connection = context.connection,
29774 	        waypoints = connection.waypoints,
29775 	        segmentStart = context.segmentStart,
29776 	        segmentStartIndex = context.segmentStartIndex,
29777 	        segmentEnd = context.segmentEnd,
29778 	        segmentEndIndex = context.segmentEndIndex,
29779 	        axis = context.axis;
29780 
29781 	    if (snapPoints) {
29782 	      return snapPoints;
29783 	    }
29784 
29785 	    var referenceWaypoints = [
29786 	      waypoints[segmentStartIndex - 1],
29787 	      segmentStart,
29788 	      segmentEnd,
29789 	      waypoints[segmentEndIndex + 1]
29790 	    ];
29791 
29792 	    if (segmentStartIndex < 2) {
29793 	      referenceWaypoints.unshift(mid(connection.source));
29794 	    }
29795 
29796 	    if (segmentEndIndex > waypoints.length - 3) {
29797 	      referenceWaypoints.unshift(mid(connection.target));
29798 	    }
29799 
29800 	    context.snapPoints = snapPoints = { horizontal: [] , vertical: [] };
29801 
29802 	    forEach(referenceWaypoints, function(p) {
29803 
29804 	      // we snap on existing bendpoints only,
29805 	      // not placeholders that are inserted during add
29806 	      if (p) {
29807 	        p = p.original || p;
29808 
29809 	        if (axis === 'y') {
29810 	          snapPoints.horizontal.push(p.y);
29811 	        }
29812 
29813 	        if (axis === 'x') {
29814 	          snapPoints.vertical.push(p.x);
29815 	        }
29816 	      }
29817 	    });
29818 
29819 	    return snapPoints;
29820 	  }
29821 
29822 	  eventBus.on('connectionSegment.move.move', 1500, function(event) {
29823 	    var context = event.context,
29824 	        snapPoints = getConnectionSegmentSnaps(context),
29825 	        x = event.x,
29826 	        y = event.y,
29827 	        sx, sy;
29828 
29829 	    if (!snapPoints) {
29830 	      return;
29831 	    }
29832 
29833 	    // snap
29834 	    sx = snapTo(snapPoints.vertical, x);
29835 	    sy = snapTo(snapPoints.horizontal, y);
29836 
29837 
29838 	    // correction x/y
29839 	    var cx = (x - sx),
29840 	        cy = (y - sy);
29841 
29842 	    // update delta
29843 	    assign(event, {
29844 	      dx: event.dx - cx,
29845 	      dy: event.dy - cy,
29846 	      x: sx,
29847 	      y: sy
29848 	    });
29849 
29850 	    // only set snapped if actually snapped
29851 	    if (cx || snapPoints.vertical.indexOf(x) !== -1) {
29852 	      setSnapped(event, 'x', sx);
29853 	    }
29854 
29855 	    if (cy || snapPoints.horizontal.indexOf(y) !== -1) {
29856 	      setSnapped(event, 'y', sy);
29857 	    }
29858 	  });
29859 
29860 
29861 	  // bendpoint snapping //////////////////////
29862 
29863 	  function getBendpointSnaps(context) {
29864 
29865 	    var snapPoints = context.snapPoints,
29866 	        waypoints = context.connection.waypoints,
29867 	        bendpointIndex = context.bendpointIndex;
29868 
29869 	    if (snapPoints) {
29870 	      return snapPoints;
29871 	    }
29872 
29873 	    var referenceWaypoints = [ waypoints[bendpointIndex - 1], waypoints[bendpointIndex + 1] ];
29874 
29875 	    context.snapPoints = snapPoints = { horizontal: [] , vertical: [] };
29876 
29877 	    forEach(referenceWaypoints, function(p) {
29878 
29879 	      // we snap on existing bendpoints only,
29880 	      // not placeholders that are inserted during add
29881 	      if (p) {
29882 	        p = p.original || p;
29883 
29884 	        snapPoints.horizontal.push(p.y);
29885 	        snapPoints.vertical.push(p.x);
29886 	      }
29887 	    });
29888 
29889 	    return snapPoints;
29890 	  }
29891 
29892 
29893 	  eventBus.on([ 'bendpoint.move.move', 'bendpoint.move.end' ], 1500, function(event) {
29894 
29895 	    var context = event.context,
29896 	        snapPoints = getBendpointSnaps(context),
29897 	        hover = context.hover,
29898 	        hoverMid = hover && mid(hover),
29899 	        x = event.x,
29900 	        y = event.y,
29901 	        sx, sy;
29902 
29903 	    if (!snapPoints) {
29904 	      return;
29905 	    }
29906 
29907 	    // snap to hover mid
29908 	    sx = snapTo(hoverMid ? snapPoints.vertical.concat([ hoverMid.x ]) : snapPoints.vertical, x);
29909 	    sy = snapTo(hoverMid ? snapPoints.horizontal.concat([ hoverMid.y ]) : snapPoints.horizontal, y);
29910 
29911 	    // correction x/y
29912 	    var cx = (x - sx),
29913 	        cy = (y - sy);
29914 
29915 	    // update delta
29916 	    assign(event, {
29917 	      dx: event.dx - cx,
29918 	      dy: event.dy - cy,
29919 	      x: event.x - cx,
29920 	      y: event.y - cy
29921 	    });
29922 
29923 	    // only set snapped if actually snapped
29924 	    if (cx || snapPoints.vertical.indexOf(x) !== -1) {
29925 	      setSnapped(event, 'x', sx);
29926 	    }
29927 
29928 	    if (cy || snapPoints.horizontal.indexOf(y) !== -1) {
29929 	      setSnapped(event, 'y', sy);
29930 	    }
29931 	  });
29932 	}
29933 
29934 
29935 	BendpointSnapping.$inject = [ 'eventBus' ];
29936 
29937 	var BendpointsModule = {
29938 	  __depends__: [
29939 	    DraggingModule,
29940 	    RulesModule$1
29941 	  ],
29942 	  __init__: [ 'bendpoints', 'bendpointSnapping', 'bendpointMovePreview' ],
29943 	  bendpoints: [ 'type', Bendpoints ],
29944 	  bendpointMove: [ 'type', BendpointMove ],
29945 	  bendpointMovePreview: [ 'type', BendpointMovePreview ],
29946 	  connectionSegmentMove: [ 'type', ConnectionSegmentMove ],
29947 	  bendpointSnapping: [ 'type', BendpointSnapping ]
29948 	};
29949 
29950 	function Connect(eventBus, dragging, modeling, rules) {
29951 
29952 	  // rules
29953 
29954 	  function canConnect(source, target) {
29955 	    return rules.allowed('connection.create', {
29956 	      source: source,
29957 	      target: target
29958 	    });
29959 	  }
29960 
29961 	  function canConnectReverse(source, target) {
29962 	    return canConnect(target, source);
29963 	  }
29964 
29965 
29966 	  // event handlers
29967 
29968 	  eventBus.on('connect.hover', function(event) {
29969 	    var context = event.context,
29970 	        start = context.start,
29971 	        hover = event.hover,
29972 	        canExecute;
29973 
29974 	    // cache hover state
29975 	    context.hover = hover;
29976 
29977 	    canExecute = context.canExecute = canConnect(start, hover);
29978 
29979 	    // ignore hover
29980 	    if (isNil(canExecute)) {
29981 	      return;
29982 	    }
29983 
29984 	    if (canExecute !== false) {
29985 	      context.source = start;
29986 	      context.target = hover;
29987 
29988 	      return;
29989 	    }
29990 
29991 	    canExecute = context.canExecute = canConnectReverse(start, hover);
29992 
29993 	    // ignore hover
29994 	    if (isNil(canExecute)) {
29995 	      return;
29996 	    }
29997 
29998 	    if (canExecute !== false) {
29999 	      context.source = hover;
30000 	      context.target = start;
30001 	    }
30002 	  });
30003 
30004 	  eventBus.on([ 'connect.out', 'connect.cleanup' ], function(event) {
30005 	    var context = event.context;
30006 
30007 	    context.hover = null;
30008 	    context.source = null;
30009 	    context.target = null;
30010 
30011 	    context.canExecute = false;
30012 	  });
30013 
30014 	  eventBus.on('connect.end', function(event) {
30015 	    var context = event.context,
30016 	        canExecute = context.canExecute,
30017 	        connectionStart = context.connectionStart,
30018 	        connectionEnd = {
30019 	          x: event.x,
30020 	          y: event.y
30021 	        },
30022 	        source = context.source,
30023 	        target = context.target;
30024 
30025 	    if (!canExecute) {
30026 	      return false;
30027 	    }
30028 
30029 	    var attrs = null,
30030 	        hints = {
30031 	          connectionStart: isReverse$1(context) ? connectionEnd : connectionStart,
30032 	          connectionEnd: isReverse$1(context) ? connectionStart : connectionEnd
30033 	        };
30034 
30035 	    if (isObject(canExecute)) {
30036 	      attrs = canExecute;
30037 	    }
30038 
30039 	    modeling.connect(source, target, attrs, hints);
30040 	  });
30041 
30042 
30043 	  // API
30044 
30045 	  /**
30046 	   * Start connect operation.
30047 	   *
30048 	   * @param {DOMEvent} event
30049 	   * @param {djs.model.Base} start
30050 	   * @param {Point} [connectionStart]
30051 	   * @param {boolean} [autoActivate=false]
30052 	   */
30053 	  this.start = function(event, start, connectionStart, autoActivate) {
30054 	    if (!isObject(connectionStart)) {
30055 	      autoActivate = connectionStart;
30056 	      connectionStart = getMid(start);
30057 	    }
30058 
30059 	    dragging.init(event, 'connect', {
30060 	      autoActivate: autoActivate,
30061 	      data: {
30062 	        shape: start,
30063 	        context: {
30064 	          start: start,
30065 	          connectionStart: connectionStart
30066 	        }
30067 	      }
30068 	    });
30069 	  };
30070 	}
30071 
30072 	Connect.$inject = [
30073 	  'eventBus',
30074 	  'dragging',
30075 	  'modeling',
30076 	  'rules'
30077 	];
30078 
30079 
30080 	// helpers //////////
30081 
30082 	function isReverse$1(context) {
30083 	  var hover = context.hover,
30084 	      source = context.source,
30085 	      target = context.target;
30086 
30087 	  return hover && source && hover === source && source !== target;
30088 	}
30089 
30090 	var HIGH_PRIORITY$h = 1100,
30091 	    LOW_PRIORITY$h = 900;
30092 
30093 	var MARKER_OK$3 = 'connect-ok',
30094 	    MARKER_NOT_OK$3 = 'connect-not-ok';
30095 
30096 	/**
30097 	 * Shows connection preview during connect.
30098 	 *
30099 	 * @param {didi.Injector} injector
30100 	 * @param {EventBus} eventBus
30101 	 * @param {Canvas} canvas
30102 	 */
30103 	function ConnectPreview(injector, eventBus, canvas) {
30104 	  var connectionPreview = injector.get('connectionPreview', false);
30105 
30106 	  connectionPreview && eventBus.on('connect.move', function(event) {
30107 	    var context = event.context,
30108 	        canConnect = context.canExecute,
30109 	        hover = context.hover,
30110 	        source = context.source,
30111 	        start = context.start,
30112 	        startPosition = context.startPosition,
30113 	        target = context.target,
30114 	        connectionStart = context.connectionStart || startPosition,
30115 	        connectionEnd = context.connectionEnd || {
30116 	          x: event.x,
30117 	          y: event.y
30118 	        },
30119 	        previewStart = connectionStart,
30120 	        previewEnd = connectionEnd;
30121 
30122 	    if (isReverse$1(context)) {
30123 	      previewStart = connectionEnd;
30124 	      previewEnd = connectionStart;
30125 	    }
30126 
30127 	    connectionPreview.drawPreview(context, canConnect, {
30128 	      source: source || start,
30129 	      target: target || hover,
30130 	      connectionStart: previewStart,
30131 	      connectionEnd: previewEnd
30132 	    });
30133 	  });
30134 
30135 	  eventBus.on('connect.hover', LOW_PRIORITY$h, function(event) {
30136 	    var context = event.context,
30137 	        hover = event.hover,
30138 	        canExecute = context.canExecute;
30139 
30140 	    // ignore hover
30141 	    if (canExecute === null) {
30142 	      return;
30143 	    }
30144 
30145 	    canvas.addMarker(hover, canExecute ? MARKER_OK$3 : MARKER_NOT_OK$3);
30146 	  });
30147 
30148 	  eventBus.on([
30149 	    'connect.out',
30150 	    'connect.cleanup'
30151 	  ], HIGH_PRIORITY$h, function(event) {
30152 	    var hover = event.hover;
30153 
30154 	    if (hover) {
30155 	      canvas.removeMarker(hover, MARKER_OK$3);
30156 	      canvas.removeMarker(hover, MARKER_NOT_OK$3);
30157 	    }
30158 	  });
30159 
30160 	  connectionPreview && eventBus.on('connect.cleanup', function(event) {
30161 	    connectionPreview.cleanUp(event.context);
30162 	  });
30163 	}
30164 
30165 	ConnectPreview.$inject = [
30166 	  'injector',
30167 	  'eventBus',
30168 	  'canvas'
30169 	];
30170 
30171 	var ConnectModule = {
30172 	  __depends__: [
30173 	    SelectionModule,
30174 	    RulesModule$1,
30175 	    DraggingModule
30176 	  ],
30177 	  __init__: [
30178 	    'connectPreview'
30179 	  ],
30180 	  connect: [ 'type', Connect ],
30181 	  connectPreview: [ 'type', ConnectPreview ]
30182 	};
30183 
30184 	var MARKER_CONNECTION_PREVIEW = 'djs-connection-preview';
30185 
30186 	/**
30187 	 * Draws connection preview. Optionally, this can use layouter and connection docking to draw
30188 	 * better looking previews.
30189 	 *
30190 	 * @param {didi.Injector} injector
30191 	 * @param {Canvas} canvas
30192 	 * @param {GraphicsFactory} graphicsFactory
30193 	 * @param {ElementFactory} elementFactory
30194 	 */
30195 	function ConnectionPreview(
30196 	    injector,
30197 	    canvas,
30198 	    graphicsFactory,
30199 	    elementFactory
30200 	) {
30201 	  this._canvas = canvas;
30202 	  this._graphicsFactory = graphicsFactory;
30203 	  this._elementFactory = elementFactory;
30204 
30205 	  // optional components
30206 	  this._connectionDocking = injector.get('connectionDocking', false);
30207 	  this._layouter = injector.get('layouter', false);
30208 	}
30209 
30210 	ConnectionPreview.$inject = [
30211 	  'injector',
30212 	  'canvas',
30213 	  'graphicsFactory',
30214 	  'elementFactory'
30215 	];
30216 
30217 	/**
30218 	 * Draw connection preview.
30219 	 *
30220 	 * Provide at least one of <source, connectionStart> and <target, connectionEnd> to create a preview.
30221 	 * In the clean up stage, call `connectionPreview#cleanUp` with the context to remove preview.
30222 	 *
30223 	 * @param {Object} context
30224 	 * @param {Object|boolean} canConnect
30225 	 * @param {Object} hints
30226 	 * @param {djs.model.shape} [hints.source] source element
30227 	 * @param {djs.model.shape} [hints.target] target element
30228 	 * @param {Point} [hints.connectionStart] connection preview start
30229 	 * @param {Point} [hints.connectionEnd] connection preview end
30230 	 * @param {Array<Point>} [hints.waypoints] provided waypoints for preview
30231 	 * @param {boolean} [hints.noLayout] true if preview should not be laid out
30232 	 * @param {boolean} [hints.noCropping] true if preview should not be cropped
30233 	 * @param {boolean} [hints.noNoop] true if simple connection should not be drawn
30234 	 */
30235 	ConnectionPreview.prototype.drawPreview = function(context, canConnect, hints) {
30236 
30237 	  hints = hints || {};
30238 
30239 	  var connectionPreviewGfx = context.connectionPreviewGfx,
30240 	      getConnection = context.getConnection,
30241 	      source = hints.source,
30242 	      target = hints.target,
30243 	      waypoints = hints.waypoints,
30244 	      connectionStart = hints.connectionStart,
30245 	      connectionEnd = hints.connectionEnd,
30246 	      noLayout = hints.noLayout,
30247 	      noCropping = hints.noCropping,
30248 	      noNoop = hints.noNoop,
30249 	      connection;
30250 
30251 	  var self = this;
30252 
30253 	  if (!connectionPreviewGfx) {
30254 	    connectionPreviewGfx = context.connectionPreviewGfx = this.createConnectionPreviewGfx();
30255 	  }
30256 
30257 	  clear(connectionPreviewGfx);
30258 
30259 	  if (!getConnection) {
30260 	    getConnection = context.getConnection = cacheReturnValues(function(canConnect, source, target) {
30261 	      return self.getConnection(canConnect, source, target);
30262 	    });
30263 	  }
30264 
30265 	  if (canConnect) {
30266 	    connection = getConnection(canConnect, source, target);
30267 	  }
30268 
30269 	  if (!connection) {
30270 	    !noNoop && this.drawNoopPreview(connectionPreviewGfx, hints);
30271 	    return;
30272 	  }
30273 
30274 	  connection.waypoints = waypoints || [];
30275 
30276 	  // optional layout
30277 	  if (this._layouter && !noLayout) {
30278 	    connection.waypoints = this._layouter.layoutConnection(connection, {
30279 	      source: source,
30280 	      target: target,
30281 	      connectionStart: connectionStart,
30282 	      connectionEnd: connectionEnd,
30283 	      waypoints: hints.waypoints || connection.waypoints
30284 	    });
30285 	  }
30286 
30287 	  // fallback if no waypoints were provided nor created with layouter
30288 	  if (!connection.waypoints || !connection.waypoints.length) {
30289 	    connection.waypoints = [
30290 	      source ? getMid(source) : connectionStart,
30291 	      target ? getMid(target) : connectionEnd
30292 	    ];
30293 	  }
30294 
30295 	  // optional cropping
30296 	  if (this._connectionDocking && (source || target) && !noCropping) {
30297 	    connection.waypoints = this._connectionDocking.getCroppedWaypoints(connection, source, target);
30298 	  }
30299 
30300 	  this._graphicsFactory.drawConnection(connectionPreviewGfx, connection);
30301 	};
30302 
30303 	/**
30304 	 * Draw simple connection between source and target or provided points.
30305 	 *
30306 	 * @param {SVGElement} connectionPreviewGfx container for the connection
30307 	 * @param {Object} hints
30308 	 * @param {djs.model.shape} [hints.source] source element
30309 	 * @param {djs.model.shape} [hints.target] target element
30310 	 * @param {Point} [hints.connectionStart] required if source is not provided
30311 	 * @param {Point} [hints.connectionEnd] required if target is not provided
30312 	 */
30313 	ConnectionPreview.prototype.drawNoopPreview = function(connectionPreviewGfx, hints) {
30314 	  var source = hints.source,
30315 	      target = hints.target,
30316 	      start = hints.connectionStart || getMid(source),
30317 	      end = hints.connectionEnd || getMid(target);
30318 
30319 	  var waypoints = this.cropWaypoints(start, end, source, target);
30320 
30321 	  var connection = this.createNoopConnection(waypoints[0], waypoints[1]);
30322 
30323 	  append(connectionPreviewGfx, connection);
30324 	};
30325 
30326 	/**
30327 	 * Return cropped waypoints.
30328 	 *
30329 	 * @param {Point} start
30330 	 * @param {Point} end
30331 	 * @param {djs.model.shape} source
30332 	 * @param {djs.model.shape} target
30333 	 *
30334 	 * @returns {Array}
30335 	 */
30336 	ConnectionPreview.prototype.cropWaypoints = function(start, end, source, target) {
30337 	  var graphicsFactory = this._graphicsFactory,
30338 	      sourcePath = source && graphicsFactory.getShapePath(source),
30339 	      targetPath = target && graphicsFactory.getShapePath(target),
30340 	      connectionPath = graphicsFactory.getConnectionPath({ waypoints: [ start, end ] });
30341 
30342 	  start = (source && getElementLineIntersection(sourcePath, connectionPath, true)) || start;
30343 	  end = (target && getElementLineIntersection(targetPath, connectionPath, false)) || end;
30344 
30345 	  return [ start, end ];
30346 	};
30347 
30348 	/**
30349 	 * Remove connection preview container if it exists.
30350 	 *
30351 	 * @param {Object} [context]
30352 	 * @param {SVGElement} [context.connectionPreviewGfx] preview container
30353 	 */
30354 	ConnectionPreview.prototype.cleanUp = function(context) {
30355 	  if (context && context.connectionPreviewGfx) {
30356 	    remove$1(context.connectionPreviewGfx);
30357 	  }
30358 	};
30359 
30360 	/**
30361 	 * Get connection that connects source and target.
30362 	 *
30363 	 * @param {Object|boolean} canConnect
30364 	 *
30365 	 * @returns {djs.model.connection}
30366 	 */
30367 	ConnectionPreview.prototype.getConnection = function(canConnect) {
30368 	  var attrs = ensureConnectionAttrs(canConnect);
30369 
30370 	  return this._elementFactory.createConnection(attrs);
30371 	};
30372 
30373 
30374 	/**
30375 	 * Add and return preview graphics.
30376 	 *
30377 	 * @returns {SVGElement}
30378 	 */
30379 	ConnectionPreview.prototype.createConnectionPreviewGfx = function() {
30380 	  var gfx = create$1('g');
30381 
30382 	  attr(gfx, {
30383 	    pointerEvents: 'none'
30384 	  });
30385 
30386 	  classes(gfx).add(MARKER_CONNECTION_PREVIEW);
30387 
30388 	  append(this._canvas.getActiveLayer(), gfx);
30389 
30390 	  return gfx;
30391 	};
30392 
30393 	/**
30394 	 * Create and return simple connection.
30395 	 *
30396 	 * @param {Point} start
30397 	 * @param {Point} end
30398 	 *
30399 	 * @returns {SVGElement}
30400 	 */
30401 	ConnectionPreview.prototype.createNoopConnection = function(start, end) {
30402 	  var connection = create$1('polyline');
30403 
30404 	  attr(connection, {
30405 	    'stroke': '#333',
30406 	    'strokeDasharray': [ 1 ],
30407 	    'strokeWidth': 2,
30408 	    'pointer-events': 'none'
30409 	  });
30410 
30411 	  attr(connection, { 'points': [ start.x, start.y, end.x, end.y ] });
30412 
30413 	  return connection;
30414 	};
30415 
30416 	// helpers //////////
30417 
30418 	/**
30419 	 * Returns function that returns cached return values referenced by stringified first argument.
30420 	 *
30421 	 * @param {Function} fn
30422 	 *
30423 	 * @return {Function}
30424 	 */
30425 	function cacheReturnValues(fn) {
30426 	  var returnValues = {};
30427 
30428 	  /**
30429 	   * Return cached return value referenced by stringified first argument.
30430 	   *
30431 	   * @returns {*}
30432 	   */
30433 	  return function(firstArgument) {
30434 	    var key = JSON.stringify(firstArgument);
30435 
30436 	    var returnValue = returnValues[key];
30437 
30438 	    if (!returnValue) {
30439 	      returnValue = returnValues[key] = fn.apply(null, arguments);
30440 	    }
30441 
30442 	    return returnValue;
30443 	  };
30444 	}
30445 
30446 	/**
30447 	 * Ensure connection attributes is object.
30448 	 *
30449 	 * @param {Object|boolean} canConnect
30450 	 *
30451 	 * @returns {Object}
30452 	 */
30453 	function ensureConnectionAttrs(canConnect) {
30454 	  if (isObject(canConnect)) {
30455 	    return canConnect;
30456 	  } else {
30457 	    return {};
30458 	  }
30459 	}
30460 
30461 	var ConnectionPreviewModule = {
30462 	  __init__: [ 'connectionPreview' ],
30463 	  connectionPreview: [ 'type', ConnectionPreview ]
30464 	};
30465 
30466 	var min$3 = Math.min,
30467 	    max$5 = Math.max;
30468 
30469 	function preventDefault(e) {
30470 	  e.preventDefault();
30471 	}
30472 
30473 	function stopPropagation(e) {
30474 	  e.stopPropagation();
30475 	}
30476 
30477 	function isTextNode(node) {
30478 	  return node.nodeType === Node.TEXT_NODE;
30479 	}
30480 
30481 	function toArray(nodeList) {
30482 	  return [].slice.call(nodeList);
30483 	}
30484 
30485 	/**
30486 	 * Initializes a container for a content editable div.
30487 	 *
30488 	 * Structure:
30489 	 *
30490 	 * container
30491 	 *   parent
30492 	 *     content
30493 	 *     resize-handle
30494 	 *
30495 	 * @param {object} options
30496 	 * @param {DOMElement} options.container The DOM element to append the contentContainer to
30497 	 * @param {Function} options.keyHandler Handler for key events
30498 	 * @param {Function} options.resizeHandler Handler for resize events
30499 	 */
30500 	function TextBox(options) {
30501 	  this.container = options.container;
30502 
30503 	  this.parent = domify(
30504 	    '<div class="djs-direct-editing-parent">' +
30505 	      '<div class="djs-direct-editing-content" contenteditable="true"></div>' +
30506 	    '</div>'
30507 	  );
30508 
30509 	  this.content = query('[contenteditable]', this.parent);
30510 
30511 	  this.keyHandler = options.keyHandler || function() {};
30512 	  this.resizeHandler = options.resizeHandler || function() {};
30513 
30514 	  this.autoResize = bind$2(this.autoResize, this);
30515 	  this.handlePaste = bind$2(this.handlePaste, this);
30516 	}
30517 
30518 
30519 	/**
30520 	 * Create a text box with the given position, size, style and text content
30521 	 *
30522 	 * @param {Object} bounds
30523 	 * @param {Number} bounds.x absolute x position
30524 	 * @param {Number} bounds.y absolute y position
30525 	 * @param {Number} [bounds.width] fixed width value
30526 	 * @param {Number} [bounds.height] fixed height value
30527 	 * @param {Number} [bounds.maxWidth] maximum width value
30528 	 * @param {Number} [bounds.maxHeight] maximum height value
30529 	 * @param {Number} [bounds.minWidth] minimum width value
30530 	 * @param {Number} [bounds.minHeight] minimum height value
30531 	 * @param {Object} [style]
30532 	 * @param {String} value text content
30533 	 *
30534 	 * @return {DOMElement} The created content DOM element
30535 	 */
30536 	TextBox.prototype.create = function(bounds, style, value, options) {
30537 	  var self = this;
30538 
30539 	  var parent = this.parent,
30540 	      content = this.content,
30541 	      container = this.container;
30542 
30543 	  options = this.options = options || {};
30544 
30545 	  style = this.style = style || {};
30546 
30547 	  var parentStyle = pick(style, [
30548 	    'width',
30549 	    'height',
30550 	    'maxWidth',
30551 	    'maxHeight',
30552 	    'minWidth',
30553 	    'minHeight',
30554 	    'left',
30555 	    'top',
30556 	    'backgroundColor',
30557 	    'position',
30558 	    'overflow',
30559 	    'border',
30560 	    'wordWrap',
30561 	    'textAlign',
30562 	    'outline',
30563 	    'transform'
30564 	  ]);
30565 
30566 	  assign(parent.style, {
30567 	    width: bounds.width + 'px',
30568 	    height: bounds.height + 'px',
30569 	    maxWidth: bounds.maxWidth + 'px',
30570 	    maxHeight: bounds.maxHeight + 'px',
30571 	    minWidth: bounds.minWidth + 'px',
30572 	    minHeight: bounds.minHeight + 'px',
30573 	    left: bounds.x + 'px',
30574 	    top: bounds.y + 'px',
30575 	    backgroundColor: '#ffffff',
30576 	    position: 'absolute',
30577 	    overflow: 'visible',
30578 	    border: '1px solid #ccc',
30579 	    boxSizing: 'border-box',
30580 	    wordWrap: 'normal',
30581 	    textAlign: 'center',
30582 	    outline: 'none'
30583 	  }, parentStyle);
30584 
30585 	  var contentStyle = pick(style, [
30586 	    'fontFamily',
30587 	    'fontSize',
30588 	    'fontWeight',
30589 	    'lineHeight',
30590 	    'padding',
30591 	    'paddingTop',
30592 	    'paddingRight',
30593 	    'paddingBottom',
30594 	    'paddingLeft'
30595 	  ]);
30596 
30597 	  assign(content.style, {
30598 	    boxSizing: 'border-box',
30599 	    width: '100%',
30600 	    outline: 'none',
30601 	    wordWrap: 'break-word'
30602 	  }, contentStyle);
30603 
30604 	  if (options.centerVertically) {
30605 	    assign(content.style, {
30606 	      position: 'absolute',
30607 	      top: '50%',
30608 	      transform: 'translate(0, -50%)'
30609 	    }, contentStyle);
30610 	  }
30611 
30612 	  content.innerText = value;
30613 
30614 	  componentEvent.bind(content, 'keydown', this.keyHandler);
30615 	  componentEvent.bind(content, 'mousedown', stopPropagation);
30616 	  componentEvent.bind(content, 'paste', self.handlePaste);
30617 
30618 	  if (options.autoResize) {
30619 	    componentEvent.bind(content, 'input', this.autoResize);
30620 	  }
30621 
30622 	  if (options.resizable) {
30623 	    this.resizable(style);
30624 	  }
30625 
30626 	  container.appendChild(parent);
30627 
30628 	  // set selection to end of text
30629 	  this.setSelection(content.lastChild, content.lastChild && content.lastChild.length);
30630 
30631 	  return parent;
30632 	};
30633 
30634 	/**
30635 	 * Intercept paste events to remove formatting from pasted text.
30636 	 */
30637 	TextBox.prototype.handlePaste = function(e) {
30638 	  var options = this.options,
30639 	      style = this.style;
30640 
30641 	  e.preventDefault();
30642 
30643 	  var text;
30644 
30645 	  if (e.clipboardData) {
30646 
30647 	    // Chrome, Firefox, Safari
30648 	    text = e.clipboardData.getData('text/plain');
30649 	  } else {
30650 
30651 	    // Internet Explorer
30652 	    text = window.clipboardData.getData('Text');
30653 	  }
30654 
30655 	  this.insertText(text);
30656 
30657 	  if (options.autoResize) {
30658 	    var hasResized = this.autoResize(style);
30659 
30660 	    if (hasResized) {
30661 	      this.resizeHandler(hasResized);
30662 	    }
30663 	  }
30664 	};
30665 
30666 	TextBox.prototype.insertText = function(text) {
30667 	  text = normalizeEndOfLineSequences(text);
30668 
30669 	  // insertText command not supported by Internet Explorer
30670 	  var success = document.execCommand('insertText', false, text);
30671 
30672 	  if (success) {
30673 	    return;
30674 	  }
30675 
30676 	  this._insertTextIE(text);
30677 	};
30678 
30679 	TextBox.prototype._insertTextIE = function(text) {
30680 
30681 	  // Internet Explorer
30682 	  var range = this.getSelection(),
30683 	      startContainer = range.startContainer,
30684 	      endContainer = range.endContainer,
30685 	      startOffset = range.startOffset,
30686 	      endOffset = range.endOffset,
30687 	      commonAncestorContainer = range.commonAncestorContainer;
30688 
30689 	  var childNodesArray = toArray(commonAncestorContainer.childNodes);
30690 
30691 	  var container,
30692 	      offset;
30693 
30694 	  if (isTextNode(commonAncestorContainer)) {
30695 	    var containerTextContent = startContainer.textContent;
30696 
30697 	    startContainer.textContent =
30698 	      containerTextContent.substring(0, startOffset)
30699 	      + text
30700 	      + containerTextContent.substring(endOffset);
30701 
30702 	    container = startContainer;
30703 	    offset = startOffset + text.length;
30704 
30705 	  } else if (startContainer === this.content && endContainer === this.content) {
30706 	    var textNode = document.createTextNode(text);
30707 
30708 	    this.content.insertBefore(textNode, childNodesArray[startOffset]);
30709 
30710 	    container = textNode;
30711 	    offset = textNode.textContent.length;
30712 	  } else {
30713 	    var startContainerChildIndex = childNodesArray.indexOf(startContainer),
30714 	        endContainerChildIndex = childNodesArray.indexOf(endContainer);
30715 
30716 	    childNodesArray.forEach(function(childNode, index) {
30717 
30718 	      if (index === startContainerChildIndex) {
30719 	        childNode.textContent =
30720 	          startContainer.textContent.substring(0, startOffset) +
30721 	          text +
30722 	          endContainer.textContent.substring(endOffset);
30723 	      } else if (index > startContainerChildIndex && index <= endContainerChildIndex) {
30724 	        remove$2(childNode);
30725 	      }
30726 	    });
30727 
30728 	    container = startContainer;
30729 	    offset = startOffset + text.length;
30730 	  }
30731 
30732 	  if (container && offset !== undefined) {
30733 
30734 	    // is necessary in Internet Explorer
30735 	    setTimeout(function() {
30736 	      self.setSelection(container, offset);
30737 	    });
30738 	  }
30739 	};
30740 
30741 	/**
30742 	 * Automatically resize element vertically to fit its content.
30743 	 */
30744 	TextBox.prototype.autoResize = function() {
30745 	  var parent = this.parent,
30746 	      content = this.content;
30747 
30748 	  var fontSize = parseInt(this.style.fontSize) || 12;
30749 
30750 	  if (content.scrollHeight > parent.offsetHeight ||
30751 	      content.scrollHeight < parent.offsetHeight - fontSize) {
30752 	    var bounds = parent.getBoundingClientRect();
30753 
30754 	    var height = content.scrollHeight;
30755 	    parent.style.height = height + 'px';
30756 
30757 	    this.resizeHandler({
30758 	      width: bounds.width,
30759 	      height: bounds.height,
30760 	      dx: 0,
30761 	      dy: height - bounds.height
30762 	    });
30763 	  }
30764 	};
30765 
30766 	/**
30767 	 * Make an element resizable by adding a resize handle.
30768 	 */
30769 	TextBox.prototype.resizable = function() {
30770 	  var self = this;
30771 
30772 	  var parent = this.parent,
30773 	      resizeHandle = this.resizeHandle;
30774 
30775 	  var minWidth = parseInt(this.style.minWidth) || 0,
30776 	      minHeight = parseInt(this.style.minHeight) || 0,
30777 	      maxWidth = parseInt(this.style.maxWidth) || Infinity,
30778 	      maxHeight = parseInt(this.style.maxHeight) || Infinity;
30779 
30780 	  if (!resizeHandle) {
30781 	    resizeHandle = this.resizeHandle = domify(
30782 	      '<div class="djs-direct-editing-resize-handle"></div>'
30783 	    );
30784 
30785 	    var startX, startY, startWidth, startHeight;
30786 
30787 	    var onMouseDown = function(e) {
30788 	      preventDefault(e);
30789 	      stopPropagation(e);
30790 
30791 	      startX = e.clientX;
30792 	      startY = e.clientY;
30793 
30794 	      var bounds = parent.getBoundingClientRect();
30795 
30796 	      startWidth = bounds.width;
30797 	      startHeight = bounds.height;
30798 
30799 	      componentEvent.bind(document, 'mousemove', onMouseMove);
30800 	      componentEvent.bind(document, 'mouseup', onMouseUp);
30801 	    };
30802 
30803 	    var onMouseMove = function(e) {
30804 	      preventDefault(e);
30805 	      stopPropagation(e);
30806 
30807 	      var newWidth = min$3(max$5(startWidth + e.clientX - startX, minWidth), maxWidth);
30808 	      var newHeight = min$3(max$5(startHeight + e.clientY - startY, minHeight), maxHeight);
30809 
30810 	      parent.style.width = newWidth + 'px';
30811 	      parent.style.height = newHeight + 'px';
30812 
30813 	      self.resizeHandler({
30814 	        width: startWidth,
30815 	        height: startHeight,
30816 	        dx: e.clientX - startX,
30817 	        dy: e.clientY - startY
30818 	      });
30819 	    };
30820 
30821 	    var onMouseUp = function(e) {
30822 	      preventDefault(e);
30823 	      stopPropagation(e);
30824 
30825 	      componentEvent.unbind(document,'mousemove', onMouseMove, false);
30826 	      componentEvent.unbind(document, 'mouseup', onMouseUp, false);
30827 	    };
30828 
30829 	    componentEvent.bind(resizeHandle, 'mousedown', onMouseDown);
30830 	  }
30831 
30832 	  assign(resizeHandle.style, {
30833 	    position: 'absolute',
30834 	    bottom: '0px',
30835 	    right: '0px',
30836 	    cursor: 'nwse-resize',
30837 	    width: '0',
30838 	    height: '0',
30839 	    borderTop: (parseInt(this.style.fontSize) / 4 || 3) + 'px solid transparent',
30840 	    borderRight: (parseInt(this.style.fontSize) / 4 || 3) + 'px solid #ccc',
30841 	    borderBottom: (parseInt(this.style.fontSize) / 4 || 3) + 'px solid #ccc',
30842 	    borderLeft: (parseInt(this.style.fontSize) / 4 || 3) + 'px solid transparent'
30843 	  });
30844 
30845 	  parent.appendChild(resizeHandle);
30846 	};
30847 
30848 
30849 	/**
30850 	 * Clear content and style of the textbox, unbind listeners and
30851 	 * reset CSS style.
30852 	 */
30853 	TextBox.prototype.destroy = function() {
30854 	  var parent = this.parent,
30855 	      content = this.content,
30856 	      resizeHandle = this.resizeHandle;
30857 
30858 	  // clear content
30859 	  content.innerText = '';
30860 
30861 	  // clear styles
30862 	  parent.removeAttribute('style');
30863 	  content.removeAttribute('style');
30864 
30865 	  componentEvent.unbind(content, 'keydown', this.keyHandler);
30866 	  componentEvent.unbind(content, 'mousedown', stopPropagation);
30867 	  componentEvent.unbind(content, 'input', this.autoResize);
30868 	  componentEvent.unbind(content, 'paste', this.handlePaste);
30869 
30870 	  if (resizeHandle) {
30871 	    resizeHandle.removeAttribute('style');
30872 
30873 	    remove$2(resizeHandle);
30874 	  }
30875 
30876 	  remove$2(parent);
30877 	};
30878 
30879 
30880 	TextBox.prototype.getValue = function() {
30881 	  return this.content.innerText.trim();
30882 	};
30883 
30884 
30885 	TextBox.prototype.getSelection = function() {
30886 	  var selection = window.getSelection(),
30887 	      range = selection.getRangeAt(0);
30888 
30889 	  return range;
30890 	};
30891 
30892 
30893 	TextBox.prototype.setSelection = function(container, offset) {
30894 	  var range = document.createRange();
30895 
30896 	  if (container === null) {
30897 	    range.selectNodeContents(this.content);
30898 	  } else {
30899 	    range.setStart(container, offset);
30900 	    range.setEnd(container, offset);
30901 	  }
30902 
30903 	  var selection = window.getSelection();
30904 
30905 	  selection.removeAllRanges();
30906 	  selection.addRange(range);
30907 	};
30908 
30909 	// helpers //////////
30910 
30911 	function normalizeEndOfLineSequences(string) {
30912 	  return string.replace(/\r\n|\r|\n/g, '\n');
30913 	}
30914 
30915 	/**
30916 	 * A direct editing component that allows users
30917 	 * to edit an elements text directly in the diagram
30918 	 *
30919 	 * @param {EventBus} eventBus the event bus
30920 	 */
30921 	function DirectEditing(eventBus, canvas) {
30922 
30923 	  this._eventBus = eventBus;
30924 
30925 	  this._providers = [];
30926 	  this._textbox = new TextBox({
30927 	    container: canvas.getContainer(),
30928 	    keyHandler: bind$2(this._handleKey, this),
30929 	    resizeHandler: bind$2(this._handleResize, this)
30930 	  });
30931 	}
30932 
30933 	DirectEditing.$inject = [ 'eventBus', 'canvas' ];
30934 
30935 
30936 	/**
30937 	 * Register a direct editing provider
30938 
30939 	 * @param {Object} provider the provider, must expose an #activate(element) method that returns
30940 	 *                          an activation context ({ bounds: {x, y, width, height }, text }) if
30941 	 *                          direct editing is available for the given element.
30942 	 *                          Additionally the provider must expose a #update(element, value) method
30943 	 *                          to receive direct editing updates.
30944 	 */
30945 	DirectEditing.prototype.registerProvider = function(provider) {
30946 	  this._providers.push(provider);
30947 	};
30948 
30949 
30950 	/**
30951 	 * Returns true if direct editing is currently active
30952 	 *
30953 	 * @return {Boolean}
30954 	 */
30955 	DirectEditing.prototype.isActive = function() {
30956 	  return !!this._active;
30957 	};
30958 
30959 
30960 	/**
30961 	 * Cancel direct editing, if it is currently active
30962 	 */
30963 	DirectEditing.prototype.cancel = function() {
30964 	  if (!this._active) {
30965 	    return;
30966 	  }
30967 
30968 	  this._fire('cancel');
30969 	  this.close();
30970 	};
30971 
30972 
30973 	DirectEditing.prototype._fire = function(event, context) {
30974 	  this._eventBus.fire('directEditing.' + event, context || { active: this._active });
30975 	};
30976 
30977 	DirectEditing.prototype.close = function() {
30978 	  this._textbox.destroy();
30979 
30980 	  this._fire('deactivate');
30981 
30982 	  this._active = null;
30983 
30984 	  this.resizable = undefined;
30985 	};
30986 
30987 
30988 	DirectEditing.prototype.complete = function() {
30989 
30990 	  var active = this._active;
30991 
30992 	  if (!active) {
30993 	    return;
30994 	  }
30995 
30996 	  var containerBounds,
30997 	      previousBounds = active.context.bounds,
30998 	      newBounds = this.$textbox.getBoundingClientRect(),
30999 	      newText = this.getValue(),
31000 	      previousText = active.context.text;
31001 
31002 	  if (
31003 	    newText !== previousText ||
31004 	    newBounds.height !== previousBounds.height ||
31005 	    newBounds.width !== previousBounds.width
31006 	  ) {
31007 	    containerBounds = this._textbox.container.getBoundingClientRect();
31008 
31009 	    active.provider.update(active.element, newText, active.context.text, {
31010 	      x: newBounds.left - containerBounds.left,
31011 	      y: newBounds.top - containerBounds.top,
31012 	      width: newBounds.width,
31013 	      height: newBounds.height
31014 	    });
31015 	  }
31016 
31017 	  this._fire('complete');
31018 
31019 	  this.close();
31020 	};
31021 
31022 
31023 	DirectEditing.prototype.getValue = function() {
31024 	  return this._textbox.getValue();
31025 	};
31026 
31027 
31028 	DirectEditing.prototype._handleKey = function(e) {
31029 
31030 	  // stop bubble
31031 	  e.stopPropagation();
31032 
31033 	  var key = e.keyCode || e.charCode;
31034 
31035 	  // ESC
31036 	  if (key === 27) {
31037 	    e.preventDefault();
31038 	    return this.cancel();
31039 	  }
31040 
31041 	  // Enter
31042 	  if (key === 13 && !e.shiftKey) {
31043 	    e.preventDefault();
31044 	    return this.complete();
31045 	  }
31046 	};
31047 
31048 
31049 	DirectEditing.prototype._handleResize = function(event) {
31050 	  this._fire('resize', event);
31051 	};
31052 
31053 
31054 	/**
31055 	 * Activate direct editing on the given element
31056 	 *
31057 	 * @param {Object} ElementDescriptor the descriptor for a shape or connection
31058 	 * @return {Boolean} true if the activation was possible
31059 	 */
31060 	DirectEditing.prototype.activate = function(element) {
31061 	  if (this.isActive()) {
31062 	    this.cancel();
31063 	  }
31064 
31065 	  // the direct editing context
31066 	  var context;
31067 
31068 	  var provider = find(this._providers, function(p) {
31069 	    return (context = p.activate(element)) ? p : null;
31070 	  });
31071 
31072 	  // check if activation took place
31073 	  if (context) {
31074 	    this.$textbox = this._textbox.create(
31075 	      context.bounds,
31076 	      context.style,
31077 	      context.text,
31078 	      context.options
31079 	    );
31080 
31081 	    this._active = {
31082 	      element: element,
31083 	      context: context,
31084 	      provider: provider
31085 	    };
31086 
31087 	    if (context.options && context.options.resizable) {
31088 	      this.resizable = true;
31089 	    }
31090 
31091 	    this._fire('activate');
31092 	  }
31093 
31094 	  return !!context;
31095 	};
31096 
31097 	var DirectEditingModule = {
31098 	  __depends__: [
31099 	    InteractionEventsModule$1
31100 	  ],
31101 	  __init__: [ 'directEditing' ],
31102 	  directEditing: [ 'type', DirectEditing ]
31103 	};
31104 
31105 	var entrySelector = '.entry';
31106 
31107 	var DEFAULT_PRIORITY$2 = 1000;
31108 
31109 
31110 	/**
31111 	 * A context pad that displays element specific, contextual actions next
31112 	 * to a diagram element.
31113 	 *
31114 	 * @param {Object} config
31115 	 * @param {boolean|Object} [config.scale={ min: 1.0, max: 1.5 }]
31116 	 * @param {number} [config.scale.min]
31117 	 * @param {number} [config.scale.max]
31118 	 * @param {EventBus} eventBus
31119 	 * @param {Overlays} overlays
31120 	 */
31121 	function ContextPad(config, eventBus, overlays) {
31122 
31123 	  this._eventBus = eventBus;
31124 	  this._overlays = overlays;
31125 
31126 	  var scale = isDefined(config && config.scale) ? config.scale : {
31127 	    min: 1,
31128 	    max: 1.5
31129 	  };
31130 
31131 	  this._overlaysConfig = {
31132 	    position: {
31133 	      right: -9,
31134 	      top: -6
31135 	    },
31136 	    scale: scale
31137 	  };
31138 
31139 	  this._current = null;
31140 
31141 	  this._init();
31142 	}
31143 
31144 	ContextPad.$inject = [
31145 	  'config.contextPad',
31146 	  'eventBus',
31147 	  'overlays'
31148 	];
31149 
31150 
31151 	/**
31152 	 * Registers events needed for interaction with other components
31153 	 */
31154 	ContextPad.prototype._init = function() {
31155 
31156 	  var eventBus = this._eventBus;
31157 
31158 	  var self = this;
31159 
31160 	  eventBus.on('selection.changed', function(e) {
31161 
31162 	    var selection = e.newSelection;
31163 
31164 	    if (selection.length === 1) {
31165 	      self.open(selection[0]);
31166 	    } else {
31167 	      self.close();
31168 	    }
31169 	  });
31170 
31171 	  eventBus.on('elements.delete', function(event) {
31172 	    var elements = event.elements;
31173 
31174 	    forEach(elements, function(e) {
31175 	      if (self.isOpen(e)) {
31176 	        self.close();
31177 	      }
31178 	    });
31179 	  });
31180 
31181 	  eventBus.on('element.changed', function(event) {
31182 	    var element = event.element,
31183 	        current = self._current;
31184 
31185 	    // force reopen if element for which we are currently opened changed
31186 	    if (current && current.element === element) {
31187 	      self.open(element, true);
31188 	    }
31189 	  });
31190 	};
31191 
31192 
31193 	/**
31194 	 * Register a provider with the context pad
31195 	 *
31196 	 * @param  {number} [priority=1000]
31197 	 * @param  {ContextPadProvider} provider
31198 	 *
31199 	 * @example
31200 	 * const contextPadProvider = {
31201 	  *   getContextPadEntries: function(element) {
31202 	  *     return function(entries) {
31203 	  *       return {
31204 	  *         ...entries,
31205 	  *         'entry-1': {
31206 	  *           label: 'My Entry',
31207 	  *           action: function() { alert("I have been clicked!"); }
31208 	  *         }
31209 	  *       };
31210 	  *     }
31211 	  *   }
31212 	  * };
31213 	  *
31214 	 * contextPad.registerProvider(800, contextPadProvider);
31215 	 */
31216 	ContextPad.prototype.registerProvider = function(priority, provider) {
31217 	  if (!provider) {
31218 	    provider = priority;
31219 	    priority = DEFAULT_PRIORITY$2;
31220 	  }
31221 
31222 	  this._eventBus.on('contextPad.getProviders', priority, function(event) {
31223 	    event.providers.push(provider);
31224 	  });
31225 	};
31226 
31227 
31228 	/**
31229 	 * Returns the context pad entries for a given element
31230 	 *
31231 	 * @param {djs.element.Base} element
31232 	 *
31233 	 * @return {Array<ContextPadEntryDescriptor>} list of entries
31234 	 */
31235 	ContextPad.prototype.getEntries = function(element) {
31236 	  var providers = this._getProviders();
31237 
31238 	  var entries = {};
31239 
31240 	  // loop through all providers and their entries.
31241 	  // group entries by id so that overriding an entry is possible
31242 	  forEach(providers, function(provider) {
31243 	    var entriesOrUpdater = provider.getContextPadEntries(element);
31244 
31245 	    if (isFunction(entriesOrUpdater)) {
31246 	      entries = entriesOrUpdater(entries);
31247 	    } else {
31248 	      forEach(entriesOrUpdater, function(entry, id) {
31249 	        entries[id] = entry;
31250 	      });
31251 	    }
31252 	  });
31253 
31254 	  return entries;
31255 	};
31256 
31257 
31258 	/**
31259 	 * Trigger an action available on the opened context pad
31260 	 *
31261 	 * @param  {string} action
31262 	 * @param  {Event} event
31263 	 * @param  {boolean} [autoActivate=false]
31264 	 */
31265 	ContextPad.prototype.trigger = function(action, event, autoActivate) {
31266 
31267 	  var element = this._current.element,
31268 	      entries = this._current.entries,
31269 	      entry,
31270 	      handler,
31271 	      originalEvent,
31272 	      button = event.delegateTarget || event.target;
31273 
31274 	  if (!button) {
31275 	    return event.preventDefault();
31276 	  }
31277 
31278 	  entry = entries[attr$1(button, 'data-action')];
31279 	  handler = entry.action;
31280 
31281 	  originalEvent = event.originalEvent || event;
31282 
31283 	  // simple action (via callback function)
31284 	  if (isFunction(handler)) {
31285 	    if (action === 'click') {
31286 	      return handler(originalEvent, element, autoActivate);
31287 	    }
31288 	  } else {
31289 	    if (handler[action]) {
31290 	      return handler[action](originalEvent, element, autoActivate);
31291 	    }
31292 	  }
31293 
31294 	  // silence other actions
31295 	  event.preventDefault();
31296 	};
31297 
31298 
31299 	/**
31300 	 * Open the context pad for the given element
31301 	 *
31302 	 * @param {djs.model.Base} element
31303 	 * @param {boolean} force if true, force reopening the context pad
31304 	 */
31305 	ContextPad.prototype.open = function(element, force) {
31306 	  if (!force && this.isOpen(element)) {
31307 	    return;
31308 	  }
31309 
31310 	  this.close();
31311 	  this._updateAndOpen(element);
31312 	};
31313 
31314 	ContextPad.prototype._getProviders = function() {
31315 
31316 	  var event = this._eventBus.createEvent({
31317 	    type: 'contextPad.getProviders',
31318 	    providers: []
31319 	  });
31320 
31321 	  this._eventBus.fire(event);
31322 
31323 	  return event.providers;
31324 	};
31325 
31326 	ContextPad.prototype._updateAndOpen = function(element) {
31327 
31328 	  var entries = this.getEntries(element),
31329 	      pad = this.getPad(element),
31330 	      html = pad.html;
31331 
31332 	  forEach(entries, function(entry, id) {
31333 	    var grouping = entry.group || 'default',
31334 	        control = domify(entry.html || '<div class="entry" draggable="true"></div>'),
31335 	        container;
31336 
31337 	    attr$1(control, 'data-action', id);
31338 
31339 	    container = query('[data-group=' + grouping + ']', html);
31340 	    if (!container) {
31341 	      container = domify('<div class="group" data-group="' + grouping + '"></div>');
31342 	      html.appendChild(container);
31343 	    }
31344 
31345 	    container.appendChild(control);
31346 
31347 	    if (entry.className) {
31348 	      addClasses$1(control, entry.className);
31349 	    }
31350 
31351 	    if (entry.title) {
31352 	      attr$1(control, 'title', entry.title);
31353 	    }
31354 
31355 	    if (entry.imageUrl) {
31356 	      control.appendChild(domify('<img src="' + entry.imageUrl + '">'));
31357 	    }
31358 	  });
31359 
31360 	  classes$1(html).add('open');
31361 
31362 	  this._current = {
31363 	    element: element,
31364 	    pad: pad,
31365 	    entries: entries
31366 	  };
31367 
31368 	  this._eventBus.fire('contextPad.open', { current: this._current });
31369 	};
31370 
31371 
31372 	ContextPad.prototype.getPad = function(element) {
31373 	  if (this.isOpen()) {
31374 	    return this._current.pad;
31375 	  }
31376 
31377 	  var self = this;
31378 
31379 	  var overlays = this._overlays;
31380 
31381 	  var html = domify('<div class="djs-context-pad"></div>');
31382 
31383 	  var overlaysConfig = assign({
31384 	    html: html
31385 	  }, this._overlaysConfig);
31386 
31387 	  delegate.bind(html, entrySelector, 'click', function(event) {
31388 	    self.trigger('click', event);
31389 	  });
31390 
31391 	  delegate.bind(html, entrySelector, 'dragstart', function(event) {
31392 	    self.trigger('dragstart', event);
31393 	  });
31394 
31395 	  // stop propagation of mouse events
31396 	  componentEvent.bind(html, 'mousedown', function(event) {
31397 	    event.stopPropagation();
31398 	  });
31399 
31400 	  this._overlayId = overlays.add(element, 'context-pad', overlaysConfig);
31401 
31402 	  var pad = overlays.get(this._overlayId);
31403 
31404 	  this._eventBus.fire('contextPad.create', { element: element, pad: pad });
31405 
31406 	  return pad;
31407 	};
31408 
31409 
31410 	/**
31411 	 * Close the context pad
31412 	 */
31413 	ContextPad.prototype.close = function() {
31414 	  if (!this.isOpen()) {
31415 	    return;
31416 	  }
31417 
31418 	  this._overlays.remove(this._overlayId);
31419 
31420 	  this._overlayId = null;
31421 
31422 	  this._eventBus.fire('contextPad.close', { current: this._current });
31423 
31424 	  this._current = null;
31425 	};
31426 
31427 	/**
31428 	 * Check if pad is open. If element is given, will check
31429 	 * if pad is opened with given element.
31430 	 *
31431 	 * @param {Element} element
31432 	 * @return {boolean}
31433 	 */
31434 	ContextPad.prototype.isOpen = function(element) {
31435 	  return !!this._current && (!element ? true : this._current.element === element);
31436 	};
31437 
31438 
31439 
31440 
31441 	// helpers //////////////////////
31442 
31443 	function addClasses$1(element, classNames) {
31444 
31445 	  var classes = classes$1(element);
31446 
31447 	  var actualClassNames = isArray$2(classNames) ? classNames : classNames.split(/\s+/g);
31448 	  actualClassNames.forEach(function(cls) {
31449 	    classes.add(cls);
31450 	  });
31451 	}
31452 
31453 	var ContextPadModule$1 = {
31454 	  __depends__: [
31455 	    InteractionEventsModule$1,
31456 	    OverlaysModule
31457 	  ],
31458 	  contextPad: [ 'type', ContextPad ]
31459 	};
31460 
31461 	var MARKER_TYPES = [
31462 	  'marker-start',
31463 	  'marker-mid',
31464 	  'marker-end'
31465 	];
31466 
31467 	var NODES_CAN_HAVE_MARKER = [
31468 	  'circle',
31469 	  'ellipse',
31470 	  'line',
31471 	  'path',
31472 	  'polygon',
31473 	  'polyline',
31474 	  'rect'
31475 	];
31476 
31477 
31478 	/**
31479 	 * Adds support for previews of moving/resizing elements.
31480 	 */
31481 	function PreviewSupport(elementRegistry, eventBus, canvas, styles) {
31482 	  this._elementRegistry = elementRegistry;
31483 	  this._canvas = canvas;
31484 	  this._styles = styles;
31485 
31486 	  this._clonedMarkers = {};
31487 
31488 	  var self = this;
31489 
31490 	  eventBus.on('drag.cleanup', function() {
31491 	    forEach(self._clonedMarkers, function(clonedMarker) {
31492 	      remove$1(clonedMarker);
31493 	    });
31494 
31495 	    self._clonedMarkers = {};
31496 	  });
31497 	}
31498 
31499 	PreviewSupport.$inject = [
31500 	  'elementRegistry',
31501 	  'eventBus',
31502 	  'canvas',
31503 	  'styles'
31504 	];
31505 
31506 
31507 	/**
31508 	 * Returns graphics of an element.
31509 	 *
31510 	 * @param {djs.model.Base} element
31511 	 *
31512 	 * @return {SVGElement}
31513 	 */
31514 	PreviewSupport.prototype.getGfx = function(element) {
31515 	  return this._elementRegistry.getGraphics(element);
31516 	};
31517 
31518 	/**
31519 	 * Adds a move preview of a given shape to a given svg group.
31520 	 *
31521 	 * @param {djs.model.Base} element
31522 	 * @param {SVGElement} group
31523 	 * @param {SVGElement} [gfx]
31524 	 *
31525 	 * @return {SVGElement} dragger
31526 	 */
31527 	PreviewSupport.prototype.addDragger = function(element, group, gfx) {
31528 	  gfx = gfx || this.getGfx(element);
31529 
31530 	  var dragger = clone$1(gfx);
31531 	  var bbox = gfx.getBoundingClientRect();
31532 
31533 	  this._cloneMarkers(getVisual(dragger));
31534 
31535 	  attr(dragger, this._styles.cls('djs-dragger', [], {
31536 	    x: bbox.top,
31537 	    y: bbox.left
31538 	  }));
31539 
31540 	  append(group, dragger);
31541 
31542 	  return dragger;
31543 	};
31544 
31545 	/**
31546 	 * Adds a resize preview of a given shape to a given svg group.
31547 	 *
31548 	 * @param {djs.model.Base} element
31549 	 * @param {SVGElement} group
31550 	 *
31551 	 * @return {SVGElement} frame
31552 	 */
31553 	PreviewSupport.prototype.addFrame = function(shape, group) {
31554 
31555 	  var frame = create$1('rect', {
31556 	    class: 'djs-resize-overlay',
31557 	    width:  shape.width,
31558 	    height: shape.height,
31559 	    x: shape.x,
31560 	    y: shape.y
31561 	  });
31562 
31563 	  append(group, frame);
31564 
31565 	  return frame;
31566 	};
31567 
31568 	/**
31569 	 * Clone all markers referenced by a node and its child nodes.
31570 	 *
31571 	 * @param {SVGElement} gfx
31572 	 */
31573 	PreviewSupport.prototype._cloneMarkers = function(gfx) {
31574 	  var self = this;
31575 
31576 	  if (gfx.childNodes) {
31577 
31578 	    // TODO: use forEach once we drop PhantomJS
31579 	    for (var i = 0; i < gfx.childNodes.length; i++) {
31580 
31581 	      // recursively clone markers of child nodes
31582 	      self._cloneMarkers(gfx.childNodes[ i ]);
31583 	    }
31584 	  }
31585 
31586 	  if (!canHaveMarker(gfx)) {
31587 	    return;
31588 	  }
31589 
31590 	  MARKER_TYPES.forEach(function(markerType) {
31591 	    if (attr(gfx, markerType)) {
31592 	      var marker = getMarker(gfx, markerType, self._canvas.getContainer());
31593 
31594 	      self._cloneMarker(gfx, marker, markerType);
31595 	    }
31596 	  });
31597 	};
31598 
31599 	/**
31600 	 * Clone marker referenced by an element.
31601 	 *
31602 	 * @param {SVGElement} gfx
31603 	 * @param {SVGElement} marker
31604 	 * @param {string} markerType
31605 	 */
31606 	PreviewSupport.prototype._cloneMarker = function(gfx, marker, markerType) {
31607 	  var markerId = marker.id;
31608 
31609 	  var clonedMarker = this._clonedMarkers[ markerId ];
31610 
31611 	  if (!clonedMarker) {
31612 	    clonedMarker = clone$1(marker);
31613 
31614 	    var clonedMarkerId = markerId + '-clone';
31615 
31616 	    clonedMarker.id = clonedMarkerId;
31617 
31618 	    classes(clonedMarker)
31619 	      .add('djs-dragger')
31620 	      .add('djs-dragger-marker');
31621 
31622 	    this._clonedMarkers[ markerId ] = clonedMarker;
31623 
31624 	    var defs = query('defs', this._canvas._svg);
31625 
31626 	    if (!defs) {
31627 	      defs = create$1('defs');
31628 
31629 	      append(this._canvas._svg, defs);
31630 	    }
31631 
31632 	    append(defs, clonedMarker);
31633 	  }
31634 
31635 	  var reference = idToReference(this._clonedMarkers[ markerId ].id);
31636 
31637 	  attr(gfx, markerType, reference);
31638 	};
31639 
31640 	// helpers //////////
31641 
31642 	/**
31643 	 * Get marker of given type referenced by node.
31644 	 *
31645 	 * @param {Node} node
31646 	 * @param {string} markerType
31647 	 * @param {Node} [parentNode]
31648 	 *
31649 	 * @param {Node}
31650 	 */
31651 	function getMarker(node, markerType, parentNode) {
31652 	  var id = referenceToId(attr(node, markerType));
31653 
31654 	  return query('marker#' + id, parentNode || document);
31655 	}
31656 
31657 	/**
31658 	 * Get ID of fragment within current document from its functional IRI reference.
31659 	 * References may use single or double quotes.
31660 	 *
31661 	 * @param {string} reference
31662 	 *
31663 	 * @returns {string}
31664 	 */
31665 	function referenceToId(reference) {
31666 	  return reference.match(/url\(['"]?#([^'"]*)['"]?\)/)[1];
31667 	}
31668 
31669 	/**
31670 	 * Get functional IRI reference for given ID of fragment within current document.
31671 	 *
31672 	 * @param {string} id
31673 	 *
31674 	 * @returns {string}
31675 	 */
31676 	function idToReference(id) {
31677 	  return 'url(#' + id + ')';
31678 	}
31679 
31680 	/**
31681 	 * Check wether node type can have marker attributes.
31682 	 *
31683 	 * @param {Node} node
31684 	 *
31685 	 * @returns {boolean}
31686 	 */
31687 	function canHaveMarker(node) {
31688 	  return NODES_CAN_HAVE_MARKER.indexOf(node.nodeName) !== -1;
31689 	}
31690 
31691 	var PreviewSupportModule = {
31692 	  __init__: [ 'previewSupport' ],
31693 	  previewSupport: [ 'type', PreviewSupport ]
31694 	};
31695 
31696 	var MARKER_OK$2 = 'drop-ok',
31697 	    MARKER_NOT_OK$2 = 'drop-not-ok',
31698 	    MARKER_ATTACH$2 = 'attach-ok',
31699 	    MARKER_NEW_PARENT$1 = 'new-parent';
31700 
31701 	var PREFIX = 'create';
31702 
31703 	var HIGH_PRIORITY$g = 2000;
31704 
31705 
31706 	/**
31707 	 * Create new elements through drag and drop.
31708 	 *
31709 	 * @param {Canvas} canvas
31710 	 * @param {Dragging} dragging
31711 	 * @param {EventBus} eventBus
31712 	 * @param {Modeling} modeling
31713 	 * @param {Rules} rules
31714 	 */
31715 	function Create(
31716 	    canvas,
31717 	    dragging,
31718 	    eventBus,
31719 	    modeling,
31720 	    rules
31721 	) {
31722 
31723 	  // rules //////////
31724 
31725 	  /**
31726 	   * Check wether elements can be created.
31727 	   *
31728 	   * @param {Array<djs.model.Base>} elements
31729 	   * @param {djs.model.Base} target
31730 	   * @param {Point} position
31731 	   * @param {djs.model.Base} [source]
31732 	   *
31733 	   * @returns {boolean|null|Object}
31734 	   */
31735 	  function canCreate(elements, target, position, source, hints) {
31736 	    if (!target) {
31737 	      return false;
31738 	    }
31739 
31740 	    // ignore child elements and external labels
31741 	    elements = filter(elements, function(element) {
31742 	      var labelTarget = element.labelTarget;
31743 
31744 	      return !element.parent && !(isLabel$5(element) && elements.indexOf(labelTarget) !== -1);
31745 	    });
31746 
31747 	    var shape = find(elements, function(element) {
31748 	      return !isConnection$b(element);
31749 	    });
31750 
31751 	    var attach = false,
31752 	        connect = false,
31753 	        create = false;
31754 
31755 	    // (1) attaching single shapes
31756 	    if (isSingleShape(elements)) {
31757 	      attach = rules.allowed('shape.attach', {
31758 	        position: position,
31759 	        shape: shape,
31760 	        target: target
31761 	      });
31762 	    }
31763 
31764 	    if (!attach) {
31765 
31766 	      // (2) creating elements
31767 	      if (isSingleShape(elements)) {
31768 	        create = rules.allowed('shape.create', {
31769 	          position: position,
31770 	          shape: shape,
31771 	          source: source,
31772 	          target: target
31773 	        });
31774 	      } else {
31775 	        create = rules.allowed('elements.create', {
31776 	          elements: elements,
31777 	          position: position,
31778 	          target: target
31779 	        });
31780 	      }
31781 
31782 	    }
31783 
31784 	    var connectionTarget = hints.connectionTarget;
31785 
31786 	    // (3) appending single shapes
31787 	    if (create || attach) {
31788 	      if (shape && source) {
31789 	        connect = rules.allowed('connection.create', {
31790 	          source: connectionTarget === source ? shape : source,
31791 	          target: connectionTarget === source ? source : shape,
31792 	          hints: {
31793 	            targetParent: target,
31794 	            targetAttach: attach
31795 	          }
31796 	        });
31797 	      }
31798 
31799 	      return {
31800 	        attach: attach,
31801 	        connect: connect
31802 	      };
31803 	    }
31804 
31805 	    // ignore wether or not elements can be created
31806 	    if (create === null || attach === null) {
31807 	      return null;
31808 	    }
31809 
31810 	    return false;
31811 	  }
31812 
31813 	  function setMarker(element, marker) {
31814 	    [ MARKER_ATTACH$2, MARKER_OK$2, MARKER_NOT_OK$2, MARKER_NEW_PARENT$1 ].forEach(function(m) {
31815 
31816 	      if (m === marker) {
31817 	        canvas.addMarker(element, m);
31818 	      } else {
31819 	        canvas.removeMarker(element, m);
31820 	      }
31821 	    });
31822 	  }
31823 
31824 	  // event handling //////////
31825 
31826 	  eventBus.on([ 'create.move', 'create.hover' ], function(event) {
31827 	    var context = event.context,
31828 	        elements = context.elements,
31829 	        hover = event.hover,
31830 	        source = context.source,
31831 	        hints = context.hints || {};
31832 
31833 	    if (!hover) {
31834 	      context.canExecute = false;
31835 	      context.target = null;
31836 
31837 	      return;
31838 	    }
31839 
31840 	    ensureConstraints$2(event);
31841 
31842 	    var position = {
31843 	      x: event.x,
31844 	      y: event.y
31845 	    };
31846 
31847 	    var canExecute = context.canExecute = hover && canCreate(elements, hover, position, source, hints);
31848 
31849 	    if (hover && canExecute !== null) {
31850 	      context.target = hover;
31851 
31852 	      if (canExecute && canExecute.attach) {
31853 	        setMarker(hover, MARKER_ATTACH$2);
31854 	      } else {
31855 	        setMarker(hover, canExecute ? MARKER_NEW_PARENT$1 : MARKER_NOT_OK$2);
31856 	      }
31857 	    }
31858 	  });
31859 
31860 	  eventBus.on([ 'create.end', 'create.out', 'create.cleanup' ], function(event) {
31861 	    var hover = event.hover;
31862 
31863 	    if (hover) {
31864 	      setMarker(hover, null);
31865 	    }
31866 	  });
31867 
31868 	  eventBus.on('create.end', function(event) {
31869 	    var context = event.context,
31870 	        source = context.source,
31871 	        shape = context.shape,
31872 	        elements = context.elements,
31873 	        target = context.target,
31874 	        canExecute = context.canExecute,
31875 	        attach = canExecute && canExecute.attach,
31876 	        connect = canExecute && canExecute.connect,
31877 	        hints = context.hints || {};
31878 
31879 	    if (canExecute === false || !target) {
31880 	      return false;
31881 	    }
31882 
31883 	    ensureConstraints$2(event);
31884 
31885 	    var position = {
31886 	      x: event.x,
31887 	      y: event.y
31888 	    };
31889 
31890 	    if (connect) {
31891 	      shape = modeling.appendShape(source, shape, position, target, {
31892 	        attach: attach,
31893 	        connection: connect === true ? {} : connect,
31894 	        connectionTarget: hints.connectionTarget
31895 	      });
31896 	    } else {
31897 	      elements = modeling.createElements(elements, position, target, assign({}, hints, {
31898 	        attach: attach
31899 	      }));
31900 
31901 	      // update shape
31902 	      shape = find(elements, function(element) {
31903 	        return !isConnection$b(element);
31904 	      });
31905 	    }
31906 
31907 	    // update elements and shape
31908 	    assign(context, {
31909 	      elements: elements,
31910 	      shape: shape
31911 	    });
31912 
31913 	    assign(event, {
31914 	      elements: elements,
31915 	      shape: shape
31916 	    });
31917 	  });
31918 
31919 	  function cancel() {
31920 	    var context = dragging.context();
31921 
31922 	    if (context && context.prefix === PREFIX) {
31923 	      dragging.cancel();
31924 	    }
31925 	  }
31926 
31927 	  // cancel on <elements.changed> that is not result of <drag.end>
31928 	  eventBus.on('create.init', function() {
31929 	    eventBus.on('elements.changed', cancel);
31930 
31931 	    eventBus.once([ 'create.cancel', 'create.end' ], HIGH_PRIORITY$g, function() {
31932 	      eventBus.off('elements.changed', cancel);
31933 	    });
31934 	  });
31935 
31936 	  // API //////////
31937 
31938 	  this.start = function(event, elements, context) {
31939 	    if (!isArray$2(elements)) {
31940 	      elements = [ elements ];
31941 	    }
31942 
31943 	    var shape = find(elements, function(element) {
31944 	      return !isConnection$b(element);
31945 	    });
31946 
31947 	    if (!shape) {
31948 
31949 	      // at least one shape is required
31950 	      return;
31951 	    }
31952 
31953 	    context = assign({
31954 	      elements: elements,
31955 	      hints: {},
31956 	      shape: shape
31957 	    }, context || {});
31958 
31959 	    // make sure each element has x and y
31960 	    forEach(elements, function(element) {
31961 	      if (!isNumber(element.x)) {
31962 	        element.x = 0;
31963 	      }
31964 
31965 	      if (!isNumber(element.y)) {
31966 	        element.y = 0;
31967 	      }
31968 	    });
31969 
31970 	    var bbox = getBBox(elements);
31971 
31972 	    // center elements around cursor
31973 	    forEach(elements, function(element) {
31974 	      if (isConnection$b(element)) {
31975 	        element.waypoints = map$1(element.waypoints, function(waypoint) {
31976 	          return {
31977 	            x: waypoint.x - bbox.x - bbox.width / 2,
31978 	            y: waypoint.y - bbox.y - bbox.height / 2
31979 	          };
31980 	        });
31981 	      }
31982 
31983 	      assign(element, {
31984 	        x: element.x - bbox.x - bbox.width / 2,
31985 	        y: element.y - bbox.y - bbox.height / 2
31986 	      });
31987 	    });
31988 
31989 	    dragging.init(event, PREFIX, {
31990 	      cursor: 'grabbing',
31991 	      autoActivate: true,
31992 	      data: {
31993 	        shape: shape,
31994 	        elements: elements,
31995 	        context: context
31996 	      }
31997 	    });
31998 	  };
31999 	}
32000 
32001 	Create.$inject = [
32002 	  'canvas',
32003 	  'dragging',
32004 	  'eventBus',
32005 	  'modeling',
32006 	  'rules'
32007 	];
32008 
32009 	// helpers //////////
32010 
32011 	function ensureConstraints$2(event) {
32012 	  var context = event.context,
32013 	      createConstraints = context.createConstraints;
32014 
32015 	  if (!createConstraints) {
32016 	    return;
32017 	  }
32018 
32019 	  if (createConstraints.left) {
32020 	    event.x = Math.max(event.x, createConstraints.left);
32021 	  }
32022 
32023 	  if (createConstraints.right) {
32024 	    event.x = Math.min(event.x, createConstraints.right);
32025 	  }
32026 
32027 	  if (createConstraints.top) {
32028 	    event.y = Math.max(event.y, createConstraints.top);
32029 	  }
32030 
32031 	  if (createConstraints.bottom) {
32032 	    event.y = Math.min(event.y, createConstraints.bottom);
32033 	  }
32034 	}
32035 
32036 	function isConnection$b(element) {
32037 	  return !!element.waypoints;
32038 	}
32039 
32040 	function isSingleShape(elements) {
32041 	  return elements && elements.length === 1 && !isConnection$b(elements[0]);
32042 	}
32043 
32044 	function isLabel$5(element) {
32045 	  return !!element.labelTarget;
32046 	}
32047 
32048 	var LOW_PRIORITY$g = 750;
32049 
32050 
32051 	function CreatePreview(
32052 	    canvas,
32053 	    eventBus,
32054 	    graphicsFactory,
32055 	    previewSupport,
32056 	    styles
32057 	) {
32058 	  function createDragGroup(elements) {
32059 	    var dragGroup = create$1('g');
32060 
32061 	    attr(dragGroup, styles.cls('djs-drag-group', [ 'no-events' ]));
32062 
32063 	    var childrenGfx = create$1('g');
32064 
32065 	    elements.forEach(function(element) {
32066 
32067 	      // create graphics
32068 	      var gfx;
32069 
32070 	      if (element.hidden) {
32071 	        return;
32072 	      }
32073 
32074 	      if (element.waypoints) {
32075 	        gfx = graphicsFactory._createContainer('connection', childrenGfx);
32076 
32077 	        graphicsFactory.drawConnection(getVisual(gfx), element);
32078 	      } else {
32079 	        gfx = graphicsFactory._createContainer('shape', childrenGfx);
32080 
32081 	        graphicsFactory.drawShape(getVisual(gfx), element);
32082 
32083 	        translate$2(gfx, element.x, element.y);
32084 	      }
32085 
32086 	      // add preview
32087 	      previewSupport.addDragger(element, dragGroup, gfx);
32088 	    });
32089 
32090 	    return dragGroup;
32091 	  }
32092 
32093 	  eventBus.on('create.move', LOW_PRIORITY$g, function(event) {
32094 
32095 	    var hover = event.hover,
32096 	        context = event.context,
32097 	        elements = context.elements,
32098 	        dragGroup = context.dragGroup;
32099 
32100 	    // lazily create previews
32101 	    if (!dragGroup) {
32102 	      dragGroup = context.dragGroup = createDragGroup(elements);
32103 	    }
32104 
32105 	    var activeLayer;
32106 
32107 	    if (hover) {
32108 	      if (!dragGroup.parentNode) {
32109 	        activeLayer = canvas.getActiveLayer();
32110 
32111 	        append(activeLayer, dragGroup);
32112 	      }
32113 
32114 	      translate$2(dragGroup, event.x, event.y);
32115 	    } else {
32116 	      remove$1(dragGroup);
32117 	    }
32118 	  });
32119 
32120 	  eventBus.on('create.cleanup', function(event) {
32121 	    var context = event.context,
32122 	        dragGroup = context.dragGroup;
32123 
32124 	    if (dragGroup) {
32125 	      remove$1(dragGroup);
32126 	    }
32127 	  });
32128 	}
32129 
32130 	CreatePreview.$inject = [
32131 	  'canvas',
32132 	  'eventBus',
32133 	  'graphicsFactory',
32134 	  'previewSupport',
32135 	  'styles'
32136 	];
32137 
32138 	var CreateModule = {
32139 	  __depends__: [
32140 	    DraggingModule,
32141 	    PreviewSupportModule,
32142 	    RulesModule$1,
32143 	    SelectionModule
32144 	  ],
32145 	  __init__: [
32146 	    'create',
32147 	    'createPreview'
32148 	  ],
32149 	  create: [ 'type', Create ],
32150 	  createPreview: [ 'type', CreatePreview ]
32151 	};
32152 
32153 	var DATA_REF = 'data-id';
32154 
32155 	var CLOSE_EVENTS = [
32156 	  'contextPad.close',
32157 	  'canvas.viewbox.changing',
32158 	  'commandStack.changed'
32159 	];
32160 
32161 	var DEFAULT_PRIORITY$1 = 1000;
32162 
32163 
32164 	/**
32165 	 * A popup menu that can be used to display a list of actions anywhere in the canvas.
32166 	 *
32167 	 * @param {Object} config
32168 	 * @param {boolean|Object} [config.scale={ min: 1.0, max: 1.5 }]
32169 	 * @param {number} [config.scale.min]
32170 	 * @param {number} [config.scale.max]
32171 	 * @param {EventBus} eventBus
32172 	 * @param {Canvas} canvas
32173 	 *
32174 	 * @class
32175 	 * @constructor
32176 	 */
32177 	function PopupMenu(config, eventBus, canvas) {
32178 
32179 	  var scale = isDefined(config && config.scale) ? config.scale : {
32180 	    min: 1,
32181 	    max: 1.5
32182 	  };
32183 
32184 	  this._config = {
32185 	    scale: scale
32186 	  };
32187 
32188 	  this._eventBus = eventBus;
32189 	  this._canvas = canvas;
32190 	  this._providers = {};
32191 	  this._current = {};
32192 	}
32193 
32194 	PopupMenu.$inject = [
32195 	  'config.popupMenu',
32196 	  'eventBus',
32197 	  'canvas'
32198 	];
32199 
32200 	/**
32201 	 * Registers a popup menu provider
32202 	 *
32203 	 * @param  {string} id
32204 	 * @param {number} [priority=1000]
32205 	 * @param  {Object} provider
32206 	 *
32207 	 * @example
32208 	 * const popupMenuProvider = {
32209 	 *   getPopupMenuEntries: function(element) {
32210 	 *     return {
32211 	 *       'entry-1': {
32212 	 *         label: 'My Entry',
32213 	 *         action: function() { alert("I have been clicked!"); }
32214 	 *       }
32215 	 *     }
32216 	 *   }
32217 	 * };
32218 	 *
32219 	 * popupMenu.registerProvider('myMenuID', popupMenuProvider);
32220 	 */
32221 	PopupMenu.prototype.registerProvider = function(id, priority, provider) {
32222 	  if (!provider) {
32223 	    provider = priority;
32224 	    priority = DEFAULT_PRIORITY$1;
32225 	  }
32226 
32227 	  this._eventBus.on('popupMenu.getProviders.' + id, priority, function(event) {
32228 	    event.providers.push(provider);
32229 	  });
32230 	};
32231 
32232 	/**
32233 	 * Determine if the popup menu has entries.
32234 	 *
32235 	 * @return {boolean} true if empty
32236 	 */
32237 	PopupMenu.prototype.isEmpty = function(element, providerId) {
32238 	  if (!element) {
32239 	    throw new Error('element parameter is missing');
32240 	  }
32241 
32242 	  if (!providerId) {
32243 	    throw new Error('providerId parameter is missing');
32244 	  }
32245 
32246 	  var providers = this._getProviders(providerId);
32247 
32248 	  if (!providers) {
32249 	    return true;
32250 	  }
32251 
32252 	  var entries = this._getEntries(element, providers),
32253 	      headerEntries = this._getHeaderEntries(element, providers);
32254 
32255 	  var hasEntries = size(entries) > 0,
32256 	      hasHeaderEntries = headerEntries && size(headerEntries) > 0;
32257 
32258 	  return !hasEntries && !hasHeaderEntries;
32259 	};
32260 
32261 
32262 	/**
32263 	 * Create entries and open popup menu at given position
32264 	 *
32265 	 * @param  {Object} element
32266 	 * @param  {string} id provider id
32267 	 * @param  {Object} position
32268 	 *
32269 	 * @return {Object} popup menu instance
32270 	 */
32271 	PopupMenu.prototype.open = function(element, id, position) {
32272 
32273 	  var providers = this._getProviders(id);
32274 
32275 	  if (!element) {
32276 	    throw new Error('Element is missing');
32277 	  }
32278 
32279 	  if (!providers || !providers.length) {
32280 	    throw new Error('No registered providers for: ' + id);
32281 	  }
32282 
32283 	  if (!position) {
32284 	    throw new Error('the position argument is missing');
32285 	  }
32286 
32287 	  if (this.isOpen()) {
32288 	    this.close();
32289 	  }
32290 
32291 	  this._emit('open');
32292 
32293 	  var current = this._current = {
32294 	    className: id,
32295 	    element: element,
32296 	    position: position
32297 	  };
32298 
32299 	  var entries = this._getEntries(element, providers),
32300 	      headerEntries = this._getHeaderEntries(element, providers);
32301 
32302 	  current.entries = assign({}, entries, headerEntries);
32303 
32304 	  current.container = this._createContainer();
32305 
32306 	  if (size(headerEntries)) {
32307 	    current.container.appendChild(
32308 	      this._createEntries(headerEntries, 'djs-popup-header')
32309 	    );
32310 	  }
32311 
32312 	  if (size(entries)) {
32313 	    current.container.appendChild(
32314 	      this._createEntries(entries, 'djs-popup-body')
32315 	    );
32316 	  }
32317 
32318 	  var canvas = this._canvas,
32319 	      parent = canvas.getContainer();
32320 
32321 	  this._attachContainer(current.container, parent, position.cursor);
32322 	  this._bindAutoClose();
32323 	};
32324 
32325 
32326 	/**
32327 	 * Removes the popup menu and unbinds the event handlers.
32328 	 */
32329 	PopupMenu.prototype.close = function() {
32330 
32331 	  if (!this.isOpen()) {
32332 	    return;
32333 	  }
32334 
32335 	  this._emit('close');
32336 
32337 	  this._unbindAutoClose();
32338 	  remove$2(this._current.container);
32339 	  this._current.container = null;
32340 	};
32341 
32342 
32343 	/**
32344 	 * Determine if an open popup menu exist.
32345 	 *
32346 	 * @return {boolean} true if open
32347 	 */
32348 	PopupMenu.prototype.isOpen = function() {
32349 	  return !!this._current.container;
32350 	};
32351 
32352 
32353 	/**
32354 	 * Trigger an action associated with an entry.
32355 	 *
32356 	 * @param {Object} event
32357 	 *
32358 	 * @return the result of the action callback, if any
32359 	 */
32360 	PopupMenu.prototype.trigger = function(event) {
32361 
32362 	  // silence other actions
32363 	  event.preventDefault();
32364 
32365 	  var element = event.delegateTarget || event.target,
32366 	      entryId = attr$1(element, DATA_REF);
32367 
32368 	  var entry = this._getEntry(entryId);
32369 
32370 	  if (entry.action) {
32371 	    return entry.action.call(null, event, entry);
32372 	  }
32373 	};
32374 
32375 	PopupMenu.prototype._getProviders = function(id) {
32376 
32377 	  var event = this._eventBus.createEvent({
32378 	    type: 'popupMenu.getProviders.' + id,
32379 	    providers: []
32380 	  });
32381 
32382 	  this._eventBus.fire(event);
32383 
32384 	  return event.providers;
32385 	};
32386 
32387 	PopupMenu.prototype._getEntries = function(element, providers) {
32388 
32389 	  var entries = {};
32390 
32391 	  forEach(providers, function(provider) {
32392 
32393 	    // handle legacy method
32394 	    if (!provider.getPopupMenuEntries) {
32395 	      forEach(provider.getEntries(element), function(entry) {
32396 	        var id = entry.id;
32397 
32398 	        if (!id) {
32399 	          throw new Error('every entry must have the id property set');
32400 	        }
32401 
32402 	        entries[id] = omit(entry, [ 'id' ]);
32403 	      });
32404 
32405 	      return;
32406 	    }
32407 
32408 	    var entriesOrUpdater = provider.getPopupMenuEntries(element);
32409 
32410 	    if (isFunction(entriesOrUpdater)) {
32411 	      entries = entriesOrUpdater(entries);
32412 	    } else {
32413 	      forEach(entriesOrUpdater, function(entry, id) {
32414 	        entries[id] = entry;
32415 	      });
32416 	    }
32417 	  });
32418 
32419 	  return entries;
32420 	};
32421 
32422 	PopupMenu.prototype._getHeaderEntries = function(element, providers) {
32423 
32424 	  var entries = {};
32425 
32426 	  forEach(providers, function(provider) {
32427 
32428 	    // handle legacy method
32429 	    if (!provider.getPopupMenuHeaderEntries) {
32430 	      if (!provider.getHeaderEntries) {
32431 	        return;
32432 	      }
32433 
32434 	      forEach(provider.getHeaderEntries(element), function(entry) {
32435 	        var id = entry.id;
32436 
32437 	        if (!id) {
32438 	          throw new Error('every entry must have the id property set');
32439 	        }
32440 
32441 	        entries[id] = omit(entry, [ 'id' ]);
32442 	      });
32443 
32444 	      return;
32445 	    }
32446 
32447 	    var entriesOrUpdater = provider.getPopupMenuHeaderEntries(element);
32448 
32449 	    if (isFunction(entriesOrUpdater)) {
32450 	      entries = entriesOrUpdater(entries);
32451 	    } else {
32452 	      forEach(entriesOrUpdater, function(entry, id) {
32453 	        entries[id] = entry;
32454 	      });
32455 	    }
32456 	  });
32457 
32458 	  return entries;
32459 
32460 
32461 	};
32462 
32463 	/**
32464 	 * Gets an entry instance (either entry or headerEntry) by id.
32465 	 *
32466 	 * @param  {string} entryId
32467 	 *
32468 	 * @return {Object} entry instance
32469 	 */
32470 	PopupMenu.prototype._getEntry = function(entryId) {
32471 
32472 	  var entry = this._current.entries[entryId];
32473 
32474 	  if (!entry) {
32475 	    throw new Error('entry not found');
32476 	  }
32477 
32478 	  return entry;
32479 	};
32480 
32481 	PopupMenu.prototype._emit = function(eventName) {
32482 	  this._eventBus.fire('popupMenu.' + eventName);
32483 	};
32484 
32485 	/**
32486 	 * Creates the popup menu container.
32487 	 *
32488 	 * @return {Object} a DOM container
32489 	 */
32490 	PopupMenu.prototype._createContainer = function() {
32491 	  var container = domify('<div class="djs-popup">'),
32492 	      position = this._current.position,
32493 	      className = this._current.className;
32494 
32495 	  assign(container.style, {
32496 	    position: 'absolute',
32497 	    left: position.x + 'px',
32498 	    top: position.y + 'px',
32499 	    visibility: 'hidden'
32500 	  });
32501 
32502 	  classes$1(container).add(className);
32503 
32504 	  return container;
32505 	};
32506 
32507 
32508 	/**
32509 	 * Attaches the container to the DOM.
32510 	 *
32511 	 * @param {Object} container
32512 	 * @param {Object} parent
32513 	 */
32514 	PopupMenu.prototype._attachContainer = function(container, parent, cursor) {
32515 	  var self = this;
32516 
32517 	  // Event handler
32518 	  delegate.bind(container, '.entry' ,'click', function(event) {
32519 	    self.trigger(event);
32520 	  });
32521 
32522 	  this._updateScale(container);
32523 
32524 	  // Attach to DOM
32525 	  parent.appendChild(container);
32526 
32527 	  if (cursor) {
32528 	    this._assureIsInbounds(container, cursor);
32529 	  }
32530 	};
32531 
32532 
32533 	/**
32534 	 * Updates popup style.transform with respect to the config and zoom level.
32535 	 *
32536 	 * @method _updateScale
32537 	 *
32538 	 * @param {Object} container
32539 	 */
32540 	PopupMenu.prototype._updateScale = function(container) {
32541 	  var zoom = this._canvas.zoom();
32542 
32543 	  var scaleConfig = this._config.scale,
32544 	      minScale,
32545 	      maxScale,
32546 	      scale = zoom;
32547 
32548 	  if (scaleConfig !== true) {
32549 
32550 	    if (scaleConfig === false) {
32551 	      minScale = 1;
32552 	      maxScale = 1;
32553 	    } else {
32554 	      minScale = scaleConfig.min;
32555 	      maxScale = scaleConfig.max;
32556 	    }
32557 
32558 	    if (isDefined(minScale) && zoom < minScale) {
32559 	      scale = minScale;
32560 	    }
32561 
32562 	    if (isDefined(maxScale) && zoom > maxScale) {
32563 	      scale = maxScale;
32564 	    }
32565 
32566 	  }
32567 
32568 	  setTransform(container, 'scale(' + scale + ')');
32569 	};
32570 
32571 
32572 	/**
32573 	 * Make sure that the menu is always fully shown
32574 	 *
32575 	 * @method function
32576 	 *
32577 	 * @param  {Object} container
32578 	 * @param  {Position} cursor {x, y}
32579 	 */
32580 	PopupMenu.prototype._assureIsInbounds = function(container, cursor) {
32581 	  var canvas = this._canvas,
32582 	      clientRect = canvas._container.getBoundingClientRect();
32583 
32584 	  var containerX = container.offsetLeft,
32585 	      containerY = container.offsetTop,
32586 	      containerWidth = container.scrollWidth,
32587 	      containerHeight = container.scrollHeight,
32588 	      overAxis = {},
32589 	      left, top;
32590 
32591 	  var cursorPosition = {
32592 	    x: cursor.x - clientRect.left,
32593 	    y: cursor.y - clientRect.top
32594 	  };
32595 
32596 	  if (containerX + containerWidth > clientRect.width) {
32597 	    overAxis.x = true;
32598 	  }
32599 
32600 	  if (containerY + containerHeight > clientRect.height) {
32601 	    overAxis.y = true;
32602 	  }
32603 
32604 	  if (overAxis.x && overAxis.y) {
32605 	    left = cursorPosition.x - containerWidth + 'px';
32606 	    top = cursorPosition.y - containerHeight + 'px';
32607 	  } else if (overAxis.x) {
32608 	    left = cursorPosition.x - containerWidth + 'px';
32609 	    top = cursorPosition.y + 'px';
32610 	  } else if (overAxis.y && cursorPosition.y < containerHeight) {
32611 	    left = cursorPosition.x + 'px';
32612 	    top = 10 + 'px';
32613 	  } else if (overAxis.y) {
32614 	    left = cursorPosition.x + 'px';
32615 	    top = cursorPosition.y - containerHeight + 'px';
32616 	  }
32617 
32618 	  assign(container.style, { left: left, top: top }, { visibility: 'visible', 'z-index': 1000 });
32619 	};
32620 
32621 
32622 	/**
32623 	 * Creates a list of entries and returns them as a DOM container.
32624 	 *
32625 	 * @param {Array<Object>} entries an array of entry objects
32626 	 * @param {string} className the class name of the entry container
32627 	 *
32628 	 * @return {Object} a DOM container
32629 	 */
32630 	PopupMenu.prototype._createEntries = function(entries, className) {
32631 
32632 	  var entriesContainer = domify('<div>'),
32633 	      self = this;
32634 
32635 	  classes$1(entriesContainer).add(className);
32636 
32637 	  forEach(entries, function(entry, id) {
32638 	    var entryContainer = self._createEntry(entry, id);
32639 	    entriesContainer.appendChild(entryContainer);
32640 	  });
32641 
32642 	  return entriesContainer;
32643 	};
32644 
32645 
32646 	/**
32647 	 * Creates a single entry and returns it as a DOM container.
32648 	 *
32649 	 * @param  {Object} entry
32650 	 *
32651 	 * @return {Object} a DOM container
32652 	 */
32653 	PopupMenu.prototype._createEntry = function(entry, id) {
32654 
32655 	  var entryContainer = domify('<div>'),
32656 	      entryClasses = classes$1(entryContainer);
32657 
32658 	  entryClasses.add('entry');
32659 
32660 	  if (entry.className) {
32661 	    entry.className.split(' ').forEach(function(className) {
32662 	      entryClasses.add(className);
32663 	    });
32664 	  }
32665 
32666 	  attr$1(entryContainer, DATA_REF, id);
32667 
32668 	  if (entry.label) {
32669 	    var label = domify('<span>');
32670 	    label.textContent = entry.label;
32671 	    entryContainer.appendChild(label);
32672 	  }
32673 
32674 	  if (entry.imageUrl) {
32675 	    entryContainer.appendChild(domify('<img src="' + entry.imageUrl + '" />'));
32676 	  }
32677 
32678 	  if (entry.active === true) {
32679 	    entryClasses.add('active');
32680 	  }
32681 
32682 	  if (entry.disabled === true) {
32683 	    entryClasses.add('disabled');
32684 	  }
32685 
32686 	  if (entry.title) {
32687 	    entryContainer.title = entry.title;
32688 	  }
32689 
32690 	  return entryContainer;
32691 	};
32692 
32693 
32694 	/**
32695 	 * Set up listener to close popup automatically on certain events.
32696 	 */
32697 	PopupMenu.prototype._bindAutoClose = function() {
32698 	  this._eventBus.once(CLOSE_EVENTS, this.close, this);
32699 	};
32700 
32701 
32702 	/**
32703 	 * Remove the auto-closing listener.
32704 	 */
32705 	PopupMenu.prototype._unbindAutoClose = function() {
32706 	  this._eventBus.off(CLOSE_EVENTS, this.close, this);
32707 	};
32708 
32709 
32710 
32711 	// helpers /////////////////////////////
32712 
32713 	function setTransform(element, transform) {
32714 	  element.style['transform-origin'] = 'top left';
32715 
32716 	  [ '', '-ms-', '-webkit-' ].forEach(function(prefix) {
32717 	    element.style[prefix + 'transform'] = transform;
32718 	  });
32719 	}
32720 
32721 	var PopupMenuModule$1 = {
32722 	  __init__: [ 'popupMenu' ],
32723 	  popupMenu: [ 'type', PopupMenu ]
32724 	};
32725 
32726 	/**
32727 	 * A clip board stub
32728 	 */
32729 	function Clipboard() {}
32730 
32731 
32732 	Clipboard.prototype.get = function() {
32733 	  return this._data;
32734 	};
32735 
32736 	Clipboard.prototype.set = function(data) {
32737 	  this._data = data;
32738 	};
32739 
32740 	Clipboard.prototype.clear = function() {
32741 	  var data = this._data;
32742 
32743 	  delete this._data;
32744 
32745 	  return data;
32746 	};
32747 
32748 	Clipboard.prototype.isEmpty = function() {
32749 	  return !this._data;
32750 	};
32751 
32752 	var ClipboardModule = {
32753 	  clipboard: [ 'type', Clipboard ]
32754 	};
32755 
32756 	function Mouse(eventBus) {
32757 	  var self = this;
32758 
32759 	  this._lastMoveEvent = null;
32760 
32761 	  function setLastMoveEvent(mousemoveEvent) {
32762 	    self._lastMoveEvent = mousemoveEvent;
32763 	  }
32764 
32765 	  eventBus.on('canvas.init', function(context) {
32766 	    var svg = self._svg = context.svg;
32767 
32768 	    svg.addEventListener('mousemove', setLastMoveEvent);
32769 	  });
32770 
32771 	  eventBus.on('canvas.destroy', function() {
32772 	    self._lastMouseEvent = null;
32773 
32774 	    self._svg.removeEventListener('mousemove', setLastMoveEvent);
32775 	  });
32776 	}
32777 
32778 	Mouse.$inject = [ 'eventBus' ];
32779 
32780 	Mouse.prototype.getLastMoveEvent = function() {
32781 	  return this._lastMoveEvent || createMoveEvent(0, 0);
32782 	};
32783 
32784 	// helpers //////////
32785 
32786 	function createMoveEvent(x, y) {
32787 	  var event = document.createEvent('MouseEvent');
32788 
32789 	  var screenX = x,
32790 	      screenY = y,
32791 	      clientX = x,
32792 	      clientY = y;
32793 
32794 	  if (event.initMouseEvent) {
32795 	    event.initMouseEvent(
32796 	      'mousemove',
32797 	      true,
32798 	      true,
32799 	      window,
32800 	      0,
32801 	      screenX,
32802 	      screenY,
32803 	      clientX,
32804 	      clientY,
32805 	      false,
32806 	      false,
32807 	      false,
32808 	      false,
32809 	      0,
32810 	      null
32811 	    );
32812 	  }
32813 
32814 	  return event;
32815 	}
32816 
32817 	var MouseModule = {
32818 	  __init__: [ 'mouse' ],
32819 	  mouse: [ 'type', Mouse ]
32820 	};
32821 
32822 	/**
32823 	 * @typedef {Function} <copyPaste.canCopyElements> listener
32824 	 *
32825 	 * @param {Object} context
32826 	 * @param {Array<djs.model.Base>} context.elements
32827 	 *
32828 	 * @returns {Array<djs.model.Base>|boolean} - Return elements to be copied or false to disallow
32829 	 * copying.
32830 	 */
32831 
32832 	/**
32833 	 * @typedef {Function} <copyPaste.copyElement> listener
32834 	 *
32835 	 * @param {Object} context
32836 	 * @param {Object} context.descriptor
32837 	 * @param {djs.model.Base} context.element
32838 	 * @param {Array<djs.model.Base>} context.elements
32839 	 */
32840 
32841 	/**
32842 	 * @typedef {Function} <copyPaste.elementsCopied> listener
32843 	 *
32844 	 * @param {Object} context
32845 	 * @param {Object} context.elements
32846 	 * @param {Object} context.tree
32847 	 */
32848 
32849 	/**
32850 	 * @typedef {Function} <copyPaste.pasteElement> listener
32851 	 *
32852 	 * @param {Object} context
32853 	 * @param {Object} context.cache - Already created elements.
32854 	 * @param {Object} context.descriptor
32855 	 */
32856 
32857 	/**
32858 	 * @typedef {Function} <copyPaste.pasteElements> listener
32859 	 *
32860 	 * @param {Object} context
32861 	 * @param {Object} context.hints - Add hints before pasting.
32862 	 */
32863 
32864 	/**
32865 	 * Copy and paste elements.
32866 	 *
32867 	 * @param {Canvas} canvas
32868 	 * @param {Create} create
32869 	 * @param {Clipboard} clipboard
32870 	 * @param {ElementFactory} elementFactory
32871 	 * @param {EventBus} eventBus
32872 	 * @param {Modeling} modeling
32873 	 * @param {Mouse} mouse
32874 	 * @param {Rules} rules
32875 	 */
32876 	function CopyPaste(
32877 	    canvas,
32878 	    create,
32879 	    clipboard,
32880 	    elementFactory,
32881 	    eventBus,
32882 	    modeling,
32883 	    mouse,
32884 	    rules
32885 	) {
32886 
32887 	  this._canvas = canvas;
32888 	  this._create = create;
32889 	  this._clipboard = clipboard;
32890 	  this._elementFactory = elementFactory;
32891 	  this._eventBus = eventBus;
32892 	  this._modeling = modeling;
32893 	  this._mouse = mouse;
32894 	  this._rules = rules;
32895 
32896 	  eventBus.on('copyPaste.copyElement', function(context) {
32897 	    var descriptor = context.descriptor,
32898 	        element = context.element,
32899 	        elements = context.elements;
32900 
32901 	    // default priority (priority = 1)
32902 	    descriptor.priority = 1;
32903 
32904 	    descriptor.id = element.id;
32905 
32906 	    var parentCopied = find(elements, function(e) {
32907 	      return e === element.parent;
32908 	    });
32909 
32910 	    // do NOT reference parent if parent wasn't copied
32911 	    if (parentCopied) {
32912 	      descriptor.parent = element.parent.id;
32913 	    }
32914 
32915 	    // attachers (priority = 2)
32916 	    if (isAttacher$1(element)) {
32917 	      descriptor.priority = 2;
32918 
32919 	      descriptor.host = element.host.id;
32920 	    }
32921 
32922 	    // connections (priority = 3)
32923 	    if (isConnection$a(element)) {
32924 	      descriptor.priority = 3;
32925 
32926 	      descriptor.source = element.source.id;
32927 	      descriptor.target = element.target.id;
32928 
32929 	      descriptor.waypoints = copyWaypoints$1(element);
32930 	    }
32931 
32932 	    // labels (priority = 4)
32933 	    if (isLabel$4(element)) {
32934 	      descriptor.priority = 4;
32935 
32936 	      descriptor.labelTarget = element.labelTarget.id;
32937 	    }
32938 
32939 	    forEach([ 'x', 'y', 'width', 'height' ], function(property) {
32940 	      if (isNumber(element[ property ])) {
32941 	        descriptor[ property ] = element[ property ];
32942 	      }
32943 	    });
32944 
32945 	    descriptor.hidden = element.hidden;
32946 	    descriptor.collapsed = element.collapsed;
32947 
32948 	  });
32949 
32950 	  eventBus.on('copyPaste.pasteElements', function(context) {
32951 	    var hints = context.hints;
32952 
32953 	    assign(hints, {
32954 	      createElementsBehavior: false
32955 	    });
32956 	  });
32957 	}
32958 
32959 	CopyPaste.$inject = [
32960 	  'canvas',
32961 	  'create',
32962 	  'clipboard',
32963 	  'elementFactory',
32964 	  'eventBus',
32965 	  'modeling',
32966 	  'mouse',
32967 	  'rules'
32968 	];
32969 
32970 
32971 	/**
32972 	 * Copy elements.
32973 	 *
32974 	 * @param {Array<djs.model.Base>} elements
32975 	 *
32976 	 * @returns {Object}
32977 	 */
32978 	CopyPaste.prototype.copy = function(elements) {
32979 	  var allowed,
32980 	      tree;
32981 
32982 	  if (!isArray$2(elements)) {
32983 	    elements = elements ? [ elements ] : [];
32984 	  }
32985 
32986 	  allowed = this._eventBus.fire('copyPaste.canCopyElements', {
32987 	    elements: elements
32988 	  });
32989 
32990 	  if (allowed === false) {
32991 	    tree = {};
32992 	  } else {
32993 	    tree = this.createTree(isArray$2(allowed) ? allowed : elements);
32994 	  }
32995 
32996 	  // we set an empty tree, selection of elements
32997 	  // to copy was empty.
32998 	  this._clipboard.set(tree);
32999 
33000 	  this._eventBus.fire('copyPaste.elementsCopied', {
33001 	    elements: elements,
33002 	    tree: tree
33003 	  });
33004 
33005 	  return tree;
33006 	};
33007 
33008 	/**
33009 	 * Paste elements.
33010 	 *
33011 	 * @param {Object} [context]
33012 	 * @param {djs.model.base} [context.element] - Parent.
33013 	 * @param {Point} [context.point] - Position.
33014 	 * @param {Object} [context.hints] - Hints.
33015 	 */
33016 	CopyPaste.prototype.paste = function(context) {
33017 	  var tree = this._clipboard.get();
33018 
33019 	  if (this._clipboard.isEmpty()) {
33020 	    return;
33021 	  }
33022 
33023 	  var hints = context && context.hints || {};
33024 
33025 	  this._eventBus.fire('copyPaste.pasteElements', {
33026 	    hints: hints
33027 	  });
33028 
33029 	  var elements = this._createElements(tree);
33030 
33031 	  // paste directly
33032 	  if (context && context.element && context.point) {
33033 	    return this._paste(elements, context.element, context.point, hints);
33034 	  }
33035 
33036 	  this._create.start(this._mouse.getLastMoveEvent(), elements, {
33037 	    hints: hints || {}
33038 	  });
33039 	};
33040 
33041 	/**
33042 	 * Paste elements directly.
33043 	 *
33044 	 * @param {Array<djs.model.Base>} elements
33045 	 * @param {djs.model.base} target
33046 	 * @param {Point} position
33047 	 * @param {Object} [hints]
33048 	 */
33049 	CopyPaste.prototype._paste = function(elements, target, position, hints) {
33050 
33051 	  // make sure each element has x and y
33052 	  forEach(elements, function(element) {
33053 	    if (!isNumber(element.x)) {
33054 	      element.x = 0;
33055 	    }
33056 
33057 	    if (!isNumber(element.y)) {
33058 	      element.y = 0;
33059 	    }
33060 	  });
33061 
33062 	  var bbox = getBBox(elements);
33063 
33064 	  // center elements around cursor
33065 	  forEach(elements, function(element) {
33066 	    if (isConnection$a(element)) {
33067 	      element.waypoints = map$1(element.waypoints, function(waypoint) {
33068 	        return {
33069 	          x: waypoint.x - bbox.x - bbox.width / 2,
33070 	          y: waypoint.y - bbox.y - bbox.height / 2
33071 	        };
33072 	      });
33073 	    }
33074 
33075 	    assign(element, {
33076 	      x: element.x - bbox.x - bbox.width / 2,
33077 	      y: element.y - bbox.y - bbox.height / 2
33078 	    });
33079 	  });
33080 
33081 	  return this._modeling.createElements(elements, position, target, assign({}, hints));
33082 	};
33083 
33084 	/**
33085 	 * Create elements from tree.
33086 	 */
33087 	CopyPaste.prototype._createElements = function(tree) {
33088 	  var self = this;
33089 
33090 	  var eventBus = this._eventBus;
33091 
33092 	  var cache = {};
33093 
33094 	  var elements = [];
33095 
33096 	  forEach(tree, function(branch, depth) {
33097 
33098 	    // sort by priority
33099 	    branch = sortBy(branch, 'priority');
33100 
33101 	    forEach(branch, function(descriptor) {
33102 
33103 	      // remove priority
33104 	      var attrs = assign({}, omit(descriptor, [ 'priority' ]));
33105 
33106 	      if (cache[ descriptor.parent ]) {
33107 	        attrs.parent = cache[ descriptor.parent ];
33108 	      } else {
33109 	        delete attrs.parent;
33110 	      }
33111 
33112 	      eventBus.fire('copyPaste.pasteElement', {
33113 	        cache: cache,
33114 	        descriptor: attrs
33115 	      });
33116 
33117 	      var element;
33118 
33119 	      if (isConnection$a(attrs)) {
33120 	        attrs.source = cache[ descriptor.source ];
33121 	        attrs.target = cache[ descriptor.target ];
33122 
33123 	        element = cache[ descriptor.id ] = self.createConnection(attrs);
33124 
33125 	        elements.push(element);
33126 
33127 	        return;
33128 	      }
33129 
33130 	      if (isLabel$4(attrs)) {
33131 	        attrs.labelTarget = cache[ attrs.labelTarget ];
33132 
33133 	        element = cache[ descriptor.id ] = self.createLabel(attrs);
33134 
33135 	        elements.push(element);
33136 
33137 	        return;
33138 	      }
33139 
33140 	      if (attrs.host) {
33141 	        attrs.host = cache[ attrs.host ];
33142 	      }
33143 
33144 	      element = cache[ descriptor.id ] = self.createShape(attrs);
33145 
33146 	      elements.push(element);
33147 	    });
33148 
33149 	  });
33150 
33151 	  return elements;
33152 	};
33153 
33154 	CopyPaste.prototype.createConnection = function(attrs) {
33155 	  var connection = this._elementFactory.createConnection(omit(attrs, [ 'id' ]));
33156 
33157 	  return connection;
33158 	};
33159 
33160 	CopyPaste.prototype.createLabel = function(attrs) {
33161 	  var label = this._elementFactory.createLabel(omit(attrs, [ 'id' ]));
33162 
33163 	  return label;
33164 	};
33165 
33166 	CopyPaste.prototype.createShape = function(attrs) {
33167 	  var shape = this._elementFactory.createShape(omit(attrs, [ 'id' ]));
33168 
33169 	  return shape;
33170 	};
33171 
33172 	/**
33173 	 * Check wether element has relations to other elements e.g. attachers, labels and connections.
33174 	 *
33175 	 * @param  {Object} element
33176 	 * @param  {Array<djs.model.Base>} elements
33177 	 *
33178 	 * @returns {boolean}
33179 	 */
33180 	CopyPaste.prototype.hasRelations = function(element, elements) {
33181 	  var labelTarget,
33182 	      source,
33183 	      target;
33184 
33185 	  if (isConnection$a(element)) {
33186 	    source = find(elements, matchPattern({ id: element.source.id }));
33187 	    target = find(elements, matchPattern({ id: element.target.id }));
33188 
33189 	    if (!source || !target) {
33190 	      return false;
33191 	    }
33192 	  }
33193 
33194 	  if (isLabel$4(element)) {
33195 	    labelTarget = find(elements, matchPattern({ id: element.labelTarget.id }));
33196 
33197 	    if (!labelTarget) {
33198 	      return false;
33199 	    }
33200 	  }
33201 
33202 	  return true;
33203 	};
33204 
33205 	/**
33206 	 * Create a tree-like structure from elements.
33207 	 *
33208 	 * @example
33209 	 * tree: {
33210 	  *  0: [
33211 	  *    { id: 'Shape_1', priority: 1, ... },
33212 	  *    { id: 'Shape_2', priority: 1, ... },
33213 	  *    { id: 'Connection_1', source: 'Shape_1', target: 'Shape_2', priority: 3, ... },
33214 	  *    ...
33215 	  *  ],
33216 	  *  1: [
33217 	  *    { id: 'Shape_3', parent: 'Shape1', priority: 1, ... },
33218 	  *    ...
33219 	  *  ]
33220 	  * };
33221 	  *
33222 	  * @param  {Array<djs.model.base>} elements
33223 	  *
33224 	  * @return {Object}
33225 	  */
33226 	CopyPaste.prototype.createTree = function(elements) {
33227 	  var rules = this._rules,
33228 	      self = this;
33229 
33230 	  var tree = {},
33231 	      elementsData = [];
33232 
33233 	  var parents = getParents$1(elements);
33234 
33235 	  function canCopy(element, elements) {
33236 	    return rules.allowed('element.copy', {
33237 	      element: element,
33238 	      elements: elements
33239 	    });
33240 	  }
33241 
33242 	  function addElementData(element, depth) {
33243 
33244 	    // (1) check wether element has already been added
33245 	    var foundElementData = find(elementsData, function(elementsData) {
33246 	      return element === elementsData.element;
33247 	    });
33248 
33249 	    // (2) add element if not already added
33250 	    if (!foundElementData) {
33251 	      elementsData.push({
33252 	        element: element,
33253 	        depth: depth
33254 	      });
33255 
33256 	      return;
33257 	    }
33258 
33259 	    // (3) update depth
33260 	    if (foundElementData.depth < depth) {
33261 	      elementsData = removeElementData(foundElementData, elementsData);
33262 
33263 	      elementsData.push({
33264 	        element: foundElementData.element,
33265 	        depth: depth
33266 	      });
33267 	    }
33268 	  }
33269 
33270 	  function removeElementData(elementData, elementsData) {
33271 	    var index = elementsData.indexOf(elementData);
33272 
33273 	    if (index !== -1) {
33274 	      elementsData.splice(index, 1);
33275 	    }
33276 
33277 	    return elementsData;
33278 	  }
33279 
33280 	  // (1) add elements
33281 	  eachElement(parents, function(element, _index, depth) {
33282 
33283 	    // do NOT add external labels directly
33284 	    if (isLabel$4(element)) {
33285 	      return;
33286 	    }
33287 
33288 	    // always copy external labels
33289 	    forEach(element.labels, function(label) {
33290 	      addElementData(label, depth);
33291 	    });
33292 
33293 	    function addRelatedElements(elements) {
33294 	      elements && elements.length && forEach(elements, function(element) {
33295 
33296 	        // add external labels
33297 	        forEach(element.labels, function(label) {
33298 	          addElementData(label, depth);
33299 	        });
33300 
33301 	        addElementData(element, depth);
33302 	      });
33303 	    }
33304 
33305 	    forEach([ element.attachers, element.incoming, element.outgoing ], addRelatedElements);
33306 
33307 	    addElementData(element, depth);
33308 
33309 	    return element.children;
33310 	  });
33311 
33312 	  elements = map$1(elementsData, function(elementData) {
33313 	    return elementData.element;
33314 	  });
33315 
33316 	  // (2) copy elements
33317 	  elementsData = map$1(elementsData, function(elementData) {
33318 	    elementData.descriptor = {};
33319 
33320 	    self._eventBus.fire('copyPaste.copyElement', {
33321 	      descriptor: elementData.descriptor,
33322 	      element: elementData.element,
33323 	      elements: elements
33324 	    });
33325 
33326 	    return elementData;
33327 	  });
33328 
33329 	  // (3) sort elements by priority
33330 	  elementsData = sortBy(elementsData, function(elementData) {
33331 	    return elementData.descriptor.priority;
33332 	  });
33333 
33334 	  elements = map$1(elementsData, function(elementData) {
33335 	    return elementData.element;
33336 	  });
33337 
33338 	  // (4) create tree
33339 	  forEach(elementsData, function(elementData) {
33340 	    var depth = elementData.depth;
33341 
33342 	    if (!self.hasRelations(elementData.element, elements)) {
33343 	      removeElement(elementData.element, elements);
33344 
33345 	      return;
33346 	    }
33347 
33348 	    if (!canCopy(elementData.element, elements)) {
33349 	      removeElement(elementData.element, elements);
33350 
33351 	      return;
33352 	    }
33353 
33354 	    if (!tree[depth]) {
33355 	      tree[depth] = [];
33356 	    }
33357 
33358 	    tree[depth].push(elementData.descriptor);
33359 	  });
33360 
33361 	  return tree;
33362 	};
33363 
33364 	// helpers //////////
33365 
33366 	function isAttacher$1(element) {
33367 	  return !!element.host;
33368 	}
33369 
33370 	function isConnection$a(element) {
33371 	  return !!element.waypoints;
33372 	}
33373 
33374 	function isLabel$4(element) {
33375 	  return !!element.labelTarget;
33376 	}
33377 
33378 	function copyWaypoints$1(element) {
33379 	  return map$1(element.waypoints, function(waypoint) {
33380 
33381 	    waypoint = copyWaypoint$1(waypoint);
33382 
33383 	    if (waypoint.original) {
33384 	      waypoint.original = copyWaypoint$1(waypoint.original);
33385 	    }
33386 
33387 	    return waypoint;
33388 	  });
33389 	}
33390 
33391 	function copyWaypoint$1(waypoint) {
33392 	  return assign({}, waypoint);
33393 	}
33394 
33395 	function removeElement(element, elements) {
33396 	  var index = elements.indexOf(element);
33397 
33398 	  if (index === -1) {
33399 	    return elements;
33400 	  }
33401 
33402 	  return elements.splice(index, 1);
33403 	}
33404 
33405 	var CopyPasteModule$1 = {
33406 	  __depends__: [
33407 	    ClipboardModule,
33408 	    CreateModule,
33409 	    MouseModule,
33410 	    RulesModule$1
33411 	  ],
33412 	  __init__: [ 'copyPaste' ],
33413 	  copyPaste: [ 'type', CopyPaste ]
33414 	};
33415 
33416 	function copyProperties$1(source, target, properties) {
33417 	  if (!isArray$2(properties)) {
33418 	    properties = [ properties ];
33419 	  }
33420 
33421 	  forEach(properties, function(property) {
33422 	    if (!isUndefined$1(source[property])) {
33423 	      target[property] = source[property];
33424 	    }
33425 	  });
33426 	}
33427 
33428 	function removeProperties(element, properties) {
33429 	  if (!isArray$2(properties)) {
33430 	    properties = [ properties ];
33431 	  }
33432 
33433 	  forEach(properties, function(property) {
33434 	    if (element[property]) {
33435 	      delete element[property];
33436 	    }
33437 	  });
33438 	}
33439 
33440 	var LOW_PRIORITY$f = 750;
33441 
33442 
33443 	function BpmnCopyPaste(bpmnFactory, eventBus, moddleCopy) {
33444 
33445 	  eventBus.on('copyPaste.copyElement', LOW_PRIORITY$f, function(context) {
33446 	    var descriptor = context.descriptor,
33447 	        element = context.element;
33448 
33449 	    var businessObject = descriptor.oldBusinessObject = getBusinessObject(element);
33450 
33451 	    descriptor.type = element.type;
33452 
33453 	    copyProperties$1(businessObject, descriptor, 'name');
33454 
33455 	    descriptor.di = {};
33456 
33457 	    // colors will be set to DI
33458 	    copyProperties$1(businessObject.di, descriptor.di, [
33459 	      'fill',
33460 	      'stroke',
33461 	      'background-color',
33462 	      'border-color',
33463 	      'color'
33464 	    ]);
33465 
33466 	    copyProperties$1(businessObject.di, descriptor, 'isExpanded');
33467 
33468 	    if (isLabel$3(descriptor)) {
33469 	      return descriptor;
33470 	    }
33471 
33472 	    // default sequence flow
33473 	    if (businessObject.default) {
33474 	      descriptor.default = businessObject.default.id;
33475 	    }
33476 	  });
33477 
33478 	  eventBus.on('moddleCopy.canCopyProperty', function(context) {
33479 	    var parent = context.parent,
33480 	        property = context.property,
33481 	        propertyName = context.propertyName,
33482 	        bpmnProcess;
33483 
33484 	    if (
33485 	      propertyName === 'processRef' &&
33486 	      is$1(parent, 'bpmn:Participant') &&
33487 	      is$1(property, 'bpmn:Process')
33488 	    ) {
33489 	      bpmnProcess = bpmnFactory.create('bpmn:Process');
33490 
33491 	      // return copy of process
33492 	      return moddleCopy.copyElement(property, bpmnProcess);
33493 	    }
33494 	  });
33495 
33496 	  var references;
33497 
33498 	  function resolveReferences(descriptor, cache) {
33499 	    var businessObject = getBusinessObject(descriptor);
33500 
33501 	    // default sequence flows
33502 	    if (descriptor.default) {
33503 
33504 	      // relationship cannot be resolved immediately
33505 	      references[ descriptor.default ] = {
33506 	        element: businessObject,
33507 	        property: 'default'
33508 	      };
33509 	    }
33510 
33511 	    // boundary events
33512 	    if (descriptor.host) {
33513 
33514 	      // relationship can be resolved immediately
33515 	      getBusinessObject(descriptor).attachedToRef = getBusinessObject(cache[ descriptor.host ]);
33516 	    }
33517 
33518 	    references = omit(references, reduce(references, function(array, reference, key) {
33519 	      var element = reference.element,
33520 	          property = reference.property;
33521 
33522 	      if (key === descriptor.id) {
33523 	        element[ property ] = businessObject;
33524 
33525 	        array.push(descriptor.id);
33526 	      }
33527 
33528 	      return array;
33529 	    }, []));
33530 	  }
33531 
33532 	  eventBus.on('copyPaste.pasteElements', function() {
33533 	    references = {};
33534 	  });
33535 
33536 	  eventBus.on('copyPaste.pasteElement', function(context) {
33537 	    var cache = context.cache,
33538 	        descriptor = context.descriptor,
33539 	        oldBusinessObject = descriptor.oldBusinessObject,
33540 	        newBusinessObject;
33541 
33542 	    // do NOT copy business object if external label
33543 	    if (isLabel$3(descriptor)) {
33544 	      descriptor.businessObject = getBusinessObject(cache[ descriptor.labelTarget ]);
33545 
33546 	      return;
33547 	    }
33548 
33549 	    newBusinessObject = bpmnFactory.create(oldBusinessObject.$type);
33550 
33551 	    descriptor.businessObject = moddleCopy.copyElement(
33552 	      oldBusinessObject,
33553 	      newBusinessObject
33554 	    );
33555 
33556 	    // resolve references e.g. default sequence flow
33557 	    resolveReferences(descriptor, cache);
33558 
33559 	    copyProperties$1(descriptor, newBusinessObject, [
33560 	      'isExpanded',
33561 	      'name'
33562 	    ]);
33563 
33564 	    removeProperties(descriptor, 'oldBusinessObject');
33565 	  });
33566 
33567 	}
33568 
33569 
33570 	BpmnCopyPaste.$inject = [
33571 	  'bpmnFactory',
33572 	  'eventBus',
33573 	  'moddleCopy'
33574 	];
33575 
33576 	// helpers //////////
33577 
33578 	function isLabel$3(element) {
33579 	  return !!element.labelTarget;
33580 	}
33581 
33582 	var DISALLOWED_PROPERTIES = [
33583 	  'artifacts',
33584 	  'dataInputAssociations',
33585 	  'dataOutputAssociations',
33586 	  'default',
33587 	  'flowElements',
33588 	  'lanes',
33589 	  'incoming',
33590 	  'outgoing'
33591 	];
33592 
33593 	/**
33594 	 * @typedef {Function} <moddleCopy.canCopyProperties> listener
33595 	 *
33596 	 * @param {Object} context
33597 	 * @param {Array<string>} context.propertyNames
33598 	 * @param {ModdleElement} context.sourceElement
33599 	 * @param {ModdleElement} context.targetElement
33600 	 *
33601 	 * @returns {Array<string>|boolean} - Return properties to be copied or false to disallow
33602 	 * copying.
33603 	 */
33604 
33605 	/**
33606 	 * @typedef {Function} <moddleCopy.canCopyProperty> listener
33607 	 *
33608 	 * @param {Object} context
33609 	 * @param {ModdleElement} context.parent
33610 	 * @param {*} context.property
33611 	 * @param {string} context.propertyName
33612 	 *
33613 	 * @returns {*|boolean} - Return copied property or false to disallow
33614 	 * copying.
33615 	 */
33616 
33617 	/**
33618 	 * @typedef {Function} <moddleCopy.canSetCopiedProperty> listener
33619 	 *
33620 	 * @param {Object} context
33621 	 * @param {ModdleElement} context.parent
33622 	 * @param {*} context.property
33623 	 * @param {string} context.propertyName
33624 	 *
33625 	 * @returns {boolean} - Return false to disallow
33626 	 * setting copied property.
33627 	 */
33628 
33629 	/**
33630 	 * Utility for copying model properties from source element to target element.
33631 	 *
33632 	 * @param {EventBus} eventBus
33633 	 * @param {BpmnFactory} bpmnFactory
33634 	 * @param {BpmnModdle} moddle
33635 	 */
33636 	function ModdleCopy(eventBus, bpmnFactory, moddle) {
33637 	  this._bpmnFactory = bpmnFactory;
33638 	  this._eventBus = eventBus;
33639 	  this._moddle = moddle;
33640 
33641 	  // copy extension elements last
33642 	  eventBus.on('moddleCopy.canCopyProperties', function(context) {
33643 	    var propertyNames = context.propertyNames;
33644 
33645 	    if (!propertyNames || !propertyNames.length) {
33646 	      return;
33647 	    }
33648 
33649 	    return sortBy(propertyNames, function(propertyName) {
33650 	      return propertyName === 'extensionElements';
33651 	    });
33652 	  });
33653 
33654 	  // default check whether property can be copied
33655 	  eventBus.on('moddleCopy.canCopyProperty', function(context) {
33656 	    var parent = context.parent,
33657 	        parentDescriptor = isObject(parent) && parent.$descriptor,
33658 	        propertyName = context.propertyName;
33659 
33660 	    if (propertyName && DISALLOWED_PROPERTIES.indexOf(propertyName) !== -1) {
33661 
33662 	      // disallow copying property
33663 	      return false;
33664 	    }
33665 
33666 	    if (propertyName &&
33667 	      parentDescriptor &&
33668 	      !find(parentDescriptor.properties, matchPattern({ name: propertyName }))) {
33669 
33670 	      // disallow copying property
33671 	      return false;
33672 	    }
33673 	  });
33674 
33675 	  // do NOT allow to copy empty extension elements
33676 	  eventBus.on('moddleCopy.canSetCopiedProperty', function(context) {
33677 	    var property = context.property;
33678 
33679 	    if (is(property, 'bpmn:ExtensionElements') && (!property.values || !property.values.length)) {
33680 
33681 	      // disallow setting copied property
33682 	      return false;
33683 	    }
33684 	  });
33685 	}
33686 
33687 	ModdleCopy.$inject = [
33688 	  'eventBus',
33689 	  'bpmnFactory',
33690 	  'moddle'
33691 	];
33692 
33693 	/**
33694 	 * Copy model properties of source element to target element.
33695 	 *
33696 	 * @param {ModdleElement} sourceElement
33697 	 * @param {ModdleElement} targetElement
33698 	 * @param {Array<string>} [propertyNames]
33699 	 *
33700 	 * @param {ModdleElement}
33701 	 */
33702 	ModdleCopy.prototype.copyElement = function(sourceElement, targetElement, propertyNames) {
33703 	  var self = this;
33704 
33705 	  if (propertyNames && !isArray$2(propertyNames)) {
33706 	    propertyNames = [ propertyNames ];
33707 	  }
33708 
33709 	  propertyNames = propertyNames || getPropertyNames(sourceElement.$descriptor);
33710 
33711 	  var canCopyProperties = this._eventBus.fire('moddleCopy.canCopyProperties', {
33712 	    propertyNames: propertyNames,
33713 	    sourceElement: sourceElement,
33714 	    targetElement: targetElement
33715 	  });
33716 
33717 	  if (canCopyProperties === false) {
33718 	    return targetElement;
33719 	  }
33720 
33721 	  if (isArray$2(canCopyProperties)) {
33722 	    propertyNames = canCopyProperties;
33723 	  }
33724 
33725 	  // copy properties
33726 	  forEach(propertyNames, function(propertyName) {
33727 	    var sourceProperty;
33728 
33729 	    if (has(sourceElement, propertyName)) {
33730 	      sourceProperty = sourceElement.get(propertyName);
33731 	    }
33732 
33733 	    var copiedProperty = self.copyProperty(sourceProperty, targetElement, propertyName);
33734 
33735 	    var canSetProperty = self._eventBus.fire('moddleCopy.canSetCopiedProperty', {
33736 	      parent: targetElement,
33737 	      property: copiedProperty,
33738 	      propertyName: propertyName
33739 	    });
33740 
33741 	    if (canSetProperty === false) {
33742 	      return;
33743 	    }
33744 
33745 	    if (isDefined(copiedProperty)) {
33746 	      targetElement.set(propertyName, copiedProperty);
33747 	    }
33748 	  });
33749 
33750 	  return targetElement;
33751 	};
33752 
33753 	/**
33754 	 * Copy model property.
33755 	 *
33756 	 * @param {*} property
33757 	 * @param {ModdleElement} parent
33758 	 * @param {string} propertyName
33759 	 *
33760 	 * @returns {*}
33761 	 */
33762 	ModdleCopy.prototype.copyProperty = function(property, parent, propertyName) {
33763 	  var self = this;
33764 
33765 	  // allow others to copy property
33766 	  var copiedProperty = this._eventBus.fire('moddleCopy.canCopyProperty', {
33767 	    parent: parent,
33768 	    property: property,
33769 	    propertyName: propertyName
33770 	  });
33771 
33772 	  // return if copying is NOT allowed
33773 	  if (copiedProperty === false) {
33774 	    return;
33775 	  }
33776 
33777 	  if (copiedProperty) {
33778 	    if (isObject(copiedProperty) && copiedProperty.$type && !copiedProperty.$parent) {
33779 	      copiedProperty.$parent = parent;
33780 	    }
33781 
33782 	    return copiedProperty;
33783 	  }
33784 
33785 	  var propertyDescriptor = this._moddle.getPropertyDescriptor(parent, propertyName);
33786 
33787 	  // do NOT copy references
33788 	  if (propertyDescriptor.isReference) {
33789 	    return;
33790 	  }
33791 
33792 	  // copy id
33793 	  if (propertyDescriptor.isId) {
33794 	    return this._copyId(property, parent);
33795 	  }
33796 
33797 	  // copy arrays
33798 	  if (isArray$2(property)) {
33799 	    return reduce(property, function(childProperties, childProperty) {
33800 
33801 	      // recursion
33802 	      copiedProperty = self.copyProperty(childProperty, parent, propertyName);
33803 
33804 	      // copying might NOT be allowed
33805 	      if (copiedProperty) {
33806 	        copiedProperty.$parent = parent;
33807 
33808 	        return childProperties.concat(copiedProperty);
33809 	      }
33810 
33811 	      return childProperties;
33812 	    }, []);
33813 	  }
33814 
33815 	  // copy model elements
33816 	  if (isObject(property) && property.$type) {
33817 	    if (this._moddle.getElementDescriptor(property).isGeneric) {
33818 	      return;
33819 	    }
33820 
33821 	    copiedProperty = self._bpmnFactory.create(property.$type);
33822 
33823 	    copiedProperty.$parent = parent;
33824 
33825 	    // recursion
33826 	    copiedProperty = self.copyElement(property, copiedProperty);
33827 
33828 	    return copiedProperty;
33829 	  }
33830 
33831 	  // copy primitive properties
33832 	  return property;
33833 	};
33834 
33835 	ModdleCopy.prototype._copyId = function(id, element) {
33836 
33837 	  // disallow if already taken
33838 	  if (this._moddle.ids.assigned(id)) {
33839 	    return;
33840 	  } else {
33841 
33842 	    this._moddle.ids.claim(id, element);
33843 	    return id;
33844 	  }
33845 	};
33846 
33847 	// helpers //////////
33848 
33849 	function getPropertyNames(descriptor, keepDefaultProperties) {
33850 	  return reduce(descriptor.properties, function(properties, property) {
33851 
33852 	    if (keepDefaultProperties && property.default) {
33853 	      return properties;
33854 	    }
33855 
33856 	    return properties.concat(property.name);
33857 	  }, []);
33858 	}
33859 
33860 	function is(element, type) {
33861 	  return element && (typeof element.$instanceOf === 'function') && element.$instanceOf(type);
33862 	}
33863 
33864 	var CopyPasteModule = {
33865 	  __depends__: [
33866 	    CopyPasteModule$1
33867 	  ],
33868 	  __init__: [ 'bpmnCopyPaste', 'moddleCopy' ],
33869 	  bpmnCopyPaste: [ 'type', BpmnCopyPaste ],
33870 	  moddleCopy: [ 'type', ModdleCopy ]
33871 	};
33872 
33873 	var round$5 = Math.round;
33874 
33875 	/**
33876 	 * Service that allow replacing of elements.
33877 	 */
33878 	function Replace(modeling) {
33879 
33880 	  this._modeling = modeling;
33881 	}
33882 
33883 	Replace.$inject = [ 'modeling' ];
33884 
33885 	/**
33886 	 * @param {Element} oldElement - Element to be replaced
33887 	 * @param {Object}  newElementData - Containing information about the new element,
33888 	 *                                   for example the new bounds and type.
33889 	 * @param {Object}  options - Custom options that will be attached to the context. It can be used to inject data
33890 	 *                            that is needed in the command chain. For example it could be used in
33891 	 *                            eventbus.on('commandStack.shape.replace.postExecute') to change shape attributes after
33892 	 *                            shape creation.
33893 	 */
33894 	Replace.prototype.replaceElement = function(oldElement, newElementData, options) {
33895 
33896 	  if (oldElement.waypoints) {
33897 
33898 	    // TODO(nikku): we do not replace connections, yet
33899 	    return null;
33900 	  }
33901 
33902 	  var modeling = this._modeling;
33903 
33904 	  var width = newElementData.width || oldElement.width,
33905 	      height = newElementData.height || oldElement.height,
33906 	      x = newElementData.x || oldElement.x,
33907 	      y = newElementData.y || oldElement.y,
33908 	      centerX = round$5(x + width / 2),
33909 	      centerY = round$5(y + height / 2);
33910 
33911 	  // modeling API requires center coordinates,
33912 	  // account for that when handling shape bounds
33913 
33914 	  return modeling.replaceShape(
33915 	    oldElement,
33916 	    assign(
33917 	      {},
33918 	      newElementData,
33919 	      {
33920 	        x: centerX,
33921 	        y: centerY,
33922 	        width: width,
33923 	        height: height
33924 	      }
33925 	    ),
33926 	    options
33927 	  );
33928 	};
33929 
33930 	var ReplaceModule$1 = {
33931 	  __init__: [ 'replace' ],
33932 	  replace: [ 'type', Replace ]
33933 	};
33934 
33935 	function copyProperties(source, target, properties) {
33936 	  if (!isArray$2(properties)) {
33937 	    properties = [ properties ];
33938 	  }
33939 
33940 	  forEach(properties, function(property) {
33941 	    if (!isUndefined$1(source[property])) {
33942 	      target[property] = source[property];
33943 	    }
33944 	  });
33945 	}
33946 
33947 	var CUSTOM_PROPERTIES = [
33948 	  'cancelActivity',
33949 	  'instantiate',
33950 	  'eventGatewayType',
33951 	  'triggeredByEvent',
33952 	  'isInterrupting'
33953 	];
33954 
33955 
33956 	function toggeling(element, target) {
33957 
33958 	  var oldCollapsed = (
33959 	    element && has(element, 'collapsed') ? element.collapsed : !isExpanded(element)
33960 	  );
33961 
33962 	  var targetCollapsed;
33963 
33964 	  if (target && (has(target, 'collapsed') || has(target, 'isExpanded'))) {
33965 
33966 	    // property is explicitly set so use it
33967 	    targetCollapsed = (
33968 	      has(target, 'collapsed') ? target.collapsed : !target.isExpanded
33969 	    );
33970 	  } else {
33971 
33972 	    // keep old state
33973 	    targetCollapsed = oldCollapsed;
33974 	  }
33975 
33976 	  if (oldCollapsed !== targetCollapsed) {
33977 	    element.collapsed = oldCollapsed;
33978 	    return true;
33979 	  }
33980 
33981 	  return false;
33982 	}
33983 
33984 
33985 
33986 	/**
33987 	 * This module takes care of replacing BPMN elements
33988 	 */
33989 	function BpmnReplace(
33990 	    bpmnFactory,
33991 	    elementFactory,
33992 	    moddleCopy,
33993 	    modeling,
33994 	    replace,
33995 	    rules,
33996 	    selection
33997 	) {
33998 
33999 	  /**
34000 	   * Prepares a new business object for the replacement element
34001 	   * and triggers the replace operation.
34002 	   *
34003 	   * @param  {djs.model.Base} element
34004 	   * @param  {Object} target
34005 	   * @param  {Object} [hints]
34006 	   *
34007 	   * @return {djs.model.Base} the newly created element
34008 	   */
34009 	  function replaceElement(element, target, hints) {
34010 
34011 	    hints = hints || {};
34012 
34013 	    var type = target.type,
34014 	        oldBusinessObject = element.businessObject;
34015 
34016 	    if (isSubProcess(oldBusinessObject)) {
34017 	      if (type === 'bpmn:SubProcess') {
34018 	        if (toggeling(element, target)) {
34019 
34020 	          // expanding or collapsing process
34021 	          modeling.toggleCollapse(element);
34022 
34023 	          return element;
34024 	        }
34025 	      }
34026 	    }
34027 
34028 	    var newBusinessObject = bpmnFactory.create(type);
34029 
34030 	    var newElement = {
34031 	      type: type,
34032 	      businessObject: newBusinessObject
34033 	    };
34034 
34035 	    var elementProps = getPropertyNames(oldBusinessObject.$descriptor),
34036 	        newElementProps = getPropertyNames(newBusinessObject.$descriptor, true),
34037 	        copyProps = intersection(elementProps, newElementProps);
34038 
34039 	    // initialize special properties defined in target definition
34040 	    assign(newBusinessObject, pick(target, CUSTOM_PROPERTIES));
34041 
34042 	    var properties = filter(copyProps, function(propertyName) {
34043 
34044 	      // copying event definitions, unless we replace
34045 	      if (propertyName === 'eventDefinitions') {
34046 	        return hasEventDefinition$1(element, target.eventDefinitionType);
34047 	      }
34048 
34049 	      // retain loop characteristics if the target element
34050 	      // is not an event sub process
34051 	      if (propertyName === 'loopCharacteristics') {
34052 	        return !isEventSubProcess(newBusinessObject);
34053 	      }
34054 
34055 	      // so the applied properties from 'target' don't get lost
34056 	      if (has(newBusinessObject, propertyName)) {
34057 	        return false;
34058 	      }
34059 
34060 	      if (propertyName === 'processRef' && target.isExpanded === false) {
34061 	        return false;
34062 	      }
34063 
34064 	      if (propertyName === 'triggeredByEvent') {
34065 	        return false;
34066 	      }
34067 
34068 	      return true;
34069 	    });
34070 
34071 	    newBusinessObject = moddleCopy.copyElement(
34072 	      oldBusinessObject,
34073 	      newBusinessObject,
34074 	      properties
34075 	    );
34076 
34077 	    // initialize custom BPMN extensions
34078 	    if (target.eventDefinitionType) {
34079 
34080 	      // only initialize with new eventDefinition
34081 	      // if we did not set an event definition yet,
34082 	      // i.e. because we copied it
34083 	      if (!hasEventDefinition$1(newBusinessObject, target.eventDefinitionType)) {
34084 	        newElement.eventDefinitionType = target.eventDefinitionType;
34085 	        newElement.eventDefinitionAttrs = target.eventDefinitionAttrs;
34086 	      }
34087 	    }
34088 
34089 	    if (is$1(oldBusinessObject, 'bpmn:Activity')) {
34090 
34091 	      if (isSubProcess(oldBusinessObject)) {
34092 
34093 	        // no toggeling, so keep old state
34094 	        newElement.isExpanded = isExpanded(oldBusinessObject);
34095 	      }
34096 
34097 	      // else if property is explicitly set, use it
34098 	      else if (target && has(target, 'isExpanded')) {
34099 	        newElement.isExpanded = target.isExpanded;
34100 	      }
34101 
34102 	      // TODO: need also to respect min/max Size
34103 	      // copy size, from an expanded subprocess to an expanded alternative subprocess
34104 	      // except bpmn:Task, because Task is always expanded
34105 	      if ((isExpanded(oldBusinessObject) && !is$1(oldBusinessObject, 'bpmn:Task')) && newElement.isExpanded) {
34106 	        newElement.width = element.width;
34107 	        newElement.height = element.height;
34108 	      }
34109 	    }
34110 
34111 	    // remove children if not expanding sub process
34112 	    if (isSubProcess(oldBusinessObject) && !isSubProcess(newBusinessObject)) {
34113 	      hints.moveChildren = false;
34114 	    }
34115 
34116 	    // transform collapsed/expanded pools
34117 	    if (is$1(oldBusinessObject, 'bpmn:Participant')) {
34118 
34119 	      // create expanded pool
34120 	      if (target.isExpanded === true) {
34121 	        newBusinessObject.processRef = bpmnFactory.create('bpmn:Process');
34122 	      } else {
34123 
34124 	        // remove children when transforming to collapsed pool
34125 	        hints.moveChildren = false;
34126 	      }
34127 
34128 	      // apply same width and default height
34129 	      newElement.width = element.width;
34130 	      newElement.height = elementFactory._getDefaultSize(newBusinessObject).height;
34131 	    }
34132 
34133 	    if (!rules.allowed('shape.resize', { shape: newBusinessObject })) {
34134 	      newElement.height = elementFactory._getDefaultSize(newBusinessObject).height;
34135 	      newElement.width = elementFactory._getDefaultSize(newBusinessObject).width;
34136 	    }
34137 
34138 	    newBusinessObject.name = oldBusinessObject.name;
34139 
34140 	    // retain default flow's reference between inclusive <-> exclusive gateways and activities
34141 	    if (
34142 	      isAny(oldBusinessObject, [
34143 	        'bpmn:ExclusiveGateway',
34144 	        'bpmn:InclusiveGateway',
34145 	        'bpmn:Activity'
34146 	      ]) &&
34147 	      isAny(newBusinessObject, [
34148 	        'bpmn:ExclusiveGateway',
34149 	        'bpmn:InclusiveGateway',
34150 	        'bpmn:Activity'
34151 	      ])
34152 	    ) {
34153 	      newBusinessObject.default = oldBusinessObject.default;
34154 	    }
34155 
34156 	    if (
34157 	      target.host &&
34158 	      !is$1(oldBusinessObject, 'bpmn:BoundaryEvent') &&
34159 	      is$1(newBusinessObject, 'bpmn:BoundaryEvent')
34160 	    ) {
34161 	      newElement.host = target.host;
34162 	    }
34163 
34164 	    // The DataStoreReference element is 14px wider than the DataObjectReference element
34165 	    // This ensures that they stay centered on the x axis when replaced
34166 	    if (
34167 	      newElement.type === 'bpmn:DataStoreReference' ||
34168 	      newElement.type === 'bpmn:DataObjectReference'
34169 	    ) {
34170 	      newElement.x = element.x + (element.width - newElement.width) / 2;
34171 	    }
34172 
34173 	    newElement.di = {};
34174 
34175 	    // colors will be set to DI
34176 	    copyProperties(oldBusinessObject.di, newElement.di, [
34177 	      'fill',
34178 	      'stroke',
34179 	      'background-color',
34180 	      'border-color',
34181 	      'color'
34182 	    ]);
34183 
34184 	    newElement = replace.replaceElement(element, newElement, hints);
34185 
34186 	    if (hints.select !== false) {
34187 	      selection.select(newElement);
34188 	    }
34189 
34190 	    return newElement;
34191 	  }
34192 
34193 	  this.replaceElement = replaceElement;
34194 	}
34195 
34196 	BpmnReplace.$inject = [
34197 	  'bpmnFactory',
34198 	  'elementFactory',
34199 	  'moddleCopy',
34200 	  'modeling',
34201 	  'replace',
34202 	  'rules',
34203 	  'selection'
34204 	];
34205 
34206 
34207 	function isSubProcess(bo) {
34208 	  return is$1(bo, 'bpmn:SubProcess');
34209 	}
34210 
34211 	function hasEventDefinition$1(element, type) {
34212 
34213 	  var bo = getBusinessObject(element);
34214 
34215 	  return type && bo.get('eventDefinitions').some(function(definition) {
34216 	    return is$1(definition, type);
34217 	  });
34218 	}
34219 
34220 	/**
34221 	 * Compute intersection between two arrays.
34222 	 */
34223 	function intersection(a1, a2) {
34224 	  return a1.filter(function(el) {
34225 	    return a2.indexOf(el) !== -1;
34226 	  });
34227 	}
34228 
34229 	var ReplaceModule = {
34230 	  __depends__: [
34231 	    CopyPasteModule,
34232 	    ReplaceModule$1,
34233 	    SelectionModule
34234 	  ],
34235 	  bpmnReplace: [ 'type', BpmnReplace ]
34236 	};
34237 
34238 	/**
34239 	 * Returns true, if an element is from a different type
34240 	 * than a target definition. Takes into account the type,
34241 	 * event definition type and triggeredByEvent property.
34242 	 *
34243 	 * @param {djs.model.Base} element
34244 	 *
34245 	 * @return {boolean}
34246 	 */
34247 	function isDifferentType(element) {
34248 
34249 	  return function(entry) {
34250 	    var target = entry.target;
34251 
34252 	    var businessObject = getBusinessObject(element),
34253 	        eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0];
34254 
34255 	    var isTypeEqual = businessObject.$type === target.type;
34256 
34257 	    var isEventDefinitionEqual = (
34258 	      (eventDefinition && eventDefinition.$type) === target.eventDefinitionType
34259 	    );
34260 
34261 	    var isTriggeredByEventEqual = (
34262 	      businessObject.triggeredByEvent === target.triggeredByEvent
34263 	    );
34264 
34265 	    var isExpandedEqual = (
34266 	      target.isExpanded === undefined ||
34267 	      target.isExpanded === isExpanded(businessObject)
34268 	    );
34269 
34270 	    return !isTypeEqual || !isEventDefinitionEqual || !isTriggeredByEventEqual || !isExpandedEqual;
34271 	  };
34272 	}
34273 
34274 	var START_EVENT = [
34275 	  {
34276 	    label: 'Start Event',
34277 	    actionName: 'replace-with-none-start',
34278 	    className: 'bpmn-icon-start-event-none',
34279 	    target: {
34280 	      type: 'bpmn:StartEvent'
34281 	    }
34282 	  },
34283 	  {
34284 	    label: 'Intermediate Throw Event',
34285 	    actionName: 'replace-with-none-intermediate-throwing',
34286 	    className: 'bpmn-icon-intermediate-event-none',
34287 	    target: {
34288 	      type: 'bpmn:IntermediateThrowEvent'
34289 	    }
34290 	  },
34291 	  {
34292 	    label: 'End Event',
34293 	    actionName: 'replace-with-none-end',
34294 	    className: 'bpmn-icon-end-event-none',
34295 	    target: {
34296 	      type: 'bpmn:EndEvent'
34297 	    }
34298 	  },
34299 	  {
34300 	    label: 'Message Start Event',
34301 	    actionName: 'replace-with-message-start',
34302 	    className: 'bpmn-icon-start-event-message',
34303 	    target: {
34304 	      type: 'bpmn:StartEvent',
34305 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34306 	    }
34307 	  },
34308 	  {
34309 	    label: 'Timer Start Event',
34310 	    actionName: 'replace-with-timer-start',
34311 	    className: 'bpmn-icon-start-event-timer',
34312 	    target: {
34313 	      type: 'bpmn:StartEvent',
34314 	      eventDefinitionType: 'bpmn:TimerEventDefinition'
34315 	    }
34316 	  },
34317 	  {
34318 	    label: 'Conditional Start Event',
34319 	    actionName: 'replace-with-conditional-start',
34320 	    className: 'bpmn-icon-start-event-condition',
34321 	    target: {
34322 	      type: 'bpmn:StartEvent',
34323 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition'
34324 	    }
34325 	  },
34326 	  {
34327 	    label: 'Signal Start Event',
34328 	    actionName: 'replace-with-signal-start',
34329 	    className: 'bpmn-icon-start-event-signal',
34330 	    target: {
34331 	      type: 'bpmn:StartEvent',
34332 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34333 	    }
34334 	  }
34335 	];
34336 
34337 	var START_EVENT_SUB_PROCESS = [
34338 	  {
34339 	    label: 'Start Event',
34340 	    actionName: 'replace-with-none-start',
34341 	    className: 'bpmn-icon-start-event-none',
34342 	    target: {
34343 	      type: 'bpmn:StartEvent'
34344 	    }
34345 	  },
34346 	  {
34347 	    label: 'Intermediate Throw Event',
34348 	    actionName: 'replace-with-none-intermediate-throwing',
34349 	    className: 'bpmn-icon-intermediate-event-none',
34350 	    target: {
34351 	      type: 'bpmn:IntermediateThrowEvent'
34352 	    }
34353 	  },
34354 	  {
34355 	    label: 'End Event',
34356 	    actionName: 'replace-with-none-end',
34357 	    className: 'bpmn-icon-end-event-none',
34358 	    target: {
34359 	      type: 'bpmn:EndEvent'
34360 	    }
34361 	  }
34362 	];
34363 
34364 	var INTERMEDIATE_EVENT = [
34365 	  {
34366 	    label: 'Start Event',
34367 	    actionName: 'replace-with-none-start',
34368 	    className: 'bpmn-icon-start-event-none',
34369 	    target: {
34370 	      type: 'bpmn:StartEvent'
34371 	    }
34372 	  },
34373 	  {
34374 	    label: 'Intermediate Throw Event',
34375 	    actionName: 'replace-with-none-intermediate-throw',
34376 	    className: 'bpmn-icon-intermediate-event-none',
34377 	    target: {
34378 	      type: 'bpmn:IntermediateThrowEvent'
34379 	    }
34380 	  },
34381 	  {
34382 	    label: 'End Event',
34383 	    actionName: 'replace-with-none-end',
34384 	    className: 'bpmn-icon-end-event-none',
34385 	    target: {
34386 	      type: 'bpmn:EndEvent'
34387 	    }
34388 	  },
34389 	  {
34390 	    label: 'Message Intermediate Catch Event',
34391 	    actionName: 'replace-with-message-intermediate-catch',
34392 	    className: 'bpmn-icon-intermediate-event-catch-message',
34393 	    target: {
34394 	      type: 'bpmn:IntermediateCatchEvent',
34395 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34396 	    }
34397 	  },
34398 	  {
34399 	    label: 'Message Intermediate Throw Event',
34400 	    actionName: 'replace-with-message-intermediate-throw',
34401 	    className: 'bpmn-icon-intermediate-event-throw-message',
34402 	    target: {
34403 	      type: 'bpmn:IntermediateThrowEvent',
34404 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34405 	    }
34406 	  },
34407 	  {
34408 	    label: 'Timer Intermediate Catch Event',
34409 	    actionName: 'replace-with-timer-intermediate-catch',
34410 	    className: 'bpmn-icon-intermediate-event-catch-timer',
34411 	    target: {
34412 	      type: 'bpmn:IntermediateCatchEvent',
34413 	      eventDefinitionType: 'bpmn:TimerEventDefinition'
34414 	    }
34415 	  },
34416 	  {
34417 	    label: 'Escalation Intermediate Throw Event',
34418 	    actionName: 'replace-with-escalation-intermediate-throw',
34419 	    className: 'bpmn-icon-intermediate-event-throw-escalation',
34420 	    target: {
34421 	      type: 'bpmn:IntermediateThrowEvent',
34422 	      eventDefinitionType: 'bpmn:EscalationEventDefinition'
34423 	    }
34424 	  },
34425 	  {
34426 	    label: 'Conditional Intermediate Catch Event',
34427 	    actionName: 'replace-with-conditional-intermediate-catch',
34428 	    className: 'bpmn-icon-intermediate-event-catch-condition',
34429 	    target: {
34430 	      type: 'bpmn:IntermediateCatchEvent',
34431 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition'
34432 	    }
34433 	  },
34434 	  {
34435 	    label: 'Link Intermediate Catch Event',
34436 	    actionName: 'replace-with-link-intermediate-catch',
34437 	    className: 'bpmn-icon-intermediate-event-catch-link',
34438 	    target: {
34439 	      type: 'bpmn:IntermediateCatchEvent',
34440 	      eventDefinitionType: 'bpmn:LinkEventDefinition',
34441 	      eventDefinitionAttrs: {
34442 	        name: ''
34443 	      }
34444 	    }
34445 	  },
34446 	  {
34447 	    label: 'Link Intermediate Throw Event',
34448 	    actionName: 'replace-with-link-intermediate-throw',
34449 	    className: 'bpmn-icon-intermediate-event-throw-link',
34450 	    target: {
34451 	      type: 'bpmn:IntermediateThrowEvent',
34452 	      eventDefinitionType: 'bpmn:LinkEventDefinition',
34453 	      eventDefinitionAttrs: {
34454 	        name: ''
34455 	      }
34456 	    }
34457 	  },
34458 	  {
34459 	    label: 'Compensation Intermediate Throw Event',
34460 	    actionName: 'replace-with-compensation-intermediate-throw',
34461 	    className: 'bpmn-icon-intermediate-event-throw-compensation',
34462 	    target: {
34463 	      type: 'bpmn:IntermediateThrowEvent',
34464 	      eventDefinitionType: 'bpmn:CompensateEventDefinition'
34465 	    }
34466 	  },
34467 	  {
34468 	    label: 'Signal Intermediate Catch Event',
34469 	    actionName: 'replace-with-signal-intermediate-catch',
34470 	    className: 'bpmn-icon-intermediate-event-catch-signal',
34471 	    target: {
34472 	      type: 'bpmn:IntermediateCatchEvent',
34473 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34474 	    }
34475 	  },
34476 	  {
34477 	    label: 'Signal Intermediate Throw Event',
34478 	    actionName: 'replace-with-signal-intermediate-throw',
34479 	    className: 'bpmn-icon-intermediate-event-throw-signal',
34480 	    target: {
34481 	      type: 'bpmn:IntermediateThrowEvent',
34482 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34483 	    }
34484 	  }
34485 	];
34486 
34487 	var END_EVENT = [
34488 	  {
34489 	    label: 'Start Event',
34490 	    actionName: 'replace-with-none-start',
34491 	    className: 'bpmn-icon-start-event-none',
34492 	    target: {
34493 	      type: 'bpmn:StartEvent'
34494 	    }
34495 	  },
34496 	  {
34497 	    label: 'Intermediate Throw Event',
34498 	    actionName: 'replace-with-none-intermediate-throw',
34499 	    className: 'bpmn-icon-intermediate-event-none',
34500 	    target: {
34501 	      type: 'bpmn:IntermediateThrowEvent'
34502 	    }
34503 	  },
34504 	  {
34505 	    label: 'End Event',
34506 	    actionName: 'replace-with-none-end',
34507 	    className: 'bpmn-icon-end-event-none',
34508 	    target: {
34509 	      type: 'bpmn:EndEvent'
34510 	    }
34511 	  },
34512 	  {
34513 	    label: 'Message End Event',
34514 	    actionName: 'replace-with-message-end',
34515 	    className: 'bpmn-icon-end-event-message',
34516 	    target: {
34517 	      type: 'bpmn:EndEvent',
34518 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34519 	    }
34520 	  },
34521 	  {
34522 	    label: 'Escalation End Event',
34523 	    actionName: 'replace-with-escalation-end',
34524 	    className: 'bpmn-icon-end-event-escalation',
34525 	    target: {
34526 	      type: 'bpmn:EndEvent',
34527 	      eventDefinitionType: 'bpmn:EscalationEventDefinition'
34528 	    }
34529 	  },
34530 	  {
34531 	    label: 'Error End Event',
34532 	    actionName: 'replace-with-error-end',
34533 	    className: 'bpmn-icon-end-event-error',
34534 	    target: {
34535 	      type: 'bpmn:EndEvent',
34536 	      eventDefinitionType: 'bpmn:ErrorEventDefinition'
34537 	    }
34538 	  },
34539 	  {
34540 	    label: 'Cancel End Event',
34541 	    actionName: 'replace-with-cancel-end',
34542 	    className: 'bpmn-icon-end-event-cancel',
34543 	    target: {
34544 	      type: 'bpmn:EndEvent',
34545 	      eventDefinitionType: 'bpmn:CancelEventDefinition'
34546 	    }
34547 	  },
34548 	  {
34549 	    label: 'Compensation End Event',
34550 	    actionName: 'replace-with-compensation-end',
34551 	    className: 'bpmn-icon-end-event-compensation',
34552 	    target: {
34553 	      type: 'bpmn:EndEvent',
34554 	      eventDefinitionType: 'bpmn:CompensateEventDefinition'
34555 	    }
34556 	  },
34557 	  {
34558 	    label: 'Signal End Event',
34559 	    actionName: 'replace-with-signal-end',
34560 	    className: 'bpmn-icon-end-event-signal',
34561 	    target: {
34562 	      type: 'bpmn:EndEvent',
34563 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34564 	    }
34565 	  },
34566 	  {
34567 	    label: 'Terminate End Event',
34568 	    actionName: 'replace-with-terminate-end',
34569 	    className: 'bpmn-icon-end-event-terminate',
34570 	    target: {
34571 	      type: 'bpmn:EndEvent',
34572 	      eventDefinitionType: 'bpmn:TerminateEventDefinition'
34573 	    }
34574 	  }
34575 	];
34576 
34577 	var GATEWAY = [
34578 	  {
34579 	    label: 'Exclusive Gateway',
34580 	    actionName: 'replace-with-exclusive-gateway',
34581 	    className: 'bpmn-icon-gateway-xor',
34582 	    target: {
34583 	      type: 'bpmn:ExclusiveGateway'
34584 	    }
34585 	  },
34586 	  {
34587 	    label: 'Parallel Gateway',
34588 	    actionName: 'replace-with-parallel-gateway',
34589 	    className: 'bpmn-icon-gateway-parallel',
34590 	    target: {
34591 	      type: 'bpmn:ParallelGateway'
34592 	    }
34593 	  },
34594 	  {
34595 	    label: 'Inclusive Gateway',
34596 	    actionName: 'replace-with-inclusive-gateway',
34597 	    className: 'bpmn-icon-gateway-or',
34598 	    target: {
34599 	      type: 'bpmn:InclusiveGateway'
34600 	    }
34601 	  },
34602 	  {
34603 	    label: 'Complex Gateway',
34604 	    actionName: 'replace-with-complex-gateway',
34605 	    className: 'bpmn-icon-gateway-complex',
34606 	    target: {
34607 	      type: 'bpmn:ComplexGateway'
34608 	    }
34609 	  },
34610 	  {
34611 	    label: 'Event based Gateway',
34612 	    actionName: 'replace-with-event-based-gateway',
34613 	    className: 'bpmn-icon-gateway-eventbased',
34614 	    target: {
34615 	      type: 'bpmn:EventBasedGateway',
34616 	      instantiate: false,
34617 	      eventGatewayType: 'Exclusive'
34618 	    }
34619 	  }
34620 
34621 	  // Gateways deactivated until https://github.com/bpmn-io/bpmn-js/issues/194
34622 	  // {
34623 	  //   label: 'Event based instantiating Gateway',
34624 	  //   actionName: 'replace-with-exclusive-event-based-gateway',
34625 	  //   className: 'bpmn-icon-exclusive-event-based',
34626 	  //   target: {
34627 	  //     type: 'bpmn:EventBasedGateway'
34628 	  //   },
34629 	  //   options: {
34630 	  //     businessObject: { instantiate: true, eventGatewayType: 'Exclusive' }
34631 	  //   }
34632 	  // },
34633 	  // {
34634 	  //   label: 'Parallel Event based instantiating Gateway',
34635 	  //   actionName: 'replace-with-parallel-event-based-instantiate-gateway',
34636 	  //   className: 'bpmn-icon-parallel-event-based-instantiate-gateway',
34637 	  //   target: {
34638 	  //     type: 'bpmn:EventBasedGateway'
34639 	  //   },
34640 	  //   options: {
34641 	  //     businessObject: { instantiate: true, eventGatewayType: 'Parallel' }
34642 	  //   }
34643 	  // }
34644 	];
34645 
34646 	var SUBPROCESS_EXPANDED = [
34647 	  {
34648 	    label: 'Transaction',
34649 	    actionName: 'replace-with-transaction',
34650 	    className: 'bpmn-icon-transaction',
34651 	    target: {
34652 	      type: 'bpmn:Transaction',
34653 	      isExpanded: true
34654 	    }
34655 	  },
34656 	  {
34657 	    label: 'Event Sub Process',
34658 	    actionName: 'replace-with-event-subprocess',
34659 	    className: 'bpmn-icon-event-subprocess-expanded',
34660 	    target: {
34661 	      type: 'bpmn:SubProcess',
34662 	      triggeredByEvent: true,
34663 	      isExpanded: true
34664 	    }
34665 	  },
34666 	  {
34667 	    label: 'Sub Process (collapsed)',
34668 	    actionName: 'replace-with-collapsed-subprocess',
34669 	    className: 'bpmn-icon-subprocess-collapsed',
34670 	    target: {
34671 	      type: 'bpmn:SubProcess',
34672 	      isExpanded: false
34673 	    }
34674 	  }
34675 	];
34676 
34677 	var TRANSACTION = [
34678 	  {
34679 	    label: 'Sub Process',
34680 	    actionName: 'replace-with-subprocess',
34681 	    className: 'bpmn-icon-subprocess-expanded',
34682 	    target: {
34683 	      type: 'bpmn:SubProcess',
34684 	      isExpanded: true
34685 	    }
34686 	  },
34687 	  {
34688 	    label: 'Event Sub Process',
34689 	    actionName: 'replace-with-event-subprocess',
34690 	    className: 'bpmn-icon-event-subprocess-expanded',
34691 	    target: {
34692 	      type: 'bpmn:SubProcess',
34693 	      triggeredByEvent: true,
34694 	      isExpanded: true
34695 	    }
34696 	  }
34697 	];
34698 
34699 	var EVENT_SUB_PROCESS = [
34700 	  {
34701 	    label: 'Sub Process',
34702 	    actionName: 'replace-with-subprocess',
34703 	    className: 'bpmn-icon-subprocess-expanded',
34704 	    target: {
34705 	      type: 'bpmn:SubProcess',
34706 	      isExpanded: true
34707 	    }
34708 	  },
34709 	  {
34710 	    label: 'Transaction',
34711 	    actionName: 'replace-with-transaction',
34712 	    className: 'bpmn-icon-transaction',
34713 	    target: {
34714 	      type: 'bpmn:Transaction',
34715 	      isExpanded: true
34716 	    }
34717 	  }
34718 	];
34719 
34720 	var TASK = [
34721 	  {
34722 	    label: 'Task',
34723 	    actionName: 'replace-with-task',
34724 	    className: 'bpmn-icon-task',
34725 	    target: {
34726 	      type: 'bpmn:Task'
34727 	    }
34728 	  },
34729 	  {
34730 	    label: 'Send Task',
34731 	    actionName: 'replace-with-send-task',
34732 	    className: 'bpmn-icon-send',
34733 	    target: {
34734 	      type: 'bpmn:SendTask'
34735 	    }
34736 	  },
34737 	  {
34738 	    label: 'Receive Task',
34739 	    actionName: 'replace-with-receive-task',
34740 	    className: 'bpmn-icon-receive',
34741 	    target: {
34742 	      type: 'bpmn:ReceiveTask'
34743 	    }
34744 	  },
34745 	  {
34746 	    label: 'User Task',
34747 	    actionName: 'replace-with-user-task',
34748 	    className: 'bpmn-icon-user',
34749 	    target: {
34750 	      type: 'bpmn:UserTask'
34751 	    }
34752 	  },
34753 	  {
34754 	    label: 'Manual Task',
34755 	    actionName: 'replace-with-manual-task',
34756 	    className: 'bpmn-icon-manual',
34757 	    target: {
34758 	      type: 'bpmn:ManualTask'
34759 	    }
34760 	  },
34761 	  {
34762 	    label: 'Business Rule Task',
34763 	    actionName: 'replace-with-rule-task',
34764 	    className: 'bpmn-icon-business-rule',
34765 	    target: {
34766 	      type: 'bpmn:BusinessRuleTask'
34767 	    }
34768 	  },
34769 	  {
34770 	    label: 'Service Task',
34771 	    actionName: 'replace-with-service-task',
34772 	    className: 'bpmn-icon-service',
34773 	    target: {
34774 	      type: 'bpmn:ServiceTask'
34775 	    }
34776 	  },
34777 	  {
34778 	    label: 'Script Task',
34779 	    actionName: 'replace-with-script-task',
34780 	    className: 'bpmn-icon-script',
34781 	    target: {
34782 	      type: 'bpmn:ScriptTask'
34783 	    }
34784 	  },
34785 	  {
34786 	    label: 'Call Activity',
34787 	    actionName: 'replace-with-call-activity',
34788 	    className: 'bpmn-icon-call-activity',
34789 	    target: {
34790 	      type: 'bpmn:CallActivity'
34791 	    }
34792 	  },
34793 	  {
34794 	    label: 'Sub Process (collapsed)',
34795 	    actionName: 'replace-with-collapsed-subprocess',
34796 	    className: 'bpmn-icon-subprocess-collapsed',
34797 	    target: {
34798 	      type: 'bpmn:SubProcess',
34799 	      isExpanded: false
34800 	    }
34801 	  },
34802 	  {
34803 	    label: 'Sub Process (expanded)',
34804 	    actionName: 'replace-with-expanded-subprocess',
34805 	    className: 'bpmn-icon-subprocess-expanded',
34806 	    target: {
34807 	      type: 'bpmn:SubProcess',
34808 	      isExpanded: true
34809 	    }
34810 	  }
34811 	];
34812 
34813 	var DATA_OBJECT_REFERENCE = [
34814 	  {
34815 	    label: 'Data Store Reference',
34816 	    actionName: 'replace-with-data-store-reference',
34817 	    className: 'bpmn-icon-data-store',
34818 	    target: {
34819 	      type: 'bpmn:DataStoreReference'
34820 	    }
34821 	  }
34822 	];
34823 
34824 	var DATA_STORE_REFERENCE = [
34825 	  {
34826 	    label: 'Data Object Reference',
34827 	    actionName: 'replace-with-data-object-reference',
34828 	    className: 'bpmn-icon-data-object',
34829 	    target: {
34830 	      type: 'bpmn:DataObjectReference'
34831 	    }
34832 	  }
34833 	];
34834 
34835 	var BOUNDARY_EVENT = [
34836 	  {
34837 	    label: 'Message Boundary Event',
34838 	    actionName: 'replace-with-message-boundary',
34839 	    className: 'bpmn-icon-intermediate-event-catch-message',
34840 	    target: {
34841 	      type: 'bpmn:BoundaryEvent',
34842 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34843 	    }
34844 	  },
34845 	  {
34846 	    label: 'Timer Boundary Event',
34847 	    actionName: 'replace-with-timer-boundary',
34848 	    className: 'bpmn-icon-intermediate-event-catch-timer',
34849 	    target: {
34850 	      type: 'bpmn:BoundaryEvent',
34851 	      eventDefinitionType: 'bpmn:TimerEventDefinition'
34852 	    }
34853 	  },
34854 	  {
34855 	    label: 'Escalation Boundary Event',
34856 	    actionName: 'replace-with-escalation-boundary',
34857 	    className: 'bpmn-icon-intermediate-event-catch-escalation',
34858 	    target: {
34859 	      type: 'bpmn:BoundaryEvent',
34860 	      eventDefinitionType: 'bpmn:EscalationEventDefinition'
34861 	    }
34862 	  },
34863 	  {
34864 	    label: 'Conditional Boundary Event',
34865 	    actionName: 'replace-with-conditional-boundary',
34866 	    className: 'bpmn-icon-intermediate-event-catch-condition',
34867 	    target: {
34868 	      type: 'bpmn:BoundaryEvent',
34869 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition'
34870 	    }
34871 	  },
34872 	  {
34873 	    label: 'Error Boundary Event',
34874 	    actionName: 'replace-with-error-boundary',
34875 	    className: 'bpmn-icon-intermediate-event-catch-error',
34876 	    target: {
34877 	      type: 'bpmn:BoundaryEvent',
34878 	      eventDefinitionType: 'bpmn:ErrorEventDefinition'
34879 	    }
34880 	  },
34881 	  {
34882 	    label: 'Cancel Boundary Event',
34883 	    actionName: 'replace-with-cancel-boundary',
34884 	    className: 'bpmn-icon-intermediate-event-catch-cancel',
34885 	    target: {
34886 	      type: 'bpmn:BoundaryEvent',
34887 	      eventDefinitionType: 'bpmn:CancelEventDefinition'
34888 	    }
34889 	  },
34890 	  {
34891 	    label: 'Signal Boundary Event',
34892 	    actionName: 'replace-with-signal-boundary',
34893 	    className: 'bpmn-icon-intermediate-event-catch-signal',
34894 	    target: {
34895 	      type: 'bpmn:BoundaryEvent',
34896 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34897 	    }
34898 	  },
34899 	  {
34900 	    label: 'Compensation Boundary Event',
34901 	    actionName: 'replace-with-compensation-boundary',
34902 	    className: 'bpmn-icon-intermediate-event-catch-compensation',
34903 	    target: {
34904 	      type: 'bpmn:BoundaryEvent',
34905 	      eventDefinitionType: 'bpmn:CompensateEventDefinition'
34906 	    }
34907 	  },
34908 	  {
34909 	    label: 'Message Boundary Event (non-interrupting)',
34910 	    actionName: 'replace-with-non-interrupting-message-boundary',
34911 	    className: 'bpmn-icon-intermediate-event-catch-non-interrupting-message',
34912 	    target: {
34913 	      type: 'bpmn:BoundaryEvent',
34914 	      eventDefinitionType: 'bpmn:MessageEventDefinition',
34915 	      cancelActivity: false
34916 	    }
34917 	  },
34918 	  {
34919 	    label: 'Timer Boundary Event (non-interrupting)',
34920 	    actionName: 'replace-with-non-interrupting-timer-boundary',
34921 	    className: 'bpmn-icon-intermediate-event-catch-non-interrupting-timer',
34922 	    target: {
34923 	      type: 'bpmn:BoundaryEvent',
34924 	      eventDefinitionType: 'bpmn:TimerEventDefinition',
34925 	      cancelActivity: false
34926 	    }
34927 	  },
34928 	  {
34929 	    label: 'Escalation Boundary Event (non-interrupting)',
34930 	    actionName: 'replace-with-non-interrupting-escalation-boundary',
34931 	    className: 'bpmn-icon-intermediate-event-catch-non-interrupting-escalation',
34932 	    target: {
34933 	      type: 'bpmn:BoundaryEvent',
34934 	      eventDefinitionType: 'bpmn:EscalationEventDefinition',
34935 	      cancelActivity: false
34936 	    }
34937 	  },
34938 	  {
34939 	    label: 'Conditional Boundary Event (non-interrupting)',
34940 	    actionName: 'replace-with-non-interrupting-conditional-boundary',
34941 	    className: 'bpmn-icon-intermediate-event-catch-non-interrupting-condition',
34942 	    target: {
34943 	      type: 'bpmn:BoundaryEvent',
34944 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition',
34945 	      cancelActivity: false
34946 	    }
34947 	  },
34948 	  {
34949 	    label: 'Signal Boundary Event (non-interrupting)',
34950 	    actionName: 'replace-with-non-interrupting-signal-boundary',
34951 	    className: 'bpmn-icon-intermediate-event-catch-non-interrupting-signal',
34952 	    target: {
34953 	      type: 'bpmn:BoundaryEvent',
34954 	      eventDefinitionType: 'bpmn:SignalEventDefinition',
34955 	      cancelActivity: false
34956 	    }
34957 	  }
34958 	];
34959 
34960 	var EVENT_SUB_PROCESS_START_EVENT = [
34961 	  {
34962 	    label: 'Message Start Event',
34963 	    actionName: 'replace-with-message-start',
34964 	    className: 'bpmn-icon-start-event-message',
34965 	    target: {
34966 	      type: 'bpmn:StartEvent',
34967 	      eventDefinitionType: 'bpmn:MessageEventDefinition'
34968 	    }
34969 	  },
34970 	  {
34971 	    label: 'Timer Start Event',
34972 	    actionName: 'replace-with-timer-start',
34973 	    className: 'bpmn-icon-start-event-timer',
34974 	    target: {
34975 	      type: 'bpmn:StartEvent',
34976 	      eventDefinitionType: 'bpmn:TimerEventDefinition'
34977 	    }
34978 	  },
34979 	  {
34980 	    label: 'Conditional Start Event',
34981 	    actionName: 'replace-with-conditional-start',
34982 	    className: 'bpmn-icon-start-event-condition',
34983 	    target: {
34984 	      type: 'bpmn:StartEvent',
34985 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition'
34986 	    }
34987 	  },
34988 	  {
34989 	    label: 'Signal Start Event',
34990 	    actionName: 'replace-with-signal-start',
34991 	    className: 'bpmn-icon-start-event-signal',
34992 	    target: {
34993 	      type: 'bpmn:StartEvent',
34994 	      eventDefinitionType: 'bpmn:SignalEventDefinition'
34995 	    }
34996 	  },
34997 	  {
34998 	    label: 'Error Start Event',
34999 	    actionName: 'replace-with-error-start',
35000 	    className: 'bpmn-icon-start-event-error',
35001 	    target: {
35002 	      type: 'bpmn:StartEvent',
35003 	      eventDefinitionType: 'bpmn:ErrorEventDefinition'
35004 	    }
35005 	  },
35006 	  {
35007 	    label: 'Escalation Start Event',
35008 	    actionName: 'replace-with-escalation-start',
35009 	    className: 'bpmn-icon-start-event-escalation',
35010 	    target: {
35011 	      type: 'bpmn:StartEvent',
35012 	      eventDefinitionType: 'bpmn:EscalationEventDefinition'
35013 	    }
35014 	  },
35015 	  {
35016 	    label: 'Compensation Start Event',
35017 	    actionName: 'replace-with-compensation-start',
35018 	    className: 'bpmn-icon-start-event-compensation',
35019 	    target: {
35020 	      type: 'bpmn:StartEvent',
35021 	      eventDefinitionType: 'bpmn:CompensateEventDefinition'
35022 	    }
35023 	  },
35024 	  {
35025 	    label: 'Message Start Event (non-interrupting)',
35026 	    actionName: 'replace-with-non-interrupting-message-start',
35027 	    className: 'bpmn-icon-start-event-non-interrupting-message',
35028 	    target: {
35029 	      type: 'bpmn:StartEvent',
35030 	      eventDefinitionType: 'bpmn:MessageEventDefinition',
35031 	      isInterrupting: false
35032 	    }
35033 	  },
35034 	  {
35035 	    label: 'Timer Start Event (non-interrupting)',
35036 	    actionName: 'replace-with-non-interrupting-timer-start',
35037 	    className: 'bpmn-icon-start-event-non-interrupting-timer',
35038 	    target: {
35039 	      type: 'bpmn:StartEvent',
35040 	      eventDefinitionType: 'bpmn:TimerEventDefinition',
35041 	      isInterrupting: false
35042 	    }
35043 	  },
35044 	  {
35045 	    label: 'Conditional Start Event (non-interrupting)',
35046 	    actionName: 'replace-with-non-interrupting-conditional-start',
35047 	    className: 'bpmn-icon-start-event-non-interrupting-condition',
35048 	    target: {
35049 	      type: 'bpmn:StartEvent',
35050 	      eventDefinitionType: 'bpmn:ConditionalEventDefinition',
35051 	      isInterrupting: false
35052 	    }
35053 	  },
35054 	  {
35055 	    label: 'Signal Start Event (non-interrupting)',
35056 	    actionName: 'replace-with-non-interrupting-signal-start',
35057 	    className: 'bpmn-icon-start-event-non-interrupting-signal',
35058 	    target: {
35059 	      type: 'bpmn:StartEvent',
35060 	      eventDefinitionType: 'bpmn:SignalEventDefinition',
35061 	      isInterrupting: false
35062 	    }
35063 	  },
35064 	  {
35065 	    label: 'Escalation Start Event (non-interrupting)',
35066 	    actionName: 'replace-with-non-interrupting-escalation-start',
35067 	    className: 'bpmn-icon-start-event-non-interrupting-escalation',
35068 	    target: {
35069 	      type: 'bpmn:StartEvent',
35070 	      eventDefinitionType: 'bpmn:EscalationEventDefinition',
35071 	      isInterrupting: false
35072 	    }
35073 	  }
35074 	];
35075 
35076 	var SEQUENCE_FLOW = [
35077 	  {
35078 	    label: 'Sequence Flow',
35079 	    actionName: 'replace-with-sequence-flow',
35080 	    className: 'bpmn-icon-connection'
35081 	  },
35082 	  {
35083 	    label: 'Default Flow',
35084 	    actionName: 'replace-with-default-flow',
35085 	    className: 'bpmn-icon-default-flow'
35086 	  },
35087 	  {
35088 	    label: 'Conditional Flow',
35089 	    actionName: 'replace-with-conditional-flow',
35090 	    className: 'bpmn-icon-conditional-flow'
35091 	  }
35092 	];
35093 
35094 	var PARTICIPANT = [
35095 	  {
35096 	    label: 'Expanded Pool',
35097 	    actionName: 'replace-with-expanded-pool',
35098 	    className: 'bpmn-icon-participant',
35099 	    target: {
35100 	      type: 'bpmn:Participant',
35101 	      isExpanded: true
35102 	    }
35103 	  },
35104 	  {
35105 	    label: function(element) {
35106 	      var label = 'Empty Pool';
35107 
35108 	      if (element.children && element.children.length) {
35109 	        label += ' (removes content)';
35110 	      }
35111 
35112 	      return label;
35113 	    },
35114 	    actionName: 'replace-with-collapsed-pool',
35115 
35116 	    // TODO(@janstuemmel): maybe design new icon
35117 	    className: 'bpmn-icon-lane',
35118 	    target: {
35119 	      type: 'bpmn:Participant',
35120 	      isExpanded: false
35121 	    }
35122 	  }
35123 	];
35124 
35125 	/**
35126 	 * This module is an element agnostic replace menu provider for the popup menu.
35127 	 */
35128 	function ReplaceMenuProvider(
35129 	    bpmnFactory, popupMenu, modeling, moddle,
35130 	    bpmnReplace, rules, translate) {
35131 
35132 	  this._bpmnFactory = bpmnFactory;
35133 	  this._popupMenu = popupMenu;
35134 	  this._modeling = modeling;
35135 	  this._moddle = moddle;
35136 	  this._bpmnReplace = bpmnReplace;
35137 	  this._rules = rules;
35138 	  this._translate = translate;
35139 
35140 	  this.register();
35141 	}
35142 
35143 	ReplaceMenuProvider.$inject = [
35144 	  'bpmnFactory',
35145 	  'popupMenu',
35146 	  'modeling',
35147 	  'moddle',
35148 	  'bpmnReplace',
35149 	  'rules',
35150 	  'translate'
35151 	];
35152 
35153 
35154 	/**
35155 	 * Register replace menu provider in the popup menu
35156 	 */
35157 	ReplaceMenuProvider.prototype.register = function() {
35158 	  this._popupMenu.registerProvider('bpmn-replace', this);
35159 	};
35160 
35161 
35162 	/**
35163 	 * Get all entries from replaceOptions for the given element and apply filters
35164 	 * on them. Get for example only elements, which are different from the current one.
35165 	 *
35166 	 * @param {djs.model.Base} element
35167 	 *
35168 	 * @return {Array<Object>} a list of menu entry items
35169 	 */
35170 	ReplaceMenuProvider.prototype.getEntries = function(element) {
35171 
35172 	  var businessObject = element.businessObject;
35173 
35174 	  var rules = this._rules;
35175 
35176 	  var entries;
35177 
35178 	  if (!rules.allowed('shape.replace', { element: element })) {
35179 	    return [];
35180 	  }
35181 
35182 	  var differentType = isDifferentType(element);
35183 
35184 	  if (is$1(businessObject, 'bpmn:DataObjectReference')) {
35185 	    return this._createEntries(element, DATA_OBJECT_REFERENCE);
35186 	  }
35187 
35188 	  if (is$1(businessObject, 'bpmn:DataStoreReference')) {
35189 	    return this._createEntries(element, DATA_STORE_REFERENCE);
35190 	  }
35191 
35192 	  // start events outside sub processes
35193 	  if (is$1(businessObject, 'bpmn:StartEvent') && !is$1(businessObject.$parent, 'bpmn:SubProcess')) {
35194 
35195 	    entries = filter(START_EVENT, differentType);
35196 
35197 	    return this._createEntries(element, entries);
35198 	  }
35199 
35200 	  // expanded/collapsed pools
35201 	  if (is$1(businessObject, 'bpmn:Participant')) {
35202 
35203 	    entries = filter(PARTICIPANT, function(entry) {
35204 	      return isExpanded(businessObject) !== entry.target.isExpanded;
35205 	    });
35206 
35207 	    return this._createEntries(element, entries);
35208 	  }
35209 
35210 	  // start events inside event sub processes
35211 	  if (is$1(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) {
35212 	    entries = filter(EVENT_SUB_PROCESS_START_EVENT, function(entry) {
35213 
35214 	      var target = entry.target;
35215 
35216 	      var isInterrupting = target.isInterrupting !== false;
35217 
35218 	      var isInterruptingEqual = getBusinessObject(element).isInterrupting === isInterrupting;
35219 
35220 	      // filters elements which types and event definition are equal but have have different interrupting types
35221 	      return differentType(entry) || !differentType(entry) && !isInterruptingEqual;
35222 
35223 	    });
35224 
35225 	    return this._createEntries(element, entries);
35226 	  }
35227 
35228 	  // start events inside sub processes
35229 	  if (is$1(businessObject, 'bpmn:StartEvent') && !isEventSubProcess(businessObject.$parent)
35230 	      && is$1(businessObject.$parent, 'bpmn:SubProcess')) {
35231 	    entries = filter(START_EVENT_SUB_PROCESS, differentType);
35232 
35233 	    return this._createEntries(element, entries);
35234 	  }
35235 
35236 	  // end events
35237 	  if (is$1(businessObject, 'bpmn:EndEvent')) {
35238 
35239 	    entries = filter(END_EVENT, function(entry) {
35240 	      var target = entry.target;
35241 
35242 	      // hide cancel end events outside transactions
35243 	      if (target.eventDefinitionType == 'bpmn:CancelEventDefinition' && !is$1(businessObject.$parent, 'bpmn:Transaction')) {
35244 	        return false;
35245 	      }
35246 
35247 	      return differentType(entry);
35248 	    });
35249 
35250 	    return this._createEntries(element, entries);
35251 	  }
35252 
35253 	  // boundary events
35254 	  if (is$1(businessObject, 'bpmn:BoundaryEvent')) {
35255 
35256 	    entries = filter(BOUNDARY_EVENT, function(entry) {
35257 
35258 	      var target = entry.target;
35259 
35260 	      if (target.eventDefinitionType == 'bpmn:CancelEventDefinition' &&
35261 	         !is$1(businessObject.attachedToRef, 'bpmn:Transaction')) {
35262 	        return false;
35263 	      }
35264 	      var cancelActivity = target.cancelActivity !== false;
35265 
35266 	      var isCancelActivityEqual = businessObject.cancelActivity == cancelActivity;
35267 
35268 	      return differentType(entry) || !differentType(entry) && !isCancelActivityEqual;
35269 	    });
35270 
35271 	    return this._createEntries(element, entries);
35272 	  }
35273 
35274 	  // intermediate events
35275 	  if (is$1(businessObject, 'bpmn:IntermediateCatchEvent') ||
35276 	      is$1(businessObject, 'bpmn:IntermediateThrowEvent')) {
35277 
35278 	    entries = filter(INTERMEDIATE_EVENT, differentType);
35279 
35280 	    return this._createEntries(element, entries);
35281 	  }
35282 
35283 	  // gateways
35284 	  if (is$1(businessObject, 'bpmn:Gateway')) {
35285 
35286 	    entries = filter(GATEWAY, differentType);
35287 
35288 	    return this._createEntries(element, entries);
35289 	  }
35290 
35291 	  // transactions
35292 	  if (is$1(businessObject, 'bpmn:Transaction')) {
35293 
35294 	    entries = filter(TRANSACTION, differentType);
35295 
35296 	    return this._createEntries(element, entries);
35297 	  }
35298 
35299 	  // expanded event sub processes
35300 	  if (isEventSubProcess(businessObject) && isExpanded(businessObject)) {
35301 
35302 	    entries = filter(EVENT_SUB_PROCESS, differentType);
35303 
35304 	    return this._createEntries(element, entries);
35305 	  }
35306 
35307 	  // expanded sub processes
35308 	  if (is$1(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {
35309 
35310 	    entries = filter(SUBPROCESS_EXPANDED, differentType);
35311 
35312 	    return this._createEntries(element, entries);
35313 	  }
35314 
35315 	  // collapsed ad hoc sub processes
35316 	  if (is$1(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {
35317 
35318 	    entries = filter(TASK, function(entry) {
35319 
35320 	      var target = entry.target;
35321 
35322 	      var isTargetSubProcess = target.type === 'bpmn:SubProcess';
35323 
35324 	      var isTargetExpanded = target.isExpanded === true;
35325 
35326 	      return isDifferentType(element) && (!isTargetSubProcess || isTargetExpanded);
35327 	    });
35328 
35329 	    return this._createEntries(element, entries);
35330 	  }
35331 
35332 	  // sequence flows
35333 	  if (is$1(businessObject, 'bpmn:SequenceFlow')) {
35334 	    return this._createSequenceFlowEntries(element, SEQUENCE_FLOW);
35335 	  }
35336 
35337 	  // flow nodes
35338 	  if (is$1(businessObject, 'bpmn:FlowNode')) {
35339 	    entries = filter(TASK, differentType);
35340 
35341 	    // collapsed SubProcess can not be replaced with itself
35342 	    if (is$1(businessObject, 'bpmn:SubProcess') && !isExpanded(businessObject)) {
35343 	      entries = filter(entries, function(entry) {
35344 	        return entry.label !== 'Sub Process (collapsed)';
35345 	      });
35346 	    }
35347 
35348 	    return this._createEntries(element, entries);
35349 	  }
35350 
35351 	  return [];
35352 	};
35353 
35354 
35355 	/**
35356 	 * Get a list of header items for the given element. This includes buttons
35357 	 * for multi instance markers and for the ad hoc marker.
35358 	 *
35359 	 * @param {djs.model.Base} element
35360 	 *
35361 	 * @return {Array<Object>} a list of menu entry items
35362 	 */
35363 	ReplaceMenuProvider.prototype.getHeaderEntries = function(element) {
35364 
35365 	  var headerEntries = [];
35366 
35367 	  if (is$1(element, 'bpmn:Activity') && !isEventSubProcess(element)) {
35368 	    headerEntries = headerEntries.concat(this._getLoopEntries(element));
35369 	  }
35370 
35371 	  if (is$1(element, 'bpmn:DataObjectReference')) {
35372 	    headerEntries = headerEntries.concat(this._getDataObjectIsCollection(element));
35373 	  }
35374 
35375 	  if (is$1(element, 'bpmn:Participant')) {
35376 	    headerEntries = headerEntries.concat(this._getParticipantMultiplicity(element));
35377 	  }
35378 
35379 	  if (is$1(element, 'bpmn:SubProcess') &&
35380 	      !is$1(element, 'bpmn:Transaction') &&
35381 	      !isEventSubProcess(element)) {
35382 	    headerEntries.push(this._getAdHocEntry(element));
35383 	  }
35384 
35385 	  return headerEntries;
35386 	};
35387 
35388 
35389 	/**
35390 	 * Creates an array of menu entry objects for a given element and filters the replaceOptions
35391 	 * according to a filter function.
35392 	 *
35393 	 * @param  {djs.model.Base} element
35394 	 * @param  {Object} replaceOptions
35395 	 *
35396 	 * @return {Array<Object>} a list of menu items
35397 	 */
35398 	ReplaceMenuProvider.prototype._createEntries = function(element, replaceOptions) {
35399 	  var menuEntries = [];
35400 
35401 	  var self = this;
35402 
35403 	  forEach(replaceOptions, function(definition) {
35404 	    var entry = self._createMenuEntry(definition, element);
35405 
35406 	    menuEntries.push(entry);
35407 	  });
35408 
35409 	  return menuEntries;
35410 	};
35411 
35412 	/**
35413 	 * Creates an array of menu entry objects for a given sequence flow.
35414 	 *
35415 	 * @param  {djs.model.Base} element
35416 	 * @param  {Object} replaceOptions
35417 
35418 	 * @return {Array<Object>} a list of menu items
35419 	 */
35420 	ReplaceMenuProvider.prototype._createSequenceFlowEntries = function(element, replaceOptions) {
35421 
35422 	  var businessObject = getBusinessObject(element);
35423 
35424 	  var menuEntries = [];
35425 
35426 	  var modeling = this._modeling,
35427 	      moddle = this._moddle;
35428 
35429 	  var self = this;
35430 
35431 	  forEach(replaceOptions, function(entry) {
35432 
35433 	    switch (entry.actionName) {
35434 	    case 'replace-with-default-flow':
35435 	      if (businessObject.sourceRef.default !== businessObject &&
35436 	            (is$1(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
35437 	             is$1(businessObject.sourceRef, 'bpmn:InclusiveGateway') ||
35438 	             is$1(businessObject.sourceRef, 'bpmn:ComplexGateway') ||
35439 	             is$1(businessObject.sourceRef, 'bpmn:Activity'))) {
35440 
35441 	        menuEntries.push(self._createMenuEntry(entry, element, function() {
35442 	          modeling.updateProperties(element.source, { default: businessObject });
35443 	        }));
35444 	      }
35445 	      break;
35446 	    case 'replace-with-conditional-flow':
35447 	      if (!businessObject.conditionExpression && is$1(businessObject.sourceRef, 'bpmn:Activity')) {
35448 
35449 	        menuEntries.push(self._createMenuEntry(entry, element, function() {
35450 	          var conditionExpression = moddle.create('bpmn:FormalExpression', { body: '' });
35451 
35452 	          modeling.updateProperties(element, { conditionExpression: conditionExpression });
35453 	        }));
35454 	      }
35455 	      break;
35456 	    default:
35457 
35458 	      // default flows
35459 	      if (is$1(businessObject.sourceRef, 'bpmn:Activity') && businessObject.conditionExpression) {
35460 	        return menuEntries.push(self._createMenuEntry(entry, element, function() {
35461 	          modeling.updateProperties(element, { conditionExpression: undefined });
35462 	        }));
35463 	      }
35464 
35465 	      // conditional flows
35466 	      if ((is$1(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
35467 	           is$1(businessObject.sourceRef, 'bpmn:InclusiveGateway') ||
35468 	           is$1(businessObject.sourceRef, 'bpmn:ComplexGateway') ||
35469 	           is$1(businessObject.sourceRef, 'bpmn:Activity')) &&
35470 	           businessObject.sourceRef.default === businessObject) {
35471 
35472 	        return menuEntries.push(self._createMenuEntry(entry, element, function() {
35473 	          modeling.updateProperties(element.source, { default: undefined });
35474 	        }));
35475 	      }
35476 	    }
35477 	  });
35478 
35479 	  return menuEntries;
35480 	};
35481 
35482 
35483 	/**
35484 	 * Creates and returns a single menu entry item.
35485 	 *
35486 	 * @param  {Object} definition a single replace options definition object
35487 	 * @param  {djs.model.Base} element
35488 	 * @param  {Function} [action] an action callback function which gets called when
35489 	 *                             the menu entry is being triggered.
35490 	 *
35491 	 * @return {Object} menu entry item
35492 	 */
35493 	ReplaceMenuProvider.prototype._createMenuEntry = function(definition, element, action) {
35494 	  var translate = this._translate;
35495 	  var replaceElement = this._bpmnReplace.replaceElement;
35496 
35497 	  var replaceAction = function() {
35498 	    return replaceElement(element, definition.target);
35499 	  };
35500 
35501 	  var label = definition.label;
35502 	  if (label && typeof label === 'function') {
35503 	    label = label(element);
35504 	  }
35505 
35506 	  action = action || replaceAction;
35507 
35508 	  var menuEntry = {
35509 	    label: translate(label),
35510 	    className: definition.className,
35511 	    id: definition.actionName,
35512 	    action: action
35513 	  };
35514 
35515 	  return menuEntry;
35516 	};
35517 
35518 	/**
35519 	 * Get a list of menu items containing buttons for multi instance markers
35520 	 *
35521 	 * @param  {djs.model.Base} element
35522 	 *
35523 	 * @return {Array<Object>} a list of menu items
35524 	 */
35525 	ReplaceMenuProvider.prototype._getLoopEntries = function(element) {
35526 
35527 	  var self = this;
35528 	  var translate = this._translate;
35529 
35530 	  function toggleLoopEntry(event, entry) {
35531 	    var loopCharacteristics;
35532 
35533 	    if (entry.active) {
35534 	      loopCharacteristics = undefined;
35535 	    } else {
35536 	      loopCharacteristics = self._moddle.create(entry.options.loopCharacteristics);
35537 
35538 	      if (entry.options.isSequential) {
35539 	        loopCharacteristics.isSequential = entry.options.isSequential;
35540 	      }
35541 	    }
35542 	    self._modeling.updateProperties(element, { loopCharacteristics: loopCharacteristics });
35543 	  }
35544 
35545 	  var businessObject = getBusinessObject(element),
35546 	      loopCharacteristics = businessObject.loopCharacteristics;
35547 
35548 	  var isSequential,
35549 	      isLoop,
35550 	      isParallel;
35551 
35552 	  if (loopCharacteristics) {
35553 	    isSequential = loopCharacteristics.isSequential;
35554 	    isLoop = loopCharacteristics.isSequential === undefined;
35555 	    isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
35556 	  }
35557 
35558 
35559 	  var loopEntries = [
35560 	    {
35561 	      id: 'toggle-parallel-mi',
35562 	      className: 'bpmn-icon-parallel-mi-marker',
35563 	      title: translate('Parallel Multi Instance'),
35564 	      active: isParallel,
35565 	      action: toggleLoopEntry,
35566 	      options: {
35567 	        loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
35568 	        isSequential: false
35569 	      }
35570 	    },
35571 	    {
35572 	      id: 'toggle-sequential-mi',
35573 	      className: 'bpmn-icon-sequential-mi-marker',
35574 	      title: translate('Sequential Multi Instance'),
35575 	      active: isSequential,
35576 	      action: toggleLoopEntry,
35577 	      options: {
35578 	        loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
35579 	        isSequential: true
35580 	      }
35581 	    },
35582 	    {
35583 	      id: 'toggle-loop',
35584 	      className: 'bpmn-icon-loop-marker',
35585 	      title: translate('Loop'),
35586 	      active: isLoop,
35587 	      action: toggleLoopEntry,
35588 	      options: {
35589 	        loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
35590 	      }
35591 	    }
35592 	  ];
35593 	  return loopEntries;
35594 	};
35595 
35596 	/**
35597 	 * Get a list of menu items containing a button for the collection marker
35598 	 *
35599 	 * @param  {djs.model.Base} element
35600 	 *
35601 	 * @return {Array<Object>} a list of menu items
35602 	 */
35603 	ReplaceMenuProvider.prototype._getDataObjectIsCollection = function(element) {
35604 
35605 	  var self = this;
35606 	  var translate = this._translate;
35607 
35608 	  function toggleIsCollection(event, entry) {
35609 	    self._modeling.updateModdleProperties(
35610 	      element,
35611 	      dataObject,
35612 	      { isCollection: !entry.active });
35613 	  }
35614 
35615 	  var dataObject = element.businessObject.dataObjectRef,
35616 	      isCollection = dataObject.isCollection;
35617 
35618 	  var dataObjectEntries = [
35619 	    {
35620 	      id: 'toggle-is-collection',
35621 	      className: 'bpmn-icon-parallel-mi-marker',
35622 	      title: translate('Collection'),
35623 	      active: isCollection,
35624 	      action: toggleIsCollection,
35625 	    }
35626 	  ];
35627 	  return dataObjectEntries;
35628 	};
35629 
35630 	/**
35631 	 * Get a list of menu items containing a button for the participant multiplicity marker
35632 	 *
35633 	 * @param  {djs.model.Base} element
35634 	 *
35635 	 * @return {Array<Object>} a list of menu items
35636 	 */
35637 	ReplaceMenuProvider.prototype._getParticipantMultiplicity = function(element) {
35638 
35639 	  var self = this;
35640 	  var bpmnFactory = this._bpmnFactory;
35641 	  var translate = this._translate;
35642 
35643 	  function toggleParticipantMultiplicity(event, entry) {
35644 	    var isActive = entry.active;
35645 	    var participantMultiplicity;
35646 
35647 	    if (!isActive) {
35648 	      participantMultiplicity = bpmnFactory.create('bpmn:ParticipantMultiplicity');
35649 	    }
35650 
35651 	    self._modeling.updateProperties(
35652 	      element,
35653 	      { participantMultiplicity: participantMultiplicity });
35654 	  }
35655 
35656 	  var participantMultiplicity = element.businessObject.participantMultiplicity;
35657 
35658 	  var participantEntries = [
35659 	    {
35660 	      id: 'toggle-participant-multiplicity',
35661 	      className: 'bpmn-icon-parallel-mi-marker',
35662 	      title: translate('Participant Multiplicity'),
35663 	      active: !!participantMultiplicity,
35664 	      action: toggleParticipantMultiplicity,
35665 	    }
35666 	  ];
35667 	  return participantEntries;
35668 	};
35669 
35670 
35671 	/**
35672 	 * Get the menu items containing a button for the ad hoc marker
35673 	 *
35674 	 * @param  {djs.model.Base} element
35675 	 *
35676 	 * @return {Object} a menu item
35677 	 */
35678 	ReplaceMenuProvider.prototype._getAdHocEntry = function(element) {
35679 	  var translate = this._translate;
35680 	  var businessObject = getBusinessObject(element);
35681 
35682 	  var isAdHoc = is$1(businessObject, 'bpmn:AdHocSubProcess');
35683 
35684 	  var replaceElement = this._bpmnReplace.replaceElement;
35685 
35686 	  var adHocEntry = {
35687 	    id: 'toggle-adhoc',
35688 	    className: 'bpmn-icon-ad-hoc-marker',
35689 	    title: translate('Ad-hoc'),
35690 	    active: isAdHoc,
35691 	    action: function(event, entry) {
35692 	      if (isAdHoc) {
35693 	        return replaceElement(element, { type: 'bpmn:SubProcess' }, {
35694 	          autoResize: false,
35695 	          layoutConnection: false
35696 	        });
35697 	      } else {
35698 	        return replaceElement(element, { type: 'bpmn:AdHocSubProcess' }, {
35699 	          autoResize: false,
35700 	          layoutConnection: false
35701 	        });
35702 	      }
35703 	    }
35704 	  };
35705 
35706 	  return adHocEntry;
35707 	};
35708 
35709 	var PopupMenuModule = {
35710 	  __depends__: [
35711 	    PopupMenuModule$1,
35712 	    ReplaceModule
35713 	  ],
35714 	  __init__: [ 'replaceMenuProvider' ],
35715 	  replaceMenuProvider: [ 'type', ReplaceMenuProvider ]
35716 	};
35717 
35718 	var max$4 = Math.max,
35719 	    min$2 = Math.min;
35720 
35721 	var DEFAULT_CHILD_BOX_PADDING = 20;
35722 
35723 
35724 	/**
35725 	 * Substract a TRBL from another
35726 	 *
35727 	 * @param  {TRBL} trblA
35728 	 * @param  {TRBL} trblB
35729 	 *
35730 	 * @return {TRBL}
35731 	 */
35732 	function substractTRBL(trblA, trblB) {
35733 	  return {
35734 	    top: trblA.top - trblB.top,
35735 	    right: trblA.right - trblB.right,
35736 	    bottom: trblA.bottom - trblB.bottom,
35737 	    left: trblA.left - trblB.left
35738 	  };
35739 	}
35740 
35741 	/**
35742 	 * Resize the given bounds by the specified delta from a given anchor point.
35743 	 *
35744 	 * @param {Bounds} bounds the bounding box that should be resized
35745 	 * @param {string} direction in which the element is resized (nw, ne, se, sw)
35746 	 * @param {Point} delta of the resize operation
35747 	 *
35748 	 * @return {Bounds} resized bounding box
35749 	 */
35750 	function resizeBounds$1(bounds, direction, delta) {
35751 	  var dx = delta.x,
35752 	      dy = delta.y;
35753 
35754 	  var newBounds = {
35755 	    x: bounds.x,
35756 	    y: bounds.y,
35757 	    width: bounds.width,
35758 	    height: bounds.height
35759 	  };
35760 
35761 	  if (direction.indexOf('n') !== -1) {
35762 	    newBounds.y = bounds.y + dy;
35763 	    newBounds.height = bounds.height - dy;
35764 	  } else if (direction.indexOf('s') !== -1) {
35765 	    newBounds.height = bounds.height + dy;
35766 	  }
35767 
35768 	  if (direction.indexOf('e') !== -1) {
35769 	    newBounds.width = bounds.width + dx;
35770 	  } else if (direction.indexOf('w') !== -1) {
35771 	    newBounds.x = bounds.x + dx;
35772 	    newBounds.width = bounds.width - dx;
35773 	  }
35774 
35775 	  return newBounds;
35776 	}
35777 
35778 
35779 	/**
35780 	 * Resize the given bounds by applying the passed
35781 	 * { top, right, bottom, left } delta.
35782 	 *
35783 	 * @param {Bounds} bounds
35784 	 * @param {TRBL} trblResize
35785 	 *
35786 	 * @return {Bounds}
35787 	 */
35788 	function resizeTRBL(bounds, resize) {
35789 	  return {
35790 	    x: bounds.x + (resize.left || 0),
35791 	    y: bounds.y + (resize.top || 0),
35792 	    width: bounds.width - (resize.left || 0) + (resize.right || 0),
35793 	    height: bounds.height - (resize.top || 0) + (resize.bottom || 0)
35794 	  };
35795 	}
35796 
35797 
35798 	function applyConstraints(attr, trbl, resizeConstraints) {
35799 
35800 	  var value = trbl[attr],
35801 	      minValue = resizeConstraints.min && resizeConstraints.min[attr],
35802 	      maxValue = resizeConstraints.max && resizeConstraints.max[attr];
35803 
35804 	  if (isNumber(minValue)) {
35805 	    value = (/top|left/.test(attr) ? min$2 : max$4)(value, minValue);
35806 	  }
35807 
35808 	  if (isNumber(maxValue)) {
35809 	    value = (/top|left/.test(attr) ? max$4 : min$2)(value, maxValue);
35810 	  }
35811 
35812 	  return value;
35813 	}
35814 
35815 	function ensureConstraints$1(currentBounds, resizeConstraints) {
35816 
35817 	  if (!resizeConstraints) {
35818 	    return currentBounds;
35819 	  }
35820 
35821 	  var currentTrbl = asTRBL(currentBounds);
35822 
35823 	  return asBounds({
35824 	    top: applyConstraints('top', currentTrbl, resizeConstraints),
35825 	    right: applyConstraints('right', currentTrbl, resizeConstraints),
35826 	    bottom: applyConstraints('bottom', currentTrbl, resizeConstraints),
35827 	    left: applyConstraints('left', currentTrbl, resizeConstraints)
35828 	  });
35829 	}
35830 
35831 
35832 	function getMinResizeBounds(direction, currentBounds, minDimensions, childrenBounds) {
35833 
35834 	  var currentBox = asTRBL(currentBounds);
35835 
35836 	  var minBox = {
35837 	    top: /n/.test(direction) ? currentBox.bottom - minDimensions.height : currentBox.top,
35838 	    left: /w/.test(direction) ? currentBox.right - minDimensions.width : currentBox.left,
35839 	    bottom: /s/.test(direction) ? currentBox.top + minDimensions.height : currentBox.bottom,
35840 	    right: /e/.test(direction) ? currentBox.left + minDimensions.width : currentBox.right
35841 	  };
35842 
35843 	  var childrenBox = childrenBounds ? asTRBL(childrenBounds) : minBox;
35844 
35845 	  var combinedBox = {
35846 	    top: min$2(minBox.top, childrenBox.top),
35847 	    left: min$2(minBox.left, childrenBox.left),
35848 	    bottom: max$4(minBox.bottom, childrenBox.bottom),
35849 	    right: max$4(minBox.right, childrenBox.right)
35850 	  };
35851 
35852 	  return asBounds(combinedBox);
35853 	}
35854 
35855 	function asPadding(mayBePadding, defaultValue) {
35856 	  if (typeof mayBePadding !== 'undefined') {
35857 	    return mayBePadding;
35858 	  } else {
35859 	    return DEFAULT_CHILD_BOX_PADDING;
35860 	  }
35861 	}
35862 
35863 	function addPadding$1(bbox, padding) {
35864 	  var left, right, top, bottom;
35865 
35866 	  if (typeof padding === 'object') {
35867 	    left = asPadding(padding.left);
35868 	    right = asPadding(padding.right);
35869 	    top = asPadding(padding.top);
35870 	    bottom = asPadding(padding.bottom);
35871 	  } else {
35872 	    left = right = top = bottom = asPadding(padding);
35873 	  }
35874 
35875 	  return {
35876 	    x: bbox.x - left,
35877 	    y: bbox.y - top,
35878 	    width: bbox.width + left + right,
35879 	    height: bbox.height + top + bottom
35880 	  };
35881 	}
35882 
35883 
35884 	/**
35885 	 * Is the given element part of the resize
35886 	 * targets min boundary box?
35887 	 *
35888 	 * This is the default implementation which excludes
35889 	 * connections and labels.
35890 	 *
35891 	 * @param {djs.model.Base} element
35892 	 */
35893 	function isBBoxChild(element) {
35894 
35895 	  // exclude connections
35896 	  if (element.waypoints) {
35897 	    return false;
35898 	  }
35899 
35900 	  // exclude labels
35901 	  if (element.type === 'label') {
35902 	    return false;
35903 	  }
35904 
35905 	  return true;
35906 	}
35907 
35908 	/**
35909 	 * Return children bounding computed from a shapes children
35910 	 * or a list of prefiltered children.
35911 	 *
35912 	 * @param  {djs.model.Shape|Array<djs.model.Shape>} shapeOrChildren
35913 	 * @param  {number|Object} padding
35914 	 *
35915 	 * @return {Bounds}
35916 	 */
35917 	function computeChildrenBBox(shapeOrChildren, padding) {
35918 
35919 	  var elements;
35920 
35921 	  // compute based on shape
35922 	  if (shapeOrChildren.length === undefined) {
35923 
35924 	    // grab all the children that are part of the
35925 	    // parents children box
35926 	    elements = filter(shapeOrChildren.children, isBBoxChild);
35927 
35928 	  } else {
35929 	    elements = shapeOrChildren;
35930 	  }
35931 
35932 	  if (elements.length) {
35933 	    return addPadding$1(getBBox(elements), padding);
35934 	  }
35935 	}
35936 
35937 	var abs$4 = Math.abs;
35938 
35939 
35940 	function getTRBLResize(oldBounds, newBounds) {
35941 	  return substractTRBL(asTRBL(newBounds), asTRBL(oldBounds));
35942 	}
35943 
35944 
35945 	var LANE_PARENTS = [
35946 	  'bpmn:Participant',
35947 	  'bpmn:Process',
35948 	  'bpmn:SubProcess'
35949 	];
35950 
35951 	var LANE_INDENTATION = 30;
35952 
35953 
35954 	/**
35955 	 * Collect all lane shapes in the given paren
35956 	 *
35957 	 * @param  {djs.model.Shape} shape
35958 	 * @param  {Array<djs.model.Base>} [collectedShapes]
35959 	 *
35960 	 * @return {Array<djs.model.Base>}
35961 	 */
35962 	function collectLanes(shape, collectedShapes) {
35963 
35964 	  collectedShapes = collectedShapes || [];
35965 
35966 	  shape.children.filter(function(s) {
35967 	    if (is$1(s, 'bpmn:Lane')) {
35968 	      collectLanes(s, collectedShapes);
35969 
35970 	      collectedShapes.push(s);
35971 	    }
35972 	  });
35973 
35974 	  return collectedShapes;
35975 	}
35976 
35977 
35978 	/**
35979 	 * Return the lane children of the given element.
35980 	 *
35981 	 * @param {djs.model.Shape} shape
35982 	 *
35983 	 * @return {Array<djs.model.Shape>}
35984 	 */
35985 	function getChildLanes(shape) {
35986 	  return shape.children.filter(function(c) {
35987 	    return is$1(c, 'bpmn:Lane');
35988 	  });
35989 	}
35990 
35991 
35992 	/**
35993 	 * Return the root element containing the given lane shape
35994 	 *
35995 	 * @param {djs.model.Shape} shape
35996 	 *
35997 	 * @return {djs.model.Shape}
35998 	 */
35999 	function getLanesRoot(shape) {
36000 	  return getParent(shape, LANE_PARENTS) || shape;
36001 	}
36002 
36003 
36004 	/**
36005 	 * Compute the required resize operations for lanes
36006 	 * adjacent to the given shape, assuming it will be
36007 	 * resized to the given new bounds.
36008 	 *
36009 	 * @param {djs.model.Shape} shape
36010 	 * @param {Bounds} newBounds
36011 	 *
36012 	 * @return {Array<Object>}
36013 	 */
36014 	function computeLanesResize(shape, newBounds) {
36015 
36016 	  var rootElement = getLanesRoot(shape);
36017 
36018 	  var initialShapes = is$1(rootElement, 'bpmn:Process') ? [] : [ rootElement ];
36019 
36020 	  var allLanes = collectLanes(rootElement, initialShapes),
36021 	      shapeTrbl = asTRBL(shape),
36022 	      shapeNewTrbl = asTRBL(newBounds),
36023 	      trblResize = getTRBLResize(shape, newBounds),
36024 	      resizeNeeded = [];
36025 
36026 	  allLanes.forEach(function(other) {
36027 
36028 	    if (other === shape) {
36029 	      return;
36030 	    }
36031 
36032 	    var topResize = 0,
36033 	        rightResize = trblResize.right,
36034 	        bottomResize = 0,
36035 	        leftResize = trblResize.left;
36036 
36037 	    var otherTrbl = asTRBL(other);
36038 
36039 	    if (trblResize.top) {
36040 	      if (abs$4(otherTrbl.bottom - shapeTrbl.top) < 10) {
36041 	        bottomResize = shapeNewTrbl.top - otherTrbl.bottom;
36042 	      }
36043 
36044 	      if (abs$4(otherTrbl.top - shapeTrbl.top) < 5) {
36045 	        topResize = shapeNewTrbl.top - otherTrbl.top;
36046 	      }
36047 	    }
36048 
36049 	    if (trblResize.bottom) {
36050 	      if (abs$4(otherTrbl.top - shapeTrbl.bottom) < 10) {
36051 	        topResize = shapeNewTrbl.bottom - otherTrbl.top;
36052 	      }
36053 
36054 	      if (abs$4(otherTrbl.bottom - shapeTrbl.bottom) < 5) {
36055 	        bottomResize = shapeNewTrbl.bottom - otherTrbl.bottom;
36056 	      }
36057 	    }
36058 
36059 	    if (topResize || rightResize || bottomResize || leftResize) {
36060 
36061 	      resizeNeeded.push({
36062 	        shape: other,
36063 	        newBounds: resizeTRBL(other, {
36064 	          top: topResize,
36065 	          right: rightResize,
36066 	          bottom: bottomResize,
36067 	          left: leftResize
36068 	        })
36069 	      });
36070 	    }
36071 
36072 	  });
36073 
36074 	  return resizeNeeded;
36075 	}
36076 
36077 	/**
36078 	 * A provider for BPMN 2.0 elements context pad
36079 	 */
36080 	function ContextPadProvider(
36081 	    config, injector, eventBus,
36082 	    contextPad, modeling, elementFactory,
36083 	    connect, create, popupMenu,
36084 	    canvas, rules, translate) {
36085 
36086 	  config = config || {};
36087 
36088 	  contextPad.registerProvider(this);
36089 
36090 	  this._contextPad = contextPad;
36091 
36092 	  this._modeling = modeling;
36093 
36094 	  this._elementFactory = elementFactory;
36095 	  this._connect = connect;
36096 	  this._create = create;
36097 	  this._popupMenu = popupMenu;
36098 	  this._canvas = canvas;
36099 	  this._rules = rules;
36100 	  this._translate = translate;
36101 
36102 	  if (config.autoPlace !== false) {
36103 	    this._autoPlace = injector.get('autoPlace', false);
36104 	  }
36105 
36106 	  eventBus.on('create.end', 250, function(event) {
36107 	    var context = event.context,
36108 	        shape = context.shape;
36109 
36110 	    if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) {
36111 	      return;
36112 	    }
36113 
36114 	    var entries = contextPad.getEntries(shape);
36115 
36116 	    if (entries.replace) {
36117 	      entries.replace.action.click(event, shape);
36118 	    }
36119 	  });
36120 	}
36121 
36122 	ContextPadProvider.$inject = [
36123 	  'config.contextPad',
36124 	  'injector',
36125 	  'eventBus',
36126 	  'contextPad',
36127 	  'modeling',
36128 	  'elementFactory',
36129 	  'connect',
36130 	  'create',
36131 	  'popupMenu',
36132 	  'canvas',
36133 	  'rules',
36134 	  'translate'
36135 	];
36136 
36137 
36138 	ContextPadProvider.prototype.getContextPadEntries = function(element) {
36139 
36140 	  var contextPad = this._contextPad,
36141 	      modeling = this._modeling,
36142 
36143 	      elementFactory = this._elementFactory,
36144 	      connect = this._connect,
36145 	      create = this._create,
36146 	      popupMenu = this._popupMenu,
36147 	      canvas = this._canvas,
36148 	      rules = this._rules,
36149 	      autoPlace = this._autoPlace,
36150 	      translate = this._translate;
36151 
36152 	  var actions = {};
36153 
36154 	  if (element.type === 'label') {
36155 	    return actions;
36156 	  }
36157 
36158 	  var businessObject = element.businessObject;
36159 
36160 	  function startConnect(event, element) {
36161 	    connect.start(event, element);
36162 	  }
36163 
36164 	  function removeElement(e) {
36165 	    modeling.removeElements([ element ]);
36166 	  }
36167 
36168 	  function getReplaceMenuPosition(element) {
36169 
36170 	    var Y_OFFSET = 5;
36171 
36172 	    var diagramContainer = canvas.getContainer(),
36173 	        pad = contextPad.getPad(element).html;
36174 
36175 	    var diagramRect = diagramContainer.getBoundingClientRect(),
36176 	        padRect = pad.getBoundingClientRect();
36177 
36178 	    var top = padRect.top - diagramRect.top;
36179 	    var left = padRect.left - diagramRect.left;
36180 
36181 	    var pos = {
36182 	      x: left,
36183 	      y: top + padRect.height + Y_OFFSET
36184 	    };
36185 
36186 	    return pos;
36187 	  }
36188 
36189 
36190 	  /**
36191 	   * Create an append action
36192 	   *
36193 	   * @param {string} type
36194 	   * @param {string} className
36195 	   * @param {string} [title]
36196 	   * @param {Object} [options]
36197 	   *
36198 	   * @return {Object} descriptor
36199 	   */
36200 	  function appendAction(type, className, title, options) {
36201 
36202 	    if (typeof title !== 'string') {
36203 	      options = title;
36204 	      title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') });
36205 	    }
36206 
36207 	    function appendStart(event, element) {
36208 
36209 	      var shape = elementFactory.createShape(assign({ type: type }, options));
36210 	      create.start(event, shape, {
36211 	        source: element
36212 	      });
36213 	    }
36214 
36215 
36216 	    var append = autoPlace ? function(event, element) {
36217 	      var shape = elementFactory.createShape(assign({ type: type }, options));
36218 
36219 	      autoPlace.append(element, shape);
36220 	    } : appendStart;
36221 
36222 
36223 	    return {
36224 	      group: 'model',
36225 	      className: className,
36226 	      title: title,
36227 	      action: {
36228 	        dragstart: appendStart,
36229 	        click: append
36230 	      }
36231 	    };
36232 	  }
36233 
36234 	  function splitLaneHandler(count) {
36235 
36236 	    return function(event, element) {
36237 
36238 	      // actual split
36239 	      modeling.splitLane(element, count);
36240 
36241 	      // refresh context pad after split to
36242 	      // get rid of split icons
36243 	      contextPad.open(element, true);
36244 	    };
36245 	  }
36246 
36247 
36248 	  if (isAny(businessObject, [ 'bpmn:Lane', 'bpmn:Participant' ]) && isExpanded(businessObject)) {
36249 
36250 	    var childLanes = getChildLanes(element);
36251 
36252 	    assign(actions, {
36253 	      'lane-insert-above': {
36254 	        group: 'lane-insert-above',
36255 	        className: 'bpmn-icon-lane-insert-above',
36256 	        title: translate('Add Lane above'),
36257 	        action: {
36258 	          click: function(event, element) {
36259 	            modeling.addLane(element, 'top');
36260 	          }
36261 	        }
36262 	      }
36263 	    });
36264 
36265 	    if (childLanes.length < 2) {
36266 
36267 	      if (element.height >= 120) {
36268 	        assign(actions, {
36269 	          'lane-divide-two': {
36270 	            group: 'lane-divide',
36271 	            className: 'bpmn-icon-lane-divide-two',
36272 	            title: translate('Divide into two Lanes'),
36273 	            action: {
36274 	              click: splitLaneHandler(2)
36275 	            }
36276 	          }
36277 	        });
36278 	      }
36279 
36280 	      if (element.height >= 180) {
36281 	        assign(actions, {
36282 	          'lane-divide-three': {
36283 	            group: 'lane-divide',
36284 	            className: 'bpmn-icon-lane-divide-three',
36285 	            title: translate('Divide into three Lanes'),
36286 	            action: {
36287 	              click: splitLaneHandler(3)
36288 	            }
36289 	          }
36290 	        });
36291 	      }
36292 	    }
36293 
36294 	    assign(actions, {
36295 	      'lane-insert-below': {
36296 	        group: 'lane-insert-below',
36297 	        className: 'bpmn-icon-lane-insert-below',
36298 	        title: translate('Add Lane below'),
36299 	        action: {
36300 	          click: function(event, element) {
36301 	            modeling.addLane(element, 'bottom');
36302 	          }
36303 	        }
36304 	      }
36305 	    });
36306 
36307 	  }
36308 
36309 	  if (is$1(businessObject, 'bpmn:FlowNode')) {
36310 
36311 	    if (is$1(businessObject, 'bpmn:EventBasedGateway')) {
36312 
36313 	      assign(actions, {
36314 	        'append.receive-task': appendAction(
36315 	          'bpmn:ReceiveTask',
36316 	          'bpmn-icon-receive-task',
36317 	          translate('Append ReceiveTask')
36318 	        ),
36319 	        'append.message-intermediate-event': appendAction(
36320 	          'bpmn:IntermediateCatchEvent',
36321 	          'bpmn-icon-intermediate-event-catch-message',
36322 	          translate('Append MessageIntermediateCatchEvent'),
36323 	          { eventDefinitionType: 'bpmn:MessageEventDefinition' }
36324 	        ),
36325 	        'append.timer-intermediate-event': appendAction(
36326 	          'bpmn:IntermediateCatchEvent',
36327 	          'bpmn-icon-intermediate-event-catch-timer',
36328 	          translate('Append TimerIntermediateCatchEvent'),
36329 	          { eventDefinitionType: 'bpmn:TimerEventDefinition' }
36330 	        ),
36331 	        'append.condition-intermediate-event': appendAction(
36332 	          'bpmn:IntermediateCatchEvent',
36333 	          'bpmn-icon-intermediate-event-catch-condition',
36334 	          translate('Append ConditionIntermediateCatchEvent'),
36335 	          { eventDefinitionType: 'bpmn:ConditionalEventDefinition' }
36336 	        ),
36337 	        'append.signal-intermediate-event': appendAction(
36338 	          'bpmn:IntermediateCatchEvent',
36339 	          'bpmn-icon-intermediate-event-catch-signal',
36340 	          translate('Append SignalIntermediateCatchEvent'),
36341 	          { eventDefinitionType: 'bpmn:SignalEventDefinition' }
36342 	        )
36343 	      });
36344 	    } else
36345 
36346 	    if (isEventType(businessObject, 'bpmn:BoundaryEvent', 'bpmn:CompensateEventDefinition')) {
36347 
36348 	      assign(actions, {
36349 	        'append.compensation-activity':
36350 	            appendAction(
36351 	              'bpmn:Task',
36352 	              'bpmn-icon-task',
36353 	              translate('Append compensation activity'),
36354 	              {
36355 	                isForCompensation: true
36356 	              }
36357 	            )
36358 	      });
36359 	    } else
36360 
36361 	    if (!is$1(businessObject, 'bpmn:EndEvent') &&
36362 	        !businessObject.isForCompensation &&
36363 	        !isEventType(businessObject, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition') &&
36364 	        !isEventSubProcess(businessObject)) {
36365 
36366 	      assign(actions, {
36367 	        'append.end-event': appendAction(
36368 	          'bpmn:EndEvent',
36369 	          'bpmn-icon-end-event-none',
36370 	          translate('Append EndEvent')
36371 	        ),
36372 	        'append.gateway': appendAction(
36373 	          'bpmn:ExclusiveGateway',
36374 	          'bpmn-icon-gateway-none',
36375 	          translate('Append Gateway')
36376 	        ),
36377 	        'append.append-task': appendAction(
36378 	          'bpmn:Task',
36379 	          'bpmn-icon-task',
36380 	          translate('Append Task')
36381 	        ),
36382 	        'append.intermediate-event': appendAction(
36383 	          'bpmn:IntermediateThrowEvent',
36384 	          'bpmn-icon-intermediate-event-none',
36385 	          translate('Append Intermediate/Boundary Event')
36386 	        )
36387 	      });
36388 	    }
36389 	  }
36390 
36391 	  if (!popupMenu.isEmpty(element, 'bpmn-replace')) {
36392 
36393 	    // Replace menu entry
36394 	    assign(actions, {
36395 	      'replace': {
36396 	        group: 'edit',
36397 	        className: 'bpmn-icon-screw-wrench',
36398 	        title: translate('Change type'),
36399 	        action: {
36400 	          click: function(event, element) {
36401 
36402 	            var position = assign(getReplaceMenuPosition(element), {
36403 	              cursor: { x: event.x, y: event.y }
36404 	            });
36405 
36406 	            popupMenu.open(element, 'bpmn-replace', position);
36407 	          }
36408 	        }
36409 	      }
36410 	    });
36411 	  }
36412 
36413 	  if (
36414 	    isAny(businessObject, [
36415 	      'bpmn:FlowNode',
36416 	      'bpmn:InteractionNode',
36417 	      'bpmn:DataObjectReference',
36418 	      'bpmn:DataStoreReference',
36419 	    ])
36420 	  ) {
36421 	    assign(actions, {
36422 	      'append.text-annotation': appendAction(
36423 	        'bpmn:TextAnnotation',
36424 	        'bpmn-icon-text-annotation'
36425 	      ),
36426 
36427 	      'connect': {
36428 	        group: 'connect',
36429 	        className: 'bpmn-icon-connection-multi',
36430 	        title: translate(
36431 	          'Connect using ' +
36432 	            (businessObject.isForCompensation
36433 	              ? ''
36434 	              : 'Sequence/MessageFlow or ') +
36435 	            'Association'
36436 	        ),
36437 	        action: {
36438 	          click: startConnect,
36439 	          dragstart: startConnect,
36440 	        },
36441 	      },
36442 	    });
36443 	  }
36444 
36445 	  if (is$1(businessObject, 'bpmn:TextAnnotation')) {
36446 	    assign(actions, {
36447 	      'connect': {
36448 	        group: 'connect',
36449 	        className: 'bpmn-icon-connection-multi',
36450 	        title: translate('Connect using Association'),
36451 	        action: {
36452 	          click: startConnect,
36453 	          dragstart: startConnect,
36454 	        },
36455 	      },
36456 	    });
36457 	  }
36458 
36459 	  if (isAny(businessObject, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
36460 	    assign(actions, {
36461 	      'connect': {
36462 	        group: 'connect',
36463 	        className: 'bpmn-icon-connection-multi',
36464 	        title: translate('Connect using DataInputAssociation'),
36465 	        action: {
36466 	          click: startConnect,
36467 	          dragstart: startConnect
36468 	        }
36469 	      }
36470 	    });
36471 	  }
36472 
36473 	  if (is$1(businessObject, 'bpmn:Group')) {
36474 	    assign(actions, {
36475 	      'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation')
36476 	    });
36477 	  }
36478 
36479 	  // delete element entry, only show if allowed by rules
36480 	  var deleteAllowed = rules.allowed('elements.delete', { elements: [ element ] });
36481 
36482 	  if (isArray$2(deleteAllowed)) {
36483 
36484 	    // was the element returned as a deletion candidate?
36485 	    deleteAllowed = deleteAllowed[0] === element;
36486 	  }
36487 
36488 	  if (deleteAllowed) {
36489 	    assign(actions, {
36490 	      'delete': {
36491 	        group: 'edit',
36492 	        className: 'bpmn-icon-trash',
36493 	        title: translate('Remove'),
36494 	        action: {
36495 	          click: removeElement
36496 	        }
36497 	      }
36498 	    });
36499 	  }
36500 
36501 	  return actions;
36502 	};
36503 
36504 
36505 	// helpers /////////
36506 
36507 	function isEventType(eventBo, type, definition) {
36508 
36509 	  var isType = eventBo.$instanceOf(type);
36510 	  var isDefinition = false;
36511 
36512 	  var definitions = eventBo.eventDefinitions || [];
36513 	  forEach(definitions, function(def) {
36514 	    if (def.$type === definition) {
36515 	      isDefinition = true;
36516 	    }
36517 	  });
36518 
36519 	  return isType && isDefinition;
36520 	}
36521 
36522 	var ContextPadModule = {
36523 	  __depends__: [
36524 	    DirectEditingModule,
36525 	    ContextPadModule$1,
36526 	    SelectionModule,
36527 	    ConnectModule,
36528 	    CreateModule,
36529 	    PopupMenuModule
36530 	  ],
36531 	  __init__: [ 'contextPadProvider' ],
36532 	  contextPadProvider: [ 'type', ContextPadProvider ]
36533 	};
36534 
36535 	var AXIS_DIMENSIONS = {
36536 	  horizontal: [ 'x', 'width' ],
36537 	  vertical: [ 'y', 'height' ]
36538 	};
36539 
36540 	var THRESHOLD = 5;
36541 
36542 
36543 	/**
36544 	 * Groups and filters elements and then trigger even distribution.
36545 	 */
36546 	function DistributeElements$1(modeling) {
36547 	  this._modeling = modeling;
36548 
36549 	  this._filters = [];
36550 
36551 	  // register filter for filtering big elements
36552 	  this.registerFilter(function(elements, axis, dimension) {
36553 	    var elementsSize = 0,
36554 	        numOfShapes = 0,
36555 	        avgDimension;
36556 
36557 	    forEach(elements, function(element) {
36558 	      if (element.waypoints || element.labelTarget) {
36559 	        return;
36560 	      }
36561 
36562 	      elementsSize += element[dimension];
36563 
36564 	      numOfShapes += 1;
36565 	    });
36566 
36567 	    avgDimension = Math.round(elementsSize / numOfShapes);
36568 
36569 	    return filter(elements, function(element) {
36570 	      return element[dimension] < (avgDimension + 50);
36571 	    });
36572 	  });
36573 
36574 	}
36575 
36576 	DistributeElements$1.$inject = [ 'modeling' ];
36577 
36578 
36579 	/**
36580 	 * Registers filter functions that allow external parties to filter
36581 	 * out certain elements.
36582 	 *
36583 	 * @param  {Function} filterFn
36584 	 */
36585 	DistributeElements$1.prototype.registerFilter = function(filterFn) {
36586 	  if (typeof filterFn !== 'function') {
36587 	    throw new Error('the filter has to be a function');
36588 	  }
36589 
36590 	  this._filters.push(filterFn);
36591 	};
36592 
36593 	/**
36594 	 * Distributes the elements with a given orientation
36595 	 *
36596 	 * @param  {Array} elements
36597 	 * @param  {string} orientation
36598 	 */
36599 	DistributeElements$1.prototype.trigger = function(elements, orientation) {
36600 	  var modeling = this._modeling;
36601 
36602 	  var groups,
36603 	      distributableElements;
36604 
36605 	  if (elements.length < 3) {
36606 	    return;
36607 	  }
36608 
36609 	  this._setOrientation(orientation);
36610 
36611 	  distributableElements = this._filterElements(elements);
36612 
36613 	  groups = this._createGroups(distributableElements);
36614 
36615 	  // nothing to distribute
36616 	  if (groups.length <= 2) {
36617 	    return;
36618 	  }
36619 
36620 	  modeling.distributeElements(groups, this._axis, this._dimension);
36621 
36622 	  return groups;
36623 	};
36624 
36625 	/**
36626 	 * Filters the elements with provided filters by external parties
36627 	 *
36628 	 * @param  {Array[Elements]} elements
36629 	 *
36630 	 * @return {Array[Elements]}
36631 	 */
36632 	DistributeElements$1.prototype._filterElements = function(elements) {
36633 	  var filters = this._filters,
36634 	      axis = this._axis,
36635 	      dimension = this._dimension,
36636 	      distributableElements = [].concat(elements);
36637 
36638 	  if (!filters.length) {
36639 	    return elements;
36640 	  }
36641 
36642 	  forEach(filters, function(filterFn) {
36643 	    distributableElements = filterFn(distributableElements, axis, dimension);
36644 	  });
36645 
36646 	  return distributableElements;
36647 	};
36648 
36649 
36650 	/**
36651 	 * Create range (min, max) groups. Also tries to group elements
36652 	 * together that share the same range.
36653 	 *
36654 	 * @example
36655 	 * 	var distributableElements = [
36656 	 * 		{
36657 	 * 			range: {
36658 	 * 				min: 100,
36659 	 * 				max: 200
36660 	 * 			},
36661 	 * 			elements: [ { id: 'shape1', .. }]
36662 	 * 		}
36663 	 * 	]
36664 	 *
36665 	 * @param  {Array} elements
36666 	 *
36667 	 * @return {Array[Objects]}
36668 	 */
36669 	DistributeElements$1.prototype._createGroups = function(elements) {
36670 	  var rangeGroups = [],
36671 	      self = this,
36672 	      axis = this._axis,
36673 	      dimension = this._dimension;
36674 
36675 	  if (!axis) {
36676 	    throw new Error('must have a defined "axis" and "dimension"');
36677 	  }
36678 
36679 	  // sort by 'left->right' or 'top->bottom'
36680 	  var sortedElements = sortBy(elements, axis);
36681 
36682 	  forEach(sortedElements, function(element, idx) {
36683 	    var elementRange = self._findRange(element, axis, dimension),
36684 	        range;
36685 
36686 	    var previous = rangeGroups[rangeGroups.length - 1];
36687 
36688 	    if (previous && self._hasIntersection(previous.range, elementRange)) {
36689 	      rangeGroups[rangeGroups.length - 1].elements.push(element);
36690 	    } else {
36691 	      range = { range: elementRange, elements: [ element ] };
36692 
36693 	      rangeGroups.push(range);
36694 	    }
36695 	  });
36696 
36697 	  return rangeGroups;
36698 	};
36699 
36700 
36701 	/**
36702 	 * Maps a direction to the according axis and dimension
36703 	 *
36704 	 * @param  {string} direction 'horizontal' or 'vertical'
36705 	 */
36706 	DistributeElements$1.prototype._setOrientation = function(direction) {
36707 	  var orientation = AXIS_DIMENSIONS[direction];
36708 
36709 	  this._axis = orientation[0];
36710 	  this._dimension = orientation[1];
36711 	};
36712 
36713 
36714 	/**
36715 	 * Checks if the two ranges intercept each other
36716 	 *
36717 	 * @param  {Object} rangeA {min, max}
36718 	 * @param  {Object} rangeB {min, max}
36719 	 *
36720 	 * @return {boolean}
36721 	 */
36722 	DistributeElements$1.prototype._hasIntersection = function(rangeA, rangeB) {
36723 	  return Math.max(rangeA.min, rangeA.max) >= Math.min(rangeB.min, rangeB.max) &&
36724 	         Math.min(rangeA.min, rangeA.max) <= Math.max(rangeB.min, rangeB.max);
36725 	};
36726 
36727 
36728 	/**
36729 	 * Returns the min and max values for an element
36730 	 *
36731 	 * @param  {Bounds} element
36732 	 * @param  {string} axis
36733 	 * @param  {string} dimension
36734 	 *
36735 	 * @return {{ min: number, max: number }}
36736 	 */
36737 	DistributeElements$1.prototype._findRange = function(element) {
36738 	  var axis = element[this._axis],
36739 	      dimension = element[this._dimension];
36740 
36741 	  return {
36742 	    min: axis + THRESHOLD,
36743 	    max: axis + dimension - THRESHOLD
36744 	  };
36745 	};
36746 
36747 	var DistributeElementsModule$1 = {
36748 	  __init__: [ 'distributeElements' ],
36749 	  distributeElements: [ 'type', DistributeElements$1 ]
36750 	};
36751 
36752 	/**
36753 	 * Registers element exclude filters for elements that
36754 	 * currently do not support distribution.
36755 	 */
36756 	function BpmnDistributeElements(distributeElements) {
36757 
36758 	  distributeElements.registerFilter(function(elements) {
36759 	    return filter(elements, function(element) {
36760 	      var cannotDistribute = isAny(element, [
36761 	        'bpmn:Association',
36762 	        'bpmn:BoundaryEvent',
36763 	        'bpmn:DataInputAssociation',
36764 	        'bpmn:DataOutputAssociation',
36765 	        'bpmn:Lane',
36766 	        'bpmn:MessageFlow',
36767 	        'bpmn:Participant',
36768 	        'bpmn:SequenceFlow',
36769 	        'bpmn:TextAnnotation'
36770 	      ]);
36771 
36772 	      return !(element.labelTarget || cannotDistribute);
36773 	    });
36774 	  });
36775 	}
36776 
36777 	BpmnDistributeElements.$inject = [ 'distributeElements' ];
36778 
36779 	var DistributeElementsModule = {
36780 	  __depends__: [
36781 	    DistributeElementsModule$1
36782 	  ],
36783 	  __init__: [ 'bpmnDistributeElements' ],
36784 	  bpmnDistributeElements: [ 'type', BpmnDistributeElements ]
36785 	};
36786 
36787 	var NOT_REGISTERED_ERROR = 'is not a registered action',
36788 	    IS_REGISTERED_ERROR = 'is already registered';
36789 
36790 
36791 	/**
36792 	 * An interface that provides access to modeling actions by decoupling
36793 	 * the one who requests the action to be triggered and the trigger itself.
36794 	 *
36795 	 * It's possible to add new actions by registering them with ´registerAction´
36796 	 * and likewise unregister existing ones with ´unregisterAction´.
36797 	 *
36798 	 *
36799 	 * ## Life-Cycle and configuration
36800 	 *
36801 	 * The editor actions will wait for diagram initialization before
36802 	 * registering default actions _and_ firing an `editorActions.init` event.
36803 	 *
36804 	 * Interested parties may listen to the `editorActions.init` event with
36805 	 * low priority to check, which actions got registered. Other components
36806 	 * may use the event to register their own actions via `registerAction`.
36807 	 *
36808 	 * @param {EventBus} eventBus
36809 	 * @param {Injector} injector
36810 	 */
36811 	function EditorActions(eventBus, injector) {
36812 
36813 	  // initialize actions
36814 	  this._actions = {};
36815 
36816 	  var self = this;
36817 
36818 	  eventBus.on('diagram.init', function() {
36819 
36820 	    // all diagram modules got loaded; check which ones
36821 	    // are available and register the respective default actions
36822 	    self._registerDefaultActions(injector);
36823 
36824 	    // ask interested parties to register available editor
36825 	    // actions on diagram initialization
36826 	    eventBus.fire('editorActions.init', {
36827 	      editorActions: self
36828 	    });
36829 	  });
36830 
36831 	}
36832 
36833 	EditorActions.$inject = [
36834 	  'eventBus',
36835 	  'injector'
36836 	];
36837 
36838 	/**
36839 	 * Register default actions.
36840 	 *
36841 	 * @param {Injector} injector
36842 	 */
36843 	EditorActions.prototype._registerDefaultActions = function(injector) {
36844 
36845 	  // (1) retrieve optional components to integrate with
36846 
36847 	  var commandStack = injector.get('commandStack', false);
36848 	  var modeling = injector.get('modeling', false);
36849 	  var selection = injector.get('selection', false);
36850 	  var zoomScroll = injector.get('zoomScroll', false);
36851 	  var copyPaste = injector.get('copyPaste', false);
36852 	  var canvas = injector.get('canvas', false);
36853 	  var rules = injector.get('rules', false);
36854 	  var keyboardMove = injector.get('keyboardMove', false);
36855 	  var keyboardMoveSelection = injector.get('keyboardMoveSelection', false);
36856 
36857 	  // (2) check components and register actions
36858 
36859 	  if (commandStack) {
36860 	    this.register('undo', function() {
36861 	      commandStack.undo();
36862 	    });
36863 
36864 	    this.register('redo', function() {
36865 	      commandStack.redo();
36866 	    });
36867 	  }
36868 
36869 	  if (copyPaste && selection) {
36870 	    this.register('copy', function() {
36871 	      var selectedElements = selection.get();
36872 
36873 	      copyPaste.copy(selectedElements);
36874 	    });
36875 	  }
36876 
36877 	  if (copyPaste) {
36878 	    this.register('paste', function() {
36879 	      copyPaste.paste();
36880 	    });
36881 	  }
36882 
36883 	  if (zoomScroll) {
36884 	    this.register('stepZoom', function(opts) {
36885 	      zoomScroll.stepZoom(opts.value);
36886 	    });
36887 	  }
36888 
36889 	  if (canvas) {
36890 	    this.register('zoom', function(opts) {
36891 	      canvas.zoom(opts.value);
36892 	    });
36893 	  }
36894 
36895 	  if (modeling && selection && rules) {
36896 	    this.register('removeSelection', function() {
36897 
36898 	      var selectedElements = selection.get();
36899 
36900 	      if (!selectedElements.length) {
36901 	        return;
36902 	      }
36903 
36904 	      var allowed = rules.allowed('elements.delete', { elements: selectedElements }),
36905 	          removableElements;
36906 
36907 	      if (allowed === false) {
36908 	        return;
36909 	      }
36910 	      else if (isArray$2(allowed)) {
36911 	        removableElements = allowed;
36912 	      }
36913 	      else {
36914 	        removableElements = selectedElements;
36915 	      }
36916 
36917 	      if (removableElements.length) {
36918 	        modeling.removeElements(removableElements.slice());
36919 	      }
36920 	    });
36921 	  }
36922 
36923 	  if (keyboardMove) {
36924 	    this.register('moveCanvas', function(opts) {
36925 	      keyboardMove.moveCanvas(opts);
36926 	    });
36927 	  }
36928 
36929 	  if (keyboardMoveSelection) {
36930 	    this.register('moveSelection', function(opts) {
36931 	      keyboardMoveSelection.moveSelection(opts.direction, opts.accelerated);
36932 	    });
36933 	  }
36934 
36935 	};
36936 
36937 
36938 	/**
36939 	 * Triggers a registered action
36940 	 *
36941 	 * @param  {string} action
36942 	 * @param  {Object} opts
36943 	 *
36944 	 * @return {Unknown} Returns what the registered listener returns
36945 	 */
36946 	EditorActions.prototype.trigger = function(action, opts) {
36947 	  if (!this._actions[action]) {
36948 	    throw error(action, NOT_REGISTERED_ERROR);
36949 	  }
36950 
36951 	  return this._actions[action](opts);
36952 	};
36953 
36954 
36955 	/**
36956 	 * Registers a collections of actions.
36957 	 * The key of the object will be the name of the action.
36958 	 *
36959 	 * @example
36960 	 * ´´´
36961 	 * var actions = {
36962 	 *   spaceTool: function() {
36963 	 *     spaceTool.activateSelection();
36964 	 *   },
36965 	 *   lassoTool: function() {
36966 	 *     lassoTool.activateSelection();
36967 	 *   }
36968 	 * ];
36969 	 *
36970 	 * editorActions.register(actions);
36971 	 *
36972 	 * editorActions.isRegistered('spaceTool'); // true
36973 	 * ´´´
36974 	 *
36975 	 * @param  {Object} actions
36976 	 */
36977 	EditorActions.prototype.register = function(actions, listener) {
36978 	  var self = this;
36979 
36980 	  if (typeof actions === 'string') {
36981 	    return this._registerAction(actions, listener);
36982 	  }
36983 
36984 	  forEach(actions, function(listener, action) {
36985 	    self._registerAction(action, listener);
36986 	  });
36987 	};
36988 
36989 	/**
36990 	 * Registers a listener to an action key
36991 	 *
36992 	 * @param  {string} action
36993 	 * @param  {Function} listener
36994 	 */
36995 	EditorActions.prototype._registerAction = function(action, listener) {
36996 	  if (this.isRegistered(action)) {
36997 	    throw error(action, IS_REGISTERED_ERROR);
36998 	  }
36999 
37000 	  this._actions[action] = listener;
37001 	};
37002 
37003 	/**
37004 	 * Unregister an existing action
37005 	 *
37006 	 * @param {string} action
37007 	 */
37008 	EditorActions.prototype.unregister = function(action) {
37009 	  if (!this.isRegistered(action)) {
37010 	    throw error(action, NOT_REGISTERED_ERROR);
37011 	  }
37012 
37013 	  this._actions[action] = undefined;
37014 	};
37015 
37016 	/**
37017 	 * Returns the number of actions that are currently registered
37018 	 *
37019 	 * @return {number}
37020 	 */
37021 	EditorActions.prototype.getActions = function() {
37022 	  return Object.keys(this._actions);
37023 	};
37024 
37025 	/**
37026 	 * Checks wether the given action is registered
37027 	 *
37028 	 * @param {string} action
37029 	 *
37030 	 * @return {boolean}
37031 	 */
37032 	EditorActions.prototype.isRegistered = function(action) {
37033 	  return !!this._actions[action];
37034 	};
37035 
37036 
37037 	function error(action, message) {
37038 	  return new Error(action + ' ' + message);
37039 	}
37040 
37041 	var EditorActionsModule$1 = {
37042 	  __init__: [ 'editorActions' ],
37043 	  editorActions: [ 'type', EditorActions ]
37044 	};
37045 
37046 	/**
37047 	 * Registers and executes BPMN specific editor actions.
37048 	 *
37049 	 * @param {Injector} injector
37050 	 */
37051 	function BpmnEditorActions(injector) {
37052 	  injector.invoke(EditorActions, this);
37053 	}
37054 
37055 	inherits$1(BpmnEditorActions, EditorActions);
37056 
37057 	BpmnEditorActions.$inject = [
37058 	  'injector'
37059 	];
37060 
37061 	/**
37062 	 * Register default actions.
37063 	 *
37064 	 * @param {Injector} injector
37065 	 */
37066 	BpmnEditorActions.prototype._registerDefaultActions = function(injector) {
37067 
37068 	  // (0) invoke super method
37069 
37070 	  EditorActions.prototype._registerDefaultActions.call(this, injector);
37071 
37072 	  // (1) retrieve optional components to integrate with
37073 
37074 	  var canvas = injector.get('canvas', false);
37075 	  var elementRegistry = injector.get('elementRegistry', false);
37076 	  var selection = injector.get('selection', false);
37077 	  var spaceTool = injector.get('spaceTool', false);
37078 	  var lassoTool = injector.get('lassoTool', false);
37079 	  var handTool = injector.get('handTool', false);
37080 	  var globalConnect = injector.get('globalConnect', false);
37081 	  var distributeElements = injector.get('distributeElements', false);
37082 	  var alignElements = injector.get('alignElements', false);
37083 	  var directEditing = injector.get('directEditing', false);
37084 	  var searchPad = injector.get('searchPad', false);
37085 	  var modeling = injector.get('modeling', false);
37086 
37087 	  // (2) check components and register actions
37088 
37089 	  if (canvas && elementRegistry && selection) {
37090 	    this._registerAction('selectElements', function() {
37091 
37092 	      // select all elements except for the invisible
37093 	      // root element
37094 	      var rootElement = canvas.getRootElement();
37095 
37096 	      var elements = elementRegistry.filter(function(element) {
37097 	        return element !== rootElement;
37098 	      });
37099 
37100 	      selection.select(elements);
37101 
37102 	      return elements;
37103 	    });
37104 	  }
37105 
37106 	  if (spaceTool) {
37107 	    this._registerAction('spaceTool', function() {
37108 	      spaceTool.toggle();
37109 	    });
37110 	  }
37111 
37112 	  if (lassoTool) {
37113 	    this._registerAction('lassoTool', function() {
37114 	      lassoTool.toggle();
37115 	    });
37116 	  }
37117 
37118 	  if (handTool) {
37119 	    this._registerAction('handTool', function() {
37120 	      handTool.toggle();
37121 	    });
37122 	  }
37123 
37124 	  if (globalConnect) {
37125 	    this._registerAction('globalConnectTool', function() {
37126 	      globalConnect.toggle();
37127 	    });
37128 	  }
37129 
37130 	  if (selection && distributeElements) {
37131 	    this._registerAction('distributeElements', function(opts) {
37132 	      var currentSelection = selection.get(),
37133 	          type = opts.type;
37134 
37135 	      if (currentSelection.length) {
37136 	        distributeElements.trigger(currentSelection, type);
37137 	      }
37138 	    });
37139 	  }
37140 
37141 	  if (selection && alignElements) {
37142 	    this._registerAction('alignElements', function(opts) {
37143 	      var currentSelection = selection.get(),
37144 	          aligneableElements = [],
37145 	          type = opts.type;
37146 
37147 	      if (currentSelection.length) {
37148 	        aligneableElements = filter(currentSelection, function(element) {
37149 	          return !is$1(element, 'bpmn:Lane');
37150 	        });
37151 
37152 	        alignElements.trigger(aligneableElements, type);
37153 	      }
37154 	    });
37155 	  }
37156 
37157 	  if (selection && modeling) {
37158 	    this._registerAction('setColor', function(opts) {
37159 	      var currentSelection = selection.get();
37160 
37161 	      if (currentSelection.length) {
37162 	        modeling.setColor(currentSelection, opts);
37163 	      }
37164 	    });
37165 	  }
37166 
37167 	  if (selection && directEditing) {
37168 	    this._registerAction('directEditing', function() {
37169 	      var currentSelection = selection.get();
37170 
37171 	      if (currentSelection.length) {
37172 	        directEditing.activate(currentSelection[0]);
37173 	      }
37174 	    });
37175 	  }
37176 
37177 	  if (searchPad) {
37178 	    this._registerAction('find', function() {
37179 	      searchPad.toggle();
37180 	    });
37181 	  }
37182 
37183 	  if (canvas && modeling) {
37184 	    this._registerAction('moveToOrigin', function() {
37185 	      var rootElement = canvas.getRootElement(),
37186 	          boundingBox,
37187 	          elements;
37188 
37189 	      if (is$1(rootElement, 'bpmn:Collaboration')) {
37190 	        elements = elementRegistry.filter(function(element) {
37191 	          return is$1(element.parent, 'bpmn:Collaboration');
37192 	        });
37193 	      } else {
37194 	        elements = elementRegistry.filter(function(element) {
37195 	          return element !== rootElement && !is$1(element.parent, 'bpmn:SubProcess');
37196 	        });
37197 	      }
37198 
37199 	      boundingBox = getBBox(elements);
37200 
37201 	      modeling.moveElements(
37202 	        elements,
37203 	        { x: -boundingBox.x, y: -boundingBox.y },
37204 	        rootElement
37205 	      );
37206 	    });
37207 	  }
37208 
37209 	};
37210 
37211 	var EditorActionsModule = {
37212 	  __depends__: [
37213 	    EditorActionsModule$1
37214 	  ],
37215 	  editorActions: [ 'type', BpmnEditorActions ]
37216 	};
37217 
37218 	function BpmnGridSnapping(eventBus) {
37219 	  eventBus.on([
37220 	    'create.init',
37221 	    'shape.move.init'
37222 	  ], function(event) {
37223 	    var context = event.context,
37224 	        shape = event.shape;
37225 
37226 	    if (isAny(shape, [
37227 	      'bpmn:Participant',
37228 	      'bpmn:SubProcess',
37229 	      'bpmn:TextAnnotation'
37230 	    ])) {
37231 	      if (!context.gridSnappingContext) {
37232 	        context.gridSnappingContext = {};
37233 	      }
37234 
37235 	      context.gridSnappingContext.snapLocation = 'top-left';
37236 	    }
37237 	  });
37238 	}
37239 
37240 	BpmnGridSnapping.$inject = [ 'eventBus' ];
37241 
37242 	var SPACING = 10;
37243 
37244 	function quantize(value, quantum, fn) {
37245 	  if (!fn) {
37246 	    fn = 'round';
37247 	  }
37248 
37249 	  return Math[ fn ](value / quantum) * quantum;
37250 	}
37251 
37252 	var LOWER_PRIORITY = 1200;
37253 	var LOW_PRIORITY$e = 800;
37254 
37255 	/**
37256 	 * Basic grid snapping that covers connecting, creating, moving, resizing shapes, moving bendpoints
37257 	 * and connection segments.
37258 	 */
37259 	function GridSnapping(elementRegistry, eventBus, config) {
37260 
37261 	  var active = !config || config.active !== false;
37262 
37263 	  this._eventBus = eventBus;
37264 
37265 	  var self = this;
37266 
37267 	  eventBus.on('diagram.init', LOW_PRIORITY$e, function() {
37268 	    self.setActive(active);
37269 	  });
37270 
37271 	  eventBus.on([
37272 	    'create.move',
37273 	    'create.end',
37274 	    'bendpoint.move.move',
37275 	    'bendpoint.move.end',
37276 	    'connect.move',
37277 	    'connect.end',
37278 	    'connectionSegment.move.move',
37279 	    'connectionSegment.move.end',
37280 	    'resize.move',
37281 	    'resize.end',
37282 	    'shape.move.move',
37283 	    'shape.move.end'
37284 	  ], LOWER_PRIORITY, function(event) {
37285 	    var originalEvent = event.originalEvent;
37286 
37287 	    if (!self.active || (originalEvent && isCmd(originalEvent))) {
37288 	      return;
37289 	    }
37290 
37291 	    var context = event.context,
37292 	        gridSnappingContext = context.gridSnappingContext;
37293 
37294 	    if (!gridSnappingContext) {
37295 	      gridSnappingContext = context.gridSnappingContext = {};
37296 	    }
37297 
37298 	    [ 'x', 'y' ].forEach(function(axis) {
37299 	      var options = {};
37300 
37301 	      // allow snapping with offset
37302 	      var snapOffset = getSnapOffset(event, axis, elementRegistry);
37303 
37304 	      if (snapOffset) {
37305 	        options.offset = snapOffset;
37306 	      }
37307 
37308 	      // allow snapping with min and max
37309 	      var snapConstraints = getSnapConstraints(event, axis);
37310 
37311 	      if (snapConstraints) {
37312 	        assign(options, snapConstraints);
37313 	      }
37314 
37315 	      if (!isSnapped(event, axis)) {
37316 	        self.snapEvent(event, axis, options);
37317 	      }
37318 	    });
37319 	  });
37320 	}
37321 
37322 	/**
37323 	 * Snap an events x or y with optional min, max and offset.
37324 	 *
37325 	 * @param {Object} event
37326 	 * @param {string} axis
37327 	 * @param {number} [options.min]
37328 	 * @param {number} [options.max]
37329 	 * @param {number} [options.offset]
37330 	 */
37331 	GridSnapping.prototype.snapEvent = function(event, axis, options) {
37332 	  var snappedValue = this.snapValue(event[ axis ], options);
37333 
37334 	  setSnapped(event, axis, snappedValue);
37335 	};
37336 
37337 	/**
37338 	 * Expose grid spacing for third parties (i.e. extensions).
37339 	 *
37340 	 * @return {number} spacing of grid dots
37341 	 */
37342 	GridSnapping.prototype.getGridSpacing = function() {
37343 	  return SPACING;
37344 	};
37345 
37346 	/**
37347 	 * Snap value with optional min, max and offset.
37348 	 *
37349 	 * @param {number} value
37350 	 * @param {Object} options
37351 	 * @param {number} [options.min]
37352 	 * @param {number} [options.max]
37353 	 * @param {number} [options.offset]
37354 	 */
37355 	GridSnapping.prototype.snapValue = function(value, options) {
37356 	  var offset = 0;
37357 
37358 	  if (options && options.offset) {
37359 	    offset = options.offset;
37360 	  }
37361 
37362 	  value += offset;
37363 
37364 	  value = quantize(value, SPACING);
37365 
37366 	  var min, max;
37367 
37368 	  if (options && options.min) {
37369 	    min = options.min;
37370 
37371 	    if (isNumber(min)) {
37372 	      min = quantize(min + offset, SPACING, 'ceil');
37373 
37374 	      value = Math.max(value, min);
37375 	    }
37376 	  }
37377 
37378 	  if (options && options.max) {
37379 	    max = options.max;
37380 
37381 	    if (isNumber(max)) {
37382 	      max = quantize(max + offset, SPACING, 'floor');
37383 
37384 	      value = Math.min(value, max);
37385 	    }
37386 	  }
37387 
37388 	  value -= offset;
37389 
37390 	  return value;
37391 	};
37392 
37393 	GridSnapping.prototype.isActive = function() {
37394 	  return this.active;
37395 	};
37396 
37397 	GridSnapping.prototype.setActive = function(active) {
37398 	  this.active = active;
37399 
37400 	  this._eventBus.fire('gridSnapping.toggle', { active: active });
37401 	};
37402 
37403 	GridSnapping.prototype.toggleActive = function() {
37404 	  this.setActive(!this.active);
37405 	};
37406 
37407 	GridSnapping.$inject = [
37408 	  'elementRegistry',
37409 	  'eventBus',
37410 	  'config.gridSnapping'
37411 	];
37412 
37413 	// helpers //////////
37414 
37415 	/**
37416 	 * Get minimum and maximum snap constraints.
37417 	 * Constraints are cached.
37418 	 *
37419 	 * @param {Object} event
37420 	 * @param {Object} event.context
37421 	 * @param {string} axis
37422 	 *
37423 	 * @returns {boolean|Object}
37424 	 */
37425 	function getSnapConstraints(event, axis) {
37426 	  var context = event.context,
37427 	      createConstraints = context.createConstraints,
37428 	      resizeConstraints = context.resizeConstraints || {},
37429 	      gridSnappingContext = context.gridSnappingContext,
37430 	      snapConstraints = gridSnappingContext.snapConstraints;
37431 
37432 	  // cache snap constraints
37433 	  if (snapConstraints && snapConstraints[ axis ]) {
37434 	    return snapConstraints[ axis ];
37435 	  }
37436 
37437 	  if (!snapConstraints) {
37438 	    snapConstraints = gridSnappingContext.snapConstraints = {};
37439 	  }
37440 
37441 	  if (!snapConstraints[ axis ]) {
37442 	    snapConstraints[ axis ] = {};
37443 	  }
37444 
37445 	  var direction = context.direction;
37446 
37447 	  // create
37448 	  if (createConstraints) {
37449 	    if (isHorizontal$3(axis)) {
37450 	      snapConstraints.x.min = createConstraints.left;
37451 	      snapConstraints.x.max = createConstraints.right;
37452 	    } else {
37453 	      snapConstraints.y.min = createConstraints.top;
37454 	      snapConstraints.y.max = createConstraints.bottom;
37455 	    }
37456 	  }
37457 
37458 	  // resize
37459 	  var minResizeConstraints = resizeConstraints.min,
37460 	      maxResizeConstraints = resizeConstraints.max;
37461 
37462 	  if (minResizeConstraints) {
37463 	    if (isHorizontal$3(axis)) {
37464 
37465 	      if (isWest(direction)) {
37466 	        snapConstraints.x.max = minResizeConstraints.left;
37467 	      } else {
37468 	        snapConstraints.x.min = minResizeConstraints.right;
37469 	      }
37470 
37471 	    } else {
37472 
37473 	      if (isNorth(direction)) {
37474 	        snapConstraints.y.max = minResizeConstraints.top;
37475 	      } else {
37476 	        snapConstraints.y.min = minResizeConstraints.bottom;
37477 	      }
37478 
37479 	    }
37480 	  }
37481 
37482 	  if (maxResizeConstraints) {
37483 	    if (isHorizontal$3(axis)) {
37484 
37485 	      if (isWest(direction)) {
37486 	        snapConstraints.x.min = maxResizeConstraints.left;
37487 	      } else {
37488 	        snapConstraints.x.max = maxResizeConstraints.right;
37489 	      }
37490 
37491 	    } else {
37492 
37493 	      if (isNorth(direction)) {
37494 	        snapConstraints.y.min = maxResizeConstraints.top;
37495 	      } else {
37496 	        snapConstraints.y.max = maxResizeConstraints.bottom;
37497 	      }
37498 
37499 	    }
37500 	  }
37501 
37502 	  return snapConstraints[ axis ];
37503 	}
37504 
37505 	/**
37506 	 * Get snap offset.
37507 	 * Offset is cached.
37508 	 *
37509 	 * @param {Object} event
37510 	 * @param {string} axis
37511 	 * @param {ElementRegistry} elementRegistry
37512 	 *
37513 	 * @returns {number}
37514 	 */
37515 	function getSnapOffset(event, axis, elementRegistry) {
37516 	  var context = event.context,
37517 	      shape = event.shape,
37518 	      gridSnappingContext = context.gridSnappingContext,
37519 	      snapLocation = gridSnappingContext.snapLocation,
37520 	      snapOffset = gridSnappingContext.snapOffset;
37521 
37522 	  // cache snap offset
37523 	  if (snapOffset && isNumber(snapOffset[ axis ])) {
37524 	    return snapOffset[ axis ];
37525 	  }
37526 
37527 	  if (!snapOffset) {
37528 	    snapOffset = gridSnappingContext.snapOffset = {};
37529 	  }
37530 
37531 	  if (!isNumber(snapOffset[ axis ])) {
37532 	    snapOffset[ axis ] = 0;
37533 	  }
37534 
37535 	  if (!shape) {
37536 	    return snapOffset[ axis ];
37537 	  }
37538 
37539 	  if (!elementRegistry.get(shape.id)) {
37540 
37541 	    if (isHorizontal$3(axis)) {
37542 	      snapOffset[ axis ] += shape[ axis ] + shape.width / 2;
37543 	    } else {
37544 	      snapOffset[ axis ] += shape[ axis ] + shape.height / 2;
37545 	    }
37546 	  }
37547 
37548 	  if (!snapLocation) {
37549 	    return snapOffset[ axis ];
37550 	  }
37551 
37552 	  if (axis === 'x') {
37553 	    if (/left/.test(snapLocation)) {
37554 	      snapOffset[ axis ] -= shape.width / 2;
37555 	    } else if (/right/.test(snapLocation)) {
37556 	      snapOffset[ axis ] += shape.width / 2;
37557 	    }
37558 	  } else {
37559 	    if (/top/.test(snapLocation)) {
37560 	      snapOffset[ axis ] -= shape.height / 2;
37561 	    } else if (/bottom/.test(snapLocation)) {
37562 	      snapOffset[ axis ] += shape.height / 2;
37563 	    }
37564 	  }
37565 
37566 	  return snapOffset[ axis ];
37567 	}
37568 
37569 	function isHorizontal$3(axis) {
37570 	  return axis === 'x';
37571 	}
37572 
37573 	function isNorth(direction) {
37574 	  return direction.indexOf('n') !== -1;
37575 	}
37576 
37577 	function isWest(direction) {
37578 	  return direction.indexOf('w') !== -1;
37579 	}
37580 
37581 	/**
37582 	 * Integrates resizing with grid snapping.
37583 	 */
37584 	function ResizeBehavior$1(eventBus, gridSnapping) {
37585 	  CommandInterceptor.call(this, eventBus);
37586 
37587 	  this._gridSnapping = gridSnapping;
37588 
37589 	  var self = this;
37590 
37591 	  this.preExecute('shape.resize', function(event) {
37592 	    var context = event.context,
37593 	        hints = context.hints || {},
37594 	        autoResize = hints.autoResize;
37595 
37596 	    if (!autoResize) {
37597 	      return;
37598 	    }
37599 
37600 	    var shape = context.shape,
37601 	        newBounds = context.newBounds;
37602 
37603 	    if (isString(autoResize)) {
37604 	      context.newBounds = self.snapComplex(newBounds, autoResize);
37605 	    } else {
37606 	      context.newBounds = self.snapSimple(shape, newBounds);
37607 	    }
37608 	  });
37609 	}
37610 
37611 	ResizeBehavior$1.$inject = [
37612 	  'eventBus',
37613 	  'gridSnapping',
37614 	  'modeling'
37615 	];
37616 
37617 	inherits$1(ResizeBehavior$1, CommandInterceptor);
37618 
37619 	/**
37620 	 * Snap width and height in relation to center.
37621 	 *
37622 	 * @param {djs.model.shape} shape
37623 	 * @param {Bounds} newBounds
37624 	 *
37625 	 * @returns {Bounds} Snapped bounds.
37626 	 */
37627 	ResizeBehavior$1.prototype.snapSimple = function(shape, newBounds) {
37628 	  var gridSnapping = this._gridSnapping;
37629 
37630 	  newBounds.width = gridSnapping.snapValue(newBounds.width, {
37631 	    min: newBounds.width
37632 	  });
37633 
37634 	  newBounds.height = gridSnapping.snapValue(newBounds.height, {
37635 	    min: newBounds.height
37636 	  });
37637 
37638 	  newBounds.x = shape.x + (shape.width / 2) - (newBounds.width / 2);
37639 	  newBounds.y = shape.y + (shape.height / 2) - (newBounds.height / 2);
37640 
37641 	  return newBounds;
37642 	};
37643 
37644 	/**
37645 	 * Snap x, y, width and height according to given directions.
37646 	 *
37647 	 * @param {Bounds} newBounds
37648 	 * @param {string} directions - Directions as {n|w|s|e}.
37649 	 *
37650 	 * @returns {Bounds} Snapped bounds.
37651 	 */
37652 	ResizeBehavior$1.prototype.snapComplex = function(newBounds, directions) {
37653 	  if (/w|e/.test(directions)) {
37654 	    newBounds = this.snapHorizontally(newBounds, directions);
37655 	  }
37656 
37657 	  if (/n|s/.test(directions)) {
37658 	    newBounds = this.snapVertically(newBounds, directions);
37659 	  }
37660 
37661 	  return newBounds;
37662 	};
37663 
37664 	/**
37665 	 * Snap in one or both directions horizontally.
37666 	 *
37667 	 * @param {Bounds} newBounds
37668 	 * @param {string} directions - Directions as {n|w|s|e}.
37669 	 *
37670 	 * @returns {Bounds} Snapped bounds.
37671 	 */
37672 	ResizeBehavior$1.prototype.snapHorizontally = function(newBounds, directions) {
37673 	  var gridSnapping = this._gridSnapping,
37674 	      west = /w/.test(directions),
37675 	      east = /e/.test(directions);
37676 
37677 	  var snappedNewBounds = {};
37678 
37679 	  snappedNewBounds.width = gridSnapping.snapValue(newBounds.width, {
37680 	    min: newBounds.width
37681 	  });
37682 
37683 	  if (east) {
37684 
37685 	    // handle <we>
37686 	    if (west) {
37687 	      snappedNewBounds.x = gridSnapping.snapValue(newBounds.x, {
37688 	        max: newBounds.x
37689 	      });
37690 
37691 	      snappedNewBounds.width += gridSnapping.snapValue(newBounds.x - snappedNewBounds.x, {
37692 	        min: newBounds.x - snappedNewBounds.x
37693 	      });
37694 	    }
37695 
37696 	    // handle <e>
37697 	    else {
37698 	      newBounds.x = newBounds.x + newBounds.width - snappedNewBounds.width;
37699 	    }
37700 	  }
37701 
37702 	  // assign snapped x and width
37703 	  assign(newBounds, snappedNewBounds);
37704 
37705 	  return newBounds;
37706 	};
37707 
37708 	/**
37709 	 * Snap in one or both directions vertically.
37710 	 *
37711 	 * @param {Bounds} newBounds
37712 	 * @param {string} directions - Directions as {n|w|s|e}.
37713 	 *
37714 	 * @returns {Bounds} Snapped bounds.
37715 	 */
37716 	ResizeBehavior$1.prototype.snapVertically = function(newBounds, directions) {
37717 	  var gridSnapping = this._gridSnapping,
37718 	      north = /n/.test(directions),
37719 	      south = /s/.test(directions);
37720 
37721 	  var snappedNewBounds = {};
37722 
37723 	  snappedNewBounds.height = gridSnapping.snapValue(newBounds.height, {
37724 	    min: newBounds.height
37725 	  });
37726 
37727 	  if (north) {
37728 
37729 	    // handle <ns>
37730 	    if (south) {
37731 	      snappedNewBounds.y = gridSnapping.snapValue(newBounds.y, {
37732 	        max: newBounds.y
37733 	      });
37734 
37735 	      snappedNewBounds.height += gridSnapping.snapValue(newBounds.y - snappedNewBounds.y, {
37736 	        min: newBounds.y - snappedNewBounds.y
37737 	      });
37738 	    }
37739 
37740 	    // handle <n>
37741 	    else {
37742 	      newBounds.y = newBounds.y + newBounds.height - snappedNewBounds.height;
37743 	    }
37744 	  }
37745 
37746 	  // assign snapped y and height
37747 	  assign(newBounds, snappedNewBounds);
37748 
37749 	  return newBounds;
37750 	};
37751 
37752 	var HIGH_PRIORITY$f = 2000;
37753 
37754 	/**
37755 	 * Integrates space tool with grid snapping.
37756 	 */
37757 	function SpaceToolBehavior$1(eventBus, gridSnapping) {
37758 	  eventBus.on([
37759 	    'spaceTool.move',
37760 	    'spaceTool.end'
37761 	  ], HIGH_PRIORITY$f, function(event) {
37762 	    var context = event.context;
37763 
37764 	    if (!context.initialized) {
37765 	      return;
37766 	    }
37767 
37768 	    var axis = context.axis;
37769 
37770 	    var snapped;
37771 
37772 	    if (axis === 'x') {
37773 
37774 	      // snap delta x to multiple of 10
37775 	      snapped = gridSnapping.snapValue(event.dx);
37776 
37777 	      event.x = event.x + snapped - event.dx;
37778 	      event.dx = snapped;
37779 	    } else {
37780 
37781 	      // snap delta y to multiple of 10
37782 	      snapped = gridSnapping.snapValue(event.dy);
37783 
37784 	      event.y = event.y + snapped - event.dy;
37785 	      event.dy = snapped;
37786 	    }
37787 	  });
37788 	}
37789 
37790 	SpaceToolBehavior$1.$inject = [
37791 	  'eventBus',
37792 	  'gridSnapping'
37793 	];
37794 
37795 	var GridSnappingBehaviorModule$1 = {
37796 	  __init__: [
37797 	    'gridSnappingResizeBehavior',
37798 	    'gridSnappingSpaceToolBehavior'
37799 	  ],
37800 	  gridSnappingResizeBehavior: [ 'type', ResizeBehavior$1 ],
37801 	  gridSnappingSpaceToolBehavior: [ 'type', SpaceToolBehavior$1 ]
37802 	};
37803 
37804 	var GridSnappingModule$1 = {
37805 	  __depends__: [ GridSnappingBehaviorModule$1 ],
37806 	  __init__: [ 'gridSnapping' ],
37807 	  gridSnapping: [ 'type', GridSnapping ]
37808 	};
37809 
37810 	var HIGH_PRIORITY$e = 2000;
37811 
37812 
37813 	function AutoPlaceBehavior(eventBus, gridSnapping) {
37814 	  eventBus.on('autoPlace', HIGH_PRIORITY$e, function(context) {
37815 	    var source = context.source,
37816 	        sourceMid = getMid(source),
37817 	        shape = context.shape;
37818 
37819 	    var position = getNewShapePosition(source, shape);
37820 
37821 	    [ 'x', 'y' ].forEach(function(axis) {
37822 	      var options = {};
37823 
37824 	      // do not snap if x/y equal
37825 	      if (position[ axis ] === sourceMid[ axis ]) {
37826 	        return;
37827 	      }
37828 
37829 	      if (position[ axis ] > sourceMid[ axis ]) {
37830 	        options.min = position[ axis ];
37831 	      } else {
37832 	        options.max = position[ axis ];
37833 	      }
37834 
37835 	      if (is$1(shape, 'bpmn:TextAnnotation')) {
37836 
37837 	        if (isHorizontal$2(axis)) {
37838 	          options.offset = -shape.width / 2;
37839 	        } else {
37840 	          options.offset = -shape.height / 2;
37841 	        }
37842 
37843 	      }
37844 
37845 	      position[ axis ] = gridSnapping.snapValue(position[ axis ], options);
37846 
37847 	    });
37848 
37849 	    // must be returned to be considered by auto place
37850 	    return position;
37851 	  });
37852 	}
37853 
37854 	AutoPlaceBehavior.$inject = [
37855 	  'eventBus',
37856 	  'gridSnapping'
37857 	];
37858 
37859 	// helpers //////////
37860 
37861 	function isHorizontal$2(axis) {
37862 	  return axis === 'x';
37863 	}
37864 
37865 	var HIGHER_PRIORITY$4 = 1750;
37866 
37867 
37868 	function CreateParticipantBehavior$1(canvas, eventBus, gridSnapping) {
37869 	  eventBus.on([
37870 	    'create.start',
37871 	    'shape.move.start'
37872 	  ], HIGHER_PRIORITY$4, function(event) {
37873 	    var context = event.context,
37874 	        shape = context.shape,
37875 	        rootElement = canvas.getRootElement();
37876 
37877 	    if (!is$1(shape, 'bpmn:Participant') ||
37878 	      !is$1(rootElement, 'bpmn:Process') ||
37879 	      !rootElement.children.length) {
37880 	      return;
37881 	    }
37882 
37883 	    var createConstraints = context.createConstraints;
37884 
37885 	    if (!createConstraints) {
37886 	      return;
37887 	    }
37888 
37889 	    shape.width = gridSnapping.snapValue(shape.width, { min: shape.width });
37890 	    shape.height = gridSnapping.snapValue(shape.height, { min: shape.height });
37891 	  });
37892 	}
37893 
37894 	CreateParticipantBehavior$1.$inject = [
37895 	  'canvas',
37896 	  'eventBus',
37897 	  'gridSnapping'
37898 	];
37899 
37900 	var HIGH_PRIORITY$d = 3000;
37901 
37902 
37903 	/**
37904 	 * Snaps connections with Manhattan layout.
37905 	 */
37906 	function LayoutConnectionBehavior(eventBus, gridSnapping, modeling) {
37907 	  CommandInterceptor.call(this, eventBus);
37908 
37909 	  this._gridSnapping = gridSnapping;
37910 
37911 	  var self = this;
37912 
37913 	  this.postExecuted([
37914 	    'connection.create',
37915 	    'connection.layout'
37916 	  ], HIGH_PRIORITY$d, function(event) {
37917 	    var context = event.context,
37918 	        connection = context.connection,
37919 	        hints = context.hints || {},
37920 	        waypoints = connection.waypoints;
37921 
37922 	    if (hints.connectionStart || hints.connectionEnd || hints.createElementsBehavior === false) {
37923 	      return;
37924 	    }
37925 
37926 	    if (!hasMiddleSegments(waypoints)) {
37927 	      return;
37928 	    }
37929 
37930 	    modeling.updateWaypoints(connection, self.snapMiddleSegments(waypoints));
37931 	  });
37932 	}
37933 
37934 	LayoutConnectionBehavior.$inject = [
37935 	  'eventBus',
37936 	  'gridSnapping',
37937 	  'modeling'
37938 	];
37939 
37940 	inherits$1(LayoutConnectionBehavior, CommandInterceptor);
37941 
37942 	/**
37943 	 * Snap middle segments of a given connection.
37944 	 *
37945 	 * @param {Array<Point>} waypoints
37946 	 *
37947 	 * @returns {Array<Point>}
37948 	 */
37949 	LayoutConnectionBehavior.prototype.snapMiddleSegments = function(waypoints) {
37950 	  var gridSnapping = this._gridSnapping,
37951 	      snapped;
37952 
37953 	  waypoints = waypoints.slice();
37954 
37955 	  for (var i = 1; i < waypoints.length - 2; i++) {
37956 
37957 	    snapped = snapSegment(gridSnapping, waypoints[i], waypoints[i + 1]);
37958 
37959 	    waypoints[i] = snapped[0];
37960 	    waypoints[i + 1] = snapped[1];
37961 	  }
37962 
37963 	  return waypoints;
37964 	};
37965 
37966 
37967 	// helpers //////////
37968 
37969 	/**
37970 	 * Check whether a connection has a middle segments.
37971 	 *
37972 	 * @param {Array} waypoints
37973 	 *
37974 	 * @returns {boolean}
37975 	 */
37976 	function hasMiddleSegments(waypoints) {
37977 	  return waypoints.length > 3;
37978 	}
37979 
37980 	/**
37981 	 * Check whether an alignment is horizontal.
37982 	 *
37983 	 * @param {string} aligned
37984 	 *
37985 	 * @returns {boolean}
37986 	 */
37987 	function horizontallyAligned(aligned) {
37988 	  return aligned === 'h';
37989 	}
37990 
37991 	/**
37992 	 * Check whether an alignment is vertical.
37993 	 *
37994 	 * @param {string} aligned
37995 	 *
37996 	 * @returns {boolean}
37997 	 */
37998 	function verticallyAligned(aligned) {
37999 	  return aligned === 'v';
38000 	}
38001 
38002 	/**
38003 	 * Get middle segments from a given connection.
38004 	 *
38005 	 * @param {Array} waypoints
38006 	 *
38007 	 * @returns {Array}
38008 	 */
38009 	function snapSegment(gridSnapping, segmentStart, segmentEnd) {
38010 
38011 	  var aligned = pointsAligned(segmentStart, segmentEnd);
38012 
38013 	  var snapped = {};
38014 
38015 	  if (horizontallyAligned(aligned)) {
38016 
38017 	    // snap horizontally
38018 	    snapped.y = gridSnapping.snapValue(segmentStart.y);
38019 	  }
38020 
38021 	  if (verticallyAligned(aligned)) {
38022 
38023 	    // snap vertically
38024 	    snapped.x = gridSnapping.snapValue(segmentStart.x);
38025 	  }
38026 
38027 	  if ('x' in snapped || 'y' in snapped) {
38028 	    segmentStart = assign({}, segmentStart, snapped);
38029 	    segmentEnd = assign({}, segmentEnd, snapped);
38030 	  }
38031 
38032 	  return [ segmentStart, segmentEnd ];
38033 	}
38034 
38035 	var GridSnappingBehaviorModule = {
38036 	  __init__: [
38037 	    'gridSnappingAutoPlaceBehavior',
38038 	    'gridSnappingCreateParticipantBehavior',
38039 	    'gridSnappingLayoutConnectionBehavior',
38040 	  ],
38041 	  gridSnappingAutoPlaceBehavior: [ 'type', AutoPlaceBehavior ],
38042 	  gridSnappingCreateParticipantBehavior: [ 'type', CreateParticipantBehavior$1 ],
38043 	  gridSnappingLayoutConnectionBehavior: [ 'type', LayoutConnectionBehavior ]
38044 	};
38045 
38046 	var GridSnappingModule = {
38047 	  __depends__: [
38048 	    GridSnappingModule$1,
38049 	    GridSnappingBehaviorModule
38050 	  ],
38051 	  __init__: [ 'bpmnGridSnapping' ],
38052 	  bpmnGridSnapping: [ 'type', BpmnGridSnapping ]
38053 	};
38054 
38055 	var LABEL_WIDTH = 30,
38056 	    LABEL_HEIGHT = 30;
38057 
38058 
38059 	/**
38060 	 * BPMN-specific hit zones and interaction fixes.
38061 	 *
38062 	 * @param {EventBus} eventBus
38063 	 * @param {InteractionEvents} interactionEvents
38064 	 */
38065 	function BpmnInteractionEvents(eventBus, interactionEvents) {
38066 
38067 	  this._interactionEvents = interactionEvents;
38068 
38069 	  var self = this;
38070 
38071 	  eventBus.on([
38072 	    'interactionEvents.createHit',
38073 	    'interactionEvents.updateHit'
38074 	  ], function(context) {
38075 	    var element = context.element,
38076 	        gfx = context.gfx;
38077 
38078 	    if (is$1(element, 'bpmn:Lane')) {
38079 	      return self.createParticipantHit(element, gfx);
38080 	    } else
38081 
38082 	    if (is$1(element, 'bpmn:Participant')) {
38083 	      if (isExpanded(element)) {
38084 	        return self.createParticipantHit(element, gfx);
38085 	      } else {
38086 	        return self.createDefaultHit(element, gfx);
38087 	      }
38088 	    } else
38089 
38090 	    if (is$1(element, 'bpmn:SubProcess')) {
38091 	      if (isExpanded(element)) {
38092 	        return self.createSubProcessHit(element, gfx);
38093 	      } else {
38094 	        return self.createDefaultHit(element, gfx);
38095 	      }
38096 	    }
38097 	  });
38098 
38099 	}
38100 
38101 	BpmnInteractionEvents.$inject = [
38102 	  'eventBus',
38103 	  'interactionEvents'
38104 	];
38105 
38106 
38107 	BpmnInteractionEvents.prototype.createDefaultHit = function(element, gfx) {
38108 	  this._interactionEvents.removeHits(gfx);
38109 
38110 	  this._interactionEvents.createDefaultHit(element, gfx);
38111 
38112 	  // indicate that we created a hit
38113 	  return true;
38114 	};
38115 
38116 	BpmnInteractionEvents.prototype.createParticipantHit = function(element, gfx) {
38117 
38118 	  // remove existing hits
38119 	  this._interactionEvents.removeHits(gfx);
38120 
38121 	  // add outline hit
38122 	  this._interactionEvents.createBoxHit(gfx, 'click-stroke', {
38123 	    width: element.width,
38124 	    height: element.height
38125 	  });
38126 
38127 	  // add label hit
38128 	  this._interactionEvents.createBoxHit(gfx, 'all', {
38129 	    width: LABEL_WIDTH,
38130 	    height: element.height
38131 	  });
38132 
38133 	  // indicate that we created a hit
38134 	  return true;
38135 	};
38136 
38137 	BpmnInteractionEvents.prototype.createSubProcessHit = function(element, gfx) {
38138 
38139 	  // remove existing hits
38140 	  this._interactionEvents.removeHits(gfx);
38141 
38142 	  // add outline hit
38143 	  this._interactionEvents.createBoxHit(gfx, 'click-stroke', {
38144 	    width: element.width,
38145 	    height: element.height
38146 	  });
38147 
38148 	  // add label hit
38149 	  this._interactionEvents.createBoxHit(gfx, 'all', {
38150 	    width: element.width,
38151 	    height: LABEL_HEIGHT
38152 	  });
38153 
38154 	  // indicate that we created a hit
38155 	  return true;
38156 	};
38157 
38158 	var InteractionEventsModule = {
38159 	  __init__: [ 'bpmnInteractionEvents' ],
38160 	  bpmnInteractionEvents: [ 'type', BpmnInteractionEvents ]
38161 	};
38162 
38163 	/**
38164 	 * BPMN 2.0 specific keyboard bindings.
38165 	 *
38166 	 * @param {Injector} injector
38167 	 */
38168 	function BpmnKeyboardBindings(injector) {
38169 	  injector.invoke(KeyboardBindings, this);
38170 	}
38171 
38172 	inherits$1(BpmnKeyboardBindings, KeyboardBindings);
38173 
38174 	BpmnKeyboardBindings.$inject = [
38175 	  'injector'
38176 	];
38177 
38178 
38179 	/**
38180 	 * Register available keyboard bindings.
38181 	 *
38182 	 * @param {Keyboard} keyboard
38183 	 * @param {EditorActions} editorActions
38184 	 */
38185 	BpmnKeyboardBindings.prototype.registerBindings = function(keyboard, editorActions) {
38186 
38187 	  // inherit default bindings
38188 	  KeyboardBindings.prototype.registerBindings.call(this, keyboard, editorActions);
38189 
38190 	  /**
38191 	   * Add keyboard binding if respective editor action
38192 	   * is registered.
38193 	   *
38194 	   * @param {string} action name
38195 	   * @param {Function} fn that implements the key binding
38196 	   */
38197 	  function addListener(action, fn) {
38198 
38199 	    if (editorActions.isRegistered(action)) {
38200 	      keyboard.addListener(fn);
38201 	    }
38202 	  }
38203 
38204 	  // select all elements
38205 	  // CTRL + A
38206 	  addListener('selectElements', function(context) {
38207 
38208 	    var event = context.keyEvent;
38209 
38210 	    if (keyboard.isKey(['a', 'A'], event) && keyboard.isCmd(event)) {
38211 	      editorActions.trigger('selectElements');
38212 
38213 	      return true;
38214 	    }
38215 	  });
38216 
38217 	  // search labels
38218 	  // CTRL + F
38219 	  addListener('find', function(context) {
38220 
38221 	    var event = context.keyEvent;
38222 
38223 	    if (keyboard.isKey(['f', 'F'], event) && keyboard.isCmd(event)) {
38224 	      editorActions.trigger('find');
38225 
38226 	      return true;
38227 	    }
38228 	  });
38229 
38230 	  // activate space tool
38231 	  // S
38232 	  addListener('spaceTool', function(context) {
38233 
38234 	    var event = context.keyEvent;
38235 
38236 	    if (keyboard.hasModifier(event)) {
38237 	      return;
38238 	    }
38239 
38240 	    if (keyboard.isKey(['s', 'S'], event)) {
38241 	      editorActions.trigger('spaceTool');
38242 
38243 	      return true;
38244 	    }
38245 	  });
38246 
38247 	  // activate lasso tool
38248 	  // L
38249 	  addListener('lassoTool', function(context) {
38250 
38251 	    var event = context.keyEvent;
38252 
38253 	    if (keyboard.hasModifier(event)) {
38254 	      return;
38255 	    }
38256 
38257 	    if (keyboard.isKey(['l', 'L'], event)) {
38258 	      editorActions.trigger('lassoTool');
38259 
38260 	      return true;
38261 	    }
38262 	  });
38263 
38264 	  // activate hand tool
38265 	  // H
38266 	  addListener('handTool', function(context) {
38267 
38268 	    var event = context.keyEvent;
38269 
38270 	    if (keyboard.hasModifier(event)) {
38271 	      return;
38272 	    }
38273 
38274 	    if (keyboard.isKey(['h', 'H'], event)) {
38275 	      editorActions.trigger('handTool');
38276 
38277 	      return true;
38278 	    }
38279 	  });
38280 
38281 	  // activate global connect tool
38282 	  // C
38283 	  addListener('globalConnectTool', function(context) {
38284 
38285 	    var event = context.keyEvent;
38286 
38287 	    if (keyboard.hasModifier(event)) {
38288 	      return;
38289 	    }
38290 
38291 	    if (keyboard.isKey(['c', 'C'], event)) {
38292 	      editorActions.trigger('globalConnectTool');
38293 
38294 	      return true;
38295 	    }
38296 	  });
38297 
38298 	  // activate direct editing
38299 	  // E
38300 	  addListener('directEditing', function(context) {
38301 
38302 	    var event = context.keyEvent;
38303 
38304 	    if (keyboard.hasModifier(event)) {
38305 	      return;
38306 	    }
38307 
38308 	    if (keyboard.isKey(['e', 'E'], event)) {
38309 	      editorActions.trigger('directEditing');
38310 
38311 	      return true;
38312 	    }
38313 	  });
38314 
38315 	};
38316 
38317 	var KeyboardModule = {
38318 	  __depends__: [
38319 	    KeyboardModule$1
38320 	  ],
38321 	  __init__: [ 'keyboardBindings' ],
38322 	  keyboardBindings: [ 'type', BpmnKeyboardBindings ]
38323 	};
38324 
38325 	var DEFAULT_CONFIG = {
38326 	  moveSpeed: 1,
38327 	  moveSpeedAccelerated: 10
38328 	};
38329 
38330 	var HIGHER_PRIORITY$3 = 1500;
38331 
38332 	var LEFT = 'left';
38333 	var UP = 'up';
38334 	var RIGHT = 'right';
38335 	var DOWN = 'down';
38336 
38337 	var KEY_TO_DIRECTION = {
38338 	  ArrowLeft: LEFT,
38339 	  Left: LEFT,
38340 	  ArrowUp: UP,
38341 	  Up: UP,
38342 	  ArrowRight: RIGHT,
38343 	  Right: RIGHT,
38344 	  ArrowDown: DOWN,
38345 	  Down: DOWN
38346 	};
38347 
38348 	var DIRECTIONS_DELTA = {
38349 	  left: function(speed) {
38350 	    return {
38351 	      x: -speed,
38352 	      y: 0
38353 	    };
38354 	  },
38355 	  up: function(speed) {
38356 	    return {
38357 	      x: 0,
38358 	      y: -speed
38359 	    };
38360 	  },
38361 	  right: function(speed) {
38362 	    return {
38363 	      x: speed,
38364 	      y: 0
38365 	    };
38366 	  },
38367 	  down: function(speed) {
38368 	    return {
38369 	      x: 0,
38370 	      y: speed
38371 	    };
38372 	  }
38373 	};
38374 
38375 
38376 	/**
38377 	 * Enables to move selection with keyboard arrows.
38378 	 * Use with Shift for modified speed (default=1, with Shift=10).
38379 	 * Pressed Cmd/Ctrl turns the feature off.
38380 	 *
38381 	 * @param {Object} config
38382 	 * @param {number} [config.moveSpeed=1]
38383 	 * @param {number} [config.moveSpeedAccelerated=10]
38384 	 * @param {Keyboard} keyboard
38385 	 * @param {Modeling} modeling
38386 	 * @param {Selection} selection
38387 	 */
38388 	function KeyboardMoveSelection(
38389 	    config,
38390 	    keyboard,
38391 	    modeling,
38392 	    rules,
38393 	    selection
38394 	) {
38395 
38396 	  var self = this;
38397 
38398 	  this._config = assign({}, DEFAULT_CONFIG, config || {});
38399 
38400 	  keyboard.addListener(HIGHER_PRIORITY$3, function(event) {
38401 
38402 	    var keyEvent = event.keyEvent;
38403 
38404 	    var direction = KEY_TO_DIRECTION[keyEvent.key];
38405 
38406 	    if (!direction) {
38407 	      return;
38408 	    }
38409 
38410 	    if (keyboard.isCmd(keyEvent)) {
38411 	      return;
38412 	    }
38413 
38414 	    var accelerated = keyboard.isShift(keyEvent);
38415 
38416 	    self.moveSelection(direction, accelerated);
38417 
38418 	    return true;
38419 	  });
38420 
38421 
38422 	  /**
38423 	   * Move selected elements in the given direction,
38424 	   * optionally specifying accelerated movement.
38425 	   *
38426 	   * @param {string} direction
38427 	   * @param {boolean} [accelerated=false]
38428 	   */
38429 	  this.moveSelection = function(direction, accelerated) {
38430 
38431 	    var selectedElements = selection.get();
38432 
38433 	    if (!selectedElements.length) {
38434 	      return;
38435 	    }
38436 
38437 	    var speed = this._config[
38438 	      accelerated ?
38439 	        'moveSpeedAccelerated' :
38440 	        'moveSpeed'
38441 	    ];
38442 
38443 	    var delta = DIRECTIONS_DELTA[direction](speed);
38444 
38445 	    var canMove = rules.allowed('elements.move', {
38446 	      shapes: selectedElements
38447 	    });
38448 
38449 	    if (canMove) {
38450 	      modeling.moveElements(selectedElements, delta);
38451 	    }
38452 	  };
38453 
38454 	}
38455 
38456 	KeyboardMoveSelection.$inject = [
38457 	  'config.keyboardMoveSelection',
38458 	  'keyboard',
38459 	  'modeling',
38460 	  'rules',
38461 	  'selection'
38462 	];
38463 
38464 	var KeyboardMoveSelectionModule = {
38465 	  __depends__: [
38466 	    KeyboardModule$1,
38467 	    SelectionModule
38468 	  ],
38469 	  __init__: [
38470 	    'keyboardMoveSelection'
38471 	  ],
38472 	  keyboardMoveSelection: [ 'type', KeyboardMoveSelection ]
38473 	};
38474 
38475 	/**
38476 	 * Adds change support to the diagram, including
38477 	 *
38478 	 * <ul>
38479 	 *   <li>redrawing shapes and connections on change</li>
38480 	 * </ul>
38481 	 *
38482 	 * @param {EventBus} eventBus
38483 	 * @param {Canvas} canvas
38484 	 * @param {ElementRegistry} elementRegistry
38485 	 * @param {GraphicsFactory} graphicsFactory
38486 	 */
38487 	function ChangeSupport(
38488 	    eventBus, canvas, elementRegistry,
38489 	    graphicsFactory) {
38490 
38491 
38492 	  // redraw shapes / connections on change
38493 
38494 	  eventBus.on('element.changed', function(event) {
38495 
38496 	    var element = event.element;
38497 
38498 	    // element might have been deleted and replaced by new element with same ID
38499 	    // thus check for parent of element except for root element
38500 	    if (element.parent || element === canvas.getRootElement()) {
38501 	      event.gfx = elementRegistry.getGraphics(element);
38502 	    }
38503 
38504 	    // shape + gfx may have been deleted
38505 	    if (!event.gfx) {
38506 	      return;
38507 	    }
38508 
38509 	    eventBus.fire(getType(element) + '.changed', event);
38510 	  });
38511 
38512 	  eventBus.on('elements.changed', function(event) {
38513 
38514 	    var elements = event.elements;
38515 
38516 	    elements.forEach(function(e) {
38517 	      eventBus.fire('element.changed', { element: e });
38518 	    });
38519 
38520 	    graphicsFactory.updateContainments(elements);
38521 	  });
38522 
38523 	  eventBus.on('shape.changed', function(event) {
38524 	    graphicsFactory.update('shape', event.element, event.gfx);
38525 	  });
38526 
38527 	  eventBus.on('connection.changed', function(event) {
38528 	    graphicsFactory.update('connection', event.element, event.gfx);
38529 	  });
38530 	}
38531 
38532 	ChangeSupport.$inject = [
38533 	  'eventBus',
38534 	  'canvas',
38535 	  'elementRegistry',
38536 	  'graphicsFactory'
38537 	];
38538 
38539 	var ChangeSupportModule = {
38540 	  __init__: [ 'changeSupport'],
38541 	  changeSupport: [ 'type', ChangeSupport ]
38542 	};
38543 
38544 	var DEFAULT_MIN_WIDTH = 10;
38545 
38546 
38547 	/**
38548 	 * A component that provides resizing of shapes on the canvas.
38549 	 *
38550 	 * The following components are part of shape resize:
38551 	 *
38552 	 *  * adding resize handles,
38553 	 *  * creating a visual during resize
38554 	 *  * checking resize rules
38555 	 *  * committing a change once finished
38556 	 *
38557 	 *
38558 	 * ## Customizing
38559 	 *
38560 	 * It's possible to customize the resizing behaviour by intercepting 'resize.start'
38561 	 * and providing the following parameters through the 'context':
38562 	 *
38563 	 *   * minDimensions ({ width, height }): minimum shape dimensions
38564 	 *
38565 	 *   * childrenBoxPadding ({ left, top, bottom, right } || number):
38566 	 *     gap between the minimum bounding box and the container
38567 	 *
38568 	 * f.ex:
38569 	 *
38570 	 * ```javascript
38571 	 * eventBus.on('resize.start', 1500, function(event) {
38572 	 *   var context = event.context,
38573 	 *
38574 	 *  context.minDimensions = { width: 140, height: 120 };
38575 	 *
38576 	 *  // Passing general padding
38577 	 *  context.childrenBoxPadding = 30;
38578 	 *
38579 	 *  // Passing padding to a specific side
38580 	 *  context.childrenBoxPadding.left = 20;
38581 	 * });
38582 	 * ```
38583 	 */
38584 	function Resize(eventBus, rules, modeling, dragging) {
38585 
38586 	  this._dragging = dragging;
38587 	  this._rules = rules;
38588 
38589 	  var self = this;
38590 
38591 
38592 	  /**
38593 	   * Handle resize move by specified delta.
38594 	   *
38595 	   * @param {Object} context
38596 	   * @param {Point} delta
38597 	   */
38598 	  function handleMove(context, delta) {
38599 
38600 	    var shape = context.shape,
38601 	        direction = context.direction,
38602 	        resizeConstraints = context.resizeConstraints,
38603 	        newBounds;
38604 
38605 	    context.delta = delta;
38606 
38607 	    newBounds = resizeBounds$1(shape, direction, delta);
38608 
38609 	    // ensure constraints during resize
38610 	    context.newBounds = ensureConstraints$1(newBounds, resizeConstraints);
38611 
38612 	    // update + cache executable state
38613 	    context.canExecute = self.canResize(context);
38614 	  }
38615 
38616 	  /**
38617 	   * Handle resize start.
38618 	   *
38619 	   * @param  {Object} context
38620 	   */
38621 	  function handleStart(context) {
38622 
38623 	    var resizeConstraints = context.resizeConstraints,
38624 
38625 	        // evaluate minBounds for backwards compatibility
38626 	        minBounds = context.minBounds;
38627 
38628 	    if (resizeConstraints !== undefined) {
38629 	      return;
38630 	    }
38631 
38632 	    if (minBounds === undefined) {
38633 	      minBounds = self.computeMinResizeBox(context);
38634 	    }
38635 
38636 	    context.resizeConstraints = {
38637 	      min: asTRBL(minBounds)
38638 	    };
38639 	  }
38640 
38641 	  /**
38642 	   * Handle resize end.
38643 	   *
38644 	   * @param  {Object} context
38645 	   */
38646 	  function handleEnd(context) {
38647 	    var shape = context.shape,
38648 	        canExecute = context.canExecute,
38649 	        newBounds = context.newBounds;
38650 
38651 	    if (canExecute) {
38652 
38653 	      // ensure we have actual pixel values for new bounds
38654 	      // (important when zoom level was > 1 during move)
38655 	      newBounds = roundBounds(newBounds);
38656 
38657 	      if (!boundsChanged(shape, newBounds)) {
38658 
38659 	        // no resize necessary
38660 	        return;
38661 	      }
38662 
38663 	      // perform the actual resize
38664 	      modeling.resizeShape(shape, newBounds);
38665 	    }
38666 	  }
38667 
38668 
38669 	  eventBus.on('resize.start', function(event) {
38670 	    handleStart(event.context);
38671 	  });
38672 
38673 	  eventBus.on('resize.move', function(event) {
38674 	    var delta = {
38675 	      x: event.dx,
38676 	      y: event.dy
38677 	    };
38678 
38679 	    handleMove(event.context, delta);
38680 	  });
38681 
38682 	  eventBus.on('resize.end', function(event) {
38683 	    handleEnd(event.context);
38684 	  });
38685 
38686 	}
38687 
38688 
38689 	Resize.prototype.canResize = function(context) {
38690 	  var rules = this._rules;
38691 
38692 	  var ctx = pick(context, [ 'newBounds', 'shape', 'delta', 'direction' ]);
38693 
38694 	  return rules.allowed('shape.resize', ctx);
38695 	};
38696 
38697 	/**
38698 	 * Activate a resize operation.
38699 	 *
38700 	 * You may specify additional contextual information and must specify a
38701 	 * resize direction during activation of the resize event.
38702 	 *
38703 	 * @param {MouseEvent} event
38704 	 * @param {djs.model.Shape} shape
38705 	 * @param {Object|string} contextOrDirection
38706 	 */
38707 	Resize.prototype.activate = function(event, shape, contextOrDirection) {
38708 	  var dragging = this._dragging,
38709 	      context,
38710 	      direction;
38711 
38712 	  if (typeof contextOrDirection === 'string') {
38713 	    contextOrDirection = {
38714 	      direction: contextOrDirection
38715 	    };
38716 	  }
38717 
38718 	  context = assign({ shape: shape }, contextOrDirection);
38719 
38720 	  direction = context.direction;
38721 
38722 	  if (!direction) {
38723 	    throw new Error('must provide a direction (n|w|s|e|nw|se|ne|sw)');
38724 	  }
38725 
38726 	  dragging.init(event, getReferencePoint$1(shape, direction), 'resize', {
38727 	    autoActivate: true,
38728 	    cursor: getCursor(direction),
38729 	    data: {
38730 	      shape: shape,
38731 	      context: context
38732 	    }
38733 	  });
38734 	};
38735 
38736 	Resize.prototype.computeMinResizeBox = function(context) {
38737 	  var shape = context.shape,
38738 	      direction = context.direction,
38739 	      minDimensions,
38740 	      childrenBounds;
38741 
38742 	  minDimensions = context.minDimensions || {
38743 	    width: DEFAULT_MIN_WIDTH,
38744 	    height: DEFAULT_MIN_WIDTH
38745 	  };
38746 
38747 	  // get children bounds
38748 	  childrenBounds = computeChildrenBBox(shape, context.childrenBoxPadding);
38749 
38750 	  // get correct minimum bounds from given resize direction
38751 	  // basically ensures that the minBounds is max(childrenBounds, minDimensions)
38752 	  return getMinResizeBounds(direction, shape, minDimensions, childrenBounds);
38753 	};
38754 
38755 
38756 	Resize.$inject = [
38757 	  'eventBus',
38758 	  'rules',
38759 	  'modeling',
38760 	  'dragging'
38761 	];
38762 
38763 	// helpers //////////
38764 
38765 	function boundsChanged(shape, newBounds) {
38766 	  return shape.x !== newBounds.x ||
38767 	    shape.y !== newBounds.y ||
38768 	    shape.width !== newBounds.width ||
38769 	    shape.height !== newBounds.height;
38770 	}
38771 
38772 	function getReferencePoint$1(shape, direction) {
38773 	  var mid = getMid(shape),
38774 	      trbl = asTRBL(shape);
38775 
38776 	  var referencePoint = {
38777 	    x: mid.x,
38778 	    y: mid.y
38779 	  };
38780 
38781 	  if (direction.indexOf('n') !== -1) {
38782 	    referencePoint.y = trbl.top;
38783 	  } else if (direction.indexOf('s') !== -1) {
38784 	    referencePoint.y = trbl.bottom;
38785 	  }
38786 
38787 	  if (direction.indexOf('e') !== -1) {
38788 	    referencePoint.x = trbl.right;
38789 	  } else if (direction.indexOf('w') !== -1) {
38790 	    referencePoint.x = trbl.left;
38791 	  }
38792 
38793 	  return referencePoint;
38794 	}
38795 
38796 	function getCursor(direction) {
38797 	  var prefix = 'resize-';
38798 
38799 	  if (direction === 'n' || direction === 's') {
38800 	    return prefix + 'ns';
38801 	  } else if (direction === 'e' || direction === 'w') {
38802 	    return prefix + 'ew';
38803 	  } else if (direction === 'nw' || direction === 'se') {
38804 	    return prefix + 'nwse';
38805 	  } else {
38806 	    return prefix + 'nesw';
38807 	  }
38808 	}
38809 
38810 	var MARKER_RESIZING$1 = 'djs-resizing',
38811 	    MARKER_RESIZE_NOT_OK = 'resize-not-ok';
38812 
38813 	var LOW_PRIORITY$d = 500;
38814 
38815 
38816 	/**
38817 	 * Provides previews for resizing shapes when resizing.
38818 	 *
38819 	 * @param {EventBus} eventBus
38820 	 * @param {Canvas} canvas
38821 	 * @param {PreviewSupport} previewSupport
38822 	 */
38823 	function ResizePreview(eventBus, canvas, previewSupport) {
38824 
38825 	  /**
38826 	   * Update resizer frame.
38827 	   *
38828 	   * @param {Object} context
38829 	   */
38830 	  function updateFrame(context) {
38831 
38832 	    var shape = context.shape,
38833 	        bounds = context.newBounds,
38834 	        frame = context.frame;
38835 
38836 	    if (!frame) {
38837 	      frame = context.frame = previewSupport.addFrame(shape, canvas.getActiveLayer());
38838 
38839 	      canvas.addMarker(shape, MARKER_RESIZING$1);
38840 	    }
38841 
38842 	    if (bounds.width > 5) {
38843 	      attr(frame, { x: bounds.x, width: bounds.width });
38844 	    }
38845 
38846 	    if (bounds.height > 5) {
38847 	      attr(frame, { y: bounds.y, height: bounds.height });
38848 	    }
38849 
38850 	    if (context.canExecute) {
38851 	      classes(frame).remove(MARKER_RESIZE_NOT_OK);
38852 	    } else {
38853 	      classes(frame).add(MARKER_RESIZE_NOT_OK);
38854 	    }
38855 	  }
38856 
38857 	  /**
38858 	   * Remove resizer frame.
38859 	   *
38860 	   * @param {Object} context
38861 	   */
38862 	  function removeFrame(context) {
38863 	    var shape = context.shape,
38864 	        frame = context.frame;
38865 
38866 	    if (frame) {
38867 	      remove$1(context.frame);
38868 	    }
38869 
38870 	    canvas.removeMarker(shape, MARKER_RESIZING$1);
38871 	  }
38872 
38873 	  // add and update previews
38874 	  eventBus.on('resize.move', LOW_PRIORITY$d, function(event) {
38875 	    updateFrame(event.context);
38876 	  });
38877 
38878 	  // remove previews
38879 	  eventBus.on('resize.cleanup', function(event) {
38880 	    removeFrame(event.context);
38881 	  });
38882 
38883 	}
38884 
38885 	ResizePreview.$inject = [
38886 	  'eventBus',
38887 	  'canvas',
38888 	  'previewSupport'
38889 	];
38890 
38891 	var HANDLE_OFFSET = -6,
38892 	    HANDLE_SIZE = 4,
38893 	    HANDLE_HIT_SIZE = 20;
38894 
38895 	var CLS_RESIZER = 'djs-resizer';
38896 
38897 	var directions = [ 'n', 'w', 's', 'e', 'nw', 'ne', 'se', 'sw' ];
38898 
38899 
38900 	/**
38901 	 * This component is responsible for adding resize handles.
38902 	 *
38903 	 * @param {EventBus} eventBus
38904 	 * @param {Canvas} canvas
38905 	 * @param {Selection} selection
38906 	 * @param {Resize} resize
38907 	 */
38908 	function ResizeHandles(eventBus, canvas, selection, resize) {
38909 
38910 	  this._resize = resize;
38911 	  this._canvas = canvas;
38912 
38913 	  var self = this;
38914 
38915 	  eventBus.on('selection.changed', function(e) {
38916 	    var newSelection = e.newSelection;
38917 
38918 	    // remove old selection markers
38919 	    self.removeResizers();
38920 
38921 	    // add new selection markers ONLY if single selection
38922 	    if (newSelection.length === 1) {
38923 	      forEach(newSelection, bind$2(self.addResizer, self));
38924 	    }
38925 	  });
38926 
38927 	  eventBus.on('shape.changed', function(e) {
38928 	    var shape = e.element;
38929 
38930 	    if (selection.isSelected(shape)) {
38931 	      self.removeResizers();
38932 
38933 	      self.addResizer(shape);
38934 	    }
38935 	  });
38936 	}
38937 
38938 
38939 	ResizeHandles.prototype.makeDraggable = function(element, gfx, direction) {
38940 	  var resize = this._resize;
38941 
38942 	  function startResize(event) {
38943 
38944 	    // only trigger on left mouse button
38945 	    if (isPrimaryButton(event)) {
38946 	      resize.activate(event, element, direction);
38947 	    }
38948 	  }
38949 
38950 	  componentEvent.bind(gfx, 'mousedown', startResize);
38951 	  componentEvent.bind(gfx, 'touchstart', startResize);
38952 	};
38953 
38954 
38955 	ResizeHandles.prototype._createResizer = function(element, x, y, direction) {
38956 	  var resizersParent = this._getResizersParent();
38957 
38958 	  var offset = getHandleOffset(direction);
38959 
38960 	  var group = create$1('g');
38961 
38962 	  classes(group).add(CLS_RESIZER);
38963 	  classes(group).add(CLS_RESIZER + '-' + element.id);
38964 	  classes(group).add(CLS_RESIZER + '-' + direction);
38965 
38966 	  append(resizersParent, group);
38967 
38968 	  var visual = create$1('rect');
38969 
38970 	  attr(visual, {
38971 	    x: -HANDLE_SIZE / 2 + offset.x,
38972 	    y: -HANDLE_SIZE / 2 + offset.y,
38973 	    width: HANDLE_SIZE,
38974 	    height: HANDLE_SIZE
38975 	  });
38976 
38977 	  classes(visual).add(CLS_RESIZER + '-visual');
38978 
38979 	  append(group, visual);
38980 
38981 	  var hit = create$1('rect');
38982 
38983 	  attr(hit, {
38984 	    x: -HANDLE_HIT_SIZE / 2 + offset.x,
38985 	    y: -HANDLE_HIT_SIZE / 2 + offset.y,
38986 	    width: HANDLE_HIT_SIZE,
38987 	    height: HANDLE_HIT_SIZE
38988 	  });
38989 
38990 	  classes(hit).add(CLS_RESIZER + '-hit');
38991 
38992 	  append(group, hit);
38993 
38994 	  transform(group, x, y);
38995 
38996 	  return group;
38997 	};
38998 
38999 	ResizeHandles.prototype.createResizer = function(element, direction) {
39000 	  var point = getReferencePoint$1(element, direction);
39001 
39002 	  var resizer = this._createResizer(element, point.x, point.y, direction);
39003 
39004 	  this.makeDraggable(element, resizer, direction);
39005 	};
39006 
39007 	// resize handles implementation ///////////////////////////////
39008 
39009 	/**
39010 	 * Add resizers for a given element.
39011 	 *
39012 	 * @param {djs.model.Shape} shape
39013 	 */
39014 	ResizeHandles.prototype.addResizer = function(shape) {
39015 	  var self = this;
39016 
39017 	  var resize = this._resize;
39018 
39019 	  if (!resize.canResize({ shape: shape })) {
39020 	    return;
39021 	  }
39022 
39023 	  forEach(directions, function(direction) {
39024 	    self.createResizer(shape, direction);
39025 	  });
39026 	};
39027 
39028 	/**
39029 	 * Remove all resizers
39030 	 */
39031 	ResizeHandles.prototype.removeResizers = function() {
39032 	  var resizersParent = this._getResizersParent();
39033 
39034 	  clear(resizersParent);
39035 	};
39036 
39037 	ResizeHandles.prototype._getResizersParent = function() {
39038 	  return this._canvas.getLayer('resizers');
39039 	};
39040 
39041 	ResizeHandles.$inject = [
39042 	  'eventBus',
39043 	  'canvas',
39044 	  'selection',
39045 	  'resize'
39046 	];
39047 
39048 	// helpers //////////
39049 
39050 	function getHandleOffset(direction) {
39051 	  var offset = {
39052 	    x: 0,
39053 	    y: 0
39054 	  };
39055 
39056 	  if (direction.indexOf('e') !== -1) {
39057 	    offset.x = -HANDLE_OFFSET;
39058 	  } else if (direction.indexOf('w') !== -1) {
39059 	    offset.x = HANDLE_OFFSET;
39060 	  }
39061 
39062 	  if (direction.indexOf('s') !== -1) {
39063 	    offset.y = -HANDLE_OFFSET;
39064 	  } else if (direction.indexOf('n') !== -1) {
39065 	    offset.y = HANDLE_OFFSET;
39066 	  }
39067 
39068 	  return offset;
39069 	}
39070 
39071 	var ResizeModule = {
39072 	  __depends__: [
39073 	    RulesModule$1,
39074 	    DraggingModule,
39075 	    PreviewSupportModule
39076 	  ],
39077 	  __init__: [
39078 	    'resize',
39079 	    'resizePreview',
39080 	    'resizeHandles'
39081 	  ],
39082 	  resize: [ 'type', Resize ],
39083 	  resizePreview: [ 'type', ResizePreview ],
39084 	  resizeHandles: [ 'type', ResizeHandles ]
39085 	};
39086 
39087 	/**
39088 	 * Creates a new bpmn:CategoryValue inside a new bpmn:Category
39089 	 *
39090 	 * @param {ModdleElement} definitions
39091 	 * @param {BpmnFactory} bpmnFactory
39092 	 *
39093 	 * @return {ModdleElement} categoryValue.
39094 	 */
39095 	function createCategoryValue(definitions, bpmnFactory) {
39096 	  var categoryValue = bpmnFactory.create('bpmn:CategoryValue'),
39097 	      category = bpmnFactory.create('bpmn:Category', {
39098 	        categoryValue: [ categoryValue ]
39099 	      });
39100 
39101 	  // add to correct place
39102 	  add(definitions.get('rootElements'), category);
39103 	  getBusinessObject(category).$parent = definitions;
39104 	  getBusinessObject(categoryValue).$parent = category;
39105 
39106 	  return categoryValue;
39107 
39108 	}
39109 
39110 	function LabelEditingProvider(
39111 	    eventBus, bpmnFactory, canvas, directEditing,
39112 	    modeling, resizeHandles, textRenderer) {
39113 
39114 	  this._bpmnFactory = bpmnFactory;
39115 	  this._canvas = canvas;
39116 	  this._modeling = modeling;
39117 	  this._textRenderer = textRenderer;
39118 
39119 	  directEditing.registerProvider(this);
39120 
39121 	  // listen to dblclick on non-root elements
39122 	  eventBus.on('element.dblclick', function(event) {
39123 	    activateDirectEdit(event.element, true);
39124 	  });
39125 
39126 	  // complete on followup canvas operation
39127 	  eventBus.on([
39128 	    'autoPlace.start',
39129 	    'canvas.viewbox.changing',
39130 	    'drag.init',
39131 	    'element.mousedown',
39132 	    'popupMenu.open'
39133 	  ], function(event) {
39134 
39135 	    if (directEditing.isActive()) {
39136 	      directEditing.complete();
39137 	    }
39138 	  });
39139 
39140 	  // cancel on command stack changes
39141 	  eventBus.on([ 'commandStack.changed' ], function(e) {
39142 	    if (directEditing.isActive()) {
39143 	      directEditing.cancel();
39144 	    }
39145 	  });
39146 
39147 
39148 	  eventBus.on('directEditing.activate', function(event) {
39149 	    resizeHandles.removeResizers();
39150 	  });
39151 
39152 	  eventBus.on('create.end', 500, function(event) {
39153 
39154 	    var context = event.context,
39155 	        element = context.shape,
39156 	        canExecute = event.context.canExecute,
39157 	        isTouch = event.isTouch;
39158 
39159 	    // TODO(nikku): we need to find a way to support the
39160 	    // direct editing on mobile devices; right now this will
39161 	    // break for desworkflowediting on mobile devices
39162 	    // as it breaks the user interaction workflow
39163 
39164 	    // TODO(nre): we should temporarily focus the edited element
39165 	    // here and release the focused viewport after the direct edit
39166 	    // operation is finished
39167 	    if (isTouch) {
39168 	      return;
39169 	    }
39170 
39171 	    if (!canExecute) {
39172 	      return;
39173 	    }
39174 
39175 	    if (context.hints && context.hints.createElementsBehavior === false) {
39176 	      return;
39177 	    }
39178 
39179 	    activateDirectEdit(element);
39180 	  });
39181 
39182 	  eventBus.on('autoPlace.end', 500, function(event) {
39183 	    activateDirectEdit(event.shape);
39184 	  });
39185 
39186 
39187 	  function activateDirectEdit(element, force) {
39188 	    if (force ||
39189 	        isAny(element, [ 'bpmn:Task', 'bpmn:TextAnnotation', 'bpmn:Group' ]) ||
39190 	        isCollapsedSubProcess(element)) {
39191 
39192 	      directEditing.activate(element);
39193 	    }
39194 	  }
39195 
39196 	}
39197 
39198 	LabelEditingProvider.$inject = [
39199 	  'eventBus',
39200 	  'bpmnFactory',
39201 	  'canvas',
39202 	  'directEditing',
39203 	  'modeling',
39204 	  'resizeHandles',
39205 	  'textRenderer'
39206 	];
39207 
39208 
39209 	/**
39210 	 * Activate direct editing for activities and text annotations.
39211 	 *
39212 	 * @param  {djs.model.Base} element
39213 	 *
39214 	 * @return {Object} an object with properties bounds (position and size), text and options
39215 	 */
39216 	LabelEditingProvider.prototype.activate = function(element) {
39217 
39218 	  // text
39219 	  var text = getLabel(element);
39220 
39221 	  if (text === undefined) {
39222 	    return;
39223 	  }
39224 
39225 	  var context = {
39226 	    text: text
39227 	  };
39228 
39229 	  // bounds
39230 	  var bounds = this.getEditingBBox(element);
39231 
39232 	  assign(context, bounds);
39233 
39234 	  var options = {};
39235 
39236 	  // tasks
39237 	  if (
39238 	    isAny(element, [
39239 	      'bpmn:Task',
39240 	      'bpmn:Participant',
39241 	      'bpmn:Lane',
39242 	      'bpmn:CallActivity'
39243 	    ]) ||
39244 	    isCollapsedSubProcess(element)
39245 	  ) {
39246 	    assign(options, {
39247 	      centerVertically: true
39248 	    });
39249 	  }
39250 
39251 	  // external labels
39252 	  if (isLabelExternal(element)) {
39253 	    assign(options, {
39254 	      autoResize: true
39255 	    });
39256 	  }
39257 
39258 	  // text annotations
39259 	  if (is$1(element, 'bpmn:TextAnnotation')) {
39260 	    assign(options, {
39261 	      resizable: true,
39262 	      autoResize: true
39263 	    });
39264 	  }
39265 
39266 	  assign(context, {
39267 	    options: options
39268 	  });
39269 
39270 	  return context;
39271 	};
39272 
39273 
39274 	/**
39275 	 * Get the editing bounding box based on the element's size and position
39276 	 *
39277 	 * @param  {djs.model.Base} element
39278 	 *
39279 	 * @return {Object} an object containing information about position
39280 	 *                  and size (fixed or minimum and/or maximum)
39281 	 */
39282 	LabelEditingProvider.prototype.getEditingBBox = function(element) {
39283 	  var canvas = this._canvas;
39284 
39285 	  var target = element.label || element;
39286 
39287 	  var bbox = canvas.getAbsoluteBBox(target);
39288 
39289 	  var mid = {
39290 	    x: bbox.x + bbox.width / 2,
39291 	    y: bbox.y + bbox.height / 2
39292 	  };
39293 
39294 	  // default position
39295 	  var bounds = { x: bbox.x, y: bbox.y };
39296 
39297 	  var zoom = canvas.zoom();
39298 
39299 	  var defaultStyle = this._textRenderer.getDefaultStyle(),
39300 	      externalStyle = this._textRenderer.getExternalStyle();
39301 
39302 	  // take zoom into account
39303 	  var externalFontSize = externalStyle.fontSize * zoom,
39304 	      externalLineHeight = externalStyle.lineHeight,
39305 	      defaultFontSize = defaultStyle.fontSize * zoom,
39306 	      defaultLineHeight = defaultStyle.lineHeight;
39307 
39308 	  var style = {
39309 	    fontFamily: this._textRenderer.getDefaultStyle().fontFamily,
39310 	    fontWeight: this._textRenderer.getDefaultStyle().fontWeight
39311 	  };
39312 
39313 	  // adjust for expanded pools AND lanes
39314 	  if (is$1(element, 'bpmn:Lane') || isExpandedPool(element)) {
39315 
39316 	    assign(bounds, {
39317 	      width: bbox.height,
39318 	      height: 30 * zoom,
39319 	      x: bbox.x - bbox.height / 2 + (15 * zoom),
39320 	      y: mid.y - (30 * zoom) / 2
39321 	    });
39322 
39323 	    assign(style, {
39324 	      fontSize: defaultFontSize + 'px',
39325 	      lineHeight: defaultLineHeight,
39326 	      paddingTop: (7 * zoom) + 'px',
39327 	      paddingBottom: (7 * zoom) + 'px',
39328 	      paddingLeft: (5 * zoom) + 'px',
39329 	      paddingRight: (5 * zoom) + 'px',
39330 	      transform: 'rotate(-90deg)'
39331 	    });
39332 	  }
39333 
39334 
39335 	  // internal labels for tasks and collapsed call activities,
39336 	  // sub processes and participants
39337 	  if (isAny(element, [ 'bpmn:Task', 'bpmn:CallActivity']) ||
39338 	      isCollapsedPool(element) ||
39339 	      isCollapsedSubProcess(element)) {
39340 
39341 	    assign(bounds, {
39342 	      width: bbox.width,
39343 	      height: bbox.height
39344 	    });
39345 
39346 	    assign(style, {
39347 	      fontSize: defaultFontSize + 'px',
39348 	      lineHeight: defaultLineHeight,
39349 	      paddingTop: (7 * zoom) + 'px',
39350 	      paddingBottom: (7 * zoom) + 'px',
39351 	      paddingLeft: (5 * zoom) + 'px',
39352 	      paddingRight: (5 * zoom) + 'px'
39353 	    });
39354 	  }
39355 
39356 
39357 	  // internal labels for expanded sub processes
39358 	  if (isExpandedSubProcess$1(element)) {
39359 	    assign(bounds, {
39360 	      width: bbox.width,
39361 	      x: bbox.x
39362 	    });
39363 
39364 	    assign(style, {
39365 	      fontSize: defaultFontSize + 'px',
39366 	      lineHeight: defaultLineHeight,
39367 	      paddingTop: (7 * zoom) + 'px',
39368 	      paddingBottom: (7 * zoom) + 'px',
39369 	      paddingLeft: (5 * zoom) + 'px',
39370 	      paddingRight: (5 * zoom) + 'px'
39371 	    });
39372 	  }
39373 
39374 	  var width = 90 * zoom,
39375 	      paddingTop = 7 * zoom,
39376 	      paddingBottom = 4 * zoom;
39377 
39378 	  // external labels for events, data elements, gateways, groups and connections
39379 	  if (target.labelTarget) {
39380 	    assign(bounds, {
39381 	      width: width,
39382 	      height: bbox.height + paddingTop + paddingBottom,
39383 	      x: mid.x - width / 2,
39384 	      y: bbox.y - paddingTop
39385 	    });
39386 
39387 	    assign(style, {
39388 	      fontSize: externalFontSize + 'px',
39389 	      lineHeight: externalLineHeight,
39390 	      paddingTop: paddingTop + 'px',
39391 	      paddingBottom: paddingBottom + 'px'
39392 	    });
39393 	  }
39394 
39395 	  // external label not yet created
39396 	  if (isLabelExternal(target)
39397 	      && !hasExternalLabel(target)
39398 	      && !isLabel$6(target)) {
39399 
39400 	    var externalLabelMid = getExternalLabelMid(element);
39401 
39402 	    var absoluteBBox = canvas.getAbsoluteBBox({
39403 	      x: externalLabelMid.x,
39404 	      y: externalLabelMid.y,
39405 	      width: 0,
39406 	      height: 0
39407 	    });
39408 
39409 	    var height = externalFontSize + paddingTop + paddingBottom;
39410 
39411 	    assign(bounds, {
39412 	      width: width,
39413 	      height: height,
39414 	      x: absoluteBBox.x - width / 2,
39415 	      y: absoluteBBox.y - height / 2
39416 	    });
39417 
39418 	    assign(style, {
39419 	      fontSize: externalFontSize + 'px',
39420 	      lineHeight: externalLineHeight,
39421 	      paddingTop: paddingTop + 'px',
39422 	      paddingBottom: paddingBottom + 'px'
39423 	    });
39424 	  }
39425 
39426 	  // text annotations
39427 	  if (is$1(element, 'bpmn:TextAnnotation')) {
39428 	    assign(bounds, {
39429 	      width: bbox.width,
39430 	      height: bbox.height,
39431 	      minWidth: 30 * zoom,
39432 	      minHeight: 10 * zoom
39433 	    });
39434 
39435 	    assign(style, {
39436 	      textAlign: 'left',
39437 	      paddingTop: (5 * zoom) + 'px',
39438 	      paddingBottom: (7 * zoom) + 'px',
39439 	      paddingLeft: (7 * zoom) + 'px',
39440 	      paddingRight: (5 * zoom) + 'px',
39441 	      fontSize: defaultFontSize + 'px',
39442 	      lineHeight: defaultLineHeight
39443 	    });
39444 	  }
39445 
39446 	  return { bounds: bounds, style: style };
39447 	};
39448 
39449 
39450 	LabelEditingProvider.prototype.update = function(
39451 	    element, newLabel,
39452 	    activeContextText, bounds) {
39453 
39454 	  var newBounds,
39455 	      bbox;
39456 
39457 	  if (is$1(element, 'bpmn:TextAnnotation')) {
39458 
39459 	    bbox = this._canvas.getAbsoluteBBox(element);
39460 
39461 	    newBounds = {
39462 	      x: element.x,
39463 	      y: element.y,
39464 	      width: element.width / bbox.width * bounds.width,
39465 	      height: element.height / bbox.height * bounds.height
39466 	    };
39467 	  }
39468 
39469 	  if (is$1(element, 'bpmn:Group')) {
39470 
39471 	    var businessObject = getBusinessObject(element);
39472 
39473 	    // initialize categoryValue if not existing
39474 	    if (!businessObject.categoryValueRef) {
39475 
39476 	      var rootElement = this._canvas.getRootElement(),
39477 	          definitions = getBusinessObject(rootElement).$parent;
39478 
39479 	      var categoryValue = createCategoryValue(definitions, this._bpmnFactory);
39480 
39481 	      getBusinessObject(element).categoryValueRef = categoryValue;
39482 	    }
39483 
39484 	  }
39485 
39486 	  if (isEmptyText$1(newLabel)) {
39487 	    newLabel = null;
39488 	  }
39489 
39490 	  this._modeling.updateLabel(element, newLabel, newBounds);
39491 	};
39492 
39493 
39494 
39495 	// helpers //////////////////////
39496 
39497 	function isCollapsedSubProcess(element) {
39498 	  return is$1(element, 'bpmn:SubProcess') && !isExpanded(element);
39499 	}
39500 
39501 	function isExpandedSubProcess$1(element) {
39502 	  return is$1(element, 'bpmn:SubProcess') && isExpanded(element);
39503 	}
39504 
39505 	function isCollapsedPool(element) {
39506 	  return is$1(element, 'bpmn:Participant') && !isExpanded(element);
39507 	}
39508 
39509 	function isExpandedPool(element) {
39510 	  return is$1(element, 'bpmn:Participant') && isExpanded(element);
39511 	}
39512 
39513 	function isEmptyText$1(label) {
39514 	  return !label || !label.trim();
39515 	}
39516 
39517 	var MARKER_HIDDEN = 'djs-element-hidden',
39518 	    MARKER_LABEL_HIDDEN = 'djs-label-hidden';
39519 
39520 
39521 	function LabelEditingPreview(
39522 	    eventBus, canvas, elementRegistry,
39523 	    pathMap) {
39524 
39525 	  var self = this;
39526 
39527 	  var defaultLayer = canvas.getDefaultLayer();
39528 
39529 	  var element, absoluteElementBBox, gfx;
39530 
39531 	  eventBus.on('directEditing.activate', function(context) {
39532 	    var activeProvider = context.active;
39533 
39534 	    element = activeProvider.element.label || activeProvider.element;
39535 
39536 	    // text annotation
39537 	    if (is$1(element, 'bpmn:TextAnnotation')) {
39538 	      absoluteElementBBox = canvas.getAbsoluteBBox(element);
39539 
39540 	      gfx = create$1('g');
39541 
39542 	      var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
39543 	        xScaleFactor: 1,
39544 	        yScaleFactor: 1,
39545 	        containerWidth: element.width,
39546 	        containerHeight: element.height,
39547 	        position: {
39548 	          mx: 0.0,
39549 	          my: 0.0
39550 	        }
39551 	      });
39552 
39553 	      var path = self.path = create$1('path');
39554 
39555 	      attr(path, {
39556 	        d: textPathData,
39557 	        strokeWidth: 2,
39558 	        stroke: getStrokeColor(element)
39559 	      });
39560 
39561 	      append(gfx, path);
39562 
39563 	      append(defaultLayer, gfx);
39564 
39565 	      translate$2(gfx, element.x, element.y);
39566 	    }
39567 
39568 	    if (is$1(element, 'bpmn:TextAnnotation') ||
39569 	        element.labelTarget) {
39570 	      canvas.addMarker(element, MARKER_HIDDEN);
39571 	    } else if (is$1(element, 'bpmn:Task') ||
39572 	               is$1(element, 'bpmn:CallActivity') ||
39573 	               is$1(element, 'bpmn:SubProcess') ||
39574 	               is$1(element, 'bpmn:Participant')) {
39575 	      canvas.addMarker(element, MARKER_LABEL_HIDDEN);
39576 	    }
39577 	  });
39578 
39579 	  eventBus.on('directEditing.resize', function(context) {
39580 
39581 	    // text annotation
39582 	    if (is$1(element, 'bpmn:TextAnnotation')) {
39583 	      var height = context.height,
39584 	          dy = context.dy;
39585 
39586 	      var newElementHeight = Math.max(element.height / absoluteElementBBox.height * (height + dy), 0);
39587 
39588 	      var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
39589 	        xScaleFactor: 1,
39590 	        yScaleFactor: 1,
39591 	        containerWidth: element.width,
39592 	        containerHeight: newElementHeight,
39593 	        position: {
39594 	          mx: 0.0,
39595 	          my: 0.0
39596 	        }
39597 	      });
39598 
39599 	      attr(self.path, {
39600 	        d: textPathData
39601 	      });
39602 	    }
39603 	  });
39604 
39605 	  eventBus.on([ 'directEditing.complete', 'directEditing.cancel' ], function(context) {
39606 	    var activeProvider = context.active;
39607 
39608 	    if (activeProvider) {
39609 	      canvas.removeMarker(activeProvider.element.label || activeProvider.element, MARKER_HIDDEN);
39610 	      canvas.removeMarker(element, MARKER_LABEL_HIDDEN);
39611 	    }
39612 
39613 	    element = undefined;
39614 	    absoluteElementBBox = undefined;
39615 
39616 	    if (gfx) {
39617 	      remove$1(gfx);
39618 
39619 	      gfx = undefined;
39620 	    }
39621 	  });
39622 	}
39623 
39624 	LabelEditingPreview.$inject = [
39625 	  'eventBus',
39626 	  'canvas',
39627 	  'elementRegistry',
39628 	  'pathMap'
39629 	];
39630 
39631 
39632 	// helpers ///////////////////
39633 
39634 	function getStrokeColor(element, defaultColor) {
39635 	  var bo = getBusinessObject(element);
39636 
39637 	  return bo.di.get('stroke') || defaultColor || 'black';
39638 	}
39639 
39640 	var LabelEditingModule = {
39641 	  __depends__: [
39642 	    ChangeSupportModule,
39643 	    ResizeModule,
39644 	    DirectEditingModule
39645 	  ],
39646 	  __init__: [
39647 	    'labelEditingProvider',
39648 	    'labelEditingPreview'
39649 	  ],
39650 	  labelEditingProvider: [ 'type', LabelEditingProvider ],
39651 	  labelEditingPreview: [ 'type', LabelEditingPreview ]
39652 	};
39653 
39654 	var ALIGNMENTS = [
39655 	  'top',
39656 	  'bottom',
39657 	  'left',
39658 	  'right'
39659 	];
39660 
39661 	var ELEMENT_LABEL_DISTANCE = 10;
39662 
39663 	/**
39664 	 * A component that makes sure that external labels are added
39665 	 * together with respective elements and properly updated (DI wise)
39666 	 * during move.
39667 	 *
39668 	 * @param {EventBus} eventBus
39669 	 * @param {Modeling} modeling
39670 	 */
39671 	function AdaptiveLabelPositioningBehavior(eventBus, modeling) {
39672 
39673 	  CommandInterceptor.call(this, eventBus);
39674 
39675 	  this.postExecuted([
39676 	    'connection.create',
39677 	    'connection.layout',
39678 	    'connection.updateWaypoints'
39679 	  ], function(event) {
39680 	    var context = event.context,
39681 	        connection = context.connection,
39682 	        source = connection.source,
39683 	        target = connection.target,
39684 	        hints = context.hints || {};
39685 
39686 	    if (hints.createElementsBehavior !== false) {
39687 	      checkLabelAdjustment(source);
39688 	      checkLabelAdjustment(target);
39689 	    }
39690 	  });
39691 
39692 
39693 	  this.postExecuted([
39694 	    'label.create'
39695 	  ], function(event) {
39696 	    var context = event.context,
39697 	        shape = context.shape,
39698 	        hints = context.hints || {};
39699 
39700 	    if (hints.createElementsBehavior !== false) {
39701 	      checkLabelAdjustment(shape.labelTarget);
39702 	    }
39703 	  });
39704 
39705 
39706 	  this.postExecuted([
39707 	    'elements.create'
39708 	  ], function(event) {
39709 	    var context = event.context,
39710 	        elements = context.elements,
39711 	        hints = context.hints || {};
39712 
39713 	    if (hints.createElementsBehavior !== false) {
39714 	      elements.forEach(function(element) {
39715 	        checkLabelAdjustment(element);
39716 	      });
39717 	    }
39718 	  });
39719 
39720 	  function checkLabelAdjustment(element) {
39721 
39722 	    // skip non-existing labels
39723 	    if (!hasExternalLabel(element)) {
39724 	      return;
39725 	    }
39726 
39727 	    var optimalPosition = getOptimalPosition(element);
39728 
39729 	    // no optimal position found
39730 	    if (!optimalPosition) {
39731 	      return;
39732 	    }
39733 
39734 	    adjustLabelPosition(element, optimalPosition);
39735 	  }
39736 
39737 	  function adjustLabelPosition(element, orientation) {
39738 
39739 	    var elementMid = getMid(element),
39740 	        label = element.label,
39741 	        labelMid = getMid(label);
39742 
39743 	    // ignore labels that are being created
39744 	    if (!label.parent) {
39745 	      return;
39746 	    }
39747 
39748 	    var elementTrbl = asTRBL(element);
39749 
39750 	    var newLabelMid;
39751 
39752 	    switch (orientation) {
39753 	    case 'top':
39754 	      newLabelMid = {
39755 	        x: elementMid.x,
39756 	        y: elementTrbl.top - ELEMENT_LABEL_DISTANCE - label.height / 2
39757 	      };
39758 
39759 	      break;
39760 
39761 	    case 'left':
39762 
39763 	      newLabelMid = {
39764 	        x: elementTrbl.left - ELEMENT_LABEL_DISTANCE - label.width / 2,
39765 	        y: elementMid.y
39766 	      };
39767 
39768 	      break;
39769 
39770 	    case 'bottom':
39771 
39772 	      newLabelMid = {
39773 	        x: elementMid.x,
39774 	        y: elementTrbl.bottom + ELEMENT_LABEL_DISTANCE + label.height / 2
39775 	      };
39776 
39777 	      break;
39778 
39779 	    case 'right':
39780 
39781 	      newLabelMid = {
39782 	        x: elementTrbl.right + ELEMENT_LABEL_DISTANCE + label.width / 2,
39783 	        y: elementMid.y
39784 	      };
39785 
39786 	      break;
39787 	    }
39788 
39789 	    var delta$1 = delta(newLabelMid, labelMid);
39790 
39791 	    modeling.moveShape(label, delta$1);
39792 	  }
39793 
39794 	}
39795 
39796 	inherits$1(AdaptiveLabelPositioningBehavior, CommandInterceptor);
39797 
39798 	AdaptiveLabelPositioningBehavior.$inject = [
39799 	  'eventBus',
39800 	  'modeling'
39801 	];
39802 
39803 
39804 	// helpers //////////////////////
39805 
39806 	/**
39807 	 * Return alignments which are taken by a boundary's host element
39808 	 *
39809 	 * @param {Shape} element
39810 	 *
39811 	 * @return {Array<string>}
39812 	 */
39813 	function getTakenHostAlignments(element) {
39814 
39815 	  var hostElement = element.host,
39816 	      elementMid = getMid(element),
39817 	      hostOrientation = getOrientation(elementMid, hostElement);
39818 
39819 	  var freeAlignments;
39820 
39821 	  // check whether there is a multi-orientation, e.g. 'top-left'
39822 	  if (hostOrientation.indexOf('-') >= 0) {
39823 	    freeAlignments = hostOrientation.split('-');
39824 	  } else {
39825 	    freeAlignments = [ hostOrientation ];
39826 	  }
39827 
39828 	  var takenAlignments = ALIGNMENTS.filter(function(alignment) {
39829 
39830 	    return freeAlignments.indexOf(alignment) === -1;
39831 	  });
39832 
39833 	  return takenAlignments;
39834 
39835 	}
39836 
39837 	/**
39838 	 * Return alignments which are taken by related connections
39839 	 *
39840 	 * @param {Shape} element
39841 	 *
39842 	 * @return {Array<string>}
39843 	 */
39844 	function getTakenConnectionAlignments(element) {
39845 
39846 	  var elementMid = getMid(element);
39847 
39848 	  var takenAlignments = [].concat(
39849 	    element.incoming.map(function(c) {
39850 	      return c.waypoints[c.waypoints.length - 2 ];
39851 	    }),
39852 	    element.outgoing.map(function(c) {
39853 	      return c.waypoints[1];
39854 	    })
39855 	  ).map(function(point) {
39856 	    return getApproximateOrientation(elementMid, point);
39857 	  });
39858 
39859 	  return takenAlignments;
39860 	}
39861 
39862 	/**
39863 	 * Return the optimal label position around an element
39864 	 * or _undefined_, if none was found.
39865 	 *
39866 	 * @param  {Shape} element
39867 	 *
39868 	 * @return {string} positioning identifier
39869 	 */
39870 	function getOptimalPosition(element) {
39871 
39872 	  var labelMid = getMid(element.label);
39873 
39874 	  var elementMid = getMid(element);
39875 
39876 	  var labelOrientation = getApproximateOrientation(elementMid, labelMid);
39877 
39878 	  if (!isAligned(labelOrientation)) {
39879 	    return;
39880 	  }
39881 
39882 	  var takenAlignments = getTakenConnectionAlignments(element);
39883 
39884 	  if (element.host) {
39885 	    var takenHostAlignments = getTakenHostAlignments(element);
39886 
39887 	    takenAlignments = takenAlignments.concat(takenHostAlignments);
39888 	  }
39889 
39890 	  var freeAlignments = ALIGNMENTS.filter(function(alignment) {
39891 
39892 	    return takenAlignments.indexOf(alignment) === -1;
39893 	  });
39894 
39895 	  // NOTHING TO DO; label already aligned a.O.K.
39896 	  if (freeAlignments.indexOf(labelOrientation) !== -1) {
39897 	    return;
39898 	  }
39899 
39900 	  return freeAlignments[0];
39901 	}
39902 
39903 	function getApproximateOrientation(p0, p1) {
39904 	  return getOrientation(p1, p0, 5);
39905 	}
39906 
39907 	function isAligned(orientation) {
39908 	  return ALIGNMENTS.indexOf(orientation) !== -1;
39909 	}
39910 
39911 	function AppendBehavior(eventBus, elementFactory, bpmnRules) {
39912 
39913 	  CommandInterceptor.call(this, eventBus);
39914 
39915 	  // assign correct shape position unless already set
39916 
39917 	  this.preExecute('shape.append', function(context) {
39918 
39919 	    var source = context.source,
39920 	        shape = context.shape;
39921 
39922 	    if (!context.position) {
39923 
39924 	      if (is$1(shape, 'bpmn:TextAnnotation')) {
39925 	        context.position = {
39926 	          x: source.x + source.width / 2 + 75,
39927 	          y: source.y - (50) - shape.height / 2
39928 	        };
39929 	      } else {
39930 	        context.position = {
39931 	          x: source.x + source.width + 80 + shape.width / 2,
39932 	          y: source.y + source.height / 2
39933 	        };
39934 	      }
39935 	    }
39936 	  }, true);
39937 	}
39938 
39939 	inherits$1(AppendBehavior, CommandInterceptor);
39940 
39941 	AppendBehavior.$inject = [
39942 	  'eventBus',
39943 	  'elementFactory',
39944 	  'bpmnRules'
39945 	];
39946 
39947 	function AssociationBehavior(injector, modeling) {
39948 	  injector.invoke(CommandInterceptor, this);
39949 
39950 	  this.postExecute('shape.move', function(context) {
39951 	    var newParent = context.newParent,
39952 	        shape = context.shape;
39953 
39954 	    var associations = filter(shape.incoming.concat(shape.outgoing), function(connection) {
39955 	      return is$1(connection, 'bpmn:Association');
39956 	    });
39957 
39958 	    forEach(associations, function(association) {
39959 	      modeling.moveConnection(association, { x: 0, y: 0 }, newParent);
39960 	    });
39961 	  }, true);
39962 	}
39963 
39964 	inherits$1(AssociationBehavior, CommandInterceptor);
39965 
39966 	AssociationBehavior.$inject = [
39967 	  'injector',
39968 	  'modeling'
39969 	];
39970 
39971 	var LOW_PRIORITY$c = 500;
39972 
39973 
39974 	/**
39975 	 * Replace intermediate event with boundary event when creating or moving results in attached event.
39976 	 */
39977 	function AttachEventBehavior(bpmnReplace, injector) {
39978 	  injector.invoke(CommandInterceptor, this);
39979 
39980 	  this._bpmnReplace = bpmnReplace;
39981 
39982 	  var self = this;
39983 
39984 	  this.postExecuted('elements.create', LOW_PRIORITY$c, function(context) {
39985 	    var elements = context.elements;
39986 
39987 	    elements = elements.filter(function(shape) {
39988 	      var host = shape.host;
39989 
39990 	      return shouldReplace$1(shape, host);
39991 	    });
39992 
39993 	    if (elements.length !== 1) {
39994 	      return;
39995 	    }
39996 
39997 	    elements.map(function(element) {
39998 	      return elements.indexOf(element);
39999 	    }).forEach(function(index) {
40000 	      var host = elements[ index ];
40001 
40002 	      context.elements[ index ] = self.replaceShape(elements[ index ], host);
40003 	    });
40004 	  }, true);
40005 
40006 
40007 	  this.preExecute('elements.move', LOW_PRIORITY$c, function(context) {
40008 	    var shapes = context.shapes,
40009 	        host = context.newHost;
40010 
40011 	    if (shapes.length !== 1) {
40012 	      return;
40013 	    }
40014 
40015 	    var shape = shapes[0];
40016 
40017 	    if (shouldReplace$1(shape, host)) {
40018 	      context.shapes = [ self.replaceShape(shape, host) ];
40019 	    }
40020 	  }, true);
40021 	}
40022 
40023 	AttachEventBehavior.$inject = [
40024 	  'bpmnReplace',
40025 	  'injector'
40026 	];
40027 
40028 	inherits$1(AttachEventBehavior, CommandInterceptor);
40029 
40030 	AttachEventBehavior.prototype.replaceShape = function(shape, host) {
40031 	  var eventDefinition = getEventDefinition$1(shape);
40032 
40033 	  var boundaryEvent = {
40034 	    type: 'bpmn:BoundaryEvent',
40035 	    host: host
40036 	  };
40037 
40038 	  if (eventDefinition) {
40039 	    boundaryEvent.eventDefinitionType = eventDefinition.$type;
40040 	  }
40041 
40042 	  return this._bpmnReplace.replaceElement(shape, boundaryEvent, { layoutConnection: false });
40043 	};
40044 
40045 
40046 	// helpers //////////
40047 
40048 	function getEventDefinition$1(element) {
40049 	  var businessObject = getBusinessObject(element),
40050 	      eventDefinitions = businessObject.eventDefinitions;
40051 
40052 	  return eventDefinitions && eventDefinitions[0];
40053 	}
40054 
40055 	function shouldReplace$1(shape, host) {
40056 	  return !isLabel$6(shape) &&
40057 	    isAny(shape, [ 'bpmn:IntermediateThrowEvent', 'bpmn:IntermediateCatchEvent' ]) && !!host;
40058 	}
40059 
40060 	var HIGH_PRIORITY$c = 2000;
40061 
40062 
40063 	/**
40064 	 * BPMN specific boundary event behavior
40065 	 */
40066 	function BoundaryEventBehavior(eventBus, moddle, modeling) {
40067 
40068 	  CommandInterceptor.call(this, eventBus);
40069 
40070 	  function getBoundaryEvents(element) {
40071 	    return filter(element.attachers, function(attacher) {
40072 	      return is$1(attacher, 'bpmn:BoundaryEvent');
40073 	    });
40074 	  }
40075 
40076 	  // remove after connecting to event-based gateway
40077 	  this.postExecute('connection.create', function(event) {
40078 	    var source = event.context.source,
40079 	        target = event.context.target,
40080 	        boundaryEvents = getBoundaryEvents(target);
40081 
40082 	    if (
40083 	      is$1(source, 'bpmn:EventBasedGateway') &&
40084 	      is$1(target, 'bpmn:ReceiveTask') &&
40085 	      boundaryEvents.length > 0
40086 	    ) {
40087 	      modeling.removeElements(boundaryEvents);
40088 	    }
40089 
40090 	  });
40091 
40092 	  // remove after replacing connected gateway with event-based gateway
40093 	  this.postExecute('connection.reconnect', function(event) {
40094 	    var oldSource = event.context.oldSource,
40095 	        newSource = event.context.newSource;
40096 
40097 	    if (is$1(oldSource, 'bpmn:Gateway') &&
40098 	        is$1(newSource, 'bpmn:EventBasedGateway')) {
40099 	      forEach(newSource.outgoing, function(connection) {
40100 	        var target = connection.target,
40101 	            attachedboundaryEvents = getBoundaryEvents(target);
40102 
40103 	        if (is$1(target, 'bpmn:ReceiveTask') &&
40104 	            attachedboundaryEvents.length > 0) {
40105 	          modeling.removeElements(attachedboundaryEvents);
40106 	        }
40107 	      });
40108 	    }
40109 	  });
40110 
40111 	  // copy reference to root element on replace
40112 	  eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY$c, function(context) {
40113 	    var parent = context.parent,
40114 	        property = context.property,
40115 	        propertyName = context.propertyName;
40116 
40117 	    var propertyDescriptor = moddle.getPropertyDescriptor(parent, propertyName);
40118 
40119 	    if (propertyDescriptor && propertyDescriptor.isReference && is$1(property, 'bpmn:RootElement')) {
40120 	      parent.set(propertyName, property);
40121 	    }
40122 	  });
40123 	}
40124 
40125 	BoundaryEventBehavior.$inject = [
40126 	  'eventBus',
40127 	  'moddle',
40128 	  'modeling'
40129 	];
40130 
40131 	inherits$1(BoundaryEventBehavior, CommandInterceptor);
40132 
40133 	var LOW_PRIORITY$b = 500;
40134 
40135 
40136 	/**
40137 	 * Add referenced root elements (error, escalation, message, signal) if they don't exist.
40138 	 * Copy referenced root elements on copy & paste.
40139 	 */
40140 	function RootElementReferenceBehavior(
40141 	    bpmnjs, eventBus, injector, moddleCopy, bpmnFactory
40142 	) {
40143 	  injector.invoke(CommandInterceptor, this);
40144 
40145 	  function canHaveRootElementReference(element) {
40146 	    return isAny(element, [ 'bpmn:ReceiveTask', 'bpmn:SendTask' ]) ||
40147 	      hasAnyEventDefinition(element, [
40148 	        'bpmn:ErrorEventDefinition',
40149 	        'bpmn:EscalationEventDefinition',
40150 	        'bpmn:MessageEventDefinition',
40151 	        'bpmn:SignalEventDefinition'
40152 	      ]);
40153 	  }
40154 
40155 	  function hasRootElement(rootElement) {
40156 	    var definitions = bpmnjs.getDefinitions(),
40157 	        rootElements = definitions.get('rootElements');
40158 
40159 	    return !!find(rootElements, matchPattern({ id: rootElement.id }));
40160 	  }
40161 
40162 	  function getRootElementReferencePropertyName(eventDefinition) {
40163 	    if (is$1(eventDefinition, 'bpmn:ErrorEventDefinition')) {
40164 	      return 'errorRef';
40165 	    } else if (is$1(eventDefinition, 'bpmn:EscalationEventDefinition')) {
40166 	      return 'escalationRef';
40167 	    } else if (is$1(eventDefinition, 'bpmn:MessageEventDefinition')) {
40168 	      return 'messageRef';
40169 	    } else if (is$1(eventDefinition, 'bpmn:SignalEventDefinition')) {
40170 	      return 'signalRef';
40171 	    }
40172 	  }
40173 
40174 	  function getRootElement(businessObject) {
40175 	    if (isAny(businessObject, [ 'bpmn:ReceiveTask', 'bpmn:SendTask' ])) {
40176 	      return businessObject.get('messageRef');
40177 	    }
40178 
40179 	    var eventDefinitions = businessObject.get('eventDefinitions'),
40180 	        eventDefinition = eventDefinitions[ 0 ];
40181 
40182 	    return eventDefinition.get(getRootElementReferencePropertyName(eventDefinition));
40183 	  }
40184 
40185 	  function setRootElement(businessObject, rootElement) {
40186 	    if (isAny(businessObject, [ 'bpmn:ReceiveTask', 'bpmn:SendTask' ])) {
40187 	      return businessObject.set('messageRef', rootElement);
40188 	    }
40189 
40190 	    var eventDefinitions = businessObject.get('eventDefinitions'),
40191 	        eventDefinition = eventDefinitions[ 0 ];
40192 
40193 	    return eventDefinition.set(getRootElementReferencePropertyName(eventDefinition), rootElement);
40194 	  }
40195 
40196 	  // create shape
40197 	  this.executed('shape.create', function(context) {
40198 	    var shape = context.shape;
40199 
40200 	    if (!canHaveRootElementReference(shape)) {
40201 	      return;
40202 	    }
40203 
40204 	    var businessObject = getBusinessObject(shape),
40205 	        rootElement = getRootElement(businessObject),
40206 	        rootElements;
40207 
40208 	    if (rootElement && !hasRootElement(rootElement)) {
40209 	      rootElements = bpmnjs.getDefinitions().get('rootElements');
40210 
40211 	      // add root element
40212 	      add(rootElements, rootElement);
40213 
40214 	      context.addedRootElement = rootElement;
40215 	    }
40216 	  }, true);
40217 
40218 	  this.reverted('shape.create', function(context) {
40219 	    var addedRootElement = context.addedRootElement;
40220 
40221 	    if (!addedRootElement) {
40222 	      return;
40223 	    }
40224 
40225 	    var rootElements = bpmnjs.getDefinitions().get('rootElements');
40226 
40227 	    // remove root element
40228 	    remove(rootElements, addedRootElement);
40229 	  }, true);
40230 
40231 	  eventBus.on('copyPaste.copyElement', function(context) {
40232 	    var descriptor = context.descriptor,
40233 	        element = context.element;
40234 
40235 	    if (!canHaveRootElementReference(element)) {
40236 	      return;
40237 	    }
40238 
40239 	    var businessObject = getBusinessObject(element),
40240 	        rootElement = getRootElement(businessObject);
40241 
40242 	    if (rootElement) {
40243 	      descriptor.referencedRootElement = rootElement;
40244 	    }
40245 	  });
40246 
40247 	  eventBus.on('copyPaste.pasteElement', LOW_PRIORITY$b, function(context) {
40248 	    var descriptor = context.descriptor,
40249 	        businessObject = descriptor.businessObject;
40250 
40251 	    if (!canHaveRootElementReference(businessObject)) {
40252 	      return;
40253 	    }
40254 
40255 	    var referencedRootElement = descriptor.referencedRootElement;
40256 
40257 	    if (!referencedRootElement) {
40258 	      return;
40259 	    }
40260 
40261 	    if (!hasRootElement(referencedRootElement)) {
40262 	      referencedRootElement = moddleCopy.copyElement(
40263 	        referencedRootElement,
40264 	        bpmnFactory.create(referencedRootElement.$type)
40265 	      );
40266 	    }
40267 
40268 	    setRootElement(businessObject, referencedRootElement);
40269 	  });
40270 	}
40271 
40272 	RootElementReferenceBehavior.$inject = [
40273 	  'bpmnjs',
40274 	  'eventBus',
40275 	  'injector',
40276 	  'moddleCopy',
40277 	  'bpmnFactory'
40278 	];
40279 
40280 	inherits$1(RootElementReferenceBehavior, CommandInterceptor);
40281 
40282 	// helpers //////////
40283 
40284 	function hasAnyEventDefinition(element, types) {
40285 	  if (!isArray$2(types)) {
40286 	    types = [ types ];
40287 	  }
40288 
40289 	  return some(types, function(type) {
40290 	    return hasEventDefinition$2(element, type);
40291 	  });
40292 	}
40293 
40294 	function CreateBehavior(injector) {
40295 	  injector.invoke(CommandInterceptor, this);
40296 
40297 	  this.preExecute('shape.create', 1500, function(event) {
40298 	    var context = event.context,
40299 	        parent = context.parent,
40300 	        shape = context.shape;
40301 
40302 	    if (is$1(parent, 'bpmn:Lane') && !is$1(shape, 'bpmn:Lane')) {
40303 	      context.parent = getParent(parent, 'bpmn:Participant');
40304 	    }
40305 	  });
40306 
40307 	}
40308 
40309 
40310 	CreateBehavior.$inject = [ 'injector' ];
40311 
40312 	inherits$1(CreateBehavior, CommandInterceptor);
40313 
40314 	var HIGH_PRIORITY$b = 1500;
40315 	var HIGHEST_PRIORITY = 2000;
40316 
40317 
40318 	/**
40319 	 * Correct hover targets in certain situations to improve diagram interaction.
40320 	 *
40321 	 * @param {ElementRegistry} elementRegistry
40322 	 * @param {EventBus} eventBus
40323 	 * @param {Canvas} canvas
40324 	 */
40325 	function FixHoverBehavior(elementRegistry, eventBus, canvas) {
40326 
40327 	  eventBus.on([
40328 	    'create.hover',
40329 	    'create.move',
40330 	    'create.out',
40331 	    'create.end',
40332 	    'shape.move.hover',
40333 	    'shape.move.move',
40334 	    'shape.move.out',
40335 	    'shape.move.end'
40336 	  ], HIGH_PRIORITY$b, function(event) {
40337 	    var context = event.context,
40338 	        shape = context.shape || event.shape,
40339 	        hover = event.hover;
40340 
40341 	    // ensure elements are not dropped onto a bpmn:Lane but onto
40342 	    // the underlying bpmn:Participant
40343 	    if (is$1(hover, 'bpmn:Lane') && !isAny(shape, [ 'bpmn:Lane', 'bpmn:Participant' ])) {
40344 	      event.hover = getLanesRoot(hover);
40345 	      event.hoverGfx = elementRegistry.getGraphics(event.hover);
40346 	    }
40347 
40348 	    var rootElement = canvas.getRootElement();
40349 
40350 	    // ensure bpmn:Group and label elements are dropped
40351 	    // always onto the root
40352 	    if (hover !== rootElement && (shape.labelTarget || is$1(shape, 'bpmn:Group'))) {
40353 	      event.hover = rootElement;
40354 	      event.hoverGfx = elementRegistry.getGraphics(event.hover);
40355 	    }
40356 	  });
40357 
40358 	  eventBus.on([
40359 	    'connect.hover',
40360 	    'connect.out',
40361 	    'connect.end',
40362 	    'connect.cleanup',
40363 	    'global-connect.hover',
40364 	    'global-connect.out',
40365 	    'global-connect.end',
40366 	    'global-connect.cleanup'
40367 	  ], HIGH_PRIORITY$b, function(event) {
40368 	    var hover = event.hover;
40369 
40370 	    // ensure connections start/end on bpmn:Participant,
40371 	    // not the underlying bpmn:Lane
40372 	    if (is$1(hover, 'bpmn:Lane')) {
40373 	      event.hover = getLanesRoot(hover) || hover;
40374 	      event.hoverGfx = elementRegistry.getGraphics(event.hover);
40375 	    }
40376 	  });
40377 
40378 
40379 	  eventBus.on([
40380 	    'bendpoint.move.hover'
40381 	  ], HIGH_PRIORITY$b, function(event) {
40382 	    var context = event.context,
40383 	        hover = event.hover,
40384 	        type = context.type;
40385 
40386 	    // ensure reconnect start/end on bpmn:Participant,
40387 	    // not the underlying bpmn:Lane
40388 	    if (is$1(hover, 'bpmn:Lane') && /reconnect/.test(type)) {
40389 	      event.hover = getLanesRoot(hover) || hover;
40390 	      event.hoverGfx = elementRegistry.getGraphics(event.hover);
40391 	    }
40392 	  });
40393 
40394 
40395 	  eventBus.on([
40396 	    'connect.start'
40397 	  ], HIGH_PRIORITY$b, function(event) {
40398 	    var context = event.context,
40399 	        start = context.start;
40400 
40401 	    // ensure connect start on bpmn:Participant,
40402 	    // not the underlying bpmn:Lane
40403 	    if (is$1(start, 'bpmn:Lane')) {
40404 	      context.start = getLanesRoot(start) || start;
40405 	    }
40406 	  });
40407 
40408 
40409 	  // allow movement of participants from lanes
40410 	  eventBus.on('shape.move.start', HIGHEST_PRIORITY, function(event) {
40411 	    var shape = event.shape;
40412 
40413 	    if (is$1(shape, 'bpmn:Lane')) {
40414 	      event.shape = getLanesRoot(shape) || shape;
40415 	    }
40416 	  });
40417 
40418 	}
40419 
40420 	FixHoverBehavior.$inject = [
40421 	  'elementRegistry',
40422 	  'eventBus',
40423 	  'canvas'
40424 	];
40425 
40426 	/**
40427 	 * BPMN specific create data object behavior
40428 	 */
40429 	function CreateDataObjectBehavior(eventBus, bpmnFactory, moddle) {
40430 
40431 	  CommandInterceptor.call(this, eventBus);
40432 
40433 	  this.preExecute('shape.create', function(event) {
40434 
40435 	    var context = event.context,
40436 	        shape = context.shape;
40437 
40438 	    if (is$1(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') {
40439 
40440 	      // create a DataObject every time a DataObjectReference is created
40441 	      var dataObject = bpmnFactory.create('bpmn:DataObject');
40442 
40443 	      // set the reference to the DataObject
40444 	      shape.businessObject.dataObjectRef = dataObject;
40445 	    }
40446 	  });
40447 
40448 	}
40449 
40450 	CreateDataObjectBehavior.$inject = [
40451 	  'eventBus',
40452 	  'bpmnFactory',
40453 	  'moddle'
40454 	];
40455 
40456 	inherits$1(CreateDataObjectBehavior, CommandInterceptor);
40457 
40458 	var HORIZONTAL_PARTICIPANT_PADDING = 20,
40459 	    VERTICAL_PARTICIPANT_PADDING = 20;
40460 
40461 	var PARTICIPANT_BORDER_WIDTH = 30;
40462 
40463 	var HIGH_PRIORITY$a = 2000;
40464 
40465 
40466 	/**
40467 	 * BPMN-specific behavior for creating participants.
40468 	 */
40469 	function CreateParticipantBehavior(canvas, eventBus, modeling) {
40470 	  CommandInterceptor.call(this, eventBus);
40471 
40472 	  // fit participant
40473 	  eventBus.on([
40474 	    'create.start',
40475 	    'shape.move.start'
40476 	  ], HIGH_PRIORITY$a, function(event) {
40477 	    var context = event.context,
40478 	        shape = context.shape,
40479 	        rootElement = canvas.getRootElement();
40480 
40481 	    if (!is$1(shape, 'bpmn:Participant') ||
40482 	      !is$1(rootElement, 'bpmn:Process') ||
40483 	      !rootElement.children.length) {
40484 	      return;
40485 	    }
40486 
40487 	    // ignore connections, groups and labels
40488 	    var children = rootElement.children.filter(function(element) {
40489 	      return !is$1(element, 'bpmn:Group') &&
40490 	        !isLabel$6(element) &&
40491 	        !isConnection$9(element);
40492 	    });
40493 
40494 	    // ensure for available children to calculate bounds
40495 	    if (!children.length) {
40496 	      return;
40497 	    }
40498 
40499 	    var childrenBBox = getBBox(children);
40500 
40501 	    var participantBounds = getParticipantBounds(shape, childrenBBox);
40502 
40503 	    // assign width and height
40504 	    assign(shape, participantBounds);
40505 
40506 	    // assign create constraints
40507 	    context.createConstraints = getParticipantCreateConstraints(shape, childrenBBox);
40508 	  });
40509 
40510 	  // force hovering process when creating first participant
40511 	  eventBus.on('create.start', HIGH_PRIORITY$a, function(event) {
40512 	    var context = event.context,
40513 	        shape = context.shape,
40514 	        rootElement = canvas.getRootElement(),
40515 	        rootElementGfx = canvas.getGraphics(rootElement);
40516 
40517 	    function ensureHoveringProcess(event) {
40518 	      event.element = rootElement;
40519 	      event.gfx = rootElementGfx;
40520 	    }
40521 
40522 	    if (is$1(shape, 'bpmn:Participant') && is$1(rootElement, 'bpmn:Process')) {
40523 	      eventBus.on('element.hover', HIGH_PRIORITY$a, ensureHoveringProcess);
40524 
40525 	      eventBus.once('create.cleanup', function() {
40526 	        eventBus.off('element.hover', ensureHoveringProcess);
40527 	      });
40528 	    }
40529 	  });
40530 
40531 	  function ensureCollaboration(context) {
40532 	    var parent = context.parent,
40533 	        collaboration;
40534 
40535 	    var rootElement = canvas.getRootElement();
40536 
40537 	    if (is$1(rootElement, 'bpmn:Collaboration')) {
40538 	      collaboration = rootElement;
40539 	    } else {
40540 
40541 	      // update root element by making collaboration
40542 	      collaboration = modeling.makeCollaboration();
40543 
40544 	      // re-use process when creating first participant
40545 	      context.process = parent;
40546 	    }
40547 
40548 	    context.parent = collaboration;
40549 	  }
40550 
40551 	  // turn process into collaboration before adding participant
40552 	  this.preExecute('shape.create', function(context) {
40553 	    var parent = context.parent,
40554 	        shape = context.shape;
40555 
40556 	    if (is$1(shape, 'bpmn:Participant') && is$1(parent, 'bpmn:Process')) {
40557 	      ensureCollaboration(context);
40558 	    }
40559 	  }, true);
40560 
40561 	  this.execute('shape.create', function(context) {
40562 	    var process = context.process,
40563 	        shape = context.shape;
40564 
40565 	    if (process) {
40566 	      context.oldProcessRef = shape.businessObject.processRef;
40567 
40568 	      // re-use process when creating first participant
40569 	      shape.businessObject.processRef = process.businessObject;
40570 	    }
40571 	  }, true);
40572 
40573 	  this.revert('shape.create', function(context) {
40574 	    var process = context.process,
40575 	        shape = context.shape;
40576 
40577 	    if (process) {
40578 
40579 	      // re-use process when creating first participant
40580 	      shape.businessObject.processRef = context.oldProcessRef;
40581 	    }
40582 	  }, true);
40583 
40584 	  this.postExecute('shape.create', function(context) {
40585 	    var process = context.process,
40586 	        shape = context.shape;
40587 
40588 	    if (process) {
40589 
40590 	      // move children from process to participant
40591 	      var processChildren = process.children.slice();
40592 
40593 	      modeling.moveElements(processChildren, { x: 0, y: 0 }, shape);
40594 	    }
40595 
40596 	  }, true);
40597 
40598 	  // turn process into collaboration when creating participants
40599 	  this.preExecute('elements.create', HIGH_PRIORITY$a, function(context) {
40600 	    var elements = context.elements,
40601 	        parent = context.parent,
40602 	        participant;
40603 
40604 	    var hasParticipants = findParticipant(elements);
40605 
40606 	    if (hasParticipants && is$1(parent, 'bpmn:Process')) {
40607 	      ensureCollaboration(context);
40608 
40609 	      participant = findParticipant(elements);
40610 
40611 	      context.oldProcessRef = participant.businessObject.processRef;
40612 
40613 	      // re-use process when creating first participant
40614 	      participant.businessObject.processRef = parent.businessObject;
40615 	    }
40616 	  }, true);
40617 
40618 	  this.revert('elements.create', function(context) {
40619 	    var elements = context.elements,
40620 	        process = context.process,
40621 	        participant;
40622 
40623 	    if (process) {
40624 	      participant = findParticipant(elements);
40625 
40626 	      // re-use process when creating first participant
40627 	      participant.businessObject.processRef = context.oldProcessRef;
40628 	    }
40629 	  }, true);
40630 
40631 	  this.postExecute('elements.create', function(context) {
40632 	    var elements = context.elements,
40633 	        process = context.process,
40634 	        participant;
40635 
40636 	    if (process) {
40637 	      participant = findParticipant(elements);
40638 
40639 	      // move children from process to first participant
40640 	      var processChildren = process.children.slice();
40641 
40642 	      modeling.moveElements(processChildren, { x: 0, y: 0 }, participant);
40643 	    }
40644 
40645 	  }, true);
40646 
40647 	}
40648 
40649 	CreateParticipantBehavior.$inject = [
40650 	  'canvas',
40651 	  'eventBus',
40652 	  'modeling'
40653 	];
40654 
40655 	inherits$1(CreateParticipantBehavior, CommandInterceptor);
40656 
40657 	// helpers //////////
40658 
40659 	function getParticipantBounds(shape, childrenBBox) {
40660 	  childrenBBox = {
40661 	    width: childrenBBox.width + HORIZONTAL_PARTICIPANT_PADDING * 2 + PARTICIPANT_BORDER_WIDTH,
40662 	    height: childrenBBox.height + VERTICAL_PARTICIPANT_PADDING * 2
40663 	  };
40664 
40665 	  var width = Math.max(shape.width, childrenBBox.width),
40666 	      height = Math.max(shape.height, childrenBBox.height);
40667 
40668 	  return {
40669 	    x: -width / 2,
40670 	    y: -height / 2,
40671 	    width: width,
40672 	    height: height
40673 	  };
40674 	}
40675 
40676 	function getParticipantCreateConstraints(shape, childrenBBox) {
40677 	  childrenBBox = asTRBL(childrenBBox);
40678 
40679 	  return {
40680 	    bottom: childrenBBox.top + shape.height / 2 - VERTICAL_PARTICIPANT_PADDING,
40681 	    left: childrenBBox.right - shape.width / 2 + HORIZONTAL_PARTICIPANT_PADDING,
40682 	    top: childrenBBox.bottom - shape.height / 2 + VERTICAL_PARTICIPANT_PADDING,
40683 	    right: childrenBBox.left + shape.width / 2 - HORIZONTAL_PARTICIPANT_PADDING - PARTICIPANT_BORDER_WIDTH
40684 	  };
40685 	}
40686 
40687 	function isConnection$9(element) {
40688 	  return !!element.waypoints;
40689 	}
40690 
40691 	function findParticipant(elements) {
40692 	  return find(elements, function(element) {
40693 	    return is$1(element, 'bpmn:Participant');
40694 	  });
40695 	}
40696 
40697 	var TARGET_REF_PLACEHOLDER_NAME = '__targetRef_placeholder';
40698 
40699 
40700 	/**
40701 	 * This behavior makes sure we always set a fake
40702 	 * DataInputAssociation#targetRef as demanded by the BPMN 2.0
40703 	 * XSD schema.
40704 	 *
40705 	 * The reference is set to a bpmn:Property{ name: '__targetRef_placeholder' }
40706 	 * which is created on the fly and cleaned up afterwards if not needed
40707 	 * anymore.
40708 	 *
40709 	 * @param {EventBus} eventBus
40710 	 * @param {BpmnFactory} bpmnFactory
40711 	 */
40712 	function DataInputAssociationBehavior(eventBus, bpmnFactory) {
40713 
40714 	  CommandInterceptor.call(this, eventBus);
40715 
40716 
40717 	  this.executed([
40718 	    'connection.create',
40719 	    'connection.delete',
40720 	    'connection.move',
40721 	    'connection.reconnect'
40722 	  ], ifDataInputAssociation(fixTargetRef));
40723 
40724 	  this.reverted([
40725 	    'connection.create',
40726 	    'connection.delete',
40727 	    'connection.move',
40728 	    'connection.reconnect'
40729 	  ], ifDataInputAssociation(fixTargetRef));
40730 
40731 
40732 	  function usesTargetRef(element, targetRef, removedConnection) {
40733 
40734 	    var inputAssociations = element.get('dataInputAssociations');
40735 
40736 	    return find(inputAssociations, function(association) {
40737 	      return association !== removedConnection &&
40738 	             association.targetRef === targetRef;
40739 	    });
40740 	  }
40741 
40742 	  function getTargetRef(element, create) {
40743 
40744 	    var properties = element.get('properties');
40745 
40746 	    var targetRefProp = find(properties, function(p) {
40747 	      return p.name === TARGET_REF_PLACEHOLDER_NAME;
40748 	    });
40749 
40750 	    if (!targetRefProp && create) {
40751 	      targetRefProp = bpmnFactory.create('bpmn:Property', {
40752 	        name: TARGET_REF_PLACEHOLDER_NAME
40753 	      });
40754 
40755 	      add(properties, targetRefProp);
40756 	    }
40757 
40758 	    return targetRefProp;
40759 	  }
40760 
40761 	  function cleanupTargetRef(element, connection) {
40762 
40763 	    var targetRefProp = getTargetRef(element);
40764 
40765 	    if (!targetRefProp) {
40766 	      return;
40767 	    }
40768 
40769 	    if (!usesTargetRef(element, targetRefProp, connection)) {
40770 	      remove(element.get('properties'), targetRefProp);
40771 	    }
40772 	  }
40773 
40774 	  /**
40775 	   * Make sure targetRef is set to a valid property or
40776 	   * `null` if the connection is detached.
40777 	   *
40778 	   * @param {Event} event
40779 	   */
40780 	  function fixTargetRef(event) {
40781 
40782 	    var context = event.context,
40783 	        connection = context.connection,
40784 	        connectionBo = connection.businessObject,
40785 	        target = connection.target,
40786 	        targetBo = target && target.businessObject,
40787 	        newTarget = context.newTarget,
40788 	        newTargetBo = newTarget && newTarget.businessObject,
40789 	        oldTarget = context.oldTarget || context.target,
40790 	        oldTargetBo = oldTarget && oldTarget.businessObject;
40791 
40792 	    var dataAssociation = connection.businessObject,
40793 	        targetRefProp;
40794 
40795 	    if (oldTargetBo && oldTargetBo !== targetBo) {
40796 	      cleanupTargetRef(oldTargetBo, connectionBo);
40797 	    }
40798 
40799 	    if (newTargetBo && newTargetBo !== targetBo) {
40800 	      cleanupTargetRef(newTargetBo, connectionBo);
40801 	    }
40802 
40803 	    if (targetBo) {
40804 	      targetRefProp = getTargetRef(targetBo, true);
40805 	      dataAssociation.targetRef = targetRefProp;
40806 	    } else {
40807 	      dataAssociation.targetRef = null;
40808 	    }
40809 	  }
40810 	}
40811 
40812 	DataInputAssociationBehavior.$inject = [
40813 	  'eventBus',
40814 	  'bpmnFactory'
40815 	];
40816 
40817 	inherits$1(DataInputAssociationBehavior, CommandInterceptor);
40818 
40819 
40820 	/**
40821 	 * Only call the given function when the event
40822 	 * touches a bpmn:DataInputAssociation.
40823 	 *
40824 	 * @param {Function} fn
40825 	 * @return {Function}
40826 	 */
40827 	function ifDataInputAssociation(fn) {
40828 
40829 	  return function(event) {
40830 	    var context = event.context,
40831 	        connection = context.connection;
40832 
40833 	    if (is$1(connection, 'bpmn:DataInputAssociation')) {
40834 	      return fn(event);
40835 	    }
40836 	  };
40837 	}
40838 
40839 	function UpdateSemanticParentHandler(bpmnUpdater) {
40840 	  this._bpmnUpdater = bpmnUpdater;
40841 	}
40842 
40843 	UpdateSemanticParentHandler.$inject = [ 'bpmnUpdater' ];
40844 
40845 
40846 	UpdateSemanticParentHandler.prototype.execute = function(context) {
40847 	  var dataStoreBo = context.dataStoreBo,
40848 	      newSemanticParent = context.newSemanticParent,
40849 	      newDiParent = context.newDiParent;
40850 
40851 	  context.oldSemanticParent = dataStoreBo.$parent;
40852 	  context.oldDiParent = dataStoreBo.di.$parent;
40853 
40854 	  // update semantic parent
40855 	  this._bpmnUpdater.updateSemanticParent(dataStoreBo, newSemanticParent);
40856 
40857 	  // update DI parent
40858 	  this._bpmnUpdater.updateDiParent(dataStoreBo.di, newDiParent);
40859 	};
40860 
40861 	UpdateSemanticParentHandler.prototype.revert = function(context) {
40862 	  var dataStoreBo = context.dataStoreBo,
40863 	      oldSemanticParent = context.oldSemanticParent,
40864 	      oldDiParent = context.oldDiParent;
40865 
40866 	  // update semantic parent
40867 	  this._bpmnUpdater.updateSemanticParent(dataStoreBo, oldSemanticParent);
40868 
40869 	  // update DI parent
40870 	  this._bpmnUpdater.updateDiParent(dataStoreBo.di, oldDiParent);
40871 	};
40872 
40873 	/**
40874 	 * BPMN specific data store behavior
40875 	 */
40876 	function DataStoreBehavior(
40877 	    canvas, commandStack, elementRegistry,
40878 	    eventBus) {
40879 
40880 	  CommandInterceptor.call(this, eventBus);
40881 
40882 	  commandStack.registerHandler('dataStore.updateContainment', UpdateSemanticParentHandler);
40883 
40884 	  function getFirstParticipantWithProcessRef() {
40885 	    return elementRegistry.filter(function(element) {
40886 	      return is$1(element, 'bpmn:Participant') && getBusinessObject(element).processRef;
40887 	    })[0];
40888 	  }
40889 
40890 	  function getDataStores(element) {
40891 	    return element.children.filter(function(child) {
40892 	      return is$1(child, 'bpmn:DataStoreReference') && !child.labelTarget;
40893 	    });
40894 	  }
40895 
40896 	  function updateDataStoreParent(dataStore, newDataStoreParent) {
40897 	    var dataStoreBo = dataStore.businessObject || dataStore;
40898 
40899 	    newDataStoreParent = newDataStoreParent || getFirstParticipantWithProcessRef();
40900 
40901 	    if (newDataStoreParent) {
40902 	      var newDataStoreParentBo = newDataStoreParent.businessObject || newDataStoreParent;
40903 
40904 	      commandStack.execute('dataStore.updateContainment', {
40905 	        dataStoreBo: dataStoreBo,
40906 	        newSemanticParent: newDataStoreParentBo.processRef || newDataStoreParentBo,
40907 	        newDiParent: newDataStoreParentBo.di
40908 	      });
40909 	    }
40910 	  }
40911 
40912 
40913 	  // disable auto-resize for data stores
40914 	  this.preExecute('shape.create', function(event) {
40915 
40916 	    var context = event.context,
40917 	        shape = context.shape;
40918 
40919 	    if (is$1(shape, 'bpmn:DataStoreReference') &&
40920 	        shape.type !== 'label') {
40921 
40922 	      if (!context.hints) {
40923 	        context.hints = {};
40924 	      }
40925 
40926 	      // prevent auto resizing
40927 	      context.hints.autoResize = false;
40928 	    }
40929 	  });
40930 
40931 
40932 	  // disable auto-resize for data stores
40933 	  this.preExecute('elements.move', function(event) {
40934 	    var context = event.context,
40935 	        shapes = context.shapes;
40936 
40937 	    var dataStoreReferences = shapes.filter(function(shape) {
40938 	      return is$1(shape, 'bpmn:DataStoreReference');
40939 	    });
40940 
40941 	    if (dataStoreReferences.length) {
40942 	      if (!context.hints) {
40943 	        context.hints = {};
40944 	      }
40945 
40946 	      // prevent auto resizing for data store references
40947 	      context.hints.autoResize = shapes.filter(function(shape) {
40948 	        return !is$1(shape, 'bpmn:DataStoreReference');
40949 	      });
40950 	    }
40951 	  });
40952 
40953 
40954 	  // update parent on data store created
40955 	  this.postExecute('shape.create', function(event) {
40956 	    var context = event.context,
40957 	        shape = context.shape,
40958 	        parent = shape.parent;
40959 
40960 
40961 	    if (is$1(shape, 'bpmn:DataStoreReference') &&
40962 	        shape.type !== 'label' &&
40963 	        is$1(parent, 'bpmn:Collaboration')) {
40964 
40965 	      updateDataStoreParent(shape);
40966 	    }
40967 	  });
40968 
40969 
40970 	  // update parent on data store moved
40971 	  this.postExecute('shape.move', function(event) {
40972 	    var context = event.context,
40973 	        shape = context.shape,
40974 	        oldParent = context.oldParent,
40975 	        parent = shape.parent;
40976 
40977 	    if (is$1(oldParent, 'bpmn:Collaboration')) {
40978 
40979 	      // do nothing if not necessary
40980 	      return;
40981 	    }
40982 
40983 	    if (is$1(shape, 'bpmn:DataStoreReference') &&
40984 	        shape.type !== 'label' &&
40985 	        is$1(parent, 'bpmn:Collaboration')) {
40986 
40987 	      var participant = is$1(oldParent, 'bpmn:Participant') ?
40988 	        oldParent :
40989 	        getAncestor(oldParent, 'bpmn:Participant');
40990 
40991 	      updateDataStoreParent(shape, participant);
40992 	    }
40993 	  });
40994 
40995 
40996 	  // update data store parents on participant or subprocess deleted
40997 	  this.postExecute('shape.delete', function(event) {
40998 	    var context = event.context,
40999 	        shape = context.shape,
41000 	        rootElement = canvas.getRootElement();
41001 
41002 	    if (isAny(shape, [ 'bpmn:Participant', 'bpmn:SubProcess' ])
41003 	        && is$1(rootElement, 'bpmn:Collaboration')) {
41004 	      getDataStores(rootElement)
41005 	        .filter(function(dataStore) {
41006 	          return isDescendant(dataStore, shape);
41007 	        })
41008 	        .forEach(function(dataStore) {
41009 	          updateDataStoreParent(dataStore);
41010 	        });
41011 	    }
41012 	  });
41013 
41014 	  // update data store parents on collaboration -> process
41015 	  this.postExecute('canvas.updateRoot', function(event) {
41016 	    var context = event.context,
41017 	        oldRoot = context.oldRoot,
41018 	        newRoot = context.newRoot;
41019 
41020 	    var dataStores = getDataStores(oldRoot);
41021 
41022 	    dataStores.forEach(function(dataStore) {
41023 
41024 	      if (is$1(newRoot, 'bpmn:Process')) {
41025 	        updateDataStoreParent(dataStore, newRoot);
41026 	      }
41027 
41028 	    });
41029 	  });
41030 	}
41031 
41032 	DataStoreBehavior.$inject = [
41033 	  'canvas',
41034 	  'commandStack',
41035 	  'elementRegistry',
41036 	  'eventBus',
41037 	];
41038 
41039 	inherits$1(DataStoreBehavior, CommandInterceptor);
41040 
41041 
41042 	// helpers //////////
41043 
41044 	function isDescendant(descendant, ancestor) {
41045 	  var descendantBo = descendant.businessObject || descendant,
41046 	      ancestorBo = ancestor.businessObject || ancestor;
41047 
41048 	  while (descendantBo.$parent) {
41049 	    if (descendantBo.$parent === ancestorBo.processRef || ancestorBo) {
41050 	      return true;
41051 	    }
41052 
41053 	    descendantBo = descendantBo.$parent;
41054 	  }
41055 
41056 	  return false;
41057 	}
41058 
41059 	function getAncestor(element, type) {
41060 
41061 	  while (element.parent) {
41062 	    if (is$1(element.parent, type)) {
41063 	      return element.parent;
41064 	    }
41065 
41066 	    element = element.parent;
41067 	  }
41068 	}
41069 
41070 	var LOW_PRIORITY$a = 500;
41071 
41072 
41073 	/**
41074 	 * BPMN specific delete lane behavior
41075 	 */
41076 	function DeleteLaneBehavior(eventBus, modeling, spaceTool) {
41077 
41078 	  CommandInterceptor.call(this, eventBus);
41079 
41080 
41081 	  function compensateLaneDelete(shape, oldParent) {
41082 
41083 	    var siblings = getChildLanes(oldParent);
41084 
41085 	    var topAffected = [];
41086 	    var bottomAffected = [];
41087 
41088 	    eachElement(siblings, function(element) {
41089 
41090 	      if (element.y > shape.y) {
41091 	        bottomAffected.push(element);
41092 	      } else {
41093 	        topAffected.push(element);
41094 	      }
41095 
41096 	      return element.children;
41097 	    });
41098 
41099 	    if (!siblings.length) {
41100 	      return;
41101 	    }
41102 
41103 	    var offset;
41104 
41105 	    if (bottomAffected.length && topAffected.length) {
41106 	      offset = shape.height / 2;
41107 	    } else {
41108 	      offset = shape.height;
41109 	    }
41110 
41111 	    var topAdjustments,
41112 	        bottomAdjustments;
41113 
41114 	    if (topAffected.length) {
41115 	      topAdjustments = spaceTool.calculateAdjustments(
41116 	        topAffected, 'y', offset, shape.y - 10);
41117 
41118 	      spaceTool.makeSpace(
41119 	        topAdjustments.movingShapes,
41120 	        topAdjustments.resizingShapes,
41121 	        { x: 0, y: offset }, 's');
41122 	    }
41123 
41124 	    if (bottomAffected.length) {
41125 	      bottomAdjustments = spaceTool.calculateAdjustments(
41126 	        bottomAffected, 'y', -offset, shape.y + shape.height + 10);
41127 
41128 	      spaceTool.makeSpace(
41129 	        bottomAdjustments.movingShapes,
41130 	        bottomAdjustments.resizingShapes,
41131 	        { x: 0, y: -offset }, 'n');
41132 	    }
41133 	  }
41134 
41135 
41136 	  /**
41137 	   * Adjust sizes of other lanes after lane deletion
41138 	   */
41139 	  this.postExecuted('shape.delete', LOW_PRIORITY$a, function(event) {
41140 
41141 	    var context = event.context,
41142 	        hints = context.hints,
41143 	        shape = context.shape,
41144 	        oldParent = context.oldParent;
41145 
41146 	    // only compensate lane deletes
41147 	    if (!is$1(shape, 'bpmn:Lane')) {
41148 	      return;
41149 	    }
41150 
41151 	    // compensate root deletes only
41152 	    if (hints && hints.nested) {
41153 	      return;
41154 	    }
41155 
41156 	    compensateLaneDelete(shape, oldParent);
41157 	  });
41158 	}
41159 
41160 	DeleteLaneBehavior.$inject = [
41161 	  'eventBus',
41162 	  'modeling',
41163 	  'spaceTool'
41164 	];
41165 
41166 	inherits$1(DeleteLaneBehavior, CommandInterceptor);
41167 
41168 	var LOW_PRIORITY$9 = 500;
41169 
41170 
41171 	/**
41172 	 * Replace boundary event with intermediate event when creating or moving results in detached event.
41173 	 */
41174 	function DetachEventBehavior(bpmnReplace, injector) {
41175 	  injector.invoke(CommandInterceptor, this);
41176 
41177 	  this._bpmnReplace = bpmnReplace;
41178 
41179 	  var self = this;
41180 
41181 	  this.postExecuted('elements.create', LOW_PRIORITY$9, function(context) {
41182 	    var elements = context.elements;
41183 
41184 	    elements.filter(function(shape) {
41185 	      var host = shape.host;
41186 
41187 	      return shouldReplace(shape, host);
41188 	    }).map(function(shape) {
41189 	      return elements.indexOf(shape);
41190 	    }).forEach(function(index) {
41191 	      context.elements[ index ] = self.replaceShape(elements[ index ]);
41192 	    });
41193 	  }, true);
41194 
41195 	  this.preExecute('elements.move', LOW_PRIORITY$9, function(context) {
41196 	    var shapes = context.shapes,
41197 	        newHost = context.newHost;
41198 
41199 	    shapes.forEach(function(shape, index) {
41200 	      var host = shape.host;
41201 
41202 	      if (shouldReplace(shape, includes$6(shapes, host) ? host : newHost)) {
41203 	        shapes[ index ] = self.replaceShape(shape);
41204 	      }
41205 	    });
41206 	  }, true);
41207 	}
41208 
41209 	DetachEventBehavior.$inject = [
41210 	  'bpmnReplace',
41211 	  'injector'
41212 	];
41213 
41214 	inherits$1(DetachEventBehavior, CommandInterceptor);
41215 
41216 	DetachEventBehavior.prototype.replaceShape = function(shape) {
41217 	  var eventDefinition = getEventDefinition(shape),
41218 	      intermediateEvent;
41219 
41220 	  if (eventDefinition) {
41221 	    intermediateEvent = {
41222 	      type: 'bpmn:IntermediateCatchEvent',
41223 	      eventDefinitionType: eventDefinition.$type
41224 	    };
41225 	  } else {
41226 	    intermediateEvent = {
41227 	      type: 'bpmn:IntermediateThrowEvent'
41228 	    };
41229 	  }
41230 
41231 	  return this._bpmnReplace.replaceElement(shape, intermediateEvent, { layoutConnection: false });
41232 	};
41233 
41234 
41235 	// helpers //////////
41236 
41237 	function getEventDefinition(element) {
41238 	  var businessObject = getBusinessObject(element),
41239 	      eventDefinitions = businessObject.eventDefinitions;
41240 
41241 	  return eventDefinitions && eventDefinitions[0];
41242 	}
41243 
41244 	function shouldReplace(shape, host) {
41245 	  return !isLabel$6(shape) && is$1(shape, 'bpmn:BoundaryEvent') && !host;
41246 	}
41247 
41248 	function includes$6(array, item) {
41249 	  return array.indexOf(item) !== -1;
41250 	}
41251 
41252 	function DropOnFlowBehavior(eventBus, bpmnRules, modeling) {
41253 
41254 	  CommandInterceptor.call(this, eventBus);
41255 
41256 	  /**
41257 	   * Reconnect start / end of a connection after
41258 	   * dropping an element on a flow.
41259 	   */
41260 
41261 	  function insertShape(shape, targetFlow, positionOrBounds) {
41262 	    var waypoints = targetFlow.waypoints,
41263 	        waypointsBefore,
41264 	        waypointsAfter,
41265 	        dockingPoint,
41266 	        source,
41267 	        target,
41268 	        incomingConnection,
41269 	        outgoingConnection,
41270 	        oldOutgoing = shape.outgoing.slice(),
41271 	        oldIncoming = shape.incoming.slice();
41272 
41273 	    var mid;
41274 
41275 	    if (isNumber(positionOrBounds.width)) {
41276 	      mid = getMid(positionOrBounds);
41277 	    } else {
41278 	      mid = positionOrBounds;
41279 	    }
41280 
41281 	    var intersection = getApproxIntersection(waypoints, mid);
41282 
41283 	    if (intersection) {
41284 	      waypointsBefore = waypoints.slice(0, intersection.index);
41285 	      waypointsAfter = waypoints.slice(intersection.index + (intersection.bendpoint ? 1 : 0));
41286 
41287 	      // due to inaccuracy intersection might have been found
41288 	      if (!waypointsBefore.length || !waypointsAfter.length) {
41289 	        return;
41290 	      }
41291 
41292 	      dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : mid;
41293 
41294 	      // if last waypointBefore is inside shape's bounds, ignore docking point
41295 	      if (!isPointInsideBBox(shape, waypointsBefore[waypointsBefore.length-1])) {
41296 	        waypointsBefore.push(copy(dockingPoint));
41297 	      }
41298 
41299 	      // if first waypointAfter is inside shape's bounds, ignore docking point
41300 	      if (!isPointInsideBBox(shape, waypointsAfter[0])) {
41301 	        waypointsAfter.unshift(copy(dockingPoint));
41302 	      }
41303 	    }
41304 
41305 	    source = targetFlow.source;
41306 	    target = targetFlow.target;
41307 
41308 	    if (bpmnRules.canConnect(source, shape, targetFlow)) {
41309 
41310 	      // reconnect source -> inserted shape
41311 	      modeling.reconnectEnd(targetFlow, shape, waypointsBefore || mid);
41312 
41313 	      incomingConnection = targetFlow;
41314 	    }
41315 
41316 	    if (bpmnRules.canConnect(shape, target, targetFlow)) {
41317 
41318 	      if (!incomingConnection) {
41319 
41320 	        // reconnect inserted shape -> end
41321 	        modeling.reconnectStart(targetFlow, shape, waypointsAfter || mid);
41322 
41323 	        outgoingConnection = targetFlow;
41324 	      } else {
41325 	        outgoingConnection = modeling.connect(
41326 	          shape, target, { type: targetFlow.type, waypoints: waypointsAfter }
41327 	        );
41328 	      }
41329 	    }
41330 
41331 	    var duplicateConnections = [].concat(
41332 
41333 	      incomingConnection && filter(oldIncoming, function(connection) {
41334 	        return connection.source === incomingConnection.source;
41335 	      }) || [],
41336 
41337 	      outgoingConnection && filter(oldOutgoing, function(connection) {
41338 	        return connection.target === outgoingConnection.target;
41339 	      }) || []
41340 	    );
41341 
41342 	    if (duplicateConnections.length) {
41343 	      modeling.removeElements(duplicateConnections);
41344 	    }
41345 	  }
41346 
41347 	  this.preExecute('elements.move', function(context) {
41348 
41349 	    var newParent = context.newParent,
41350 	        shapes = context.shapes,
41351 	        delta = context.delta,
41352 	        shape = shapes[0];
41353 
41354 	    if (!shape || !newParent) {
41355 	      return;
41356 	    }
41357 
41358 	    // if the new parent is a connection,
41359 	    // change it to the new parent's parent
41360 	    if (newParent && newParent.waypoints) {
41361 	      context.newParent = newParent = newParent.parent;
41362 	    }
41363 
41364 	    var shapeMid = getMid(shape);
41365 	    var newShapeMid = {
41366 	      x: shapeMid.x + delta.x,
41367 	      y: shapeMid.y + delta.y
41368 	    };
41369 
41370 	    // find a connection which intersects with the
41371 	    // element's mid point
41372 	    var connection = find(newParent.children, function(element) {
41373 	      var canInsert = bpmnRules.canInsert(shapes, element);
41374 
41375 	      return canInsert && getApproxIntersection(element.waypoints, newShapeMid);
41376 	    });
41377 
41378 	    if (connection) {
41379 	      context.targetFlow = connection;
41380 	      context.position = newShapeMid;
41381 	    }
41382 
41383 	  }, true);
41384 
41385 	  this.postExecuted('elements.move', function(context) {
41386 
41387 	    var shapes = context.shapes,
41388 	        targetFlow = context.targetFlow,
41389 	        position = context.position;
41390 
41391 	    if (targetFlow) {
41392 	      insertShape(shapes[0], targetFlow, position);
41393 	    }
41394 
41395 	  }, true);
41396 
41397 	  this.preExecute('shape.create', function(context) {
41398 
41399 	    var parent = context.parent,
41400 	        shape = context.shape;
41401 
41402 	    if (bpmnRules.canInsert(shape, parent)) {
41403 	      context.targetFlow = parent;
41404 	      context.parent = parent.parent;
41405 	    }
41406 	  }, true);
41407 
41408 	  this.postExecuted('shape.create', function(context) {
41409 
41410 	    var shape = context.shape,
41411 	        targetFlow = context.targetFlow,
41412 	        positionOrBounds = context.position;
41413 
41414 	    if (targetFlow) {
41415 	      insertShape(shape, targetFlow, positionOrBounds);
41416 	    }
41417 	  }, true);
41418 	}
41419 
41420 	inherits$1(DropOnFlowBehavior, CommandInterceptor);
41421 
41422 	DropOnFlowBehavior.$inject = [
41423 	  'eventBus',
41424 	  'bpmnRules',
41425 	  'modeling'
41426 	];
41427 
41428 
41429 	// helpers /////////////////////
41430 
41431 	function isPointInsideBBox(bbox, point) {
41432 	  var x = point.x,
41433 	      y = point.y;
41434 
41435 	  return x >= bbox.x &&
41436 	    x <= bbox.x + bbox.width &&
41437 	    y >= bbox.y &&
41438 	    y <= bbox.y + bbox.height;
41439 	}
41440 
41441 	function copy(obj) {
41442 	  return assign({}, obj);
41443 	}
41444 
41445 	function EventBasedGatewayBehavior(eventBus, modeling) {
41446 
41447 	  CommandInterceptor.call(this, eventBus);
41448 
41449 	  /**
41450 	   * Remove existing sequence flows of event-based target before connecting
41451 	   * from event-based gateway.
41452 	   */
41453 	  this.preExecuted('connection.create', function(event) {
41454 
41455 	    var context = event.context,
41456 	        source = context.source,
41457 	        target = context.target,
41458 	        existingIncomingConnections = target.incoming.slice();
41459 
41460 	    if (context.hints && context.hints.createElementsBehavior === false) {
41461 	      return;
41462 	    }
41463 
41464 	    if (
41465 	      is$1(source, 'bpmn:EventBasedGateway') &&
41466 	      target.incoming.length
41467 	    ) {
41468 
41469 	      existingIncomingConnections.filter(isSequenceFlow)
41470 	        .forEach(function(sequenceFlow) {
41471 	          modeling.removeConnection(sequenceFlow);
41472 	        });
41473 	    }
41474 	  });
41475 
41476 	  /**
41477 	   *  After replacing shape with event-based gateway, remove incoming sequence
41478 	   *  flows of event-based targets which do not belong to event-based gateway
41479 	   *  source.
41480 	   */
41481 	  this.preExecuted('shape.replace', function(event) {
41482 
41483 	    var newShape = event.context.newShape,
41484 	        newShapeTargets,
41485 	        newShapeTargetsIncomingSequenceFlows;
41486 
41487 	    if (!is$1(newShape, 'bpmn:EventBasedGateway')) {
41488 	      return;
41489 	    }
41490 
41491 	    newShapeTargets = newShape.outgoing.filter(isSequenceFlow)
41492 	      .map(function(sequenceFlow) {
41493 	        return sequenceFlow.target;
41494 	      });
41495 
41496 	    newShapeTargetsIncomingSequenceFlows = newShapeTargets.reduce(function(sequenceFlows, target) {
41497 	      var incomingSequenceFlows = target.incoming.filter(isSequenceFlow);
41498 
41499 	      return sequenceFlows.concat(incomingSequenceFlows);
41500 	    }, []);
41501 
41502 	    newShapeTargetsIncomingSequenceFlows.forEach(function(sequenceFlow) {
41503 	      if (sequenceFlow.source !== newShape) {
41504 	        modeling.removeConnection(sequenceFlow);
41505 	      }
41506 	    });
41507 	  });
41508 	}
41509 
41510 	EventBasedGatewayBehavior.$inject = [
41511 	  'eventBus',
41512 	  'modeling'
41513 	];
41514 
41515 	inherits$1(EventBasedGatewayBehavior, CommandInterceptor);
41516 
41517 
41518 
41519 	// helpers //////////////////////
41520 
41521 	function isSequenceFlow(connection) {
41522 	  return is$1(connection, 'bpmn:SequenceFlow');
41523 	}
41524 
41525 	var HIGH_PRIORITY$9 = 2000;
41526 
41527 
41528 	/**
41529 	 * BPMN specific Group behavior
41530 	 */
41531 	function GroupBehavior(
41532 	    bpmnFactory,
41533 	    canvas,
41534 	    elementRegistry,
41535 	    eventBus,
41536 	    injector,
41537 	    moddleCopy
41538 	) {
41539 	  injector.invoke(CommandInterceptor, this);
41540 
41541 	  /**
41542 	   * Gets process definitions
41543 	   *
41544 	   * @return {ModdleElement} definitions
41545 	   */
41546 	  function getDefinitions() {
41547 	    var rootElement = canvas.getRootElement(),
41548 	        businessObject = getBusinessObject(rootElement);
41549 
41550 	    return businessObject.$parent;
41551 	  }
41552 
41553 	  /**
41554 	   * Removes a referenced category value for a given group shape
41555 	   *
41556 	   * @param {djs.model.Shape} shape
41557 	   */
41558 	  function removeReferencedCategoryValue(shape) {
41559 
41560 	    var businessObject = getBusinessObject(shape),
41561 	        categoryValue = businessObject.categoryValueRef;
41562 
41563 	    if (!categoryValue) {
41564 	      return;
41565 	    }
41566 
41567 	    var category = categoryValue.$parent;
41568 
41569 	    if (!categoryValue) {
41570 	      return;
41571 	    }
41572 
41573 	    remove(category.categoryValue, categoryValue);
41574 
41575 	    // cleanup category if it is empty
41576 	    if (category && !category.categoryValue.length) {
41577 	      removeCategory(category);
41578 	    }
41579 	  }
41580 
41581 	  /**
41582 	   * Removes a given category from the definitions
41583 	   *
41584 	   * @param {ModdleElement} category
41585 	   */
41586 	  function removeCategory(category) {
41587 
41588 	    var definitions = getDefinitions();
41589 
41590 	    remove(definitions.get('rootElements'), category);
41591 	  }
41592 
41593 	  /**
41594 	   * Returns all group element in the current registry
41595 	   *
41596 	   * @return {Array<djs.model.shape>} a list of group shapes
41597 	   */
41598 	  function getGroupElements() {
41599 	    return elementRegistry.filter(function(e) {
41600 	      return is$1(e, 'bpmn:Group');
41601 	    });
41602 	  }
41603 
41604 	  /**
41605 	   * Returns true if given categoryValue is referenced in one of the given elements
41606 	   *
41607 	   * @param {Array<djs.model.shape>} elements
41608 	   * @param {ModdleElement} categoryValue
41609 	   * @return {boolean}
41610 	   */
41611 	  function isReferenced(elements, categoryValue) {
41612 	    return elements.some(function(e) {
41613 
41614 	      var businessObject = getBusinessObject(e);
41615 
41616 	      return businessObject.categoryValueRef
41617 	        && businessObject.categoryValueRef === categoryValue;
41618 	    });
41619 	  }
41620 
41621 	  /**
41622 	   * remove referenced category + value when group was deleted
41623 	   */
41624 	  this.executed('shape.delete', function(event) {
41625 
41626 	    var context = event.context,
41627 	        shape = context.shape;
41628 
41629 	    if (is$1(shape, 'bpmn:Group')) {
41630 
41631 	      var businessObject = getBusinessObject(shape),
41632 	          categoryValueRef = businessObject.categoryValueRef,
41633 	          groupElements = getGroupElements();
41634 
41635 	      if (!isReferenced(groupElements, categoryValueRef)) {
41636 	        removeReferencedCategoryValue(shape);
41637 	      }
41638 	    }
41639 	  });
41640 
41641 	  /**
41642 	   * re-attach removed category
41643 	   */
41644 	  this.reverted('shape.delete', function(event) {
41645 
41646 	    var context = event.context,
41647 	        shape = context.shape;
41648 
41649 	    if (is$1(shape, 'bpmn:Group')) {
41650 
41651 	      var businessObject = getBusinessObject(shape),
41652 	          categoryValueRef = businessObject.categoryValueRef,
41653 	          definitions = getDefinitions(),
41654 	          category = categoryValueRef ? categoryValueRef.$parent : null;
41655 
41656 	      add(category.get('categoryValue'), categoryValueRef);
41657 	      add(definitions.get('rootElements'), category);
41658 	    }
41659 	  });
41660 
41661 	  /**
41662 	   * create new category + value when group was created
41663 	   */
41664 	  this.execute('shape.create', function(event) {
41665 	    var context = event.context,
41666 	        shape = context.shape,
41667 	        businessObject = getBusinessObject(shape);
41668 
41669 	    if (is$1(businessObject, 'bpmn:Group') && !businessObject.categoryValueRef) {
41670 
41671 	      var definitions = getDefinitions(),
41672 	          categoryValue = createCategoryValue(definitions, bpmnFactory);
41673 
41674 	      // link the reference to the Group
41675 	      businessObject.categoryValueRef = categoryValue;
41676 	    }
41677 	  });
41678 
41679 
41680 	  this.revert('shape.create', function(event) {
41681 
41682 	    var context = event.context,
41683 	        shape = context.shape;
41684 
41685 	    if (is$1(shape, 'bpmn:Group')) {
41686 	      removeReferencedCategoryValue(shape);
41687 
41688 	      delete getBusinessObject(shape).categoryValueRef;
41689 
41690 	    }
41691 	  });
41692 
41693 	  // copy bpmn:CategoryValue when copying element
41694 	  eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY$9, function(context) {
41695 	    var property = context.property,
41696 	        categoryValue;
41697 
41698 	    if (is$1(property, 'bpmn:CategoryValue')) {
41699 	      categoryValue = createCategoryValue(getDefinitions(), bpmnFactory);
41700 
41701 	      // return copy of category
41702 	      return moddleCopy.copyElement(property, categoryValue);
41703 	    }
41704 	  });
41705 
41706 	}
41707 
41708 	GroupBehavior.$inject = [
41709 	  'bpmnFactory',
41710 	  'canvas',
41711 	  'elementRegistry',
41712 	  'eventBus',
41713 	  'injector',
41714 	  'moddleCopy'
41715 	];
41716 
41717 	inherits$1(GroupBehavior, CommandInterceptor);
41718 
41719 	/**
41720 	 * Returns the intersection between two line segments a and b.
41721 	 *
41722 	 * @param {Point} l1s
41723 	 * @param {Point} l1e
41724 	 * @param {Point} l2s
41725 	 * @param {Point} l2e
41726 	 *
41727 	 * @return {Point}
41728 	 */
41729 	function lineIntersect(l1s, l1e, l2s, l2e) {
41730 
41731 	  // if the lines intersect, the result contains the x and y of the
41732 	  // intersection (treating the lines as infinite) and booleans for
41733 	  // whether line segment 1 or line segment 2 contain the point
41734 	  var denominator, a, b, c, numerator;
41735 
41736 	  denominator = ((l2e.y - l2s.y) * (l1e.x - l1s.x)) - ((l2e.x - l2s.x) * (l1e.y - l1s.y));
41737 
41738 	  if (denominator == 0) {
41739 	    return null;
41740 	  }
41741 
41742 	  a = l1s.y - l2s.y;
41743 	  b = l1s.x - l2s.x;
41744 	  numerator = ((l2e.x - l2s.x) * a) - ((l2e.y - l2s.y) * b);
41745 
41746 	  c = numerator / denominator;
41747 
41748 	  // if we cast these lines infinitely in
41749 	  // both directions, they intersect here
41750 	  return {
41751 	    x: Math.round(l1s.x + (c * (l1e.x - l1s.x))),
41752 	    y: Math.round(l1s.y + (c * (l1e.y - l1s.y)))
41753 	  };
41754 	}
41755 
41756 	/**
41757 	 * Fix broken dockings after DI imports.
41758 	 *
41759 	 * @param {EventBus} eventBus
41760 	 */
41761 	function ImportDockingFix(eventBus) {
41762 
41763 	  function adjustDocking(startPoint, nextPoint, elementMid) {
41764 
41765 	    var elementTop = {
41766 	      x: elementMid.x,
41767 	      y: elementMid.y - 50
41768 	    };
41769 
41770 	    var elementLeft = {
41771 	      x: elementMid.x - 50,
41772 	      y: elementMid.y
41773 	    };
41774 
41775 	    var verticalIntersect = lineIntersect(startPoint, nextPoint, elementMid, elementTop),
41776 	        horizontalIntersect = lineIntersect(startPoint, nextPoint, elementMid, elementLeft);
41777 
41778 	    // original is horizontal or vertical center cross intersection
41779 	    var centerIntersect;
41780 
41781 	    if (verticalIntersect && horizontalIntersect) {
41782 	      if (getDistance$1(verticalIntersect, elementMid) > getDistance$1(horizontalIntersect, elementMid)) {
41783 	        centerIntersect = horizontalIntersect;
41784 	      } else {
41785 	        centerIntersect = verticalIntersect;
41786 	      }
41787 	    } else {
41788 	      centerIntersect = verticalIntersect || horizontalIntersect;
41789 	    }
41790 
41791 	    startPoint.original = centerIntersect;
41792 	  }
41793 
41794 	  function fixDockings(connection) {
41795 	    var waypoints = connection.waypoints;
41796 
41797 	    adjustDocking(
41798 	      waypoints[0],
41799 	      waypoints[1],
41800 	      getMid(connection.source)
41801 	    );
41802 
41803 	    adjustDocking(
41804 	      waypoints[waypoints.length - 1],
41805 	      waypoints[waypoints.length - 2],
41806 	      getMid(connection.target)
41807 	    );
41808 	  }
41809 
41810 	  eventBus.on('bpmnElement.added', function(e) {
41811 
41812 	    var element = e.element;
41813 
41814 	    if (element.waypoints) {
41815 	      fixDockings(element);
41816 	    }
41817 	  });
41818 	}
41819 
41820 	ImportDockingFix.$inject = [
41821 	  'eventBus'
41822 	];
41823 
41824 
41825 	// helpers //////////////////////
41826 
41827 	function getDistance$1(p1, p2) {
41828 	  return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
41829 	}
41830 
41831 	/**
41832 	 * A component that makes sure that each created or updated
41833 	 * Pool and Lane is assigned an isHorizontal property set to true.
41834 	 *
41835 	 * @param {EventBus} eventBus
41836 	 */
41837 	function IsHorizontalFix(eventBus) {
41838 
41839 	  CommandInterceptor.call(this, eventBus);
41840 
41841 	  var elementTypesToUpdate = [
41842 	    'bpmn:Participant',
41843 	    'bpmn:Lane'
41844 	  ];
41845 
41846 	  this.executed([ 'shape.move', 'shape.create', 'shape.resize' ], function(event) {
41847 	    var bo = getBusinessObject(event.context.shape);
41848 
41849 	    if (isAny(bo, elementTypesToUpdate) && !bo.di.get('isHorizontal')) {
41850 
41851 	      // set attribute directly to avoid modeling#updateProperty side effects
41852 	      bo.di.set('isHorizontal', true);
41853 	    }
41854 	  });
41855 
41856 	}
41857 
41858 	IsHorizontalFix.$inject = [ 'eventBus' ];
41859 
41860 	inherits$1(IsHorizontalFix, CommandInterceptor);
41861 
41862 	/**
41863 	 * Returns the length of a vector
41864 	 *
41865 	 * @param {Vector}
41866 	 * @return {Float}
41867 	 */
41868 	function vectorLength(v) {
41869 	  return Math.sqrt(Math.pow(v.x, 2) + Math.pow(v.y, 2));
41870 	}
41871 
41872 
41873 	/**
41874 	 * Calculates the angle between a line a the yAxis
41875 	 *
41876 	 * @param {Array}
41877 	 * @return {Float}
41878 	 */
41879 	function getAngle(line) {
41880 
41881 	  // return value is between 0, 180 and -180, -0
41882 	  // @janstuemmel: maybe replace return a/b with b/a
41883 	  return Math.atan((line[1].y - line[0].y) / (line[1].x - line[0].x));
41884 	}
41885 
41886 
41887 	/**
41888 	 * Rotates a vector by a given angle
41889 	 *
41890 	 * @param {Vector}
41891 	 * @param {Float} Angle in radians
41892 	 * @return {Vector}
41893 	 */
41894 	function rotateVector(vector, angle) {
41895 	  return (!angle) ? vector : {
41896 	    x: Math.cos(angle) * vector.x - Math.sin(angle) * vector.y,
41897 	    y: Math.sin(angle) * vector.x + Math.cos(angle) * vector.y
41898 	  };
41899 	}
41900 
41901 
41902 	/**
41903 	 * Solves a 2D equation system
41904 	 * a + r*b = c, where a,b,c are 2D vectors
41905 	 *
41906 	 * @param {Vector}
41907 	 * @param {Vector}
41908 	 * @param {Vector}
41909 	 * @return {Float}
41910 	 */
41911 	function solveLambaSystem(a, b, c) {
41912 
41913 	  // the 2d system
41914 	  var system = [
41915 	    { n: a[0] - c[0], lambda: b[0] },
41916 	    { n: a[1] - c[1], lambda: b[1] }
41917 	  ];
41918 
41919 	  // solve
41920 	  var n = system[0].n * b[0] + system[1].n * b[1],
41921 	      l = system[0].lambda * b[0] + system[1].lambda * b[1];
41922 
41923 	  return -n/l;
41924 	}
41925 
41926 
41927 	/**
41928 	 * Position of perpendicular foot
41929 	 *
41930 	 * @param {Point}
41931 	 * @param [ {Point}, {Point} ] line defined through two points
41932 	 * @return {Point} the perpendicular foot position
41933 	 */
41934 	function perpendicularFoot(point, line) {
41935 
41936 	  var a = line[0], b = line[1];
41937 
41938 	  // relative position of b from a
41939 	  var bd = { x: b.x - a.x, y: b.y - a.y };
41940 
41941 	  // solve equation system to the parametrized vectors param real value
41942 	  var r = solveLambaSystem([ a.x, a.y ], [ bd.x, bd.y ], [ point.x, point.y ]);
41943 
41944 	  return { x: a.x + r*bd.x, y: a.y + r*bd.y };
41945 	}
41946 
41947 
41948 	/**
41949 	 * Calculates the distance between a point and a line
41950 	 *
41951 	 * @param {Point}
41952 	 * @param [ {Point}, {Point} ] line defined through two points
41953 	 * @return {Float} distance
41954 	 */
41955 	function getDistancePointLine(point, line) {
41956 
41957 	  var pfPoint = perpendicularFoot(point, line);
41958 
41959 	  // distance vector
41960 	  var connectionVector = {
41961 	    x: pfPoint.x - point.x,
41962 	    y: pfPoint.y - point.y
41963 	  };
41964 
41965 	  return vectorLength(connectionVector);
41966 	}
41967 
41968 
41969 	/**
41970 	 * Calculates the distance between two points
41971 	 *
41972 	 * @param {Point}
41973 	 * @param {Point}
41974 	 * @return {Float} distance
41975 	 */
41976 	function getDistancePointPoint(point1, point2) {
41977 
41978 	  return vectorLength({
41979 	    x: point1.x - point2.x,
41980 	    y: point1.y - point2.y
41981 	  });
41982 	}
41983 
41984 	var sqrt = Math.sqrt,
41985 	    min$1 = Math.min,
41986 	    max$3 = Math.max,
41987 	    abs$3 = Math.abs;
41988 
41989 	/**
41990 	 * Calculate the square (power to two) of a number.
41991 	 *
41992 	 * @param {number} n
41993 	 *
41994 	 * @return {number}
41995 	 */
41996 	function sq(n) {
41997 	  return Math.pow(n, 2);
41998 	}
41999 
42000 	/**
42001 	 * Get distance between two points.
42002 	 *
42003 	 * @param {Point} p1
42004 	 * @param {Point} p2
42005 	 *
42006 	 * @return {number}
42007 	 */
42008 	function getDistance(p1, p2) {
42009 	  return sqrt(sq(p1.x - p2.x) + sq(p1.y - p2.y));
42010 	}
42011 
42012 	/**
42013 	 * Return the attachment of the given point on the specified line.
42014 	 *
42015 	 * The attachment is either a bendpoint (attached to the given point)
42016 	 * or segment (attached to a location on a line segment) attachment:
42017 	 *
42018 	 * ```javascript
42019 	 * var pointAttachment = {
42020 	 *   type: 'bendpoint',
42021 	 *   bendpointIndex: 3,
42022 	 *   position: { x: 10, y: 10 } // the attach point on the line
42023 	 * };
42024 	 *
42025 	 * var segmentAttachment = {
42026 	 *   type: 'segment',
42027 	 *   segmentIndex: 2,
42028 	 *   relativeLocation: 0.31, // attach point location between 0 (at start) and 1 (at end)
42029 	 *   position: { x: 10, y: 10 } // the attach point on the line
42030 	 * };
42031 	 * ```
42032 	 *
42033 	 * @param {Point} point
42034 	 * @param {Array<Point>} line
42035 	 *
42036 	 * @return {Object} attachment
42037 	 */
42038 	function getAttachment(point, line) {
42039 
42040 	  var idx = 0,
42041 	      segmentStart,
42042 	      segmentEnd,
42043 	      segmentStartDistance,
42044 	      segmentEndDistance,
42045 	      attachmentPosition,
42046 	      minDistance,
42047 	      intersections,
42048 	      attachment,
42049 	      attachmentDistance,
42050 	      closestAttachmentDistance,
42051 	      closestAttachment;
42052 
42053 	  for (idx = 0; idx < line.length - 1; idx++) {
42054 
42055 	    segmentStart = line[idx];
42056 	    segmentEnd = line[idx + 1];
42057 
42058 	    if (pointsEqual(segmentStart, segmentEnd)) {
42059 	      intersections = [ segmentStart ];
42060 	    } else {
42061 	      segmentStartDistance = getDistance(point, segmentStart);
42062 	      segmentEndDistance = getDistance(point, segmentEnd);
42063 
42064 	      minDistance = min$1(segmentStartDistance, segmentEndDistance);
42065 
42066 	      intersections = getCircleSegmentIntersections(segmentStart, segmentEnd, point, minDistance);
42067 	    }
42068 
42069 	    if (intersections.length < 1) {
42070 	      throw new Error('expected between [1, 2] circle -> line intersections');
42071 	    }
42072 
42073 	    // one intersection -> bendpoint attachment
42074 	    if (intersections.length === 1) {
42075 	      attachment = {
42076 	        type: 'bendpoint',
42077 	        position: intersections[0],
42078 	        segmentIndex: idx,
42079 	        bendpointIndex: pointsEqual(segmentStart, intersections[0]) ? idx : idx + 1
42080 	      };
42081 	    }
42082 
42083 	    // two intersections -> segment attachment
42084 	    if (intersections.length === 2) {
42085 
42086 	      attachmentPosition = mid$1(intersections[0], intersections[1]);
42087 
42088 	      attachment = {
42089 	        type: 'segment',
42090 	        position: attachmentPosition,
42091 	        segmentIndex: idx,
42092 	        relativeLocation: getDistance(segmentStart, attachmentPosition) / getDistance(segmentStart, segmentEnd)
42093 	      };
42094 	    }
42095 
42096 	    attachmentDistance = getDistance(attachment.position, point);
42097 
42098 	    if (!closestAttachment || closestAttachmentDistance > attachmentDistance) {
42099 	      closestAttachment = attachment;
42100 	      closestAttachmentDistance = attachmentDistance;
42101 	    }
42102 	  }
42103 
42104 	  return closestAttachment;
42105 	}
42106 
42107 	/**
42108 	 * Gets the intersection between a circle and a line segment.
42109 	 *
42110 	 * @param {Point} s1 segment start
42111 	 * @param {Point} s2 segment end
42112 	 * @param {Point} cc circle center
42113 	 * @param {number} cr circle radius
42114 	 *
42115 	 * @return {Array<Point>} intersections
42116 	 */
42117 	function getCircleSegmentIntersections(s1, s2, cc, cr) {
42118 
42119 	  var baX = s2.x - s1.x;
42120 	  var baY = s2.y - s1.y;
42121 	  var caX = cc.x - s1.x;
42122 	  var caY = cc.y - s1.y;
42123 
42124 	  var a = baX * baX + baY * baY;
42125 	  var bBy2 = baX * caX + baY * caY;
42126 	  var c = caX * caX + caY * caY - cr * cr;
42127 
42128 	  var pBy2 = bBy2 / a;
42129 	  var q = c / a;
42130 
42131 	  var disc = pBy2 * pBy2 - q;
42132 
42133 	  // check against negative value to work around
42134 	  // negative, very close to zero results (-4e-15)
42135 	  // being produced in some environments
42136 	  if (disc < 0 && disc > -0.000001) {
42137 	    disc = 0;
42138 	  }
42139 
42140 	  if (disc < 0) {
42141 	    return [];
42142 	  }
42143 
42144 	  // if disc == 0 ... dealt with later
42145 	  var tmpSqrt = sqrt(disc);
42146 	  var abScalingFactor1 = -pBy2 + tmpSqrt;
42147 	  var abScalingFactor2 = -pBy2 - tmpSqrt;
42148 
42149 	  var i1 = {
42150 	    x: s1.x - baX * abScalingFactor1,
42151 	    y: s1.y - baY * abScalingFactor1
42152 	  };
42153 
42154 	  if (disc === 0) { // abScalingFactor1 == abScalingFactor2
42155 	    return [ i1 ];
42156 	  }
42157 
42158 	  var i2 = {
42159 	    x: s1.x - baX * abScalingFactor2,
42160 	    y: s1.y - baY * abScalingFactor2
42161 	  };
42162 
42163 	  // return only points on line segment
42164 	  return [ i1, i2 ].filter(function(p) {
42165 	    return isPointInSegment(p, s1, s2);
42166 	  });
42167 	}
42168 
42169 
42170 	function isPointInSegment(p, segmentStart, segmentEnd) {
42171 	  return (
42172 	    fenced(p.x, segmentStart.x, segmentEnd.x) &&
42173 	    fenced(p.y, segmentStart.y, segmentEnd.y)
42174 	  );
42175 	}
42176 
42177 	function fenced(n, rangeStart, rangeEnd) {
42178 
42179 	  // use matching threshold to work around
42180 	  // precision errors in intersection computation
42181 
42182 	  return (
42183 	    n >= min$1(rangeStart, rangeEnd) - EQUAL_THRESHOLD &&
42184 	    n <= max$3(rangeStart, rangeEnd) + EQUAL_THRESHOLD
42185 	  );
42186 	}
42187 
42188 	/**
42189 	 * Calculate mid of two points.
42190 	 *
42191 	 * @param {Point} p1
42192 	 * @param {Point} p2
42193 	 *
42194 	 * @return {Point}
42195 	 */
42196 	function mid$1(p1, p2) {
42197 
42198 	  return {
42199 	    x: (p1.x + p2.x) / 2,
42200 	    y: (p1.y + p2.y) / 2
42201 	  };
42202 	}
42203 
42204 	var EQUAL_THRESHOLD = 0.1;
42205 
42206 	function pointsEqual(p1, p2) {
42207 
42208 	  return (
42209 	    abs$3(p1.x - p2.x) <= EQUAL_THRESHOLD &&
42210 	    abs$3(p1.y - p2.y) <= EQUAL_THRESHOLD
42211 	  );
42212 	}
42213 
42214 	function findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints) {
42215 
42216 	  var index = attachment.segmentIndex;
42217 
42218 	  var offset = newWaypoints.length - oldWaypoints.length;
42219 
42220 	  // segmentMove happened
42221 	  if (hints.segmentMove) {
42222 
42223 	    var oldSegmentStartIndex = hints.segmentMove.segmentStartIndex,
42224 	        newSegmentStartIndex = hints.segmentMove.newSegmentStartIndex;
42225 
42226 	    // if label was on moved segment return new segment index
42227 	    if (index === oldSegmentStartIndex) {
42228 	      return newSegmentStartIndex;
42229 	    }
42230 
42231 	    // label is after new segment index
42232 	    if (index >= newSegmentStartIndex) {
42233 	      return (index+offset < newSegmentStartIndex) ? newSegmentStartIndex : index+offset;
42234 	    }
42235 
42236 	    // if label is before new segment index
42237 	    return index;
42238 	  }
42239 
42240 	  // bendpointMove happened
42241 	  if (hints.bendpointMove) {
42242 
42243 	    var insert = hints.bendpointMove.insert,
42244 	        bendpointIndex = hints.bendpointMove.bendpointIndex,
42245 	        newIndex;
42246 
42247 	    // waypoints length didnt change
42248 	    if (offset === 0) {
42249 	      return index;
42250 	    }
42251 
42252 	    // label behind new/removed bendpoint
42253 	    if (index >= bendpointIndex) {
42254 	      newIndex = insert ? index + 1 : index - 1;
42255 	    }
42256 
42257 	    // label before new/removed bendpoint
42258 	    if (index < bendpointIndex) {
42259 
42260 	      newIndex = index;
42261 
42262 	      // decide label should take right or left segment
42263 	      if (insert && attachment.type !== 'bendpoint' && bendpointIndex-1 === index) {
42264 
42265 	        var rel = relativePositionMidWaypoint(newWaypoints, bendpointIndex);
42266 
42267 	        if (rel < attachment.relativeLocation) {
42268 	          newIndex++;
42269 	        }
42270 	      }
42271 	    }
42272 
42273 	    return newIndex;
42274 	  }
42275 
42276 	  // start/end changed
42277 	  if (offset === 0) {
42278 	    return index;
42279 	  }
42280 
42281 	  if (hints.connectionStart) {
42282 	    return (index === 0) ? 0 : null;
42283 	  }
42284 
42285 	  if (hints.connectionEnd) {
42286 	    return (index === oldWaypoints.length - 2) ? newWaypoints.length - 2 : null;
42287 	  }
42288 
42289 	  // if nothing fits, return null
42290 	  return null;
42291 	}
42292 
42293 
42294 	/**
42295 	 * Calculate the required adjustment (move delta) for the given label
42296 	 * after the connection waypoints got updated.
42297 	 *
42298 	 * @param {djs.model.Label} label
42299 	 * @param {Array<Point>} newWaypoints
42300 	 * @param {Array<Point>} oldWaypoints
42301 	 * @param {Object} hints
42302 	 *
42303 	 * @return {Point} delta
42304 	 */
42305 	function getLabelAdjustment(label, newWaypoints, oldWaypoints, hints) {
42306 
42307 	  var x = 0,
42308 	      y = 0;
42309 
42310 	  var labelPosition = getLabelMid(label);
42311 
42312 	  // get closest attachment
42313 	  var attachment = getAttachment(labelPosition, oldWaypoints),
42314 	      oldLabelLineIndex = attachment.segmentIndex,
42315 	      newLabelLineIndex = findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints);
42316 
42317 	  if (newLabelLineIndex === null) {
42318 	    return { x: x, y: y };
42319 	  }
42320 
42321 	  // should never happen
42322 	  // TODO(@janstuemmel): throw an error here when connectionSegmentMove is refactored
42323 	  if (newLabelLineIndex < 0 ||
42324 	      newLabelLineIndex > newWaypoints.length - 2) {
42325 	    return { x: x, y: y };
42326 	  }
42327 
42328 	  var oldLabelLine = getLine(oldWaypoints, oldLabelLineIndex),
42329 	      newLabelLine = getLine(newWaypoints, newLabelLineIndex),
42330 	      oldFoot = attachment.position;
42331 
42332 	  var relativeFootPosition = getRelativeFootPosition(oldLabelLine, oldFoot),
42333 	      angleDelta = getAngleDelta(oldLabelLine, newLabelLine);
42334 
42335 	  // special rule if label on bendpoint
42336 	  if (attachment.type === 'bendpoint') {
42337 
42338 	    var offset = newWaypoints.length - oldWaypoints.length,
42339 	        oldBendpointIndex = attachment.bendpointIndex,
42340 	        oldBendpoint = oldWaypoints[oldBendpointIndex];
42341 
42342 	    // bendpoint position hasn't changed, return same position
42343 	    if (newWaypoints.indexOf(oldBendpoint) !== -1) {
42344 	      return { x: x, y: y };
42345 	    }
42346 
42347 	    // new bendpoint and old bendpoint have same index, then just return the offset
42348 	    if (offset === 0) {
42349 	      var newBendpoint = newWaypoints[oldBendpointIndex];
42350 
42351 	      return {
42352 	        x: newBendpoint.x - attachment.position.x,
42353 	        y: newBendpoint.y - attachment.position.y
42354 	      };
42355 	    }
42356 
42357 	    // if bendpoints get removed
42358 	    if (offset < 0 && oldBendpointIndex !== 0 && oldBendpointIndex < oldWaypoints.length - 1) {
42359 	      relativeFootPosition = relativePositionMidWaypoint(oldWaypoints, oldBendpointIndex);
42360 	    }
42361 	  }
42362 
42363 	  var newFoot = {
42364 	    x: (newLabelLine[1].x - newLabelLine[0].x) * relativeFootPosition + newLabelLine[0].x,
42365 	    y: (newLabelLine[1].y - newLabelLine[0].y) * relativeFootPosition + newLabelLine[0].y
42366 	  };
42367 
42368 	  // the rotated vector to label
42369 	  var newLabelVector = rotateVector({
42370 	    x: labelPosition.x - oldFoot.x,
42371 	    y: labelPosition.y - oldFoot.y
42372 	  }, angleDelta);
42373 
42374 	  // the new relative position
42375 	  x = newFoot.x + newLabelVector.x - labelPosition.x;
42376 	  y = newFoot.y + newLabelVector.y - labelPosition.y;
42377 
42378 	  return roundPoint({
42379 	    x: x,
42380 	    y: y
42381 	  });
42382 	}
42383 
42384 
42385 	// HELPERS //////////////////////
42386 
42387 	function relativePositionMidWaypoint(waypoints, idx) {
42388 
42389 	  var distanceSegment1 = getDistancePointPoint(waypoints[idx-1], waypoints[idx]),
42390 	      distanceSegment2 = getDistancePointPoint(waypoints[idx], waypoints[idx+1]);
42391 
42392 	  var relativePosition = distanceSegment1 / (distanceSegment1 + distanceSegment2);
42393 
42394 	  return relativePosition;
42395 	}
42396 
42397 	function getLabelMid(label) {
42398 	  return {
42399 	    x: label.x + label.width / 2,
42400 	    y: label.y + label.height / 2
42401 	  };
42402 	}
42403 
42404 	function getAngleDelta(l1, l2) {
42405 	  var a1 = getAngle(l1),
42406 	      a2 = getAngle(l2);
42407 	  return a2 - a1;
42408 	}
42409 
42410 	function getLine(waypoints, idx) {
42411 	  return [ waypoints[idx], waypoints[idx+1] ];
42412 	}
42413 
42414 	function getRelativeFootPosition(line, foot) {
42415 
42416 	  var length = getDistancePointPoint(line[0], line[1]),
42417 	      lengthToFoot = getDistancePointPoint(line[0], foot);
42418 
42419 	  return length === 0 ? 0 : lengthToFoot / length;
42420 	}
42421 
42422 	/**
42423 	 * Calculates the absolute point relative to the new element's position
42424 	 *
42425 	 * @param {point} point [absolute]
42426 	 * @param {bounds} oldBounds
42427 	 * @param {bounds} newBounds
42428 	 *
42429 	 * @return {point} point [absolute]
42430 	 */
42431 	function getNewAttachPoint(point, oldBounds, newBounds) {
42432 	  var oldCenter = center(oldBounds),
42433 	      newCenter = center(newBounds),
42434 	      oldDelta = delta(point, oldCenter);
42435 
42436 	  var newDelta = {
42437 	    x: oldDelta.x * (newBounds.width / oldBounds.width),
42438 	    y: oldDelta.y * (newBounds.height / oldBounds.height)
42439 	  };
42440 
42441 	  return roundPoint({
42442 	    x: newCenter.x + newDelta.x,
42443 	    y: newCenter.y + newDelta.y
42444 	  });
42445 	}
42446 
42447 
42448 	/**
42449 	 * Calculates the shape's delta relative to a new position
42450 	 * of a certain element's bounds
42451 	 *
42452 	 * @param {djs.model.Shape} point [absolute]
42453 	 * @param {bounds} oldBounds
42454 	 * @param {bounds} newBounds
42455 	 *
42456 	 * @return {delta} delta
42457 	 */
42458 	function getNewAttachShapeDelta(shape, oldBounds, newBounds) {
42459 	  var shapeCenter = center(shape),
42460 	      oldCenter = center(oldBounds),
42461 	      newCenter = center(newBounds),
42462 	      shapeDelta = delta(shape, shapeCenter),
42463 	      oldCenterDelta = delta(shapeCenter, oldCenter),
42464 	      stickyPositionDelta = getStickyPositionDelta(shapeCenter, oldBounds, newBounds);
42465 
42466 	  if (stickyPositionDelta) {
42467 	    return stickyPositionDelta;
42468 	  }
42469 
42470 	  var newCenterDelta = {
42471 	    x: oldCenterDelta.x * (newBounds.width / oldBounds.width),
42472 	    y: oldCenterDelta.y * (newBounds.height / oldBounds.height)
42473 	  };
42474 
42475 	  var newShapeCenter = {
42476 	    x: newCenter.x + newCenterDelta.x,
42477 	    y: newCenter.y + newCenterDelta.y
42478 	  };
42479 
42480 	  return roundPoint({
42481 	    x: newShapeCenter.x + shapeDelta.x - shape.x,
42482 	    y: newShapeCenter.y + shapeDelta.y - shape.y
42483 	  });
42484 	}
42485 
42486 	function getStickyPositionDelta(oldShapeCenter, oldBounds, newBounds) {
42487 	  var oldTRBL = asTRBL(oldBounds),
42488 	      newTRBL = asTRBL(newBounds);
42489 
42490 	  if (isMoved(oldTRBL, newTRBL)) {
42491 	    return null;
42492 	  }
42493 
42494 	  var oldOrientation = getOrientation(oldBounds, oldShapeCenter),
42495 	      stickyPositionDelta,
42496 	      newShapeCenter,
42497 	      newOrientation;
42498 
42499 	  if (oldOrientation === 'top') {
42500 	    stickyPositionDelta = {
42501 	      x: 0,
42502 	      y: newTRBL.bottom - oldTRBL.bottom
42503 	    };
42504 	  } else if (oldOrientation === 'bottom') {
42505 	    stickyPositionDelta = {
42506 	      x: 0,
42507 	      y: newTRBL.top - oldTRBL.top
42508 	    };
42509 	  } else if (oldOrientation === 'right') {
42510 	    stickyPositionDelta = {
42511 	      x: newTRBL.left - oldTRBL.left,
42512 	      y: 0
42513 	    };
42514 	  } else if (oldOrientation === 'left') {
42515 	    stickyPositionDelta = {
42516 	      x: newTRBL.right - oldTRBL.right,
42517 	      y: 0
42518 	    };
42519 	  } else {
42520 
42521 	    // fallback to proportional movement for corner-placed attachments
42522 	    return null;
42523 	  }
42524 
42525 	  newShapeCenter = {
42526 	    x: oldShapeCenter.x + stickyPositionDelta.x,
42527 	    y: oldShapeCenter.y + stickyPositionDelta.y
42528 	  };
42529 
42530 	  newOrientation = getOrientation(newBounds, newShapeCenter);
42531 
42532 	  if (newOrientation !== oldOrientation) {
42533 
42534 	    // fallback to proportional movement if orientation would otherwise change
42535 	    return null;
42536 	  }
42537 
42538 	  return stickyPositionDelta;
42539 	}
42540 
42541 	function isMoved(oldTRBL, newTRBL) {
42542 	  return isHorizontallyMoved(oldTRBL, newTRBL) || isVerticallyMoved(oldTRBL, newTRBL);
42543 	}
42544 
42545 	function isHorizontallyMoved(oldTRBL, newTRBL) {
42546 	  return oldTRBL.right !== newTRBL.right && oldTRBL.left !== newTRBL.left;
42547 	}
42548 
42549 	function isVerticallyMoved(oldTRBL, newTRBL) {
42550 	  return oldTRBL.top !== newTRBL.top && oldTRBL.bottom !== newTRBL.bottom;
42551 	}
42552 
42553 	var DEFAULT_LABEL_DIMENSIONS = {
42554 	  width: 90,
42555 	  height: 20
42556 	};
42557 
42558 	var NAME_PROPERTY = 'name';
42559 	var TEXT_PROPERTY = 'text';
42560 
42561 	/**
42562 	 * A component that makes sure that external labels are added
42563 	 * together with respective elements and properly updated (DI wise)
42564 	 * during move.
42565 	 *
42566 	 * @param {EventBus} eventBus
42567 	 * @param {Modeling} modeling
42568 	 * @param {BpmnFactory} bpmnFactory
42569 	 * @param {TextRenderer} textRenderer
42570 	 */
42571 	function LabelBehavior(
42572 	    eventBus, modeling, bpmnFactory,
42573 	    textRenderer) {
42574 
42575 	  CommandInterceptor.call(this, eventBus);
42576 
42577 	  // update label if name property was updated
42578 	  this.postExecute('element.updateProperties', function(e) {
42579 	    var context = e.context,
42580 	        element = context.element,
42581 	        properties = context.properties;
42582 
42583 	    if (NAME_PROPERTY in properties) {
42584 	      modeling.updateLabel(element, properties[NAME_PROPERTY]);
42585 	    }
42586 
42587 	    if (TEXT_PROPERTY in properties
42588 	        && is$1(element, 'bpmn:TextAnnotation')) {
42589 
42590 	      var newBounds = textRenderer.getTextAnnotationBounds(
42591 	        {
42592 	          x: element.x,
42593 	          y: element.y,
42594 	          width: element.width,
42595 	          height: element.height
42596 	        },
42597 	        properties[TEXT_PROPERTY] || ''
42598 	      );
42599 
42600 	      modeling.updateLabel(element, properties.text, newBounds);
42601 	    }
42602 	  });
42603 
42604 	  // create label shape after shape/connection was created
42605 	  this.postExecute([ 'shape.create', 'connection.create' ], function(e) {
42606 	    var context = e.context,
42607 	        hints = context.hints || {};
42608 
42609 	    if (hints.createElementsBehavior === false) {
42610 	      return;
42611 	    }
42612 
42613 	    var element = context.shape || context.connection,
42614 	        businessObject = element.businessObject;
42615 
42616 	    if (isLabel$6(element) || !isLabelExternal(element)) {
42617 	      return;
42618 	    }
42619 
42620 	    // only create label if attribute available
42621 	    if (!getLabel(element)) {
42622 	      return;
42623 	    }
42624 
42625 	    var labelCenter = getExternalLabelMid(element);
42626 
42627 	    // we don't care about x and y
42628 	    var labelDimensions = textRenderer.getExternalLabelBounds(
42629 	      DEFAULT_LABEL_DIMENSIONS,
42630 	      getLabel(element)
42631 	    );
42632 
42633 	    modeling.createLabel(element, labelCenter, {
42634 	      id: businessObject.id + '_label',
42635 	      businessObject: businessObject,
42636 	      width: labelDimensions.width,
42637 	      height: labelDimensions.height
42638 	    });
42639 	  });
42640 
42641 	  // update label after label shape was deleted
42642 	  this.postExecute('shape.delete', function(event) {
42643 	    var context = event.context,
42644 	        labelTarget = context.labelTarget,
42645 	        hints = context.hints || {};
42646 
42647 	    // check if label
42648 	    if (labelTarget && hints.unsetLabel !== false) {
42649 	      modeling.updateLabel(labelTarget, null, null, { removeShape: false });
42650 	    }
42651 	  });
42652 
42653 	  // update di information on label creation
42654 	  this.postExecute([ 'label.create' ], function(event) {
42655 
42656 	    var context = event.context,
42657 	        element = context.shape,
42658 	        businessObject,
42659 	        di;
42660 
42661 	    // we want to trigger on real labels only
42662 	    if (!element.labelTarget) {
42663 	      return;
42664 	    }
42665 
42666 	    // we want to trigger on BPMN elements only
42667 	    if (!is$1(element.labelTarget || element, 'bpmn:BaseElement')) {
42668 	      return;
42669 	    }
42670 
42671 	    businessObject = element.businessObject,
42672 	    di = businessObject.di;
42673 
42674 
42675 	    if (!di.label) {
42676 	      di.label = bpmnFactory.create('bpmndi:BPMNLabel', {
42677 	        bounds: bpmnFactory.create('dc:Bounds')
42678 	      });
42679 	    }
42680 
42681 	    assign(di.label.bounds, {
42682 	      x: element.x,
42683 	      y: element.y,
42684 	      width: element.width,
42685 	      height: element.height
42686 	    });
42687 	  });
42688 
42689 	  function getVisibleLabelAdjustment(event) {
42690 
42691 	    var context = event.context,
42692 	        connection = context.connection,
42693 	        label = connection.label,
42694 	        hints = assign({}, context.hints),
42695 	        newWaypoints = context.newWaypoints || connection.waypoints,
42696 	        oldWaypoints = context.oldWaypoints;
42697 
42698 
42699 	    if (typeof hints.startChanged === 'undefined') {
42700 	      hints.startChanged = !!hints.connectionStart;
42701 	    }
42702 
42703 	    if (typeof hints.endChanged === 'undefined') {
42704 	      hints.endChanged = !!hints.connectionEnd;
42705 	    }
42706 
42707 	    return getLabelAdjustment(label, newWaypoints, oldWaypoints, hints);
42708 	  }
42709 
42710 	  this.postExecute([
42711 	    'connection.layout',
42712 	    'connection.updateWaypoints'
42713 	  ], function(event) {
42714 	    var context = event.context,
42715 	        hints = context.hints || {};
42716 
42717 	    if (hints.labelBehavior === false) {
42718 	      return;
42719 	    }
42720 
42721 	    var connection = context.connection,
42722 	        label = connection.label,
42723 	        labelAdjustment;
42724 
42725 	    // handle missing label as well as the case
42726 	    // that the label parent does not exist (yet),
42727 	    // because it is being pasted / created via multi element create
42728 	    //
42729 	    // Cf. https://github.com/bpmn-io/bpmn-js/pull/1227
42730 	    if (!label || !label.parent) {
42731 	      return;
42732 	    }
42733 
42734 	    labelAdjustment = getVisibleLabelAdjustment(event);
42735 
42736 	    modeling.moveShape(label, labelAdjustment);
42737 	  });
42738 
42739 
42740 	  // keep label position on shape replace
42741 	  this.postExecute([ 'shape.replace' ], function(event) {
42742 	    var context = event.context,
42743 	        newShape = context.newShape,
42744 	        oldShape = context.oldShape;
42745 
42746 	    var businessObject = getBusinessObject(newShape);
42747 
42748 	    if (businessObject
42749 	      && isLabelExternal(businessObject)
42750 	      && oldShape.label
42751 	      && newShape.label) {
42752 	      newShape.label.x = oldShape.label.x;
42753 	      newShape.label.y = oldShape.label.y;
42754 	    }
42755 	  });
42756 
42757 
42758 	  // move external label after resizing
42759 	  this.postExecute('shape.resize', function(event) {
42760 
42761 	    var context = event.context,
42762 	        shape = context.shape,
42763 	        newBounds = context.newBounds,
42764 	        oldBounds = context.oldBounds;
42765 
42766 	    if (hasExternalLabel(shape)) {
42767 
42768 	      var label = shape.label,
42769 	          labelMid = getMid(label),
42770 	          edges = asEdges(oldBounds);
42771 
42772 	      // get nearest border point to label as reference point
42773 	      var referencePoint = getReferencePoint(labelMid, edges);
42774 
42775 	      var delta = getReferencePointDelta(referencePoint, oldBounds, newBounds);
42776 
42777 	      modeling.moveShape(label, delta);
42778 
42779 	    }
42780 
42781 	  });
42782 
42783 	}
42784 
42785 	inherits$1(LabelBehavior, CommandInterceptor);
42786 
42787 	LabelBehavior.$inject = [
42788 	  'eventBus',
42789 	  'modeling',
42790 	  'bpmnFactory',
42791 	  'textRenderer'
42792 	];
42793 
42794 	// helpers //////////////////////
42795 
42796 	/**
42797 	 * Calculates a reference point delta relative to a new position
42798 	 * of a certain element's bounds
42799 	 *
42800 	 * @param {Point} point
42801 	 * @param {Bounds} oldBounds
42802 	 * @param {Bounds} newBounds
42803 	 *
42804 	 * @return {Delta} delta
42805 	 */
42806 	function getReferencePointDelta(referencePoint, oldBounds, newBounds) {
42807 
42808 	  var newReferencePoint = getNewAttachPoint(referencePoint, oldBounds, newBounds);
42809 
42810 	  return roundPoint(delta(newReferencePoint, referencePoint));
42811 	}
42812 
42813 	/**
42814 	 * Generates the nearest point (reference point) for a given point
42815 	 * onto given set of lines
42816 	 *
42817 	 * @param {Array<Point, Point>} lines
42818 	 * @param {Point} point
42819 	 *
42820 	 * @param {Point}
42821 	 */
42822 	function getReferencePoint(point, lines) {
42823 
42824 	  if (!lines.length) {
42825 	    return;
42826 	  }
42827 
42828 	  var nearestLine = getNearestLine(point, lines);
42829 
42830 	  return perpendicularFoot(point, nearestLine);
42831 	}
42832 
42833 	/**
42834 	 * Convert the given bounds to a lines array containing all edges
42835 	 *
42836 	 * @param {Bounds|Point} bounds
42837 	 *
42838 	 * @return Array<Point>
42839 	 */
42840 	function asEdges(bounds) {
42841 	  return [
42842 	    [ // top
42843 	      {
42844 	        x: bounds.x,
42845 	        y: bounds.y
42846 	      },
42847 	      {
42848 	        x: bounds.x + (bounds.width || 0),
42849 	        y: bounds.y
42850 	      }
42851 	    ],
42852 	    [ // right
42853 	      {
42854 	        x: bounds.x + (bounds.width || 0),
42855 	        y: bounds.y
42856 	      },
42857 	      {
42858 	        x: bounds.x + (bounds.width || 0),
42859 	        y: bounds.y + (bounds.height || 0)
42860 	      }
42861 	    ],
42862 	    [ // bottom
42863 	      {
42864 	        x: bounds.x,
42865 	        y: bounds.y + (bounds.height || 0)
42866 	      },
42867 	      {
42868 	        x: bounds.x + (bounds.width || 0),
42869 	        y: bounds.y + (bounds.height || 0)
42870 	      }
42871 	    ],
42872 	    [ // left
42873 	      {
42874 	        x: bounds.x,
42875 	        y: bounds.y
42876 	      },
42877 	      {
42878 	        x: bounds.x,
42879 	        y: bounds.y + (bounds.height || 0)
42880 	      }
42881 	    ]
42882 	  ];
42883 	}
42884 
42885 	/**
42886 	 * Returns the nearest line for a given point by distance
42887 	 * @param {Point} point
42888 	 * @param Array<Point> lines
42889 	 *
42890 	 * @return Array<Point>
42891 	 */
42892 	function getNearestLine(point, lines) {
42893 
42894 	  var distances = lines.map(function(l) {
42895 	    return {
42896 	      line: l,
42897 	      distance: getDistancePointLine(point, l)
42898 	    };
42899 	  });
42900 
42901 	  var sorted = sortBy(distances, 'distance');
42902 
42903 	  return sorted[0].line;
42904 	}
42905 
42906 	function getResizedSourceAnchor(connection, shape, oldBounds) {
42907 
42908 	  var waypoints = safeGetWaypoints(connection),
42909 	      waypointsInsideNewBounds = getWaypointsInsideBounds(waypoints, shape),
42910 	      oldAnchor = waypoints[0];
42911 
42912 	  // new anchor is the last waypoint enclosed be resized source
42913 	  if (waypointsInsideNewBounds.length) {
42914 	    return waypointsInsideNewBounds[ waypointsInsideNewBounds.length - 1 ];
42915 	  }
42916 
42917 	  return getNewAttachPoint(oldAnchor.original || oldAnchor, oldBounds, shape);
42918 	}
42919 
42920 
42921 	function getResizedTargetAnchor(connection, shape, oldBounds) {
42922 
42923 	  var waypoints = safeGetWaypoints(connection),
42924 	      waypointsInsideNewBounds = getWaypointsInsideBounds(waypoints, shape),
42925 	      oldAnchor = waypoints[waypoints.length - 1];
42926 
42927 	  // new anchor is the first waypoint enclosed be resized target
42928 	  if (waypointsInsideNewBounds.length) {
42929 	    return waypointsInsideNewBounds[ 0 ];
42930 	  }
42931 
42932 	  return getNewAttachPoint(oldAnchor.original || oldAnchor, oldBounds, shape);
42933 	}
42934 
42935 
42936 	function getMovedSourceAnchor(connection, source, moveDelta) {
42937 
42938 	  var waypoints = safeGetWaypoints(connection),
42939 	      oldBounds = subtract(source, moveDelta),
42940 	      oldAnchor = waypoints[ 0 ];
42941 
42942 	  return getNewAttachPoint(oldAnchor.original || oldAnchor, oldBounds, source);
42943 	}
42944 
42945 
42946 	function getMovedTargetAnchor(connection, target, moveDelta) {
42947 
42948 	  var waypoints = safeGetWaypoints(connection),
42949 	      oldBounds = subtract(target, moveDelta),
42950 	      oldAnchor = waypoints[ waypoints.length - 1 ];
42951 
42952 	  return getNewAttachPoint(oldAnchor.original || oldAnchor, oldBounds, target);
42953 	}
42954 
42955 
42956 	// helpers //////////////////////
42957 
42958 	function subtract(bounds, delta) {
42959 	  return {
42960 	    x: bounds.x - delta.x,
42961 	    y: bounds.y - delta.y,
42962 	    width: bounds.width,
42963 	    height: bounds.height
42964 	  };
42965 	}
42966 
42967 
42968 	/**
42969 	 * Return waypoints of given connection; throw if non exists (should not happen!!).
42970 	 *
42971 	 * @param {Connection} connection
42972 	 *
42973 	 * @return {Array<Point>}
42974 	 */
42975 	function safeGetWaypoints(connection) {
42976 
42977 	  var waypoints = connection.waypoints;
42978 
42979 	  if (!waypoints.length) {
42980 	    throw new Error('connection#' + connection.id + ': no waypoints');
42981 	  }
42982 
42983 	  return waypoints;
42984 	}
42985 
42986 	function getWaypointsInsideBounds(waypoints, bounds) {
42987 	  var originalWaypoints = map$1(waypoints, getOriginal);
42988 
42989 	  return filter(originalWaypoints, function(waypoint) {
42990 	    return isInsideBounds(waypoint, bounds);
42991 	  });
42992 	}
42993 
42994 	/**
42995 	 * Checks if point is inside bounds, incl. edges.
42996 	 *
42997 	 * @param {Point} point
42998 	 * @param {Bounds} bounds
42999 	 */
43000 	function isInsideBounds(point, bounds) {
43001 	  return getOrientation(bounds, point, 1) === 'intersect';
43002 	}
43003 
43004 	function getOriginal(point) {
43005 	  return point.original || point;
43006 	}
43007 
43008 	/**
43009 	 * BPMN-specific message flow behavior.
43010 	 */
43011 	function MessageFlowBehavior(eventBus, modeling) {
43012 
43013 	  CommandInterceptor.call(this, eventBus);
43014 
43015 	  this.postExecute('shape.replace', function(context) {
43016 	    var oldShape = context.oldShape,
43017 	        newShape = context.newShape;
43018 
43019 	    if (!isParticipantCollapse(oldShape, newShape)) {
43020 	      return;
43021 	    }
43022 
43023 	    var messageFlows = getMessageFlows(oldShape);
43024 
43025 	    messageFlows.incoming.forEach(function(incoming) {
43026 	      var anchor = getResizedTargetAnchor(incoming, newShape, oldShape);
43027 
43028 	      modeling.reconnectEnd(incoming, newShape, anchor);
43029 	    });
43030 
43031 	    messageFlows.outgoing.forEach(function(outgoing) {
43032 	      var anchor = getResizedSourceAnchor(outgoing, newShape, oldShape);
43033 
43034 	      modeling.reconnectStart(outgoing, newShape, anchor);
43035 	    });
43036 	  }, true);
43037 
43038 	}
43039 
43040 	MessageFlowBehavior.$inject = [ 'eventBus', 'modeling' ];
43041 
43042 	inherits$1(MessageFlowBehavior, CommandInterceptor);
43043 
43044 	// helpers //////////
43045 
43046 	function isParticipantCollapse(oldShape, newShape) {
43047 	  return is$1(oldShape, 'bpmn:Participant')
43048 	    && isExpanded(oldShape)
43049 	    && is$1(newShape, 'bpmn:Participant')
43050 	    && !isExpanded(newShape);
43051 	}
43052 
43053 	function getMessageFlows(parent) {
43054 	  var elements = selfAndAllChildren([ parent ], false);
43055 
43056 	  var incoming = [],
43057 	      outgoing = [];
43058 
43059 	  elements.forEach(function(element) {
43060 	    if (element === parent) {
43061 	      return;
43062 	    }
43063 
43064 	    element.incoming.forEach(function(connection) {
43065 	      if (is$1(connection, 'bpmn:MessageFlow')) {
43066 	        incoming.push(connection);
43067 	      }
43068 	    });
43069 
43070 	    element.outgoing.forEach(function(connection) {
43071 	      if (is$1(connection, 'bpmn:MessageFlow')) {
43072 	        outgoing.push(connection);
43073 	      }
43074 	    });
43075 	  }, []);
43076 
43077 	  return {
43078 	    incoming: incoming,
43079 	    outgoing: outgoing
43080 	  };
43081 	}
43082 
43083 	var COLLAB_ERR_MSG = 'flow elements must be children of pools/participants';
43084 
43085 	function ModelingFeedback(eventBus, tooltips, translate) {
43086 
43087 	  function showError(position, message, timeout) {
43088 	    tooltips.add({
43089 	      position: {
43090 	        x: position.x + 5,
43091 	        y: position.y + 5
43092 	      },
43093 	      type: 'error',
43094 	      timeout: timeout || 2000,
43095 	      html: '<div>' + message + '</div>'
43096 	    });
43097 	  }
43098 
43099 	  eventBus.on([ 'shape.move.rejected', 'create.rejected' ], function(event) {
43100 	    var context = event.context,
43101 	        shape = context.shape,
43102 	        target = context.target;
43103 
43104 	    if (is$1(target, 'bpmn:Collaboration') && is$1(shape, 'bpmn:FlowNode')) {
43105 	      showError(event, translate(COLLAB_ERR_MSG));
43106 	    }
43107 	  });
43108 
43109 	}
43110 
43111 	ModelingFeedback.$inject = [
43112 	  'eventBus',
43113 	  'tooltips',
43114 	  'translate'
43115 	];
43116 
43117 	function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules, injector) {
43118 
43119 	  CommandInterceptor.call(this, eventBus);
43120 
43121 	  var dragging = injector.get('dragging', false);
43122 
43123 	  function fixConnection(connection) {
43124 
43125 	    var source = connection.source,
43126 	        target = connection.target,
43127 	        parent = connection.parent;
43128 
43129 	    // do not do anything if connection
43130 	    // is already deleted (may happen due to other
43131 	    // behaviors plugged-in before)
43132 	    if (!parent) {
43133 	      return;
43134 	    }
43135 
43136 	    var replacementType,
43137 	        remove;
43138 
43139 	    /**
43140 	     * Check if incoming or outgoing connections
43141 	     * can stay or could be substituted with an
43142 	     * appropriate replacement.
43143 	     *
43144 	     * This holds true for SequenceFlow <> MessageFlow.
43145 	     */
43146 
43147 	    if (is$1(connection, 'bpmn:SequenceFlow')) {
43148 	      if (!bpmnRules.canConnectSequenceFlow(source, target)) {
43149 	        remove = true;
43150 	      }
43151 
43152 	      if (bpmnRules.canConnectMessageFlow(source, target)) {
43153 	        replacementType = 'bpmn:MessageFlow';
43154 	      }
43155 	    }
43156 
43157 	    // transform message flows into sequence flows, if possible
43158 
43159 	    if (is$1(connection, 'bpmn:MessageFlow')) {
43160 
43161 	      if (!bpmnRules.canConnectMessageFlow(source, target)) {
43162 	        remove = true;
43163 	      }
43164 
43165 	      if (bpmnRules.canConnectSequenceFlow(source, target)) {
43166 	        replacementType = 'bpmn:SequenceFlow';
43167 	      }
43168 	    }
43169 
43170 	    if (is$1(connection, 'bpmn:Association') && !bpmnRules.canConnectAssociation(source, target)) {
43171 	      remove = true;
43172 	    }
43173 
43174 
43175 	    // remove invalid connection,
43176 	    // unless it has been removed already
43177 	    if (remove) {
43178 	      modeling.removeConnection(connection);
43179 	    }
43180 
43181 	    // replace SequenceFlow <> MessageFlow
43182 
43183 	    if (replacementType) {
43184 	      modeling.connect(source, target, {
43185 	        type: replacementType,
43186 	        waypoints: connection.waypoints.slice()
43187 	      });
43188 	    }
43189 	  }
43190 
43191 	  function replaceReconnectedConnection(event) {
43192 
43193 	    var context = event.context,
43194 	        connection = context.connection,
43195 	        source = context.newSource || connection.source,
43196 	        target = context.newTarget || connection.target,
43197 	        allowed,
43198 	        replacement;
43199 
43200 	    allowed = bpmnRules.canConnect(source, target);
43201 
43202 	    if (!allowed || allowed.type === connection.type) {
43203 	      return;
43204 	    }
43205 
43206 	    replacement = modeling.connect(source, target, {
43207 	      type: allowed.type,
43208 	      waypoints: connection.waypoints.slice()
43209 	    });
43210 
43211 	    // remove old connection
43212 	    modeling.removeConnection(connection);
43213 
43214 	    // replace connection in context to reconnect end/start
43215 	    context.connection = replacement;
43216 
43217 	    if (dragging) {
43218 	      cleanDraggingSelection(connection, replacement);
43219 	    }
43220 	  }
43221 
43222 	  // monkey-patch selection saved in dragging in order to re-select it when operation is finished
43223 	  function cleanDraggingSelection(oldConnection, newConnection) {
43224 	    var context = dragging.context(),
43225 	        previousSelection = context && context.payload.previousSelection,
43226 	        index;
43227 
43228 	    // do nothing if not dragging or no selection was present
43229 	    if (!previousSelection || !previousSelection.length) {
43230 	      return;
43231 	    }
43232 
43233 	    index = previousSelection.indexOf(oldConnection);
43234 
43235 	    if (index === -1) {
43236 	      return;
43237 	    }
43238 
43239 	    previousSelection.splice(index, 1, newConnection);
43240 	  }
43241 
43242 	  // lifecycle hooks
43243 
43244 	  this.postExecuted('elements.move', function(context) {
43245 
43246 	    var closure = context.closure,
43247 	        allConnections = closure.allConnections;
43248 
43249 	    forEach(allConnections, fixConnection);
43250 	  }, true);
43251 
43252 	  this.preExecute('connection.reconnect', replaceReconnectedConnection);
43253 
43254 	  this.postExecuted('element.updateProperties', function(event) {
43255 	    var context = event.context,
43256 	        properties = context.properties,
43257 	        element = context.element,
43258 	        businessObject = element.businessObject,
43259 	        connection;
43260 
43261 	    // remove condition on change to default
43262 	    if (properties.default) {
43263 	      connection = find(
43264 	        element.outgoing,
43265 	        matchPattern({ id: element.businessObject.default.id })
43266 	      );
43267 
43268 	      if (connection) {
43269 	        modeling.updateProperties(connection, { conditionExpression: undefined });
43270 	      }
43271 	    }
43272 
43273 	    // remove default from source on change to conditional
43274 	    if (properties.conditionExpression && businessObject.sourceRef.default === businessObject) {
43275 	      modeling.updateProperties(element.source, { default: undefined });
43276 	    }
43277 	  });
43278 	}
43279 
43280 	inherits$1(ReplaceConnectionBehavior, CommandInterceptor);
43281 
43282 	ReplaceConnectionBehavior.$inject = [
43283 	  'eventBus',
43284 	  'modeling',
43285 	  'bpmnRules',
43286 	  'injector'
43287 	];
43288 
43289 	/**
43290 	 * BPMN specific remove behavior
43291 	 */
43292 	function RemoveParticipantBehavior(eventBus, modeling) {
43293 
43294 	  CommandInterceptor.call(this, eventBus);
43295 
43296 
43297 	  /**
43298 	   * morph collaboration diagram into process diagram
43299 	   * after the last participant has been removed
43300 	   */
43301 
43302 	  this.preExecute('shape.delete', function(context) {
43303 
43304 	    var shape = context.shape,
43305 	        parent = shape.parent;
43306 
43307 	    // activate the behavior if the shape to be removed
43308 	    // is a participant
43309 	    if (is$1(shape, 'bpmn:Participant')) {
43310 	      context.collaborationRoot = parent;
43311 	    }
43312 	  }, true);
43313 
43314 	  this.postExecute('shape.delete', function(context) {
43315 
43316 	    var collaborationRoot = context.collaborationRoot;
43317 
43318 	    if (collaborationRoot && !collaborationRoot.businessObject.participants.length) {
43319 
43320 	      // replace empty collaboration with process diagram
43321 	      modeling.makeProcess();
43322 	    }
43323 	  }, true);
43324 
43325 	}
43326 
43327 	RemoveParticipantBehavior.$inject = [ 'eventBus', 'modeling' ];
43328 
43329 	inherits$1(RemoveParticipantBehavior, CommandInterceptor);
43330 
43331 	/**
43332 	 * BPMN-specific replace behavior.
43333 	 */
43334 	function ReplaceElementBehaviour(
43335 	    bpmnReplace,
43336 	    bpmnRules,
43337 	    elementRegistry,
43338 	    injector,
43339 	    modeling,
43340 	    selection
43341 	) {
43342 	  injector.invoke(CommandInterceptor, this);
43343 
43344 	  this._bpmnReplace = bpmnReplace;
43345 	  this._elementRegistry = elementRegistry;
43346 	  this._selection = selection;
43347 
43348 	  // replace elements on create, e.g. during copy-paste
43349 	  this.postExecuted([ 'elements.create' ], 500, function(event) {
43350 	    var context = event.context,
43351 	        target = context.parent,
43352 	        elements = context.elements;
43353 
43354 	    var canReplace = bpmnRules.canReplace(elements, target);
43355 
43356 	    if (canReplace) {
43357 	      this.replaceElements(elements, canReplace.replacements);
43358 	    }
43359 	  }, this);
43360 
43361 	  // replace elements on move
43362 	  this.postExecuted([ 'elements.move' ], 500, function(event) {
43363 	    var context = event.context,
43364 	        target = context.newParent,
43365 	        newHost = context.newHost,
43366 	        elements = [];
43367 
43368 	    forEach(context.closure.topLevel, function(topLevelElements) {
43369 	      if (isEventSubProcess(topLevelElements)) {
43370 	        elements = elements.concat(topLevelElements.children);
43371 	      } else {
43372 	        elements = elements.concat(topLevelElements);
43373 	      }
43374 	    });
43375 
43376 	    // set target to host if attaching
43377 	    if (elements.length === 1 && newHost) {
43378 	      target = newHost;
43379 	    }
43380 
43381 	    var canReplace = bpmnRules.canReplace(elements, target);
43382 
43383 	    if (canReplace) {
43384 	      this.replaceElements(elements, canReplace.replacements, newHost);
43385 	    }
43386 	  }, this);
43387 
43388 	  // update attachments on host replace
43389 	  this.postExecute([ 'shape.replace' ], 1500, function(e) {
43390 	    var context = e.context,
43391 	        oldShape = context.oldShape,
43392 	        newShape = context.newShape,
43393 	        attachers = oldShape.attachers,
43394 	        canReplace;
43395 
43396 	    if (attachers && attachers.length) {
43397 	      canReplace = bpmnRules.canReplace(attachers, newShape);
43398 
43399 	      this.replaceElements(attachers, canReplace.replacements);
43400 	    }
43401 
43402 	  }, this);
43403 
43404 	  // keep ID on shape replace
43405 	  this.postExecuted([ 'shape.replace' ], 1500, function(e) {
43406 	    var context = e.context,
43407 	        oldShape = context.oldShape,
43408 	        newShape = context.newShape;
43409 
43410 	    modeling.unclaimId(oldShape.businessObject.id, oldShape.businessObject);
43411 	    modeling.updateProperties(newShape, { id: oldShape.id });
43412 	  });
43413 	}
43414 
43415 	inherits$1(ReplaceElementBehaviour, CommandInterceptor);
43416 
43417 	ReplaceElementBehaviour.prototype.replaceElements = function(elements, newElements) {
43418 	  var elementRegistry = this._elementRegistry,
43419 	      bpmnReplace = this._bpmnReplace,
43420 	      selection = this._selection;
43421 
43422 	  forEach(newElements, function(replacement) {
43423 	    var newElement = {
43424 	      type: replacement.newElementType
43425 	    };
43426 
43427 	    var oldElement = elementRegistry.get(replacement.oldElementId);
43428 
43429 	    var idx = elements.indexOf(oldElement);
43430 
43431 	    elements[idx] = bpmnReplace.replaceElement(oldElement, newElement, { select: false });
43432 	  });
43433 
43434 	  if (newElements) {
43435 	    selection.select(elements);
43436 	  }
43437 	};
43438 
43439 	ReplaceElementBehaviour.$inject = [
43440 	  'bpmnReplace',
43441 	  'bpmnRules',
43442 	  'elementRegistry',
43443 	  'injector',
43444 	  'modeling',
43445 	  'selection'
43446 	];
43447 
43448 	var HIGH_PRIORITY$8 = 1500;
43449 
43450 	var LANE_MIN_DIMENSIONS = { width: 300, height: 60 };
43451 
43452 	var PARTICIPANT_MIN_DIMENSIONS = { width: 300, height: 150 };
43453 
43454 	var SUB_PROCESS_MIN_DIMENSIONS = { width: 140, height: 120 };
43455 
43456 	var TEXT_ANNOTATION_MIN_DIMENSIONS = { width: 50, height: 30 };
43457 
43458 	/**
43459 	 * Set minimum bounds/resize constraints on resize.
43460 	 *
43461 	 * @param {EventBus} eventBus
43462 	 */
43463 	function ResizeBehavior(eventBus) {
43464 	  eventBus.on('resize.start', HIGH_PRIORITY$8, function(event) {
43465 	    var context = event.context,
43466 	        shape = context.shape,
43467 	        direction = context.direction,
43468 	        balanced = context.balanced;
43469 
43470 	    if (is$1(shape, 'bpmn:Lane') || is$1(shape, 'bpmn:Participant')) {
43471 	      context.resizeConstraints = getParticipantResizeConstraints(shape, direction, balanced);
43472 	    }
43473 
43474 	    if (is$1(shape, 'bpmn:Participant')) {
43475 	      context.minDimensions = PARTICIPANT_MIN_DIMENSIONS;
43476 	    }
43477 
43478 	    if (is$1(shape, 'bpmn:SubProcess') && isExpanded(shape)) {
43479 	      context.minDimensions = SUB_PROCESS_MIN_DIMENSIONS;
43480 	    }
43481 
43482 	    if (is$1(shape, 'bpmn:TextAnnotation')) {
43483 	      context.minDimensions = TEXT_ANNOTATION_MIN_DIMENSIONS;
43484 	    }
43485 	  });
43486 	}
43487 
43488 	ResizeBehavior.$inject = [ 'eventBus' ];
43489 
43490 
43491 	var abs$2 = Math.abs,
43492 	    min = Math.min,
43493 	    max$2 = Math.max;
43494 
43495 
43496 	function addToTrbl(trbl, attr, value, choice) {
43497 	  var current = trbl[attr];
43498 
43499 	  // make sure to set the value if it does not exist
43500 	  // or apply the correct value by comparing against
43501 	  // choice(value, currentValue)
43502 	  trbl[attr] = current === undefined ? value : choice(value, current);
43503 	}
43504 
43505 	function addMin(trbl, attr, value) {
43506 	  return addToTrbl(trbl, attr, value, min);
43507 	}
43508 
43509 	function addMax(trbl, attr, value) {
43510 	  return addToTrbl(trbl, attr, value, max$2);
43511 	}
43512 
43513 	var LANE_RIGHT_PADDING = 20,
43514 	    LANE_LEFT_PADDING = 50,
43515 	    LANE_TOP_PADDING = 20,
43516 	    LANE_BOTTOM_PADDING = 20;
43517 
43518 	function getParticipantResizeConstraints(laneShape, resizeDirection, balanced) {
43519 	  var lanesRoot = getLanesRoot(laneShape);
43520 
43521 	  var isFirst = true,
43522 	      isLast = true;
43523 
43524 	  // max top/bottom size for lanes
43525 	  var allLanes = collectLanes(lanesRoot, [ lanesRoot ]);
43526 
43527 	  var laneTrbl = asTRBL(laneShape);
43528 
43529 	  var maxTrbl = {},
43530 	      minTrbl = {};
43531 
43532 	  if (/e/.test(resizeDirection)) {
43533 	    minTrbl.right = laneTrbl.left + LANE_MIN_DIMENSIONS.width;
43534 	  } else
43535 	  if (/w/.test(resizeDirection)) {
43536 	    minTrbl.left = laneTrbl.right - LANE_MIN_DIMENSIONS.width;
43537 	  }
43538 
43539 	  allLanes.forEach(function(other) {
43540 
43541 	    var otherTrbl = asTRBL(other);
43542 
43543 	    if (/n/.test(resizeDirection)) {
43544 
43545 	      if (otherTrbl.top < (laneTrbl.top - 10)) {
43546 	        isFirst = false;
43547 	      }
43548 
43549 	      // max top size (based on next element)
43550 	      if (balanced && abs$2(laneTrbl.top - otherTrbl.bottom) < 10) {
43551 	        addMax(maxTrbl, 'top', otherTrbl.top + LANE_MIN_DIMENSIONS.height);
43552 	      }
43553 
43554 	      // min top size (based on self or nested element)
43555 	      if (abs$2(laneTrbl.top - otherTrbl.top) < 5) {
43556 	        addMin(minTrbl, 'top', otherTrbl.bottom - LANE_MIN_DIMENSIONS.height);
43557 	      }
43558 	    }
43559 
43560 	    if (/s/.test(resizeDirection)) {
43561 
43562 	      if (otherTrbl.bottom > (laneTrbl.bottom + 10)) {
43563 	        isLast = false;
43564 	      }
43565 
43566 	      // max bottom size (based on previous element)
43567 	      if (balanced && abs$2(laneTrbl.bottom - otherTrbl.top) < 10) {
43568 	        addMin(maxTrbl, 'bottom', otherTrbl.bottom - LANE_MIN_DIMENSIONS.height);
43569 	      }
43570 
43571 	      // min bottom size (based on self or nested element)
43572 	      if (abs$2(laneTrbl.bottom - otherTrbl.bottom) < 5) {
43573 	        addMax(minTrbl, 'bottom', otherTrbl.top + LANE_MIN_DIMENSIONS.height);
43574 	      }
43575 	    }
43576 	  });
43577 
43578 	  // max top/bottom/left/right size based on flow nodes
43579 	  var flowElements = lanesRoot.children.filter(function(s) {
43580 	    return !s.hidden && !s.waypoints && (is$1(s, 'bpmn:FlowElement') || is$1(s, 'bpmn:Artifact'));
43581 	  });
43582 
43583 	  flowElements.forEach(function(flowElement) {
43584 
43585 	    var flowElementTrbl = asTRBL(flowElement);
43586 
43587 	    if (isFirst && /n/.test(resizeDirection)) {
43588 	      addMin(minTrbl, 'top', flowElementTrbl.top - LANE_TOP_PADDING);
43589 	    }
43590 
43591 	    if (/e/.test(resizeDirection)) {
43592 	      addMax(minTrbl, 'right', flowElementTrbl.right + LANE_RIGHT_PADDING);
43593 	    }
43594 
43595 	    if (isLast && /s/.test(resizeDirection)) {
43596 	      addMax(minTrbl, 'bottom', flowElementTrbl.bottom + LANE_BOTTOM_PADDING);
43597 	    }
43598 
43599 	    if (/w/.test(resizeDirection)) {
43600 	      addMin(minTrbl, 'left', flowElementTrbl.left - LANE_LEFT_PADDING);
43601 	    }
43602 	  });
43603 
43604 	  return {
43605 	    min: minTrbl,
43606 	    max: maxTrbl
43607 	  };
43608 	}
43609 
43610 	var SLIGHTLY_HIGHER_PRIORITY = 1001;
43611 
43612 
43613 	/**
43614 	 * Invoke {@link Modeling#resizeLane} instead of
43615 	 * {@link Modeling#resizeShape} when resizing a Lane
43616 	 * or Participant shape.
43617 	 */
43618 	function ResizeLaneBehavior(eventBus, modeling) {
43619 
43620 	  eventBus.on('resize.start', SLIGHTLY_HIGHER_PRIORITY + 500, function(event) {
43621 	    var context = event.context,
43622 	        shape = context.shape;
43623 
43624 	    if (is$1(shape, 'bpmn:Lane') || is$1(shape, 'bpmn:Participant')) {
43625 
43626 	      // should we resize the opposite lane(s) in
43627 	      // order to compensate for the resize operation?
43628 	      context.balanced = !hasPrimaryModifier(event);
43629 	    }
43630 	  });
43631 
43632 	  /**
43633 	   * Intercept resize end and call resize lane function instead.
43634 	   */
43635 	  eventBus.on('resize.end', SLIGHTLY_HIGHER_PRIORITY, function(event) {
43636 	    var context = event.context,
43637 	        shape = context.shape,
43638 	        canExecute = context.canExecute,
43639 	        newBounds = context.newBounds;
43640 
43641 	    if (is$1(shape, 'bpmn:Lane') || is$1(shape, 'bpmn:Participant')) {
43642 
43643 	      if (canExecute) {
43644 
43645 	        // ensure we have actual pixel values for new bounds
43646 	        // (important when zoom level was > 1 during move)
43647 	        newBounds = roundBounds(newBounds);
43648 
43649 	        // perform the actual resize
43650 	        modeling.resizeLane(shape, newBounds, context.balanced);
43651 	      }
43652 
43653 	      // stop propagation
43654 	      return false;
43655 	    }
43656 	  });
43657 	}
43658 
43659 	ResizeLaneBehavior.$inject = [
43660 	  'eventBus',
43661 	  'modeling'
43662 	];
43663 
43664 	function RemoveElementBehavior(eventBus, bpmnRules, modeling) {
43665 
43666 	  CommandInterceptor.call(this, eventBus);
43667 
43668 	  /**
43669 	   * Combine sequence flows when deleting an element
43670 	   * if there is one incoming and one outgoing
43671 	   * sequence flow
43672 	   */
43673 	  this.preExecute('shape.delete', function(e) {
43674 
43675 	    var shape = e.context.shape;
43676 
43677 	    // only handle [a] -> [shape] -> [b] patterns
43678 	    if (shape.incoming.length !== 1 || shape.outgoing.length !== 1) {
43679 	      return;
43680 	    }
43681 
43682 	    var inConnection = shape.incoming[0],
43683 	        outConnection = shape.outgoing[0];
43684 
43685 	    // only handle sequence flows
43686 	    if (!is$1(inConnection, 'bpmn:SequenceFlow') || !is$1(outConnection, 'bpmn:SequenceFlow')) {
43687 	      return;
43688 	    }
43689 
43690 	    if (bpmnRules.canConnect(inConnection.source, outConnection.target, inConnection)) {
43691 
43692 	      // compute new, combined waypoints
43693 	      var newWaypoints = getNewWaypoints(inConnection.waypoints, outConnection.waypoints);
43694 
43695 	      modeling.reconnectEnd(inConnection, outConnection.target, newWaypoints);
43696 	    }
43697 	  });
43698 
43699 	}
43700 
43701 	inherits$1(RemoveElementBehavior, CommandInterceptor);
43702 
43703 	RemoveElementBehavior.$inject = [
43704 	  'eventBus',
43705 	  'bpmnRules',
43706 	  'modeling'
43707 	];
43708 
43709 
43710 	// helpers //////////////////////
43711 
43712 	function getDocking$1(point) {
43713 	  return point.original || point;
43714 	}
43715 
43716 
43717 	function getNewWaypoints(inWaypoints, outWaypoints) {
43718 
43719 	  var intersection = lineIntersect(
43720 	    getDocking$1(inWaypoints[inWaypoints.length - 2]),
43721 	    getDocking$1(inWaypoints[inWaypoints.length - 1]),
43722 	    getDocking$1(outWaypoints[1]),
43723 	    getDocking$1(outWaypoints[0]));
43724 
43725 	  if (intersection) {
43726 	    return [].concat(
43727 	      inWaypoints.slice(0, inWaypoints.length - 1),
43728 	      [ intersection ],
43729 	      outWaypoints.slice(1));
43730 	  } else {
43731 	    return [
43732 	      getDocking$1(inWaypoints[0]),
43733 	      getDocking$1(outWaypoints[outWaypoints.length - 1])
43734 	    ];
43735 	  }
43736 	}
43737 
43738 	var max$1 = Math.max;
43739 
43740 
43741 	function SpaceToolBehavior(eventBus) {
43742 	  eventBus.on('spaceTool.getMinDimensions', function(context) {
43743 	    var shapes = context.shapes,
43744 	        axis = context.axis,
43745 	        start = context.start,
43746 	        minDimensions = {};
43747 
43748 	    forEach(shapes, function(shape) {
43749 	      var id = shape.id;
43750 
43751 	      if (is$1(shape, 'bpmn:Participant')) {
43752 
43753 	        if (isHorizontal$1(axis)) {
43754 	          minDimensions[ id ] = PARTICIPANT_MIN_DIMENSIONS;
43755 	        } else {
43756 	          minDimensions[ id ] = {
43757 	            width: PARTICIPANT_MIN_DIMENSIONS.width,
43758 	            height: getParticipantMinHeight(shape, start)
43759 	          };
43760 	        }
43761 
43762 	      }
43763 
43764 	      if (is$1(shape, 'bpmn:SubProcess') && isExpanded(shape)) {
43765 	        minDimensions[ id ] = SUB_PROCESS_MIN_DIMENSIONS;
43766 	      }
43767 
43768 	      if (is$1(shape, 'bpmn:TextAnnotation')) {
43769 	        minDimensions[ id ] = TEXT_ANNOTATION_MIN_DIMENSIONS;
43770 	      }
43771 	    });
43772 
43773 	    return minDimensions;
43774 	  });
43775 	}
43776 
43777 	SpaceToolBehavior.$inject = [ 'eventBus' ];
43778 
43779 
43780 	// helpers //////////
43781 	function isHorizontal$1(axis) {
43782 	  return axis === 'x';
43783 	}
43784 
43785 	/**
43786 	 * Get minimum height for participant taking lanes into account.
43787 	 *
43788 	 * @param {<djs.model.Shape>} participant
43789 	 * @param {number} start
43790 	 *
43791 	 * @returns {Object}
43792 	 */
43793 	function getParticipantMinHeight(participant, start) {
43794 	  var lanesMinHeight;
43795 
43796 	  if (!hasChildLanes(participant)) {
43797 	    return PARTICIPANT_MIN_DIMENSIONS.height;
43798 	  }
43799 
43800 	  lanesMinHeight = getLanesMinHeight(participant, start);
43801 
43802 	  return max$1(PARTICIPANT_MIN_DIMENSIONS.height, lanesMinHeight);
43803 	}
43804 
43805 	function hasChildLanes(element) {
43806 	  return !!getChildLanes(element).length;
43807 	}
43808 
43809 	function getLanesMinHeight(participant, resizeStart) {
43810 	  var lanes = getChildLanes(participant),
43811 	      resizedLane;
43812 
43813 	  // find the nested lane which is currently resized
43814 	  resizedLane = findResizedLane(lanes, resizeStart);
43815 
43816 	  // resized lane cannot shrink below the minimum height
43817 	  // but remaining lanes' dimensions are kept intact
43818 	  return participant.height - resizedLane.height + LANE_MIN_DIMENSIONS.height;
43819 	}
43820 
43821 	/**
43822 	 * Find nested lane which is currently resized.
43823 	 *
43824 	 * @param {Array<djs.model.Shape>} lanes
43825 	 * @param {number} resizeStart
43826 	 */
43827 	function findResizedLane(lanes, resizeStart) {
43828 	  var i, lane, childLanes;
43829 
43830 	  for (i = 0; i < lanes.length; i++) {
43831 	    lane = lanes[i];
43832 
43833 	    // resizing current lane or a lane nested
43834 	    if (resizeStart >= lane.y && resizeStart <= lane.y + lane.height) {
43835 	      childLanes = getChildLanes(lane);
43836 
43837 	      // a nested lane is resized
43838 	      if (childLanes.length) {
43839 	        return findResizedLane(childLanes, resizeStart);
43840 	      }
43841 
43842 	      // current lane is the resized one
43843 	      return lane;
43844 	    }
43845 	  }
43846 	}
43847 
43848 	/**
43849 	 * Add start event replacing element with expanded sub process.
43850 	 *
43851 	 * @param {Injector} injector
43852 	 * @param {Modeling} modeling
43853 	 */
43854 	function SubProcessStartEventBehavior(injector, modeling) {
43855 	  injector.invoke(CommandInterceptor, this);
43856 
43857 	  this.postExecuted('shape.replace', function(event) {
43858 	    var oldShape = event.context.oldShape,
43859 	        newShape = event.context.newShape;
43860 
43861 	    if (
43862 	      !is$1(newShape, 'bpmn:SubProcess') ||
43863 	      !is$1(oldShape, 'bpmn:Task') ||
43864 	      !isExpanded(newShape)
43865 	    ) {
43866 	      return;
43867 	    }
43868 
43869 	    var position = getStartEventPosition(newShape);
43870 
43871 	    modeling.createShape({ type: 'bpmn:StartEvent' }, position, newShape);
43872 	  });
43873 	}
43874 
43875 	SubProcessStartEventBehavior.$inject = [
43876 	  'injector',
43877 	  'modeling'
43878 	];
43879 
43880 	inherits$1(SubProcessStartEventBehavior, CommandInterceptor);
43881 
43882 	// helpers //////////
43883 
43884 	function getStartEventPosition(shape) {
43885 	  return {
43886 	    x: shape.x + shape.width / 6,
43887 	    y: shape.y + shape.height / 2
43888 	  };
43889 	}
43890 
43891 	var LOW_PRIORITY$8 = 500;
43892 
43893 
43894 	function ToggleElementCollapseBehaviour(
43895 	    eventBus, elementFactory, modeling,
43896 	    resize) {
43897 
43898 	  CommandInterceptor.call(this, eventBus);
43899 
43900 
43901 	  function hideEmptyLabels(children) {
43902 	    if (children.length) {
43903 	      children.forEach(function(child) {
43904 	        if (child.type === 'label' && !child.businessObject.name) {
43905 	          child.hidden = true;
43906 	        }
43907 	      });
43908 	    }
43909 	  }
43910 
43911 	  function expandedBounds(shape, defaultSize) {
43912 	    var children = shape.children,
43913 	        newBounds = defaultSize,
43914 	        visibleElements,
43915 	        visibleBBox;
43916 
43917 	    visibleElements = filterVisible(children).concat([ shape ]);
43918 
43919 	    visibleBBox = computeChildrenBBox(visibleElements);
43920 
43921 	    if (visibleBBox) {
43922 
43923 	      // center to visibleBBox with max(defaultSize, childrenBounds)
43924 	      newBounds.width = Math.max(visibleBBox.width, newBounds.width);
43925 	      newBounds.height = Math.max(visibleBBox.height, newBounds.height);
43926 
43927 	      newBounds.x = visibleBBox.x + (visibleBBox.width - newBounds.width) / 2;
43928 	      newBounds.y = visibleBBox.y + (visibleBBox.height - newBounds.height) / 2;
43929 	    } else {
43930 
43931 	      // center to collapsed shape with defaultSize
43932 	      newBounds.x = shape.x + (shape.width - newBounds.width) / 2;
43933 	      newBounds.y = shape.y + (shape.height - newBounds.height) / 2;
43934 	    }
43935 
43936 	    return newBounds;
43937 	  }
43938 
43939 	  function collapsedBounds(shape, defaultSize) {
43940 
43941 	    return {
43942 	      x: shape.x + (shape.width - defaultSize.width) / 2,
43943 	      y: shape.y + (shape.height - defaultSize.height) / 2,
43944 	      width: defaultSize.width,
43945 	      height: defaultSize.height
43946 	    };
43947 	  }
43948 
43949 	  this.executed([ 'shape.toggleCollapse' ], LOW_PRIORITY$8, function(e) {
43950 
43951 	    var context = e.context,
43952 	        shape = context.shape;
43953 
43954 	    if (!is$1(shape, 'bpmn:SubProcess')) {
43955 	      return;
43956 	    }
43957 
43958 	    if (!shape.collapsed) {
43959 
43960 	      // all children got made visible through djs, hide empty labels
43961 	      hideEmptyLabels(shape.children);
43962 
43963 	      // remove collapsed marker
43964 	      getBusinessObject(shape).di.isExpanded = true;
43965 	    } else {
43966 
43967 	      // place collapsed marker
43968 	      getBusinessObject(shape).di.isExpanded = false;
43969 	    }
43970 	  });
43971 
43972 	  this.reverted([ 'shape.toggleCollapse' ], LOW_PRIORITY$8, function(e) {
43973 
43974 	    var context = e.context;
43975 	    var shape = context.shape;
43976 
43977 
43978 	    // revert removing/placing collapsed marker
43979 	    if (!shape.collapsed) {
43980 	      getBusinessObject(shape).di.isExpanded = true;
43981 
43982 	    } else {
43983 	      getBusinessObject(shape).di.isExpanded = false;
43984 	    }
43985 	  });
43986 
43987 	  this.postExecuted([ 'shape.toggleCollapse' ], LOW_PRIORITY$8, function(e) {
43988 	    var shape = e.context.shape,
43989 	        defaultSize = elementFactory._getDefaultSize(shape),
43990 	        newBounds;
43991 
43992 	    if (shape.collapsed) {
43993 
43994 	      // resize to default size of collapsed shapes
43995 	      newBounds = collapsedBounds(shape, defaultSize);
43996 	    } else {
43997 
43998 	      // resize to bounds of max(visible children, defaultSize)
43999 	      newBounds = expandedBounds(shape, defaultSize);
44000 	    }
44001 
44002 	    modeling.resizeShape(shape, newBounds, null, {
44003 	      autoResize: shape.collapsed ? false : 'nwse'
44004 	    });
44005 	  });
44006 
44007 	}
44008 
44009 
44010 	inherits$1(ToggleElementCollapseBehaviour, CommandInterceptor);
44011 
44012 	ToggleElementCollapseBehaviour.$inject = [
44013 	  'eventBus',
44014 	  'elementFactory',
44015 	  'modeling'
44016 	];
44017 
44018 
44019 	// helpers //////////////////////
44020 
44021 	function filterVisible(elements) {
44022 	  return elements.filter(function(e) {
44023 	    return !e.hidden;
44024 	  });
44025 	}
44026 
44027 	/**
44028 	 * Unclaims model IDs on element deletion.
44029 	 *
44030 	 * @param {Canvas} canvas
44031 	 * @param {Injector} injector
44032 	 * @param {Moddle} moddle
44033 	 * @param {Modeling} modeling
44034 	 */
44035 	function UnclaimIdBehavior(canvas, injector, moddle, modeling) {
44036 	  injector.invoke(CommandInterceptor, this);
44037 
44038 	  this.preExecute('shape.delete', function(event) {
44039 	    var context = event.context,
44040 	        shape = context.shape,
44041 	        shapeBo = shape.businessObject;
44042 
44043 	    if (isLabel$6(shape)) {
44044 	      return;
44045 	    }
44046 
44047 	    if (is$1(shape, 'bpmn:Participant') && isExpanded(shape)) {
44048 	      moddle.ids.unclaim(shapeBo.processRef.id);
44049 	    }
44050 
44051 	    modeling.unclaimId(shapeBo.id, shapeBo);
44052 	  });
44053 
44054 
44055 	  this.preExecute('connection.delete', function(event) {
44056 	    var context = event.context,
44057 	        connection = context.connection,
44058 	        connectionBo = connection.businessObject;
44059 
44060 	    modeling.unclaimId(connectionBo.id, connectionBo);
44061 	  });
44062 
44063 	  this.preExecute('canvas.updateRoot', function() {
44064 	    var rootElement = canvas.getRootElement(),
44065 	        rootElementBo = rootElement.businessObject;
44066 
44067 	    moddle.ids.unclaim(rootElementBo.id);
44068 	  });
44069 	}
44070 
44071 	inherits$1(UnclaimIdBehavior, CommandInterceptor);
44072 
44073 	UnclaimIdBehavior.$inject = [ 'canvas', 'injector', 'moddle', 'modeling' ];
44074 
44075 	var LOW_PRIORITY$7 = 500,
44076 	    HIGH_PRIORITY$7 = 5000;
44077 
44078 
44079 	/**
44080 	 * BPMN specific delete lane behavior
44081 	 */
44082 	function UpdateFlowNodeRefsBehavior(eventBus, modeling, translate) {
44083 
44084 	  CommandInterceptor.call(this, eventBus);
44085 
44086 	  /**
44087 	   * Ok, this is it:
44088 	   *
44089 	   * We have to update the Lane#flowNodeRefs _and_
44090 	   * FlowNode#lanes with every FlowNode move/resize and
44091 	   * Lane move/resize.
44092 	   *
44093 	   * We want to group that stuff to recompute containments
44094 	   * as efficient as possible.
44095 	   *
44096 	   * Yea!
44097 	   */
44098 
44099 	  // the update context
44100 	  var context;
44101 
44102 
44103 	  function initContext() {
44104 	    context = context || new UpdateContext();
44105 	    context.enter();
44106 
44107 	    return context;
44108 	  }
44109 
44110 	  function getContext() {
44111 	    if (!context) {
44112 	      throw new Error(translate('out of bounds release'));
44113 	    }
44114 
44115 	    return context;
44116 	  }
44117 
44118 	  function releaseContext() {
44119 
44120 	    if (!context) {
44121 	      throw new Error(translate('out of bounds release'));
44122 	    }
44123 
44124 	    var triggerUpdate = context.leave();
44125 
44126 	    if (triggerUpdate) {
44127 	      modeling.updateLaneRefs(context.flowNodes, context.lanes);
44128 
44129 	      context = null;
44130 	    }
44131 
44132 	    return triggerUpdate;
44133 	  }
44134 
44135 
44136 	  var laneRefUpdateEvents = [
44137 	    'spaceTool',
44138 	    'lane.add',
44139 	    'lane.resize',
44140 	    'lane.split',
44141 	    'elements.create',
44142 	    'elements.delete',
44143 	    'elements.move',
44144 	    'shape.create',
44145 	    'shape.delete',
44146 	    'shape.move',
44147 	    'shape.resize'
44148 	  ];
44149 
44150 
44151 	  // listen to a lot of stuff to group lane updates
44152 
44153 	  this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY$7, function(event) {
44154 	    initContext();
44155 	  });
44156 
44157 	  this.postExecuted(laneRefUpdateEvents, LOW_PRIORITY$7, function(event) {
44158 	    releaseContext();
44159 	  });
44160 
44161 
44162 	  // Mark flow nodes + lanes that need an update
44163 
44164 	  this.preExecute([
44165 	    'shape.create',
44166 	    'shape.move',
44167 	    'shape.delete',
44168 	    'shape.resize'
44169 	  ], function(event) {
44170 
44171 	    var context = event.context,
44172 	        shape = context.shape;
44173 
44174 	    var updateContext = getContext();
44175 
44176 	    // no need to update labels
44177 	    if (shape.labelTarget) {
44178 	      return;
44179 	    }
44180 
44181 	    if (is$1(shape, 'bpmn:Lane')) {
44182 	      updateContext.addLane(shape);
44183 	    }
44184 
44185 	    if (is$1(shape, 'bpmn:FlowNode')) {
44186 	      updateContext.addFlowNode(shape);
44187 	    }
44188 	  });
44189 	}
44190 
44191 	UpdateFlowNodeRefsBehavior.$inject = [
44192 	  'eventBus',
44193 	  'modeling' ,
44194 	  'translate'
44195 	];
44196 
44197 	inherits$1(UpdateFlowNodeRefsBehavior, CommandInterceptor);
44198 
44199 
44200 	function UpdateContext() {
44201 
44202 	  this.flowNodes = [];
44203 	  this.lanes = [];
44204 
44205 	  this.counter = 0;
44206 
44207 	  this.addLane = function(lane) {
44208 	    this.lanes.push(lane);
44209 	  };
44210 
44211 	  this.addFlowNode = function(flowNode) {
44212 	    this.flowNodes.push(flowNode);
44213 	  };
44214 
44215 	  this.enter = function() {
44216 	    this.counter++;
44217 	  };
44218 
44219 	  this.leave = function() {
44220 	    this.counter--;
44221 
44222 	    return !this.counter;
44223 	  };
44224 	}
44225 
44226 	/**
44227 	 * A behavior that unsets the Default property of
44228 	 * sequence flow source on element delete, if the
44229 	 * removed element is the Gateway or Task's default flow.
44230 	 *
44231 	 * @param {EventBus} eventBus
44232 	 * @param {Modeling} modeling
44233 	 */
44234 	function DeleteSequenceFlowBehavior(eventBus, modeling) {
44235 
44236 	  CommandInterceptor.call(this, eventBus);
44237 
44238 
44239 	  this.preExecute('connection.delete', function(event) {
44240 	    var context = event.context,
44241 	        connection = context.connection,
44242 	        source = connection.source;
44243 
44244 	    if (isDefaultFlow(connection, source)) {
44245 	      modeling.updateProperties(source, {
44246 	        'default': null
44247 	      });
44248 	    }
44249 	  });
44250 	}
44251 
44252 	inherits$1(DeleteSequenceFlowBehavior, CommandInterceptor);
44253 
44254 	DeleteSequenceFlowBehavior.$inject = [
44255 	  'eventBus',
44256 	  'modeling'
44257 	];
44258 
44259 
44260 	// helpers //////////////////////
44261 
44262 	function isDefaultFlow(connection, source) {
44263 
44264 	  if (!is$1(connection, 'bpmn:SequenceFlow')) {
44265 	    return false;
44266 	  }
44267 
44268 	  var sourceBo = getBusinessObject(source),
44269 	      sequenceFlow = getBusinessObject(connection);
44270 
44271 	  return sourceBo.get('default') === sequenceFlow;
44272 	}
44273 
44274 	var BehaviorModule = {
44275 	  __init__: [
44276 	    'adaptiveLabelPositioningBehavior',
44277 	    'appendBehavior',
44278 	    'associationBehavior',
44279 	    'attachEventBehavior',
44280 	    'boundaryEventBehavior',
44281 	    'rootElementReferenceBehavior',
44282 	    'createBehavior',
44283 	    'fixHoverBehavior',
44284 	    'createDataObjectBehavior',
44285 	    'createParticipantBehavior',
44286 	    'dataStoreBehavior',
44287 	    'dataInputAssociationBehavior',
44288 	    'deleteLaneBehavior',
44289 	    'detachEventBehavior',
44290 	    'dropOnFlowBehavior',
44291 	    'eventBasedGatewayBehavior',
44292 	    'groupBehavior',
44293 	    'importDockingFix',
44294 	    'isHorizontalFix',
44295 	    'labelBehavior',
44296 	    'messageFlowBehavior',
44297 	    'modelingFeedback',
44298 	    'removeElementBehavior',
44299 	    'removeParticipantBehavior',
44300 	    'replaceConnectionBehavior',
44301 	    'replaceElementBehaviour',
44302 	    'resizeBehavior',
44303 	    'resizeLaneBehavior',
44304 	    'toggleElementCollapseBehaviour',
44305 	    'spaceToolBehavior',
44306 	    'subProcessStartEventBehavior',
44307 	    'unclaimIdBehavior',
44308 	    'unsetDefaultFlowBehavior',
44309 	    'updateFlowNodeRefsBehavior'
44310 	  ],
44311 	  adaptiveLabelPositioningBehavior: [ 'type', AdaptiveLabelPositioningBehavior ],
44312 	  appendBehavior: [ 'type', AppendBehavior ],
44313 	  associationBehavior: [ 'type', AssociationBehavior ],
44314 	  attachEventBehavior: [ 'type', AttachEventBehavior ],
44315 	  boundaryEventBehavior: [ 'type', BoundaryEventBehavior ],
44316 	  rootElementReferenceBehavior: [ 'type', RootElementReferenceBehavior ],
44317 	  createBehavior: [ 'type', CreateBehavior ],
44318 	  fixHoverBehavior: [ 'type', FixHoverBehavior ],
44319 	  createDataObjectBehavior: [ 'type', CreateDataObjectBehavior ],
44320 	  createParticipantBehavior: [ 'type', CreateParticipantBehavior ],
44321 	  dataInputAssociationBehavior: [ 'type', DataInputAssociationBehavior ],
44322 	  dataStoreBehavior: [ 'type', DataStoreBehavior ],
44323 	  deleteLaneBehavior: [ 'type', DeleteLaneBehavior ],
44324 	  detachEventBehavior: [ 'type', DetachEventBehavior ],
44325 	  dropOnFlowBehavior: [ 'type', DropOnFlowBehavior ],
44326 	  eventBasedGatewayBehavior: [ 'type', EventBasedGatewayBehavior ],
44327 	  groupBehavior: [ 'type', GroupBehavior ],
44328 	  importDockingFix: [ 'type', ImportDockingFix ],
44329 	  isHorizontalFix: [ 'type', IsHorizontalFix ],
44330 	  labelBehavior: [ 'type', LabelBehavior ],
44331 	  messageFlowBehavior: [ 'type', MessageFlowBehavior ],
44332 	  modelingFeedback: [ 'type', ModelingFeedback ],
44333 	  replaceConnectionBehavior: [ 'type', ReplaceConnectionBehavior ],
44334 	  removeParticipantBehavior: [ 'type', RemoveParticipantBehavior ],
44335 	  replaceElementBehaviour: [ 'type', ReplaceElementBehaviour ],
44336 	  resizeBehavior: [ 'type', ResizeBehavior ],
44337 	  resizeLaneBehavior: [ 'type', ResizeLaneBehavior ],
44338 	  removeElementBehavior: [ 'type', RemoveElementBehavior ],
44339 	  toggleElementCollapseBehaviour : [ 'type', ToggleElementCollapseBehaviour ],
44340 	  spaceToolBehavior: [ 'type', SpaceToolBehavior ],
44341 	  subProcessStartEventBehavior: [ 'type', SubProcessStartEventBehavior ],
44342 	  unclaimIdBehavior: [ 'type', UnclaimIdBehavior ],
44343 	  updateFlowNodeRefsBehavior: [ 'type', UpdateFlowNodeRefsBehavior ],
44344 	  unsetDefaultFlowBehavior: [ 'type', DeleteSequenceFlowBehavior ]
44345 	};
44346 
44347 	function getBoundaryAttachment(position, targetBounds) {
44348 
44349 	  var orientation = getOrientation(position, targetBounds, -15);
44350 
44351 	  if (orientation !== 'intersect') {
44352 	    return orientation;
44353 	  } else {
44354 	    return null;
44355 	  }
44356 	}
44357 
44358 	/**
44359 	 * BPMN specific modeling rule
44360 	 */
44361 	function BpmnRules(eventBus) {
44362 	  RuleProvider.call(this, eventBus);
44363 	}
44364 
44365 	inherits$1(BpmnRules, RuleProvider);
44366 
44367 	BpmnRules.$inject = [ 'eventBus' ];
44368 
44369 	BpmnRules.prototype.init = function() {
44370 
44371 	  this.addRule('connection.start', function(context) {
44372 	    var source = context.source;
44373 
44374 	    return canStartConnection(source);
44375 	  });
44376 
44377 	  this.addRule('connection.create', function(context) {
44378 	    var source = context.source,
44379 	        target = context.target,
44380 	        hints = context.hints || {},
44381 	        targetParent = hints.targetParent,
44382 	        targetAttach = hints.targetAttach;
44383 
44384 	    // don't allow incoming connections on
44385 	    // newly created boundary events
44386 	    // to boundary events
44387 	    if (targetAttach) {
44388 	      return false;
44389 	    }
44390 
44391 	    // temporarily set target parent for scoping
44392 	    // checks to work
44393 	    if (targetParent) {
44394 	      target.parent = targetParent;
44395 	    }
44396 
44397 	    try {
44398 	      return canConnect(source, target);
44399 	    } finally {
44400 
44401 	      // unset temporary target parent
44402 	      if (targetParent) {
44403 	        target.parent = null;
44404 	      }
44405 	    }
44406 	  });
44407 
44408 	  this.addRule('connection.reconnect', function(context) {
44409 
44410 	    var connection = context.connection,
44411 	        source = context.source,
44412 	        target = context.target;
44413 
44414 	    return canConnect(source, target, connection);
44415 	  });
44416 
44417 	  this.addRule('connection.updateWaypoints', function(context) {
44418 	    return {
44419 	      type: context.connection.type
44420 	    };
44421 	  });
44422 
44423 	  this.addRule('shape.resize', function(context) {
44424 
44425 	    var shape = context.shape,
44426 	        newBounds = context.newBounds;
44427 
44428 	    return canResize(shape, newBounds);
44429 	  });
44430 
44431 	  this.addRule('elements.create', function(context) {
44432 	    var elements = context.elements,
44433 	        position = context.position,
44434 	        target = context.target;
44435 
44436 	    if (isConnection$8(target) && !canInsert(elements, target)) {
44437 	      return false;
44438 	    }
44439 
44440 	    return every(elements, function(element) {
44441 	      if (isConnection$8(element)) {
44442 	        return canConnect(element.source, element.target, element);
44443 	      }
44444 
44445 	      if (element.host) {
44446 	        return canAttach(element, element.host, null, position);
44447 	      }
44448 
44449 	      return canCreate(element, target, null);
44450 	    });
44451 	  });
44452 
44453 	  this.addRule('elements.move', function(context) {
44454 
44455 	    var target = context.target,
44456 	        shapes = context.shapes,
44457 	        position = context.position;
44458 
44459 	    return canAttach(shapes, target, null, position) ||
44460 	           canReplace(shapes, target, position) ||
44461 	           canMove(shapes, target) ||
44462 	           canInsert(shapes, target);
44463 	  });
44464 
44465 	  this.addRule('shape.create', function(context) {
44466 	    return canCreate(
44467 	      context.shape,
44468 	      context.target,
44469 	      context.source,
44470 	      context.position
44471 	    );
44472 	  });
44473 
44474 	  this.addRule('shape.attach', function(context) {
44475 
44476 	    return canAttach(
44477 	      context.shape,
44478 	      context.target,
44479 	      null,
44480 	      context.position
44481 	    );
44482 	  });
44483 
44484 	  this.addRule('element.copy', function(context) {
44485 	    var element = context.element,
44486 	        elements = context.elements;
44487 
44488 	    return canCopy(elements, element);
44489 	  });
44490 	};
44491 
44492 	BpmnRules.prototype.canConnectMessageFlow = canConnectMessageFlow;
44493 
44494 	BpmnRules.prototype.canConnectSequenceFlow = canConnectSequenceFlow;
44495 
44496 	BpmnRules.prototype.canConnectDataAssociation = canConnectDataAssociation;
44497 
44498 	BpmnRules.prototype.canConnectAssociation = canConnectAssociation;
44499 
44500 	BpmnRules.prototype.canMove = canMove;
44501 
44502 	BpmnRules.prototype.canAttach = canAttach;
44503 
44504 	BpmnRules.prototype.canReplace = canReplace;
44505 
44506 	BpmnRules.prototype.canDrop = canDrop;
44507 
44508 	BpmnRules.prototype.canInsert = canInsert;
44509 
44510 	BpmnRules.prototype.canCreate = canCreate;
44511 
44512 	BpmnRules.prototype.canConnect = canConnect;
44513 
44514 	BpmnRules.prototype.canResize = canResize;
44515 
44516 	BpmnRules.prototype.canCopy = canCopy;
44517 
44518 	/**
44519 	 * Utility functions for rule checking
44520 	 */
44521 
44522 	/**
44523 	 * Checks if given element can be used for starting connection.
44524 	 *
44525 	 * @param  {Element} source
44526 	 * @return {boolean}
44527 	 */
44528 	function canStartConnection(element) {
44529 	  if (nonExistingOrLabel(element)) {
44530 	    return null;
44531 	  }
44532 
44533 	  return isAny(element, [
44534 	    'bpmn:FlowNode',
44535 	    'bpmn:InteractionNode',
44536 	    'bpmn:DataObjectReference',
44537 	    'bpmn:DataStoreReference',
44538 	    'bpmn:Group',
44539 	    'bpmn:TextAnnotation'
44540 	  ]);
44541 	}
44542 
44543 	function nonExistingOrLabel(element) {
44544 	  return !element || isLabel$6(element);
44545 	}
44546 
44547 	function isSame$1(a, b) {
44548 	  return a === b;
44549 	}
44550 
44551 	function getOrganizationalParent(element) {
44552 
44553 	  do {
44554 	    if (is$1(element, 'bpmn:Process')) {
44555 	      return getBusinessObject(element);
44556 	    }
44557 
44558 	    if (is$1(element, 'bpmn:Participant')) {
44559 	      return (
44560 	        getBusinessObject(element).processRef ||
44561 	        getBusinessObject(element)
44562 	      );
44563 	    }
44564 	  } while ((element = element.parent));
44565 
44566 	}
44567 
44568 	function isTextAnnotation(element) {
44569 	  return is$1(element, 'bpmn:TextAnnotation');
44570 	}
44571 
44572 	function isGroup(element) {
44573 	  return is$1(element, 'bpmn:Group') && !element.labelTarget;
44574 	}
44575 
44576 	function isCompensationBoundary(element) {
44577 	  return is$1(element, 'bpmn:BoundaryEvent') &&
44578 	         hasEventDefinition(element, 'bpmn:CompensateEventDefinition');
44579 	}
44580 
44581 	function isForCompensation(e) {
44582 	  return getBusinessObject(e).isForCompensation;
44583 	}
44584 
44585 	function isSameOrganization(a, b) {
44586 	  var parentA = getOrganizationalParent(a),
44587 	      parentB = getOrganizationalParent(b);
44588 
44589 	  return parentA === parentB;
44590 	}
44591 
44592 	function isMessageFlowSource(element) {
44593 	  return (
44594 	    is$1(element, 'bpmn:InteractionNode') &&
44595 	    !is$1(element, 'bpmn:BoundaryEvent') && (
44596 	      !is$1(element, 'bpmn:Event') || (
44597 	        is$1(element, 'bpmn:ThrowEvent') &&
44598 	        hasEventDefinitionOrNone(element, 'bpmn:MessageEventDefinition')
44599 	      )
44600 	    )
44601 	  );
44602 	}
44603 
44604 	function isMessageFlowTarget(element) {
44605 	  return (
44606 	    is$1(element, 'bpmn:InteractionNode') &&
44607 	    !isForCompensation(element) && (
44608 	      !is$1(element, 'bpmn:Event') || (
44609 	        is$1(element, 'bpmn:CatchEvent') &&
44610 	        hasEventDefinitionOrNone(element, 'bpmn:MessageEventDefinition')
44611 	      )
44612 	    ) && !(
44613 	      is$1(element, 'bpmn:BoundaryEvent') &&
44614 	      !hasEventDefinition(element, 'bpmn:MessageEventDefinition')
44615 	    )
44616 	  );
44617 	}
44618 
44619 	function getScopeParent(element) {
44620 
44621 	  var parent = element;
44622 
44623 	  while ((parent = parent.parent)) {
44624 
44625 	    if (is$1(parent, 'bpmn:FlowElementsContainer')) {
44626 	      return getBusinessObject(parent);
44627 	    }
44628 
44629 	    if (is$1(parent, 'bpmn:Participant')) {
44630 	      return getBusinessObject(parent).processRef;
44631 	    }
44632 	  }
44633 
44634 	  return null;
44635 	}
44636 
44637 	function isSameScope(a, b) {
44638 	  var scopeParentA = getScopeParent(a),
44639 	      scopeParentB = getScopeParent(b);
44640 
44641 	  return scopeParentA === scopeParentB;
44642 	}
44643 
44644 	function hasEventDefinition(element, eventDefinition) {
44645 	  var bo = getBusinessObject(element);
44646 
44647 	  return !!find(bo.eventDefinitions || [], function(definition) {
44648 	    return is$1(definition, eventDefinition);
44649 	  });
44650 	}
44651 
44652 	function hasEventDefinitionOrNone(element, eventDefinition) {
44653 	  var bo = getBusinessObject(element);
44654 
44655 	  return (bo.eventDefinitions || []).every(function(definition) {
44656 	    return is$1(definition, eventDefinition);
44657 	  });
44658 	}
44659 
44660 	function isSequenceFlowSource(element) {
44661 	  return (
44662 	    is$1(element, 'bpmn:FlowNode') &&
44663 	    !is$1(element, 'bpmn:EndEvent') &&
44664 	    !isEventSubProcess(element) &&
44665 	    !(is$1(element, 'bpmn:IntermediateThrowEvent') &&
44666 	      hasEventDefinition(element, 'bpmn:LinkEventDefinition')
44667 	    ) &&
44668 	    !isCompensationBoundary(element) &&
44669 	    !isForCompensation(element)
44670 	  );
44671 	}
44672 
44673 	function isSequenceFlowTarget(element) {
44674 	  return (
44675 	    is$1(element, 'bpmn:FlowNode') &&
44676 	    !is$1(element, 'bpmn:StartEvent') &&
44677 	    !is$1(element, 'bpmn:BoundaryEvent') &&
44678 	    !isEventSubProcess(element) &&
44679 	    !(is$1(element, 'bpmn:IntermediateCatchEvent') &&
44680 	      hasEventDefinition(element, 'bpmn:LinkEventDefinition')
44681 	    ) &&
44682 	    !isForCompensation(element)
44683 	  );
44684 	}
44685 
44686 	function isEventBasedTarget(element) {
44687 	  return (
44688 	    is$1(element, 'bpmn:ReceiveTask') || (
44689 	      is$1(element, 'bpmn:IntermediateCatchEvent') && (
44690 	        hasEventDefinition(element, 'bpmn:MessageEventDefinition') ||
44691 	        hasEventDefinition(element, 'bpmn:TimerEventDefinition') ||
44692 	        hasEventDefinition(element, 'bpmn:ConditionalEventDefinition') ||
44693 	        hasEventDefinition(element, 'bpmn:SignalEventDefinition')
44694 	      )
44695 	    )
44696 	  );
44697 	}
44698 
44699 	function isConnection$8(element) {
44700 	  return element.waypoints;
44701 	}
44702 
44703 	function getParents(element) {
44704 
44705 	  var parents = [];
44706 
44707 	  while (element) {
44708 	    element = element.parent;
44709 
44710 	    if (element) {
44711 	      parents.push(element);
44712 	    }
44713 	  }
44714 
44715 	  return parents;
44716 	}
44717 
44718 	function isParent(possibleParent, element) {
44719 	  var allParents = getParents(element);
44720 	  return allParents.indexOf(possibleParent) !== -1;
44721 	}
44722 
44723 	function canConnect(source, target, connection) {
44724 
44725 	  if (nonExistingOrLabel(source) || nonExistingOrLabel(target)) {
44726 	    return null;
44727 	  }
44728 
44729 	  if (!is$1(connection, 'bpmn:DataAssociation')) {
44730 
44731 	    if (canConnectMessageFlow(source, target)) {
44732 	      return { type: 'bpmn:MessageFlow' };
44733 	    }
44734 
44735 	    if (canConnectSequenceFlow(source, target)) {
44736 	      return { type: 'bpmn:SequenceFlow' };
44737 	    }
44738 	  }
44739 
44740 	  var connectDataAssociation = canConnectDataAssociation(source, target);
44741 
44742 	  if (connectDataAssociation) {
44743 	    return connectDataAssociation;
44744 	  }
44745 
44746 	  if (isCompensationBoundary(source) && isForCompensation(target)) {
44747 	    return {
44748 	      type: 'bpmn:Association',
44749 	      associationDirection: 'One'
44750 	    };
44751 	  }
44752 
44753 	  if (canConnectAssociation(source, target)) {
44754 
44755 	    return {
44756 	      type: 'bpmn:Association'
44757 	    };
44758 	  }
44759 
44760 	  return false;
44761 	}
44762 
44763 	/**
44764 	 * Can an element be dropped into the target element
44765 	 *
44766 	 * @return {boolean}
44767 	 */
44768 	function canDrop(element, target, position) {
44769 
44770 	  // can move labels and groups everywhere
44771 	  if (isLabel$6(element) || isGroup(element)) {
44772 	    return true;
44773 	  }
44774 
44775 
44776 	  // disallow to create elements on collapsed pools
44777 	  if (is$1(target, 'bpmn:Participant') && !isExpanded(target)) {
44778 	    return false;
44779 	  }
44780 
44781 	  // allow to create new participants on
44782 	  // existing collaboration and process diagrams
44783 	  if (is$1(element, 'bpmn:Participant')) {
44784 	    return is$1(target, 'bpmn:Process') || is$1(target, 'bpmn:Collaboration');
44785 	  }
44786 
44787 	  // allow moving DataInput / DataOutput within its original container only
44788 	  if (isAny(element, [ 'bpmn:DataInput', 'bpmn:DataOutput' ])) {
44789 
44790 	    if (element.parent) {
44791 	      return target === element.parent;
44792 	    }
44793 	  }
44794 
44795 	  // allow creating lanes on participants and other lanes only
44796 	  if (is$1(element, 'bpmn:Lane')) {
44797 	    return is$1(target, 'bpmn:Participant') || is$1(target, 'bpmn:Lane');
44798 	  }
44799 
44800 	  // disallow dropping boundary events which cannot replace with intermediate event
44801 	  if (is$1(element, 'bpmn:BoundaryEvent') && !isDroppableBoundaryEvent(element)) {
44802 	    return false;
44803 	  }
44804 
44805 	  // drop flow elements onto flow element containers
44806 	  // and participants
44807 	  if (is$1(element, 'bpmn:FlowElement') && !is$1(element, 'bpmn:DataStoreReference')) {
44808 	    if (is$1(target, 'bpmn:FlowElementsContainer')) {
44809 	      return isExpanded(target);
44810 	    }
44811 
44812 	    return isAny(target, [ 'bpmn:Participant', 'bpmn:Lane' ]);
44813 	  }
44814 
44815 	  // disallow dropping data store reference if there is no process to append to
44816 	  if (is$1(element, 'bpmn:DataStoreReference') && is$1(target, 'bpmn:Collaboration')) {
44817 	    return some(getBusinessObject(target).get('participants'), function(participant) {
44818 	      return !!participant.get('processRef');
44819 	    });
44820 	  }
44821 
44822 	  // account for the fact that data associations are always
44823 	  // rendered and moved to top (Process or Collaboration level)
44824 	  //
44825 	  // artifacts may be placed wherever, too
44826 	  if (isAny(element, [ 'bpmn:Artifact', 'bpmn:DataAssociation', 'bpmn:DataStoreReference' ])) {
44827 	    return isAny(target, [
44828 	      'bpmn:Collaboration',
44829 	      'bpmn:Lane',
44830 	      'bpmn:Participant',
44831 	      'bpmn:Process',
44832 	      'bpmn:SubProcess' ]);
44833 	  }
44834 
44835 	  if (is$1(element, 'bpmn:MessageFlow')) {
44836 	    return is$1(target, 'bpmn:Collaboration')
44837 	      || element.source.parent == target
44838 	      || element.target.parent == target;
44839 	  }
44840 
44841 	  return false;
44842 	}
44843 
44844 	function isDroppableBoundaryEvent(event) {
44845 	  return getBusinessObject(event).cancelActivity && (
44846 	    hasNoEventDefinition(event) || hasCommonBoundaryIntermediateEventDefinition(event)
44847 	  );
44848 	}
44849 
44850 	function isBoundaryEvent(element) {
44851 	  return !isLabel$6(element) && is$1(element, 'bpmn:BoundaryEvent');
44852 	}
44853 
44854 	function isLane(element) {
44855 	  return is$1(element, 'bpmn:Lane');
44856 	}
44857 
44858 	/**
44859 	 * We treat IntermediateThrowEvents as boundary events during create,
44860 	 * this must be reflected in the rules.
44861 	 */
44862 	function isBoundaryCandidate(element) {
44863 	  if (isBoundaryEvent(element)) {
44864 	    return true;
44865 	  }
44866 
44867 	  if (is$1(element, 'bpmn:IntermediateThrowEvent') && hasNoEventDefinition(element)) {
44868 	    return true;
44869 	  }
44870 
44871 	  return (
44872 	    is$1(element, 'bpmn:IntermediateCatchEvent') &&
44873 	    hasCommonBoundaryIntermediateEventDefinition(element)
44874 	  );
44875 	}
44876 
44877 	function hasNoEventDefinition(element) {
44878 	  var bo = getBusinessObject(element);
44879 
44880 	  return bo && !(bo.eventDefinitions && bo.eventDefinitions.length);
44881 	}
44882 
44883 	function hasCommonBoundaryIntermediateEventDefinition(element) {
44884 	  return hasOneOfEventDefinitions(element, [
44885 	    'bpmn:MessageEventDefinition',
44886 	    'bpmn:TimerEventDefinition',
44887 	    'bpmn:SignalEventDefinition',
44888 	    'bpmn:ConditionalEventDefinition'
44889 	  ]);
44890 	}
44891 
44892 	function hasOneOfEventDefinitions(element, eventDefinitions) {
44893 	  return eventDefinitions.some(function(definition) {
44894 	    return hasEventDefinition(element, definition);
44895 	  });
44896 	}
44897 
44898 	function isReceiveTaskAfterEventBasedGateway(element) {
44899 	  return (
44900 	    is$1(element, 'bpmn:ReceiveTask') &&
44901 	    find(element.incoming, function(incoming) {
44902 	      return is$1(incoming.source, 'bpmn:EventBasedGateway');
44903 	    })
44904 	  );
44905 	}
44906 
44907 
44908 	function canAttach(elements, target, source, position) {
44909 
44910 	  if (!Array.isArray(elements)) {
44911 	    elements = [ elements ];
44912 	  }
44913 
44914 	  // only (re-)attach one element at a time
44915 	  if (elements.length !== 1) {
44916 	    return false;
44917 	  }
44918 
44919 	  var element = elements[0];
44920 
44921 	  // do not attach labels
44922 	  if (isLabel$6(element)) {
44923 	    return false;
44924 	  }
44925 
44926 	  // only handle boundary events
44927 	  if (!isBoundaryCandidate(element)) {
44928 	    return false;
44929 	  }
44930 
44931 	  // disallow drop on event sub processes
44932 	  if (isEventSubProcess(target)) {
44933 	    return false;
44934 	  }
44935 
44936 	  // only allow drop on non compensation activities
44937 	  if (!is$1(target, 'bpmn:Activity') || isForCompensation(target)) {
44938 	    return false;
44939 	  }
44940 
44941 	  // only attach to subprocess border
44942 	  if (position && !getBoundaryAttachment(position, target)) {
44943 	    return false;
44944 	  }
44945 
44946 	  // do not attach on receive tasks after event based gateways
44947 	  if (isReceiveTaskAfterEventBasedGateway(target)) {
44948 	    return false;
44949 	  }
44950 
44951 	  return 'attach';
44952 	}
44953 
44954 
44955 	/**
44956 	 * Defines how to replace elements for a given target.
44957 	 *
44958 	 * Returns an array containing all elements which will be replaced.
44959 	 *
44960 	 * @example
44961 	 *
44962 	 *  [{ id: 'IntermediateEvent_2',
44963 	 *     type: 'bpmn:StartEvent'
44964 	 *   },
44965 	 *   { id: 'IntermediateEvent_5',
44966 	 *     type: 'bpmn:EndEvent'
44967 	 *   }]
44968 	 *
44969 	 * @param  {Array} elements
44970 	 * @param  {Object} target
44971 	 *
44972 	 * @return {Object} an object containing all elements which have to be replaced
44973 	 */
44974 	function canReplace(elements, target, position) {
44975 
44976 	  if (!target) {
44977 	    return false;
44978 	  }
44979 
44980 	  var canExecute = {
44981 	    replacements: []
44982 	  };
44983 
44984 	  forEach(elements, function(element) {
44985 
44986 	    if (!isEventSubProcess(target)) {
44987 
44988 	      if (is$1(element, 'bpmn:StartEvent') &&
44989 	          element.type !== 'label' &&
44990 	          canDrop(element, target)) {
44991 
44992 	        // replace a non-interrupting start event by a blank interrupting start event
44993 	        // when the target is not an event sub process
44994 	        if (!isInterrupting(element)) {
44995 	          canExecute.replacements.push({
44996 	            oldElementId: element.id,
44997 	            newElementType: 'bpmn:StartEvent'
44998 	          });
44999 	        }
45000 
45001 	        // replace an error/escalation/compensate start event by a blank interrupting start event
45002 	        // when the target is not an event sub process
45003 	        if (hasErrorEventDefinition(element) ||
45004 	            hasEscalationEventDefinition(element) ||
45005 	            hasCompensateEventDefinition(element)) {
45006 	          canExecute.replacements.push({
45007 	            oldElementId: element.id,
45008 	            newElementType: 'bpmn:StartEvent'
45009 	          });
45010 	        }
45011 
45012 	        // replace a typed start event by a blank interrupting start event
45013 	        // when the target is a sub process but not an event sub process
45014 	        if (hasOneOfEventDefinitions(element,
45015 	          [
45016 	            'bpmn:MessageEventDefinition',
45017 	            'bpmn:TimerEventDefinition',
45018 	            'bpmn:SignalEventDefinition',
45019 	            'bpmn:ConditionalEventDefinition'
45020 	          ]) &&
45021 	            is$1(target, 'bpmn:SubProcess')) {
45022 	          canExecute.replacements.push({
45023 	            oldElementId: element.id,
45024 	            newElementType: 'bpmn:StartEvent'
45025 	          });
45026 	        }
45027 	      }
45028 	    }
45029 
45030 	    if (!is$1(target, 'bpmn:Transaction')) {
45031 	      if (hasEventDefinition(element, 'bpmn:CancelEventDefinition') &&
45032 	          element.type !== 'label') {
45033 
45034 	        if (is$1(element, 'bpmn:EndEvent') && canDrop(element, target)) {
45035 	          canExecute.replacements.push({
45036 	            oldElementId: element.id,
45037 	            newElementType: 'bpmn:EndEvent'
45038 	          });
45039 	        }
45040 
45041 	        if (is$1(element, 'bpmn:BoundaryEvent') && canAttach(element, target, null, position)) {
45042 	          canExecute.replacements.push({
45043 	            oldElementId: element.id,
45044 	            newElementType: 'bpmn:BoundaryEvent'
45045 	          });
45046 	        }
45047 	      }
45048 	    }
45049 	  });
45050 
45051 	  return canExecute.replacements.length ? canExecute : false;
45052 	}
45053 
45054 	function canMove(elements, target) {
45055 
45056 	  // do not move selection containing lanes
45057 	  if (some(elements, isLane)) {
45058 	    return false;
45059 	  }
45060 
45061 	  // allow default move check to start move operation
45062 	  if (!target) {
45063 	    return true;
45064 	  }
45065 
45066 	  return elements.every(function(element) {
45067 	    return canDrop(element, target);
45068 	  });
45069 	}
45070 
45071 	function canCreate(shape, target, source, position) {
45072 
45073 	  if (!target) {
45074 	    return false;
45075 	  }
45076 
45077 	  if (isLabel$6(shape) || isGroup(shape)) {
45078 	    return true;
45079 	  }
45080 
45081 	  if (isSame$1(source, target)) {
45082 	    return false;
45083 	  }
45084 
45085 	  // ensure we do not drop the element
45086 	  // into source
45087 	  if (source && isParent(source, target)) {
45088 	    return false;
45089 	  }
45090 
45091 	  return canDrop(shape, target) || canInsert(shape, target);
45092 	}
45093 
45094 	function canResize(shape, newBounds) {
45095 	  if (is$1(shape, 'bpmn:SubProcess')) {
45096 	    return (
45097 	      isExpanded(shape) && (
45098 	        !newBounds || (newBounds.width >= 100 && newBounds.height >= 80)
45099 	      )
45100 	    );
45101 	  }
45102 
45103 	  if (is$1(shape, 'bpmn:Lane')) {
45104 	    return !newBounds || (newBounds.width >= 130 && newBounds.height >= 60);
45105 	  }
45106 
45107 	  if (is$1(shape, 'bpmn:Participant')) {
45108 	    return !newBounds || (newBounds.width >= 250 && newBounds.height >= 50);
45109 	  }
45110 
45111 	  if (isTextAnnotation(shape)) {
45112 	    return true;
45113 	  }
45114 
45115 	  if (isGroup(shape)) {
45116 	    return true;
45117 	  }
45118 
45119 	  return false;
45120 	}
45121 
45122 	/**
45123 	 * Check, whether one side of the relationship
45124 	 * is a text annotation.
45125 	 */
45126 	function isOneTextAnnotation(source, target) {
45127 
45128 	  var sourceTextAnnotation = isTextAnnotation(source),
45129 	      targetTextAnnotation = isTextAnnotation(target);
45130 
45131 	  return (
45132 	    (sourceTextAnnotation || targetTextAnnotation) &&
45133 	    (sourceTextAnnotation !== targetTextAnnotation)
45134 	  );
45135 	}
45136 
45137 
45138 	function canConnectAssociation(source, target) {
45139 
45140 	  // do not connect connections
45141 	  if (isConnection$8(source) || isConnection$8(target)) {
45142 	    return false;
45143 	  }
45144 
45145 	  // compensation boundary events are exception
45146 	  if (isCompensationBoundary(source) && isForCompensation(target)) {
45147 	    return true;
45148 	  }
45149 
45150 	  // don't connect parent <-> child
45151 	  if (isParent(target, source) || isParent(source, target)) {
45152 	    return false;
45153 	  }
45154 
45155 	  // allow connection of associations between <!TextAnnotation> and <TextAnnotation>
45156 	  if (isOneTextAnnotation(source, target)) {
45157 	    return true;
45158 	  }
45159 
45160 	  // can connect associations where we can connect
45161 	  // data associations, too (!)
45162 	  return !!canConnectDataAssociation(source, target);
45163 	}
45164 
45165 	function canConnectMessageFlow(source, target) {
45166 
45167 	  // during connect user might move mouse out of canvas
45168 	  // https://github.com/bpmn-io/bpmn-js/issues/1033
45169 	  if (getRootElement(source) && !getRootElement(target)) {
45170 	    return false;
45171 	  }
45172 
45173 	  return (
45174 	    isMessageFlowSource(source) &&
45175 	    isMessageFlowTarget(target) &&
45176 	    !isSameOrganization(source, target)
45177 	  );
45178 	}
45179 
45180 	function canConnectSequenceFlow(source, target) {
45181 
45182 	  if (
45183 	    isEventBasedTarget(target) &&
45184 	    target.incoming.length > 0 &&
45185 	    areOutgoingEventBasedGatewayConnections(target.incoming) &&
45186 	    !is$1(source, 'bpmn:EventBasedGateway')
45187 	  ) {
45188 	    return false;
45189 	  }
45190 
45191 	  return isSequenceFlowSource(source) &&
45192 	         isSequenceFlowTarget(target) &&
45193 	         isSameScope(source, target) &&
45194 	         !(is$1(source, 'bpmn:EventBasedGateway') && !isEventBasedTarget(target));
45195 	}
45196 
45197 
45198 	function canConnectDataAssociation(source, target) {
45199 
45200 	  if (isAny(source, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ]) &&
45201 	      isAny(target, [ 'bpmn:Activity', 'bpmn:ThrowEvent' ])) {
45202 	    return { type: 'bpmn:DataInputAssociation' };
45203 	  }
45204 
45205 	  if (isAny(target, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ]) &&
45206 	      isAny(source, [ 'bpmn:Activity', 'bpmn:CatchEvent' ])) {
45207 	    return { type: 'bpmn:DataOutputAssociation' };
45208 	  }
45209 
45210 	  return false;
45211 	}
45212 
45213 	function canInsert(shape, flow, position) {
45214 
45215 	  if (!flow) {
45216 	    return false;
45217 	  }
45218 
45219 	  if (Array.isArray(shape)) {
45220 	    if (shape.length !== 1) {
45221 	      return false;
45222 	    }
45223 
45224 	    shape = shape[0];
45225 	  }
45226 
45227 	  if (flow.source === shape ||
45228 	      flow.target === shape) {
45229 	    return false;
45230 	  }
45231 
45232 	  // return true if we can drop on the
45233 	  // underlying flow parent
45234 	  //
45235 	  // at this point we are not really able to talk
45236 	  // about connection rules (yet)
45237 
45238 	  return (
45239 	    isAny(flow, [ 'bpmn:SequenceFlow', 'bpmn:MessageFlow' ]) &&
45240 	    !isLabel$6(flow) &&
45241 	    is$1(shape, 'bpmn:FlowNode') &&
45242 	    !is$1(shape, 'bpmn:BoundaryEvent') &&
45243 	    canDrop(shape, flow.parent));
45244 	}
45245 
45246 	function includes$5(elements, element) {
45247 	  return (elements && element) && elements.indexOf(element) !== -1;
45248 	}
45249 
45250 	function canCopy(elements, element) {
45251 	  if (isLabel$6(element)) {
45252 	    return true;
45253 	  }
45254 
45255 	  if (is$1(element, 'bpmn:Lane') && !includes$5(elements, element.parent)) {
45256 	    return false;
45257 	  }
45258 
45259 	  return true;
45260 	}
45261 
45262 	function isOutgoingEventBasedGatewayConnection(connection) {
45263 
45264 	  if (connection && connection.source) {
45265 	    return is$1(connection.source, 'bpmn:EventBasedGateway');
45266 	  }
45267 	}
45268 
45269 	function areOutgoingEventBasedGatewayConnections(connections) {
45270 	  connections = connections || [];
45271 
45272 	  return connections.some(isOutgoingEventBasedGatewayConnection);
45273 	}
45274 
45275 	function getRootElement(element) {
45276 	  return getParent(element, 'bpmn:Process') || getParent(element, 'bpmn:Collaboration');
45277 	}
45278 
45279 	var RulesModule = {
45280 	  __depends__: [
45281 	    RulesModule$1
45282 	  ],
45283 	  __init__: [ 'bpmnRules' ],
45284 	  bpmnRules: [ 'type', BpmnRules ]
45285 	};
45286 
45287 	var HIGH_PRIORITY$6 = 2000;
45288 
45289 	function BpmnDiOrdering(eventBus, canvas) {
45290 
45291 	  eventBus.on('saveXML.start', HIGH_PRIORITY$6, orderDi);
45292 
45293 	  function orderDi() {
45294 	    var root = canvas.getRootElement(),
45295 	        rootDi = getBusinessObject(root).di,
45296 	        elements,
45297 	        diElements;
45298 
45299 	    elements = selfAndAllChildren([ root ], false);
45300 
45301 	    // only bpmndi:Shape and bpmndi:Edge can be direct children of bpmndi:Plane
45302 	    elements = filter(elements, function(element) {
45303 	      return element !== root && !element.labelTarget;
45304 	    });
45305 
45306 	    diElements = map$1(elements, getDi);
45307 
45308 	    rootDi.set('planeElement', diElements);
45309 	  }
45310 	}
45311 
45312 	BpmnDiOrdering.$inject = [ 'eventBus', 'canvas' ];
45313 
45314 	var DiOrderingModule = {
45315 	  __init__: [
45316 	    'bpmnDiOrdering'
45317 	  ],
45318 	  bpmnDiOrdering: [ 'type', BpmnDiOrdering ]
45319 	};
45320 
45321 	/**
45322 	 * An abstract provider that allows modelers to implement a custom
45323 	 * ordering of diagram elements on the canvas.
45324 	 *
45325 	 * It makes sure that the order is always preserved during element
45326 	 * creation and move operations.
45327 	 *
45328 	 * In order to use this behavior, inherit from it and override
45329 	 * the method {@link OrderingProvider#getOrdering}.
45330 	 *
45331 	 * @example
45332 	 *
45333 	 * ```javascript
45334 	 * function CustomOrderingProvider(eventBus) {
45335 	 *   OrderingProvider.call(this, eventBus);
45336 	 *
45337 	 *   this.getOrdering = function(element, newParent) {
45338 	 *     // always insert elements at the front
45339 	 *     // when moving
45340 	 *     return {
45341 	 *       index: 0,
45342 	 *       parent: newParent
45343 	 *     };
45344 	 *   };
45345 	 * }
45346 	 * ```
45347 	 *
45348 	 * @param {EventBus} eventBus
45349 	 */
45350 	function OrderingProvider(eventBus) {
45351 
45352 	  CommandInterceptor.call(this, eventBus);
45353 
45354 
45355 	  var self = this;
45356 
45357 	  this.preExecute([ 'shape.create', 'connection.create' ], function(event) {
45358 
45359 	    var context = event.context,
45360 	        element = context.shape || context.connection,
45361 	        parent = context.parent;
45362 
45363 	    var ordering = self.getOrdering(element, parent);
45364 
45365 	    if (ordering) {
45366 
45367 	      if (ordering.parent !== undefined) {
45368 	        context.parent = ordering.parent;
45369 	      }
45370 
45371 	      context.parentIndex = ordering.index;
45372 	    }
45373 	  });
45374 
45375 	  this.preExecute([ 'shape.move', 'connection.move' ], function(event) {
45376 
45377 	    var context = event.context,
45378 	        element = context.shape || context.connection,
45379 	        parent = context.newParent || element.parent;
45380 
45381 	    var ordering = self.getOrdering(element, parent);
45382 
45383 	    if (ordering) {
45384 
45385 	      if (ordering.parent !== undefined) {
45386 	        context.newParent = ordering.parent;
45387 	      }
45388 
45389 	      context.newParentIndex = ordering.index;
45390 	    }
45391 	  });
45392 	}
45393 
45394 	/**
45395 	 * Return a custom ordering of the element, both in terms
45396 	 * of parent element and index in the new parent.
45397 	 *
45398 	 * Implementors of this method must return an object with
45399 	 * `parent` _and_ `index` in it.
45400 	 *
45401 	 * @param {djs.model.Base} element
45402 	 * @param {djs.model.Shape} newParent
45403 	 *
45404 	 * @return {Object} ordering descriptor
45405 	 */
45406 	OrderingProvider.prototype.getOrdering = function(element, newParent) {
45407 	  return null;
45408 	};
45409 
45410 	inherits$1(OrderingProvider, CommandInterceptor);
45411 
45412 	/**
45413 	 * a simple ordering provider that makes sure:
45414 	 *
45415 	 * (0) labels and groups are rendered always on top
45416 	 * (1) elements are ordered by a {level} property
45417 	 */
45418 	function BpmnOrderingProvider(eventBus, canvas, translate) {
45419 
45420 	  OrderingProvider.call(this, eventBus);
45421 
45422 	  var orders = [
45423 	    { type: 'bpmn:SubProcess', order: { level: 6 } },
45424 	    {
45425 	      type: 'bpmn:SequenceFlow',
45426 	      order: {
45427 	        level: 3,
45428 	        containers: [
45429 	          'bpmn:Participant',
45430 	          'bpmn:FlowElementsContainer'
45431 	        ]
45432 	      }
45433 	    },
45434 
45435 	    // handle DataAssociation(s) like message flows and render them always on top
45436 	    {
45437 	      type: 'bpmn:DataAssociation',
45438 	      order: {
45439 	        level: 9,
45440 	        containers: [
45441 	          'bpmn:Collaboration',
45442 	          'bpmn:Process'
45443 	        ]
45444 	      }
45445 	    },
45446 	    {
45447 	      type: 'bpmn:MessageFlow', order: {
45448 	        level: 9,
45449 	        containers: [ 'bpmn:Collaboration' ]
45450 	      }
45451 	    },
45452 	    {
45453 	      type: 'bpmn:Association',
45454 	      order: {
45455 	        level: 6,
45456 	        containers: [
45457 	          'bpmn:Participant',
45458 	          'bpmn:FlowElementsContainer',
45459 	          'bpmn:Collaboration'
45460 	        ]
45461 	      }
45462 	    },
45463 	    { type: 'bpmn:BoundaryEvent', order: { level: 8 } },
45464 	    {
45465 	      type: 'bpmn:Group',
45466 	      order: {
45467 	        level: 10,
45468 	        containers: [
45469 	          'bpmn:Collaboration',
45470 	          'bpmn:Process'
45471 	        ]
45472 	      }
45473 	    },
45474 	    { type: 'bpmn:FlowElement', order: { level: 5 } },
45475 	    { type: 'bpmn:Participant', order: { level: -2 } },
45476 	    { type: 'bpmn:Lane', order: { level: -1 } }
45477 	  ];
45478 
45479 	  function computeOrder(element) {
45480 	    if (element.labelTarget) {
45481 	      return { level: 10 };
45482 	    }
45483 
45484 	    var entry = find(orders, function(o) {
45485 	      return isAny(element, [ o.type ]);
45486 	    });
45487 
45488 	    return entry && entry.order || { level: 1 };
45489 	  }
45490 
45491 	  function getOrder(element) {
45492 
45493 	    var order = element.order;
45494 
45495 	    if (!order) {
45496 	      element.order = order = computeOrder(element);
45497 	    }
45498 
45499 	    if (!order) {
45500 	      throw new Error('no order for <' + element.id + '>');
45501 	    }
45502 
45503 	    return order;
45504 	  }
45505 
45506 	  function findActualParent(element, newParent, containers) {
45507 
45508 	    var actualParent = newParent;
45509 
45510 	    while (actualParent) {
45511 
45512 	      if (isAny(actualParent, containers)) {
45513 	        break;
45514 	      }
45515 
45516 	      actualParent = actualParent.parent;
45517 	    }
45518 
45519 	    if (!actualParent) {
45520 	      throw new Error('no parent for <' + element.id + '> in <' + (newParent && newParent.id) + '>');
45521 	    }
45522 
45523 	    return actualParent;
45524 	  }
45525 
45526 	  this.getOrdering = function(element, newParent) {
45527 
45528 	    // render labels always on top
45529 	    if (element.labelTarget) {
45530 	      return {
45531 	        parent: canvas.getRootElement(),
45532 	        index: -1
45533 	      };
45534 	    }
45535 
45536 	    var elementOrder = getOrder(element);
45537 
45538 	    if (elementOrder.containers) {
45539 	      newParent = findActualParent(element, newParent, elementOrder.containers);
45540 	    }
45541 
45542 	    var currentIndex = newParent.children.indexOf(element);
45543 
45544 	    var insertIndex = findIndex(newParent.children, function(child) {
45545 
45546 	      // do not compare with labels, they are created
45547 	      // in the wrong order (right after elements) during import and
45548 	      // mess up the positioning.
45549 	      if (!element.labelTarget && child.labelTarget) {
45550 	        return false;
45551 	      }
45552 
45553 	      return elementOrder.level < getOrder(child).level;
45554 	    });
45555 
45556 
45557 	    // if the element is already in the child list at
45558 	    // a smaller index, we need to adjust the insert index.
45559 	    // this takes into account that the element is being removed
45560 	    // before being re-inserted
45561 	    if (insertIndex !== -1) {
45562 	      if (currentIndex !== -1 && currentIndex < insertIndex) {
45563 	        insertIndex -= 1;
45564 	      }
45565 	    }
45566 
45567 	    return {
45568 	      index: insertIndex,
45569 	      parent: newParent
45570 	    };
45571 	  };
45572 	}
45573 
45574 	BpmnOrderingProvider.$inject = [ 'eventBus', 'canvas', 'translate' ];
45575 
45576 	inherits$1(BpmnOrderingProvider, OrderingProvider);
45577 
45578 	var OrderingModule = {
45579 	  __depends__: [
45580 	    translate
45581 	  ],
45582 	  __init__: [ 'bpmnOrderingProvider' ],
45583 	  bpmnOrderingProvider: [ 'type', BpmnOrderingProvider ]
45584 	};
45585 
45586 	/**
45587 	 * A service that offers un- and redoable execution of commands.
45588 	 *
45589 	 * The command stack is responsible for executing modeling actions
45590 	 * in a un- and redoable manner. To do this it delegates the actual
45591 	 * command execution to {@link CommandHandler}s.
45592 	 *
45593 	 * Command handlers provide {@link CommandHandler#execute(ctx)} and
45594 	 * {@link CommandHandler#revert(ctx)} methods to un- and redo a command
45595 	 * identified by a command context.
45596 	 *
45597 	 *
45598 	 * ## Life-Cycle events
45599 	 *
45600 	 * In the process the command stack fires a number of life-cycle events
45601 	 * that other components to participate in the command execution.
45602 	 *
45603 	 *    * preExecute
45604 	 *    * preExecuted
45605 	 *    * execute
45606 	 *    * executed
45607 	 *    * postExecute
45608 	 *    * postExecuted
45609 	 *    * revert
45610 	 *    * reverted
45611 	 *
45612 	 * A special event is used for validating, whether a command can be
45613 	 * performed prior to its execution.
45614 	 *
45615 	 *    * canExecute
45616 	 *
45617 	 * Each of the events is fired as `commandStack.{eventName}` and
45618 	 * `commandStack.{commandName}.{eventName}`, respectively. This gives
45619 	 * components fine grained control on where to hook into.
45620 	 *
45621 	 * The event object fired transports `command`, the name of the
45622 	 * command and `context`, the command context.
45623 	 *
45624 	 *
45625 	 * ## Creating Command Handlers
45626 	 *
45627 	 * Command handlers should provide the {@link CommandHandler#execute(ctx)}
45628 	 * and {@link CommandHandler#revert(ctx)} methods to implement
45629 	 * redoing and undoing of a command.
45630 	 *
45631 	 * A command handler _must_ ensure undo is performed properly in order
45632 	 * not to break the undo chain. It must also return the shapes that
45633 	 * got changed during the `execute` and `revert` operations.
45634 	 *
45635 	 * Command handlers may execute other modeling operations (and thus
45636 	 * commands) in their `preExecute` and `postExecute` phases. The command
45637 	 * stack will properly group all commands together into a logical unit
45638 	 * that may be re- and undone atomically.
45639 	 *
45640 	 * Command handlers must not execute other commands from within their
45641 	 * core implementation (`execute`, `revert`).
45642 	 *
45643 	 *
45644 	 * ## Change Tracking
45645 	 *
45646 	 * During the execution of the CommandStack it will keep track of all
45647 	 * elements that have been touched during the command's execution.
45648 	 *
45649 	 * At the end of the CommandStack execution it will notify interested
45650 	 * components via an 'elements.changed' event with all the dirty
45651 	 * elements.
45652 	 *
45653 	 * The event can be picked up by components that are interested in the fact
45654 	 * that elements have been changed. One use case for this is updating
45655 	 * their graphical representation after moving / resizing or deletion.
45656 	 *
45657 	 * @see CommandHandler
45658 	 *
45659 	 * @param {EventBus} eventBus
45660 	 * @param {Injector} injector
45661 	 */
45662 	function CommandStack(eventBus, injector) {
45663 
45664 	  /**
45665 	   * A map of all registered command handlers.
45666 	   *
45667 	   * @type {Object}
45668 	   */
45669 	  this._handlerMap = {};
45670 
45671 	  /**
45672 	   * A stack containing all re/undoable actions on the diagram
45673 	   *
45674 	   * @type {Array<Object>}
45675 	   */
45676 	  this._stack = [];
45677 
45678 	  /**
45679 	   * The current index on the stack
45680 	   *
45681 	   * @type {number}
45682 	   */
45683 	  this._stackIdx = -1;
45684 
45685 	  /**
45686 	   * Current active commandStack execution
45687 	   *
45688 	   * @type {Object}
45689 	   * @property {Object[]} actions
45690 	   * @property {Object[]} dirty
45691 	   * @property { 'undo' | 'redo' | 'clear' | 'execute' | null } trigger the cause of the current excecution
45692 	   */
45693 	  this._currentExecution = {
45694 	    actions: [],
45695 	    dirty: [],
45696 	    trigger: null
45697 	  };
45698 
45699 
45700 	  this._injector = injector;
45701 	  this._eventBus = eventBus;
45702 
45703 	  this._uid = 1;
45704 
45705 	  eventBus.on([
45706 	    'diagram.destroy',
45707 	    'diagram.clear'
45708 	  ], function() {
45709 	    this.clear(false);
45710 	  }, this);
45711 	}
45712 
45713 	CommandStack.$inject = [ 'eventBus', 'injector' ];
45714 
45715 
45716 	/**
45717 	 * Execute a command
45718 	 *
45719 	 * @param {string} command the command to execute
45720 	 * @param {Object} context the environment to execute the command in
45721 	 */
45722 	CommandStack.prototype.execute = function(command, context) {
45723 	  if (!command) {
45724 	    throw new Error('command required');
45725 	  }
45726 
45727 	  this._currentExecution.trigger = 'execute';
45728 
45729 	  var action = { command: command, context: context };
45730 
45731 	  this._pushAction(action);
45732 	  this._internalExecute(action);
45733 	  this._popAction(action);
45734 	};
45735 
45736 
45737 	/**
45738 	 * Ask whether a given command can be executed.
45739 	 *
45740 	 * Implementors may hook into the mechanism on two ways:
45741 	 *
45742 	 *   * in event listeners:
45743 	 *
45744 	 *     Users may prevent the execution via an event listener.
45745 	 *     It must prevent the default action for `commandStack.(<command>.)canExecute` events.
45746 	 *
45747 	 *   * in command handlers:
45748 	 *
45749 	 *     If the method {@link CommandHandler#canExecute} is implemented in a handler
45750 	 *     it will be called to figure out whether the execution is allowed.
45751 	 *
45752 	 * @param  {string} command the command to execute
45753 	 * @param  {Object} context the environment to execute the command in
45754 	 *
45755 	 * @return {boolean} true if the command can be executed
45756 	 */
45757 	CommandStack.prototype.canExecute = function(command, context) {
45758 
45759 	  var action = { command: command, context: context };
45760 
45761 	  var handler = this._getHandler(command);
45762 
45763 	  var result = this._fire(command, 'canExecute', action);
45764 
45765 	  // handler#canExecute will only be called if no listener
45766 	  // decided on a result already
45767 	  if (result === undefined) {
45768 	    if (!handler) {
45769 	      return false;
45770 	    }
45771 
45772 	    if (handler.canExecute) {
45773 	      result = handler.canExecute(context);
45774 	    }
45775 	  }
45776 
45777 	  return result;
45778 	};
45779 
45780 
45781 	/**
45782 	 * Clear the command stack, erasing all undo / redo history
45783 	 */
45784 	CommandStack.prototype.clear = function(emit) {
45785 	  this._stack.length = 0;
45786 	  this._stackIdx = -1;
45787 
45788 	  if (emit !== false) {
45789 	    this._fire('changed', { trigger: 'clear' });
45790 	  }
45791 	};
45792 
45793 
45794 	/**
45795 	 * Undo last command(s)
45796 	 */
45797 	CommandStack.prototype.undo = function() {
45798 	  var action = this._getUndoAction(),
45799 	      next;
45800 
45801 	  if (action) {
45802 	    this._currentExecution.trigger = 'undo';
45803 
45804 	    this._pushAction(action);
45805 
45806 	    while (action) {
45807 	      this._internalUndo(action);
45808 	      next = this._getUndoAction();
45809 
45810 	      if (!next || next.id !== action.id) {
45811 	        break;
45812 	      }
45813 
45814 	      action = next;
45815 	    }
45816 
45817 	    this._popAction();
45818 	  }
45819 	};
45820 
45821 
45822 	/**
45823 	 * Redo last command(s)
45824 	 */
45825 	CommandStack.prototype.redo = function() {
45826 	  var action = this._getRedoAction(),
45827 	      next;
45828 
45829 	  if (action) {
45830 	    this._currentExecution.trigger = 'redo';
45831 
45832 	    this._pushAction(action);
45833 
45834 	    while (action) {
45835 	      this._internalExecute(action, true);
45836 	      next = this._getRedoAction();
45837 
45838 	      if (!next || next.id !== action.id) {
45839 	        break;
45840 	      }
45841 
45842 	      action = next;
45843 	    }
45844 
45845 	    this._popAction();
45846 	  }
45847 	};
45848 
45849 
45850 	/**
45851 	 * Register a handler instance with the command stack
45852 	 *
45853 	 * @param {string} command
45854 	 * @param {CommandHandler} handler
45855 	 */
45856 	CommandStack.prototype.register = function(command, handler) {
45857 	  this._setHandler(command, handler);
45858 	};
45859 
45860 
45861 	/**
45862 	 * Register a handler type with the command stack
45863 	 * by instantiating it and injecting its dependencies.
45864 	 *
45865 	 * @param {string} command
45866 	 * @param {Function} a constructor for a {@link CommandHandler}
45867 	 */
45868 	CommandStack.prototype.registerHandler = function(command, handlerCls) {
45869 
45870 	  if (!command || !handlerCls) {
45871 	    throw new Error('command and handlerCls must be defined');
45872 	  }
45873 
45874 	  var handler = this._injector.instantiate(handlerCls);
45875 	  this.register(command, handler);
45876 	};
45877 
45878 	CommandStack.prototype.canUndo = function() {
45879 	  return !!this._getUndoAction();
45880 	};
45881 
45882 	CommandStack.prototype.canRedo = function() {
45883 	  return !!this._getRedoAction();
45884 	};
45885 
45886 	// stack access  //////////////////////
45887 
45888 	CommandStack.prototype._getRedoAction = function() {
45889 	  return this._stack[this._stackIdx + 1];
45890 	};
45891 
45892 
45893 	CommandStack.prototype._getUndoAction = function() {
45894 	  return this._stack[this._stackIdx];
45895 	};
45896 
45897 
45898 	// internal functionality //////////////////////
45899 
45900 	CommandStack.prototype._internalUndo = function(action) {
45901 	  var self = this;
45902 
45903 	  var command = action.command,
45904 	      context = action.context;
45905 
45906 	  var handler = this._getHandler(command);
45907 
45908 	  // guard against illegal nested command stack invocations
45909 	  this._atomicDo(function() {
45910 	    self._fire(command, 'revert', action);
45911 
45912 	    if (handler.revert) {
45913 	      self._markDirty(handler.revert(context));
45914 	    }
45915 
45916 	    self._revertedAction(action);
45917 
45918 	    self._fire(command, 'reverted', action);
45919 	  });
45920 	};
45921 
45922 
45923 	CommandStack.prototype._fire = function(command, qualifier, event) {
45924 	  if (arguments.length < 3) {
45925 	    event = qualifier;
45926 	    qualifier = null;
45927 	  }
45928 
45929 	  var names = qualifier ? [ command + '.' + qualifier, qualifier ] : [ command ],
45930 	      i, name, result;
45931 
45932 	  event = this._eventBus.createEvent(event);
45933 
45934 	  for (i = 0; (name = names[i]); i++) {
45935 	    result = this._eventBus.fire('commandStack.' + name, event);
45936 
45937 	    if (event.cancelBubble) {
45938 	      break;
45939 	    }
45940 	  }
45941 
45942 	  return result;
45943 	};
45944 
45945 	CommandStack.prototype._createId = function() {
45946 	  return this._uid++;
45947 	};
45948 
45949 	CommandStack.prototype._atomicDo = function(fn) {
45950 
45951 	  var execution = this._currentExecution;
45952 
45953 	  execution.atomic = true;
45954 
45955 	  try {
45956 	    fn();
45957 	  } finally {
45958 	    execution.atomic = false;
45959 	  }
45960 	};
45961 
45962 	CommandStack.prototype._internalExecute = function(action, redo) {
45963 	  var self = this;
45964 
45965 	  var command = action.command,
45966 	      context = action.context;
45967 
45968 	  var handler = this._getHandler(command);
45969 
45970 	  if (!handler) {
45971 	    throw new Error('no command handler registered for <' + command + '>');
45972 	  }
45973 
45974 	  this._pushAction(action);
45975 
45976 	  if (!redo) {
45977 	    this._fire(command, 'preExecute', action);
45978 
45979 	    if (handler.preExecute) {
45980 	      handler.preExecute(context);
45981 	    }
45982 
45983 	    this._fire(command, 'preExecuted', action);
45984 	  }
45985 
45986 	  // guard against illegal nested command stack invocations
45987 	  this._atomicDo(function() {
45988 
45989 	    self._fire(command, 'execute', action);
45990 
45991 	    if (handler.execute) {
45992 
45993 	      // actual execute + mark return results as dirty
45994 	      self._markDirty(handler.execute(context));
45995 	    }
45996 
45997 	    // log to stack
45998 	    self._executedAction(action, redo);
45999 
46000 	    self._fire(command, 'executed', action);
46001 	  });
46002 
46003 	  if (!redo) {
46004 	    this._fire(command, 'postExecute', action);
46005 
46006 	    if (handler.postExecute) {
46007 	      handler.postExecute(context);
46008 	    }
46009 
46010 	    this._fire(command, 'postExecuted', action);
46011 	  }
46012 
46013 	  this._popAction(action);
46014 	};
46015 
46016 
46017 	CommandStack.prototype._pushAction = function(action) {
46018 
46019 	  var execution = this._currentExecution,
46020 	      actions = execution.actions;
46021 
46022 	  var baseAction = actions[0];
46023 
46024 	  if (execution.atomic) {
46025 	    throw new Error('illegal invocation in <execute> or <revert> phase (action: ' + action.command + ')');
46026 	  }
46027 
46028 	  if (!action.id) {
46029 	    action.id = (baseAction && baseAction.id) || this._createId();
46030 	  }
46031 
46032 	  actions.push(action);
46033 	};
46034 
46035 
46036 	CommandStack.prototype._popAction = function() {
46037 	  var execution = this._currentExecution,
46038 	      trigger = execution.trigger,
46039 	      actions = execution.actions,
46040 	      dirty = execution.dirty;
46041 
46042 	  actions.pop();
46043 
46044 	  if (!actions.length) {
46045 	    this._eventBus.fire('elements.changed', { elements: uniqueBy('id', dirty.reverse()) });
46046 
46047 	    dirty.length = 0;
46048 
46049 	    this._fire('changed', { trigger: trigger });
46050 
46051 	    execution.trigger = null;
46052 	  }
46053 	};
46054 
46055 
46056 	CommandStack.prototype._markDirty = function(elements) {
46057 	  var execution = this._currentExecution;
46058 
46059 	  if (!elements) {
46060 	    return;
46061 	  }
46062 
46063 	  elements = isArray$2(elements) ? elements : [ elements ];
46064 
46065 	  execution.dirty = execution.dirty.concat(elements);
46066 	};
46067 
46068 
46069 	CommandStack.prototype._executedAction = function(action, redo) {
46070 	  var stackIdx = ++this._stackIdx;
46071 
46072 	  if (!redo) {
46073 	    this._stack.splice(stackIdx, this._stack.length, action);
46074 	  }
46075 	};
46076 
46077 
46078 	CommandStack.prototype._revertedAction = function(action) {
46079 	  this._stackIdx--;
46080 	};
46081 
46082 
46083 	CommandStack.prototype._getHandler = function(command) {
46084 	  return this._handlerMap[command];
46085 	};
46086 
46087 	CommandStack.prototype._setHandler = function(command, handler) {
46088 	  if (!command || !handler) {
46089 	    throw new Error('command and handler required');
46090 	  }
46091 
46092 	  if (this._handlerMap[command]) {
46093 	    throw new Error('overriding handler for command <' + command + '>');
46094 	  }
46095 
46096 	  this._handlerMap[command] = handler;
46097 	};
46098 
46099 	var CommandModule = {
46100 	  commandStack: [ 'type', CommandStack ]
46101 	};
46102 
46103 	// document wide unique tooltip ids
46104 	var ids = new IdGenerator('tt');
46105 
46106 
46107 	function createRoot(parentNode) {
46108 	  var root = domify(
46109 	    '<div class="djs-tooltip-container" style="position: absolute; width: 0; height: 0;" />'
46110 	  );
46111 
46112 	  parentNode.insertBefore(root, parentNode.firstChild);
46113 
46114 	  return root;
46115 	}
46116 
46117 
46118 	function setPosition(el, x, y) {
46119 	  assign(el.style, { left: x + 'px', top: y + 'px' });
46120 	}
46121 
46122 	function setVisible(el, visible) {
46123 	  el.style.display = visible === false ? 'none' : '';
46124 	}
46125 
46126 
46127 	var tooltipClass = 'djs-tooltip',
46128 	    tooltipSelector = '.' + tooltipClass;
46129 
46130 	/**
46131 	 * A service that allows users to render tool tips on the diagram.
46132 	 *
46133 	 * The tooltip service will take care of updating the tooltip positioning
46134 	 * during navigation + zooming.
46135 	 *
46136 	 * @example
46137 	 *
46138 	 * ```javascript
46139 	 *
46140 	 * // add a pink badge on the top left of the shape
46141 	 * tooltips.add({
46142 	 *   position: {
46143 	 *     x: 50,
46144 	 *     y: 100
46145 	 *   },
46146 	 *   html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
46147 	 * });
46148 	 *
46149 	 * // or with optional life span
46150 	 * tooltips.add({
46151 	 *   position: {
46152 	 *     top: -5,
46153 	 *     left: -5
46154 	 *   },
46155 	 *   html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>',
46156 	 *   ttl: 2000
46157 	 * });
46158 	 *
46159 	 * // remove a tool tip
46160 	 * var id = tooltips.add(...);
46161 	 * tooltips.remove(id);
46162 	 * ```
46163 	 *
46164 	 * @param {EventBus} eventBus
46165 	 * @param {Canvas} canvas
46166 	 */
46167 	function Tooltips(eventBus, canvas) {
46168 
46169 	  this._eventBus = eventBus;
46170 	  this._canvas = canvas;
46171 
46172 	  this._ids = ids;
46173 
46174 	  this._tooltipDefaults = {
46175 	    show: {
46176 	      minZoom: 0.7,
46177 	      maxZoom: 5.0
46178 	    }
46179 	  };
46180 
46181 	  /**
46182 	   * Mapping tooltipId -> tooltip
46183 	   */
46184 	  this._tooltips = {};
46185 
46186 	  // root html element for all tooltips
46187 	  this._tooltipRoot = createRoot(canvas.getContainer());
46188 
46189 
46190 	  var self = this;
46191 
46192 	  delegate.bind(this._tooltipRoot, tooltipSelector, 'mousedown', function(event) {
46193 	    event.stopPropagation();
46194 	  });
46195 
46196 	  delegate.bind(this._tooltipRoot, tooltipSelector, 'mouseover', function(event) {
46197 	    self.trigger('mouseover', event);
46198 	  });
46199 
46200 	  delegate.bind(this._tooltipRoot, tooltipSelector, 'mouseout', function(event) {
46201 	    self.trigger('mouseout', event);
46202 	  });
46203 
46204 	  this._init();
46205 	}
46206 
46207 
46208 	Tooltips.$inject = [ 'eventBus', 'canvas' ];
46209 
46210 
46211 	/**
46212 	 * Adds a HTML tooltip to the diagram
46213 	 *
46214 	 * @param {Object}               tooltip   the tooltip configuration
46215 	 *
46216 	 * @param {string|DOMElement}    tooltip.html                 html element to use as an tooltip
46217 	 * @param {Object}               [tooltip.show]               show configuration
46218 	 * @param {number}               [tooltip.show.minZoom]       minimal zoom level to show the tooltip
46219 	 * @param {number}               [tooltip.show.maxZoom]       maximum zoom level to show the tooltip
46220 	 * @param {Object}               tooltip.position             where to attach the tooltip
46221 	 * @param {number}               [tooltip.position.left]      relative to element bbox left attachment
46222 	 * @param {number}               [tooltip.position.top]       relative to element bbox top attachment
46223 	 * @param {number}               [tooltip.position.bottom]    relative to element bbox bottom attachment
46224 	 * @param {number}               [tooltip.position.right]     relative to element bbox right attachment
46225 	 * @param {number}               [tooltip.timeout=-1]
46226 	 *
46227 	 * @return {string}              id that may be used to reference the tooltip for update or removal
46228 	 */
46229 	Tooltips.prototype.add = function(tooltip) {
46230 
46231 	  if (!tooltip.position) {
46232 	    throw new Error('must specifiy tooltip position');
46233 	  }
46234 
46235 	  if (!tooltip.html) {
46236 	    throw new Error('must specifiy tooltip html');
46237 	  }
46238 
46239 	  var id = this._ids.next();
46240 
46241 	  tooltip = assign({}, this._tooltipDefaults, tooltip, {
46242 	    id: id
46243 	  });
46244 
46245 	  this._addTooltip(tooltip);
46246 
46247 	  if (tooltip.timeout) {
46248 	    this.setTimeout(tooltip);
46249 	  }
46250 
46251 	  return id;
46252 	};
46253 
46254 	Tooltips.prototype.trigger = function(action, event) {
46255 
46256 	  var node = event.delegateTarget || event.target;
46257 
46258 	  var tooltip = this.get(attr$1(node, 'data-tooltip-id'));
46259 
46260 	  if (!tooltip) {
46261 	    return;
46262 	  }
46263 
46264 	  if (action === 'mouseover' && tooltip.timeout) {
46265 	    this.clearTimeout(tooltip);
46266 	  }
46267 
46268 	  if (action === 'mouseout' && tooltip.timeout) {
46269 
46270 	    // cut timeout after mouse out
46271 	    tooltip.timeout = 1000;
46272 
46273 	    this.setTimeout(tooltip);
46274 	  }
46275 	};
46276 
46277 	/**
46278 	 * Get a tooltip with the given id
46279 	 *
46280 	 * @param {string} id
46281 	 */
46282 	Tooltips.prototype.get = function(id) {
46283 
46284 	  if (typeof id !== 'string') {
46285 	    id = id.id;
46286 	  }
46287 
46288 	  return this._tooltips[id];
46289 	};
46290 
46291 	Tooltips.prototype.clearTimeout = function(tooltip) {
46292 
46293 	  tooltip = this.get(tooltip);
46294 
46295 	  if (!tooltip) {
46296 	    return;
46297 	  }
46298 
46299 	  var removeTimer = tooltip.removeTimer;
46300 
46301 	  if (removeTimer) {
46302 	    clearTimeout(removeTimer);
46303 	    tooltip.removeTimer = null;
46304 	  }
46305 	};
46306 
46307 	Tooltips.prototype.setTimeout = function(tooltip) {
46308 
46309 	  tooltip = this.get(tooltip);
46310 
46311 	  if (!tooltip) {
46312 	    return;
46313 	  }
46314 
46315 	  this.clearTimeout(tooltip);
46316 
46317 	  var self = this;
46318 
46319 	  tooltip.removeTimer = setTimeout(function() {
46320 	    self.remove(tooltip);
46321 	  }, tooltip.timeout);
46322 	};
46323 
46324 	/**
46325 	 * Remove an tooltip with the given id
46326 	 *
46327 	 * @param {string} id
46328 	 */
46329 	Tooltips.prototype.remove = function(id) {
46330 
46331 	  var tooltip = this.get(id);
46332 
46333 	  if (tooltip) {
46334 	    remove$2(tooltip.html);
46335 	    remove$2(tooltip.htmlContainer);
46336 
46337 	    delete tooltip.htmlContainer;
46338 
46339 	    delete this._tooltips[tooltip.id];
46340 	  }
46341 	};
46342 
46343 
46344 	Tooltips.prototype.show = function() {
46345 	  setVisible(this._tooltipRoot);
46346 	};
46347 
46348 
46349 	Tooltips.prototype.hide = function() {
46350 	  setVisible(this._tooltipRoot, false);
46351 	};
46352 
46353 
46354 	Tooltips.prototype._updateRoot = function(viewbox) {
46355 	  var a = viewbox.scale || 1;
46356 	  var d = viewbox.scale || 1;
46357 
46358 	  var matrix = 'matrix(' + a + ',0,0,' + d + ',' + (-1 * viewbox.x * a) + ',' + (-1 * viewbox.y * d) + ')';
46359 
46360 	  this._tooltipRoot.style.transform = matrix;
46361 	  this._tooltipRoot.style['-ms-transform'] = matrix;
46362 	};
46363 
46364 
46365 	Tooltips.prototype._addTooltip = function(tooltip) {
46366 
46367 	  var id = tooltip.id,
46368 	      html = tooltip.html,
46369 	      htmlContainer,
46370 	      tooltipRoot = this._tooltipRoot;
46371 
46372 	  // unwrap jquery (for those who need it)
46373 	  if (html.get && html.constructor.prototype.jquery) {
46374 	    html = html.get(0);
46375 	  }
46376 
46377 	  // create proper html elements from
46378 	  // tooltip HTML strings
46379 	  if (isString(html)) {
46380 	    html = domify(html);
46381 	  }
46382 
46383 	  htmlContainer = domify('<div data-tooltip-id="' + id + '" class="' + tooltipClass + '" style="position: absolute">');
46384 
46385 	  htmlContainer.appendChild(html);
46386 
46387 	  if (tooltip.type) {
46388 	    classes$1(htmlContainer).add('djs-tooltip-' + tooltip.type);
46389 	  }
46390 
46391 	  if (tooltip.className) {
46392 	    classes$1(htmlContainer).add(tooltip.className);
46393 	  }
46394 
46395 	  tooltip.htmlContainer = htmlContainer;
46396 
46397 	  tooltipRoot.appendChild(htmlContainer);
46398 
46399 	  this._tooltips[id] = tooltip;
46400 
46401 	  this._updateTooltip(tooltip);
46402 	};
46403 
46404 
46405 	Tooltips.prototype._updateTooltip = function(tooltip) {
46406 
46407 	  var position = tooltip.position,
46408 	      htmlContainer = tooltip.htmlContainer;
46409 
46410 	  // update overlay html based on tooltip x, y
46411 
46412 	  setPosition(htmlContainer, position.x, position.y);
46413 	};
46414 
46415 
46416 	Tooltips.prototype._updateTooltipVisibilty = function(viewbox) {
46417 
46418 	  forEach(this._tooltips, function(tooltip) {
46419 	    var show = tooltip.show,
46420 	        htmlContainer = tooltip.htmlContainer,
46421 	        visible = true;
46422 
46423 	    if (show) {
46424 	      if (show.minZoom > viewbox.scale ||
46425 	          show.maxZoom < viewbox.scale) {
46426 	        visible = false;
46427 	      }
46428 
46429 	      setVisible(htmlContainer, visible);
46430 	    }
46431 	  });
46432 	};
46433 
46434 	Tooltips.prototype._init = function() {
46435 
46436 	  var self = this;
46437 
46438 	  // scroll/zoom integration
46439 
46440 	  function updateViewbox(viewbox) {
46441 	    self._updateRoot(viewbox);
46442 	    self._updateTooltipVisibilty(viewbox);
46443 
46444 	    self.show();
46445 	  }
46446 
46447 	  this._eventBus.on('canvas.viewbox.changing', function(event) {
46448 	    self.hide();
46449 	  });
46450 
46451 	  this._eventBus.on('canvas.viewbox.changed', function(event) {
46452 	    updateViewbox(event.viewbox);
46453 	  });
46454 	};
46455 
46456 	var TooltipsModule = {
46457 	  __init__: [ 'tooltips' ],
46458 	  tooltips: [ 'type', Tooltips ]
46459 	};
46460 
46461 	/**
46462 	 * Remove from the beginning of a collection until it is empty.
46463 	 *
46464 	 * This is a null-safe operation that ensures elements
46465 	 * are being removed from the given collection until the
46466 	 * collection is empty.
46467 	 *
46468 	 * The implementation deals with the fact that a remove operation
46469 	 * may touch, i.e. remove multiple elements in the collection
46470 	 * at a time.
46471 	 *
46472 	 * @param {Array<Object>} [collection]
46473 	 * @param {Function} removeFn
46474 	 *
46475 	 * @return {Array<Object>} the cleared collection
46476 	 */
46477 	function saveClear(collection, removeFn) {
46478 
46479 	  if (typeof removeFn !== 'function') {
46480 	    throw new Error('removeFn iterator must be a function');
46481 	  }
46482 
46483 	  if (!collection) {
46484 	    return;
46485 	  }
46486 
46487 	  var e;
46488 
46489 	  while ((e = collection[0])) {
46490 	    removeFn(e);
46491 	  }
46492 
46493 	  return collection;
46494 	}
46495 
46496 	var LOW_PRIORITY$6 = 250,
46497 	    HIGH_PRIORITY$5 = 1400;
46498 
46499 
46500 	/**
46501 	 * A handler that makes sure labels are properly moved with
46502 	 * their label targets.
46503 	 *
46504 	 * @param {didi.Injector} injector
46505 	 * @param {EventBus} eventBus
46506 	 * @param {Modeling} modeling
46507 	 */
46508 	function LabelSupport(injector, eventBus, modeling) {
46509 
46510 	  CommandInterceptor.call(this, eventBus);
46511 
46512 	  var movePreview = injector.get('movePreview', false);
46513 
46514 	  // remove labels from the collection that are being
46515 	  // moved with other elements anyway
46516 	  eventBus.on('shape.move.start', HIGH_PRIORITY$5, function(e) {
46517 
46518 	    var context = e.context,
46519 	        shapes = context.shapes,
46520 	        validatedShapes = context.validatedShapes;
46521 
46522 	    context.shapes = removeLabels(shapes);
46523 	    context.validatedShapes = removeLabels(validatedShapes);
46524 	  });
46525 
46526 	  // add labels to visual's group
46527 	  movePreview && eventBus.on('shape.move.start', LOW_PRIORITY$6, function(e) {
46528 
46529 	    var context = e.context,
46530 	        shapes = context.shapes;
46531 
46532 	    var labels = [];
46533 
46534 	    forEach(shapes, function(element) {
46535 
46536 	      forEach(element.labels, function(label) {
46537 
46538 	        if (!label.hidden && context.shapes.indexOf(label) === -1) {
46539 	          labels.push(label);
46540 	        }
46541 
46542 	        if (element.labelTarget) {
46543 	          labels.push(element);
46544 	        }
46545 	      });
46546 	    });
46547 
46548 	    forEach(labels, function(label) {
46549 	      movePreview.makeDraggable(context, label, true);
46550 	    });
46551 
46552 	  });
46553 
46554 	  // add all labels to move closure
46555 	  this.preExecuted('elements.move', HIGH_PRIORITY$5, function(e) {
46556 	    var context = e.context,
46557 	        closure = context.closure,
46558 	        enclosedElements = closure.enclosedElements;
46559 
46560 	    var enclosedLabels = [];
46561 
46562 	    // find labels that are not part of
46563 	    // move closure yet and add them
46564 	    forEach(enclosedElements, function(element) {
46565 	      forEach(element.labels, function(label) {
46566 
46567 	        if (!enclosedElements[label.id]) {
46568 	          enclosedLabels.push(label);
46569 	        }
46570 	      });
46571 	    });
46572 
46573 	    closure.addAll(enclosedLabels);
46574 	  });
46575 
46576 
46577 	  this.preExecute([
46578 	    'connection.delete',
46579 	    'shape.delete'
46580 	  ], function(e) {
46581 
46582 	    var context = e.context,
46583 	        element = context.connection || context.shape;
46584 
46585 	    saveClear(element.labels, function(label) {
46586 	      modeling.removeShape(label, { nested: true });
46587 	    });
46588 	  });
46589 
46590 
46591 	  this.execute('shape.delete', function(e) {
46592 
46593 	    var context = e.context,
46594 	        shape = context.shape,
46595 	        labelTarget = shape.labelTarget;
46596 
46597 	    // unset labelTarget
46598 	    if (labelTarget) {
46599 	      context.labelTargetIndex = indexOf(labelTarget.labels, shape);
46600 	      context.labelTarget = labelTarget;
46601 
46602 	      shape.labelTarget = null;
46603 	    }
46604 	  });
46605 
46606 	  this.revert('shape.delete', function(e) {
46607 
46608 	    var context = e.context,
46609 	        shape = context.shape,
46610 	        labelTarget = context.labelTarget,
46611 	        labelTargetIndex = context.labelTargetIndex;
46612 
46613 	    // restore labelTarget
46614 	    if (labelTarget) {
46615 	      add(labelTarget.labels, shape, labelTargetIndex);
46616 
46617 	      shape.labelTarget = labelTarget;
46618 	    }
46619 	  });
46620 
46621 	}
46622 
46623 	inherits$1(LabelSupport, CommandInterceptor);
46624 
46625 	LabelSupport.$inject = [
46626 	  'injector',
46627 	  'eventBus',
46628 	  'modeling'
46629 	];
46630 
46631 
46632 	/**
46633 	 * Return a filtered list of elements that do not
46634 	 * contain attached elements with hosts being part
46635 	 * of the selection.
46636 	 *
46637 	 * @param  {Array<djs.model.Base>} elements
46638 	 *
46639 	 * @return {Array<djs.model.Base>} filtered
46640 	 */
46641 	function removeLabels(elements) {
46642 
46643 	  return filter(elements, function(element) {
46644 
46645 	    // filter out labels that are move together
46646 	    // with their label targets
46647 	    return elements.indexOf(element.labelTarget) === -1;
46648 	  });
46649 	}
46650 
46651 	var LabelSupportModule = {
46652 	  __init__: [ 'labelSupport'],
46653 	  labelSupport: [ 'type', LabelSupport ]
46654 	};
46655 
46656 	var LOW_PRIORITY$5 = 251,
46657 	    HIGH_PRIORITY$4 = 1401;
46658 
46659 	var MARKER_ATTACH$1 = 'attach-ok';
46660 
46661 
46662 	/**
46663 	 * Adds the notion of attached elements to the modeler.
46664 	 *
46665 	 * Optionally depends on `diagram-js/lib/features/move` to render
46666 	 * the attached elements during move preview.
46667 	 *
46668 	 * Optionally depends on `diagram-js/lib/features/label-support`
46669 	 * to render attached labels during move preview.
46670 	 *
46671 	 * @param {didi.Injector} injector
46672 	 * @param {EventBus} eventBus
46673 	 * @param {Canvas} canvas
46674 	 * @param {Rules} rules
46675 	 * @param {Modeling} modeling
46676 	 */
46677 	function AttachSupport(injector, eventBus, canvas, rules, modeling) {
46678 
46679 	  CommandInterceptor.call(this, eventBus);
46680 
46681 	  var movePreview = injector.get('movePreview', false);
46682 
46683 
46684 	  // remove all the attached elements from the shapes to be validated
46685 	  // add all the attached shapes to the overall list of moved shapes
46686 	  eventBus.on('shape.move.start', HIGH_PRIORITY$4, function(e) {
46687 
46688 	    var context = e.context,
46689 	        shapes = context.shapes,
46690 	        validatedShapes = context.validatedShapes;
46691 
46692 	    context.shapes = addAttached(shapes);
46693 
46694 	    context.validatedShapes = removeAttached(validatedShapes);
46695 	  });
46696 
46697 	  // add attachers to the visual's group
46698 	  movePreview && eventBus.on('shape.move.start', LOW_PRIORITY$5, function(e) {
46699 
46700 	    var context = e.context,
46701 	        shapes = context.shapes,
46702 	        attachers = getAttachers(shapes);
46703 
46704 	    forEach(attachers, function(attacher) {
46705 	      movePreview.makeDraggable(context, attacher, true);
46706 
46707 	      forEach(attacher.labels, function(label) {
46708 	        movePreview.makeDraggable(context, label, true);
46709 	      });
46710 	    });
46711 	  });
46712 
46713 	  // add attach-ok marker to current host
46714 	  movePreview && eventBus.on('shape.move.start', function(event) {
46715 	    var context = event.context,
46716 	        shapes = context.shapes;
46717 
46718 	    if (shapes.length !== 1) {
46719 	      return;
46720 	    }
46721 
46722 	    var shape = shapes[0];
46723 
46724 	    var host = shape.host;
46725 
46726 	    if (host) {
46727 	      canvas.addMarker(host, MARKER_ATTACH$1);
46728 
46729 	      eventBus.once([
46730 	        'shape.move.out',
46731 	        'shape.move.cleanup'
46732 	      ], function() {
46733 	        canvas.removeMarker(host, MARKER_ATTACH$1);
46734 	      });
46735 	    }
46736 	  });
46737 
46738 	  // add all attachers to move closure
46739 	  this.preExecuted('elements.move', HIGH_PRIORITY$4, function(e) {
46740 	    var context = e.context,
46741 	        closure = context.closure,
46742 	        shapes = context.shapes,
46743 	        attachers = getAttachers(shapes);
46744 
46745 	    forEach(attachers, function(attacher) {
46746 	      closure.add(attacher, closure.topLevel[attacher.host.id]);
46747 	    });
46748 	  });
46749 
46750 	  // perform the attaching after shapes are done moving
46751 	  this.postExecuted('elements.move', function(e) {
46752 
46753 	    var context = e.context,
46754 	        shapes = context.shapes,
46755 	        newHost = context.newHost,
46756 	        attachers;
46757 
46758 	    // only single elements can be attached
46759 	    // multiply elements can be detached
46760 	    if (newHost && shapes.length !== 1) {
46761 	      return;
46762 	    }
46763 
46764 	    if (newHost) {
46765 	      attachers = shapes;
46766 	    } else {
46767 
46768 	      // find attachers moved without host
46769 	      attachers = filter(shapes, function(shape) {
46770 	        var host = shape.host;
46771 
46772 	        return isAttacher(shape) && !includes$4(shapes, host);
46773 	      });
46774 	    }
46775 
46776 	    forEach(attachers, function(attacher) {
46777 	      modeling.updateAttachment(attacher, newHost);
46778 	    });
46779 	  });
46780 
46781 	  // ensure invalid attachment connections are removed
46782 	  this.postExecuted('elements.move', function(e) {
46783 
46784 	    var shapes = e.context.shapes;
46785 
46786 	    forEach(shapes, function(shape) {
46787 
46788 	      forEach(shape.attachers, function(attacher) {
46789 
46790 	        // remove invalid outgoing connections
46791 	        forEach(attacher.outgoing.slice(), function(connection) {
46792 	          var allowed = rules.allowed('connection.reconnect', {
46793 	            connection: connection,
46794 	            source: connection.source,
46795 	            target: connection.target
46796 	          });
46797 
46798 	          if (!allowed) {
46799 	            modeling.removeConnection(connection);
46800 	          }
46801 	        });
46802 
46803 	        // remove invalid incoming connections
46804 	        forEach(attacher.incoming.slice(), function(connection) {
46805 	          var allowed = rules.allowed('connection.reconnect', {
46806 	            connection: connection,
46807 	            source: connection.source,
46808 	            target: connection.target
46809 	          });
46810 
46811 	          if (!allowed) {
46812 	            modeling.removeConnection(connection);
46813 	          }
46814 	        });
46815 	      });
46816 	    });
46817 	  });
46818 
46819 	  this.postExecute('shape.create', function(e) {
46820 	    var context = e.context,
46821 	        shape = context.shape,
46822 	        host = context.host;
46823 
46824 	    if (host) {
46825 	      modeling.updateAttachment(shape, host);
46826 	    }
46827 	  });
46828 
46829 	  // update attachments if the host is replaced
46830 	  this.postExecute('shape.replace', function(e) {
46831 
46832 	    var context = e.context,
46833 	        oldShape = context.oldShape,
46834 	        newShape = context.newShape;
46835 
46836 	    // move the attachers to the new host
46837 	    saveClear(oldShape.attachers, function(attacher) {
46838 	      var allowed = rules.allowed('elements.move', {
46839 	        target: newShape,
46840 	        shapes: [attacher]
46841 	      });
46842 
46843 	      if (allowed === 'attach') {
46844 	        modeling.updateAttachment(attacher, newShape);
46845 	      } else {
46846 	        modeling.removeShape(attacher);
46847 	      }
46848 	    });
46849 
46850 	    // move attachers if new host has different size
46851 	    if (newShape.attachers.length) {
46852 
46853 	      forEach(newShape.attachers, function(attacher) {
46854 	        var delta = getNewAttachShapeDelta(attacher, oldShape, newShape);
46855 	        modeling.moveShape(attacher, delta, attacher.parent);
46856 	      });
46857 	    }
46858 
46859 	  });
46860 
46861 	  // move shape on host resize
46862 	  this.postExecute('shape.resize', function(event) {
46863 	    var context = event.context,
46864 	        shape = context.shape,
46865 	        oldBounds = context.oldBounds,
46866 	        newBounds = context.newBounds,
46867 	        attachers = shape.attachers,
46868 	        hints = context.hints || {};
46869 
46870 	    if (hints.attachSupport === false) {
46871 	      return;
46872 	    }
46873 
46874 	    forEach(attachers, function(attacher) {
46875 	      var delta = getNewAttachShapeDelta(attacher, oldBounds, newBounds);
46876 
46877 	      modeling.moveShape(attacher, delta, attacher.parent);
46878 
46879 	      forEach(attacher.labels, function(label) {
46880 	        modeling.moveShape(label, delta, label.parent);
46881 	      });
46882 	    });
46883 	  });
46884 
46885 	  // remove attachments
46886 	  this.preExecute('shape.delete', function(event) {
46887 
46888 	    var shape = event.context.shape;
46889 
46890 	    saveClear(shape.attachers, function(attacher) {
46891 	      modeling.removeShape(attacher);
46892 	    });
46893 
46894 	    if (shape.host) {
46895 	      modeling.updateAttachment(shape, null);
46896 	    }
46897 	  });
46898 	}
46899 
46900 	inherits$1(AttachSupport, CommandInterceptor);
46901 
46902 	AttachSupport.$inject = [
46903 	  'injector',
46904 	  'eventBus',
46905 	  'canvas',
46906 	  'rules',
46907 	  'modeling'
46908 	];
46909 
46910 
46911 	/**
46912 	 * Return attachers of the given shapes
46913 	 *
46914 	 * @param {Array<djs.model.Base>} shapes
46915 	 * @return {Array<djs.model.Base>}
46916 	 */
46917 	function getAttachers(shapes) {
46918 	  return flatten(map$1(shapes, function(s) {
46919 	    return s.attachers || [];
46920 	  }));
46921 	}
46922 
46923 	/**
46924 	 * Return a combined list of elements and
46925 	 * attachers.
46926 	 *
46927 	 * @param {Array<djs.model.Base>} elements
46928 	 * @return {Array<djs.model.Base>} filtered
46929 	 */
46930 	function addAttached(elements) {
46931 	  var attachers = getAttachers(elements);
46932 
46933 	  return unionBy('id', elements, attachers);
46934 	}
46935 
46936 	/**
46937 	 * Return a filtered list of elements that do not
46938 	 * contain attached elements with hosts being part
46939 	 * of the selection.
46940 	 *
46941 	 * @param  {Array<djs.model.Base>} elements
46942 	 *
46943 	 * @return {Array<djs.model.Base>} filtered
46944 	 */
46945 	function removeAttached(elements) {
46946 
46947 	  var ids = groupBy(elements, 'id');
46948 
46949 	  return filter(elements, function(element) {
46950 	    while (element) {
46951 
46952 	      // host in selection
46953 	      if (element.host && ids[element.host.id]) {
46954 	        return false;
46955 	      }
46956 
46957 	      element = element.parent;
46958 	    }
46959 
46960 	    return true;
46961 	  });
46962 	}
46963 
46964 	function isAttacher(shape) {
46965 	  return !!shape.host;
46966 	}
46967 
46968 	function includes$4(array, item) {
46969 	  return array.indexOf(item) !== -1;
46970 	}
46971 
46972 	var AttachSupportModule = {
46973 	  __depends__: [
46974 	    RulesModule$1
46975 	  ],
46976 	  __init__: [ 'attachSupport' ],
46977 	  attachSupport: [ 'type', AttachSupport ]
46978 	};
46979 
46980 	var LOW_PRIORITY$4 = 250;
46981 
46982 	/**
46983 	 * The tool manager acts as middle-man between the available tool's and the Palette,
46984 	 * it takes care of making sure that the correct active state is set.
46985 	 *
46986 	 * @param  {Object}    eventBus
46987 	 * @param  {Object}    dragging
46988 	 */
46989 	function ToolManager(eventBus, dragging) {
46990 	  this._eventBus = eventBus;
46991 	  this._dragging = dragging;
46992 
46993 	  this._tools = [];
46994 	  this._active = null;
46995 	}
46996 
46997 	ToolManager.$inject = [ 'eventBus', 'dragging' ];
46998 
46999 	ToolManager.prototype.registerTool = function(name, events) {
47000 	  var tools = this._tools;
47001 
47002 	  if (!events) {
47003 	    throw new Error('A tool has to be registered with it\'s "events"');
47004 	  }
47005 
47006 	  tools.push(name);
47007 
47008 	  this.bindEvents(name, events);
47009 	};
47010 
47011 	ToolManager.prototype.isActive = function(tool) {
47012 	  return tool && this._active === tool;
47013 	};
47014 
47015 	ToolManager.prototype.length = function(tool) {
47016 	  return this._tools.length;
47017 	};
47018 
47019 	ToolManager.prototype.setActive = function(tool) {
47020 	  var eventBus = this._eventBus;
47021 
47022 	  if (this._active !== tool) {
47023 	    this._active = tool;
47024 
47025 	    eventBus.fire('tool-manager.update', { tool: tool });
47026 	  }
47027 	};
47028 
47029 	ToolManager.prototype.bindEvents = function(name, events) {
47030 	  var eventBus = this._eventBus,
47031 	      dragging = this._dragging;
47032 
47033 	  var eventsToRegister = [];
47034 
47035 	  eventBus.on(events.tool + '.init', function(event) {
47036 	    var context = event.context;
47037 
47038 	    // Active tools that want to reactivate themselves must do this explicitly
47039 	    if (!context.reactivate && this.isActive(name)) {
47040 	      this.setActive(null);
47041 
47042 	      dragging.cancel();
47043 	      return;
47044 	    }
47045 
47046 	    this.setActive(name);
47047 
47048 	  }, this);
47049 
47050 	  // Todo[ricardo]: add test cases
47051 	  forEach(events, function(event) {
47052 	    eventsToRegister.push(event + '.ended');
47053 	    eventsToRegister.push(event + '.canceled');
47054 	  });
47055 
47056 	  eventBus.on(eventsToRegister, LOW_PRIORITY$4, function(event) {
47057 
47058 	    // We defer the de-activation of the tool to the .activate phase,
47059 	    // so we're able to check if we want to toggle off the current
47060 	    // active tool or switch to a new one
47061 	    if (!this._active) {
47062 	      return;
47063 	    }
47064 
47065 	    if (isPaletteClick(event)) {
47066 	      return;
47067 	    }
47068 
47069 	    this.setActive(null);
47070 	  }, this);
47071 
47072 	};
47073 
47074 
47075 	// helpers ///////////////
47076 
47077 	/**
47078 	 * Check if a given event is a palette click event.
47079 	 *
47080 	 * @param {EventBus.Event} event
47081 	 *
47082 	 * @return {boolean}
47083 	 */
47084 	function isPaletteClick(event) {
47085 	  var target = event.originalEvent && event.originalEvent.target;
47086 
47087 	  return target && closest(target, '.group[data-group="tools"]');
47088 	}
47089 
47090 	var ToolManagerModule = {
47091 	  __depends__: [
47092 	    DraggingModule
47093 	  ],
47094 	  __init__: [ 'toolManager' ],
47095 	  toolManager: [ 'type', ToolManager ]
47096 	};
47097 
47098 	/**
47099 	 * Return direction given axis and delta.
47100 	 *
47101 	 * @param {string} axis
47102 	 * @param {number} delta
47103 	 *
47104 	 * @return {string}
47105 	 */
47106 	function getDirection(axis, delta) {
47107 
47108 	  if (axis === 'x') {
47109 	    if (delta > 0) {
47110 	      return 'e';
47111 	    }
47112 
47113 	    if (delta < 0) {
47114 	      return 'w';
47115 	    }
47116 	  }
47117 
47118 	  if (axis === 'y') {
47119 	    if (delta > 0) {
47120 	      return 's';
47121 	    }
47122 
47123 	    if (delta < 0) {
47124 	      return 'n';
47125 	    }
47126 	  }
47127 
47128 	  return null;
47129 	}
47130 
47131 	/**
47132 	 * Returns connections whose waypoints are to be updated. Waypoints are to be updated if start
47133 	 * or end is to be moved or resized.
47134 	 *
47135 	 * @param {Array<djs.model.Shape} movingShapes
47136 	 * @param {Array<djs.model.Shape} resizingShapes
47137 	 *
47138 	 * @returns {Array<djs.model.Connection>}
47139 	 */
47140 	function getWaypointsUpdatingConnections(movingShapes, resizingShapes) {
47141 	  var waypointsUpdatingConnections = [];
47142 
47143 	  forEach(movingShapes.concat(resizingShapes), function(shape) {
47144 	    var incoming = shape.incoming,
47145 	        outgoing = shape.outgoing;
47146 
47147 	    forEach(incoming.concat(outgoing), function(connection) {
47148 	      var source = connection.source,
47149 	          target = connection.target;
47150 
47151 	      if (includes$3(movingShapes, source) ||
47152 	        includes$3(movingShapes, target) ||
47153 	        includes$3(resizingShapes, source) ||
47154 	        includes$3(resizingShapes, target)) {
47155 
47156 	        if (!includes$3(waypointsUpdatingConnections, connection)) {
47157 	          waypointsUpdatingConnections.push(connection);
47158 	        }
47159 	      }
47160 	    });
47161 	  });
47162 
47163 	  return waypointsUpdatingConnections;
47164 	}
47165 
47166 	function includes$3(array, item) {
47167 	  return array.indexOf(item) !== -1;
47168 	}
47169 
47170 	/**
47171 	 * Resize bounds.
47172 	 *
47173 	 * @param {Object} bounds
47174 	 * @param {number} bounds.x
47175 	 * @param {number} bounds.y
47176 	 * @param {number} bounds.width
47177 	 * @param {number} bounds.height
47178 	 * @param {string} direction
47179 	 * @param {Object} delta
47180 	 * @param {number} delta.x
47181 	 * @param {number} delta.y
47182 	 *
47183 	 * @return {Object}
47184 	 */
47185 	function resizeBounds(bounds, direction, delta) {
47186 	  var x = bounds.x,
47187 	      y = bounds.y,
47188 	      width = bounds.width,
47189 	      height = bounds.height,
47190 	      dx = delta.x,
47191 	      dy = delta.y;
47192 
47193 	  switch (direction) {
47194 	  case 'n':
47195 	    return {
47196 	      x: x,
47197 	      y: y + dy,
47198 	      width: width,
47199 	      height: height - dy
47200 	    };
47201 	  case 's':
47202 	    return {
47203 	      x: x,
47204 	      y: y,
47205 	      width: width,
47206 	      height: height + dy
47207 	    };
47208 	  case 'w':
47209 	    return {
47210 	      x: x + dx,
47211 	      y: y,
47212 	      width: width - dx,
47213 	      height: height
47214 	    };
47215 	  case 'e':
47216 	    return {
47217 	      x: x,
47218 	      y: y,
47219 	      width: width + dx,
47220 	      height: height
47221 	    };
47222 	  default:
47223 	    throw new Error('unknown direction: ' + direction);
47224 	  }
47225 	}
47226 
47227 	var abs$1 = Math.abs,
47228 	    round$4 = Math.round;
47229 
47230 	var AXIS_TO_DIMENSION = {
47231 	  x: 'width',
47232 	  y: 'height'
47233 	};
47234 
47235 	var CURSOR_CROSSHAIR = 'crosshair';
47236 
47237 	var DIRECTION_TO_TRBL = {
47238 	  n: 'top',
47239 	  w: 'left',
47240 	  s: 'bottom',
47241 	  e: 'right'
47242 	};
47243 
47244 	var HIGH_PRIORITY$3 = 1500;
47245 
47246 	var DIRECTION_TO_OPPOSITE = {
47247 	  n: 's',
47248 	  w: 'e',
47249 	  s: 'n',
47250 	  e: 'w'
47251 	};
47252 
47253 	var PADDING = 20;
47254 
47255 
47256 	/**
47257 	 * Add or remove space by moving and resizing elements.
47258 	 *
47259 	 * @param {Canvas} canvas
47260 	 * @param {Dragging} dragging
47261 	 * @param {EventBus} eventBus
47262 	 * @param {Modeling} modeling
47263 	 * @param {Rules} rules
47264 	 * @param {ToolManager} toolManager
47265 	 * @param {Mouse} mouse
47266 	 */
47267 	function SpaceTool(
47268 	    canvas, dragging, eventBus,
47269 	    modeling, rules, toolManager,
47270 	    mouse) {
47271 
47272 	  this._canvas = canvas;
47273 	  this._dragging = dragging;
47274 	  this._eventBus = eventBus;
47275 	  this._modeling = modeling;
47276 	  this._rules = rules;
47277 	  this._toolManager = toolManager;
47278 	  this._mouse = mouse;
47279 
47280 	  var self = this;
47281 
47282 	  toolManager.registerTool('space', {
47283 	    tool: 'spaceTool.selection',
47284 	    dragging: 'spaceTool'
47285 	  });
47286 
47287 	  eventBus.on('spaceTool.selection.end', function(event) {
47288 	    eventBus.once('spaceTool.selection.ended', function() {
47289 	      self.activateMakeSpace(event.originalEvent);
47290 	    });
47291 	  });
47292 
47293 	  eventBus.on('spaceTool.move', HIGH_PRIORITY$3 , function(event) {
47294 	    var context = event.context,
47295 	        initialized = context.initialized;
47296 
47297 	    if (!initialized) {
47298 	      initialized = context.initialized = self.init(event, context);
47299 	    }
47300 
47301 	    if (initialized) {
47302 	      ensureConstraints(event);
47303 	    }
47304 	  });
47305 
47306 	  eventBus.on('spaceTool.end', function(event) {
47307 	    var context = event.context,
47308 	        axis = context.axis,
47309 	        direction = context.direction,
47310 	        movingShapes = context.movingShapes,
47311 	        resizingShapes = context.resizingShapes,
47312 	        start = context.start;
47313 
47314 	    if (!context.initialized) {
47315 	      return;
47316 	    }
47317 
47318 	    ensureConstraints(event);
47319 
47320 	    var delta = {
47321 	      x: 0,
47322 	      y: 0
47323 	    };
47324 
47325 	    delta[ axis ] = round$4(event[ 'd' + axis ]);
47326 
47327 	    self.makeSpace(movingShapes, resizingShapes, delta, direction, start);
47328 
47329 	    eventBus.once('spaceTool.ended', function(event) {
47330 
47331 	      // activate space tool selection after make space
47332 	      self.activateSelection(event.originalEvent, true, true);
47333 	    });
47334 	  });
47335 	}
47336 
47337 	SpaceTool.$inject = [
47338 	  'canvas',
47339 	  'dragging',
47340 	  'eventBus',
47341 	  'modeling',
47342 	  'rules',
47343 	  'toolManager',
47344 	  'mouse'
47345 	];
47346 
47347 	/**
47348 	 * Activate space tool selection.
47349 	 *
47350 	 * @param {Object} event
47351 	 * @param {boolean} autoActivate
47352 	 */
47353 	SpaceTool.prototype.activateSelection = function(event, autoActivate, reactivate) {
47354 	  this._dragging.init(event, 'spaceTool.selection', {
47355 	    autoActivate: autoActivate,
47356 	    cursor: CURSOR_CROSSHAIR,
47357 	    data: {
47358 	      context: {
47359 	        reactivate: reactivate
47360 	      }
47361 	    },
47362 	    trapClick: false
47363 	  });
47364 	};
47365 
47366 	/**
47367 	 * Activate space tool make space.
47368 	 *
47369 	 * @param  {MouseEvent} event
47370 	 */
47371 	SpaceTool.prototype.activateMakeSpace = function(event) {
47372 	  this._dragging.init(event, 'spaceTool', {
47373 	    autoActivate: true,
47374 	    cursor: CURSOR_CROSSHAIR,
47375 	    data: {
47376 	      context: {}
47377 	    }
47378 	  });
47379 	};
47380 
47381 	/**
47382 	 * Make space.
47383 	 *
47384 	 * @param  {Array<djs.model.Shape>} movingShapes
47385 	 * @param  {Array<djs.model.Shape>} resizingShapes
47386 	 * @param  {Object} delta
47387 	 * @param  {number} delta.x
47388 	 * @param  {number} delta.y
47389 	 * @param  {string} direction
47390 	 * @param  {number} start
47391 	 */
47392 	SpaceTool.prototype.makeSpace = function(movingShapes, resizingShapes, delta, direction, start) {
47393 	  return this._modeling.createSpace(movingShapes, resizingShapes, delta, direction, start);
47394 	};
47395 
47396 	/**
47397 	 * Initialize make space and return true if that was successful.
47398 	 *
47399 	 * @param {Object} event
47400 	 * @param {Object} context
47401 	 *
47402 	 * @return {boolean}
47403 	 */
47404 	SpaceTool.prototype.init = function(event, context) {
47405 	  var axis = abs$1(event.dx) > abs$1(event.dy) ? 'x' : 'y',
47406 	      delta = event[ 'd' + axis ],
47407 	      start = event[ axis ] - delta;
47408 
47409 	  if (abs$1(delta) < 5) {
47410 	    return false;
47411 	  }
47412 
47413 	  // invert delta to remove space when moving left
47414 	  if (delta < 0) {
47415 	    delta *= -1;
47416 	  }
47417 
47418 	  // invert delta to add/remove space when removing/adding space if modifier key is pressed
47419 	  if (hasPrimaryModifier(event)) {
47420 	    delta *= -1;
47421 	  }
47422 
47423 	  var direction = getDirection(axis, delta);
47424 
47425 	  var root = this._canvas.getRootElement();
47426 
47427 	  var children = selfAndAllChildren(root, true);
47428 
47429 	  var elements = this.calculateAdjustments(children, axis, delta, start);
47430 
47431 	  var minDimensions = this._eventBus.fire('spaceTool.getMinDimensions', {
47432 	    axis: axis,
47433 	    direction: direction,
47434 	    shapes: elements.resizingShapes,
47435 	    start: start
47436 	  });
47437 
47438 	  var spaceToolConstraints = getSpaceToolConstraints(elements, axis, direction, start, minDimensions);
47439 
47440 	  assign(
47441 	    context,
47442 	    elements,
47443 	    {
47444 	      axis: axis,
47445 	      direction: direction,
47446 	      spaceToolConstraints: spaceToolConstraints,
47447 	      start: start
47448 	    }
47449 	  );
47450 
47451 	  set('resize-' + (axis === 'x' ? 'ew' : 'ns'));
47452 
47453 	  return true;
47454 	};
47455 
47456 	/**
47457 	 * Get elements to be moved and resized.
47458 	 *
47459 	 * @param  {Array<djs.model.Shape>} elements
47460 	 * @param  {string} axis
47461 	 * @param  {number} delta
47462 	 * @param  {number} start
47463 	 *
47464 	 * @return {Object}
47465 	 */
47466 	SpaceTool.prototype.calculateAdjustments = function(elements, axis, delta, start) {
47467 	  var rules = this._rules;
47468 
47469 	  var movingShapes = [],
47470 	      resizingShapes = [];
47471 
47472 	  forEach(elements, function(element) {
47473 	    if (!element.parent || isConnection$7(element)) {
47474 	      return;
47475 	    }
47476 
47477 	    var shapeStart = element[ axis ],
47478 	        shapeEnd = shapeStart + element[ AXIS_TO_DIMENSION[ axis ] ];
47479 
47480 	    // shape to be moved
47481 	    if ((delta > 0 && shapeStart > start) || (delta < 0 && shapeEnd < start)) {
47482 	      return movingShapes.push(element);
47483 	    }
47484 
47485 	    // shape to be resized
47486 	    if (shapeStart < start &&
47487 	      shapeEnd > start &&
47488 	      rules.allowed('shape.resize', { shape: element })
47489 	    ) {
47490 
47491 	      return resizingShapes.push(element);
47492 	    }
47493 	  });
47494 
47495 	  return {
47496 	    movingShapes: movingShapes,
47497 	    resizingShapes: resizingShapes
47498 	  };
47499 	};
47500 
47501 	SpaceTool.prototype.toggle = function() {
47502 
47503 	  if (this.isActive()) {
47504 	    return this._dragging.cancel();
47505 	  }
47506 
47507 	  var mouseEvent = this._mouse.getLastMoveEvent();
47508 
47509 	  this.activateSelection(mouseEvent, !!mouseEvent);
47510 	};
47511 
47512 	SpaceTool.prototype.isActive = function() {
47513 	  var context = this._dragging.context();
47514 
47515 	  return context && /^spaceTool/.test(context.prefix);
47516 	};
47517 
47518 	// helpers //////////
47519 
47520 	function addPadding(trbl) {
47521 	  return {
47522 	    top: trbl.top - PADDING,
47523 	    right: trbl.right + PADDING,
47524 	    bottom: trbl.bottom + PADDING,
47525 	    left: trbl.left - PADDING
47526 	  };
47527 	}
47528 
47529 	function ensureConstraints(event) {
47530 	  var context = event.context,
47531 	      spaceToolConstraints = context.spaceToolConstraints;
47532 
47533 	  if (!spaceToolConstraints) {
47534 	    return;
47535 	  }
47536 
47537 	  var x, y;
47538 
47539 	  if (isNumber(spaceToolConstraints.left)) {
47540 	    x = Math.max(event.x, spaceToolConstraints.left);
47541 
47542 	    event.dx = event.dx + x - event.x;
47543 	    event.x = x;
47544 	  }
47545 
47546 	  if (isNumber(spaceToolConstraints.right)) {
47547 	    x = Math.min(event.x, spaceToolConstraints.right);
47548 
47549 	    event.dx = event.dx + x - event.x;
47550 	    event.x = x;
47551 	  }
47552 
47553 	  if (isNumber(spaceToolConstraints.top)) {
47554 	    y = Math.max(event.y, spaceToolConstraints.top);
47555 
47556 	    event.dy = event.dy + y - event.y;
47557 	    event.y = y;
47558 	  }
47559 
47560 	  if (isNumber(spaceToolConstraints.bottom)) {
47561 	    y = Math.min(event.y, spaceToolConstraints.bottom);
47562 
47563 	    event.dy = event.dy + y - event.y;
47564 	    event.y = y;
47565 	  }
47566 	}
47567 
47568 	function getSpaceToolConstraints(elements, axis, direction, start, minDimensions) {
47569 	  var movingShapes = elements.movingShapes,
47570 	      resizingShapes = elements.resizingShapes;
47571 
47572 	  if (!resizingShapes.length) {
47573 	    return;
47574 	  }
47575 
47576 	  var spaceToolConstraints = {},
47577 	      min,
47578 	      max;
47579 
47580 	  forEach(resizingShapes, function(resizingShape) {
47581 	    var resizingShapeBBox = asTRBL(resizingShape);
47582 
47583 	    // find children that are not moving or resizing
47584 	    var nonMovingResizingChildren = filter(resizingShape.children, function(child) {
47585 	      return !isConnection$7(child) &&
47586 	        !isLabel$2(child) &&
47587 	        !includes$2(movingShapes, child) &&
47588 	        !includes$2(resizingShapes, child);
47589 	    });
47590 
47591 	    // find children that are moving
47592 	    var movingChildren = filter(resizingShape.children, function(child) {
47593 	      return !isConnection$7(child) && !isLabel$2(child) && includes$2(movingShapes, child);
47594 	    });
47595 
47596 	    var minOrMax,
47597 	        nonMovingResizingChildrenBBox,
47598 	        movingChildrenBBox;
47599 
47600 	    if (nonMovingResizingChildren.length) {
47601 	      nonMovingResizingChildrenBBox = addPadding(asTRBL(getBBox(nonMovingResizingChildren)));
47602 
47603 	      minOrMax = start -
47604 	        resizingShapeBBox[ DIRECTION_TO_TRBL[ direction ] ] +
47605 	        nonMovingResizingChildrenBBox[ DIRECTION_TO_TRBL[ direction ] ];
47606 
47607 	      if (direction === 'n') {
47608 	        spaceToolConstraints.bottom = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47609 	      } else if (direction === 'w') {
47610 	        spaceToolConstraints.right = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47611 	      } else if (direction === 's') {
47612 	        spaceToolConstraints.top = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47613 	      } else if (direction === 'e') {
47614 	        spaceToolConstraints.left = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47615 	      }
47616 	    }
47617 
47618 	    if (movingChildren.length) {
47619 	      movingChildrenBBox = addPadding(asTRBL(getBBox(movingChildren)));
47620 
47621 	      minOrMax = start -
47622 	        movingChildrenBBox[ DIRECTION_TO_TRBL[ DIRECTION_TO_OPPOSITE[ direction ] ] ] +
47623 	        resizingShapeBBox[ DIRECTION_TO_TRBL[ DIRECTION_TO_OPPOSITE[ direction ] ] ];
47624 
47625 	      if (direction === 'n') {
47626 	        spaceToolConstraints.bottom = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47627 	      } else if (direction === 'w') {
47628 	        spaceToolConstraints.right = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47629 	      } else if (direction === 's') {
47630 	        spaceToolConstraints.top = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47631 	      } else if (direction === 'e') {
47632 	        spaceToolConstraints.left = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47633 	      }
47634 	    }
47635 
47636 	    var resizingShapeMinDimensions = minDimensions && minDimensions[ resizingShape.id ];
47637 
47638 	    if (resizingShapeMinDimensions) {
47639 	      if (direction === 'n') {
47640 	        minOrMax = start +
47641 	          resizingShape[ AXIS_TO_DIMENSION [ axis ] ] -
47642 	          resizingShapeMinDimensions[ AXIS_TO_DIMENSION[ axis ] ];
47643 
47644 	        spaceToolConstraints.bottom = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47645 	      } else if (direction === 'w') {
47646 	        minOrMax = start +
47647 	          resizingShape[ AXIS_TO_DIMENSION [ axis ] ] -
47648 	          resizingShapeMinDimensions[ AXIS_TO_DIMENSION[ axis ] ];
47649 
47650 	        spaceToolConstraints.right = max = isNumber(max) ? Math.min(max, minOrMax) : minOrMax;
47651 	      } else if (direction === 's') {
47652 	        minOrMax = start -
47653 	          resizingShape[ AXIS_TO_DIMENSION [ axis ] ] +
47654 	          resizingShapeMinDimensions[ AXIS_TO_DIMENSION[ axis ] ];
47655 
47656 	        spaceToolConstraints.top = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47657 	      } else if (direction === 'e') {
47658 	        minOrMax = start -
47659 	          resizingShape[ AXIS_TO_DIMENSION [ axis ] ] +
47660 	          resizingShapeMinDimensions[ AXIS_TO_DIMENSION[ axis ] ];
47661 
47662 	        spaceToolConstraints.left = min = isNumber(min) ? Math.max(min, minOrMax) : minOrMax;
47663 	      }
47664 	    }
47665 	  });
47666 
47667 	  return spaceToolConstraints;
47668 	}
47669 
47670 	function includes$2(array, item) {
47671 	  return array.indexOf(item) !== -1;
47672 	}
47673 
47674 	function isConnection$7(element) {
47675 	  return !!element.waypoints;
47676 	}
47677 
47678 	function isLabel$2(element) {
47679 	  return !!element.labelTarget;
47680 	}
47681 
47682 	var MARKER_DRAGGING$1 = 'djs-dragging',
47683 	    MARKER_RESIZING = 'djs-resizing';
47684 
47685 	var LOW_PRIORITY$3 = 250;
47686 
47687 	var max = Math.max;
47688 
47689 
47690 	/**
47691 	 * Provides previews for selecting/moving/resizing shapes when creating/removing space.
47692 	 *
47693 	 * @param {EventBus} eventBus
47694 	 * @param {ElementRegistry} elementRegistry
47695 	 * @param {Canvas} canvas
47696 	 * @param {Styles} styles
47697 	 */
47698 	function SpaceToolPreview(
47699 	    eventBus, elementRegistry, canvas,
47700 	    styles, previewSupport) {
47701 
47702 	  function addPreviewGfx(collection, dragGroup) {
47703 	    forEach(collection, function(element) {
47704 	      previewSupport.addDragger(element, dragGroup);
47705 
47706 	      canvas.addMarker(element, MARKER_DRAGGING$1);
47707 	    });
47708 	  }
47709 
47710 	  // add crosshair
47711 	  eventBus.on('spaceTool.selection.start', function(event) {
47712 	    var space = canvas.getLayer('space'),
47713 	        context = event.context;
47714 
47715 	    var orientation = {
47716 	      x: 'M 0,-10000 L 0,10000',
47717 	      y: 'M -10000,0 L 10000,0'
47718 	    };
47719 
47720 	    var crosshairGroup = create$1('g');
47721 	    attr(crosshairGroup, styles.cls('djs-crosshair-group', [ 'no-events' ]));
47722 
47723 	    append(space, crosshairGroup);
47724 
47725 	    // horizontal path
47726 	    var pathX = create$1('path');
47727 	    attr(pathX, 'd', orientation.x);
47728 	    classes(pathX).add('djs-crosshair');
47729 
47730 	    append(crosshairGroup, pathX);
47731 
47732 	    // vertical path
47733 	    var pathY = create$1('path');
47734 	    attr(pathY, 'd', orientation.y);
47735 	    classes(pathY).add('djs-crosshair');
47736 
47737 	    append(crosshairGroup, pathY);
47738 
47739 	    context.crosshairGroup = crosshairGroup;
47740 	  });
47741 
47742 	  // update crosshair
47743 	  eventBus.on('spaceTool.selection.move', function(event) {
47744 	    var crosshairGroup = event.context.crosshairGroup;
47745 
47746 	    translate$2(crosshairGroup, event.x, event.y);
47747 	  });
47748 
47749 	  // remove crosshair
47750 	  eventBus.on('spaceTool.selection.cleanup', function(event) {
47751 	    var context = event.context,
47752 	        crosshairGroup = context.crosshairGroup;
47753 
47754 	    if (crosshairGroup) {
47755 	      remove$1(crosshairGroup);
47756 	    }
47757 	  });
47758 
47759 	  // add and update move/resize previews
47760 	  eventBus.on('spaceTool.move', LOW_PRIORITY$3, function(event) {
47761 
47762 	    var context = event.context,
47763 	        line = context.line,
47764 	        axis = context.axis,
47765 	        movingShapes = context.movingShapes,
47766 	        resizingShapes = context.resizingShapes;
47767 
47768 	    if (!context.initialized) {
47769 	      return;
47770 	    }
47771 
47772 	    if (!context.dragGroup) {
47773 	      var spaceLayer = canvas.getLayer('space');
47774 
47775 	      line = create$1('path');
47776 	      attr(line, 'd', 'M0,0 L0,0');
47777 	      classes(line).add('djs-crosshair');
47778 
47779 	      append(spaceLayer, line);
47780 
47781 	      context.line = line;
47782 
47783 	      var dragGroup = create$1('g');
47784 	      attr(dragGroup, styles.cls('djs-drag-group', [ 'no-events' ]));
47785 
47786 	      append(canvas.getActiveLayer(), dragGroup);
47787 
47788 	      // shapes
47789 	      addPreviewGfx(movingShapes, dragGroup);
47790 
47791 	      // connections
47792 	      var movingConnections = context.movingConnections = elementRegistry.filter(function(element) {
47793 	        var sourceIsMoving = false;
47794 
47795 	        forEach(movingShapes, function(shape) {
47796 	          forEach(shape.outgoing, function(connection) {
47797 	            if (element === connection) {
47798 	              sourceIsMoving = true;
47799 	            }
47800 	          });
47801 	        });
47802 
47803 	        var targetIsMoving = false;
47804 
47805 	        forEach(movingShapes, function(shape) {
47806 	          forEach(shape.incoming, function(connection) {
47807 	            if (element === connection) {
47808 	              targetIsMoving = true;
47809 	            }
47810 	          });
47811 	        });
47812 
47813 	        var sourceIsResizing = false;
47814 
47815 	        forEach(resizingShapes, function(shape) {
47816 	          forEach(shape.outgoing, function(connection) {
47817 	            if (element === connection) {
47818 	              sourceIsResizing = true;
47819 	            }
47820 	          });
47821 	        });
47822 
47823 	        var targetIsResizing = false;
47824 
47825 	        forEach(resizingShapes, function(shape) {
47826 	          forEach(shape.incoming, function(connection) {
47827 	            if (element === connection) {
47828 	              targetIsResizing = true;
47829 	            }
47830 	          });
47831 	        });
47832 
47833 	        return isConnection$6(element)
47834 	          && (sourceIsMoving || sourceIsResizing)
47835 	          && (targetIsMoving || targetIsResizing);
47836 	      });
47837 
47838 
47839 	      addPreviewGfx(movingConnections, dragGroup);
47840 
47841 	      context.dragGroup = dragGroup;
47842 	    }
47843 
47844 	    if (!context.frameGroup) {
47845 	      var frameGroup = create$1('g');
47846 	      attr(frameGroup, styles.cls('djs-frame-group', [ 'no-events' ]));
47847 
47848 	      append(canvas.getActiveLayer(), frameGroup);
47849 
47850 	      var frames = [];
47851 
47852 	      forEach(resizingShapes, function(shape) {
47853 	        var frame = previewSupport.addFrame(shape, frameGroup);
47854 
47855 	        var initialBounds = frame.getBBox();
47856 
47857 	        frames.push({
47858 	          element: frame,
47859 	          initialBounds: initialBounds
47860 	        });
47861 
47862 	        canvas.addMarker(shape, MARKER_RESIZING);
47863 	      });
47864 
47865 	      context.frameGroup = frameGroup;
47866 	      context.frames = frames;
47867 	    }
47868 
47869 	    var orientation = {
47870 	      x: 'M' + event.x + ', -10000 L' + event.x + ', 10000',
47871 	      y: 'M -10000, ' + event.y + ' L 10000, ' + event.y
47872 	    };
47873 
47874 	    attr(line, { d: orientation[ axis ] });
47875 
47876 	    var opposite = { x: 'y', y: 'x' };
47877 	    var delta = { x: event.dx, y: event.dy };
47878 	    delta[ opposite[ context.axis ] ] = 0;
47879 
47880 	    // update move previews
47881 	    translate$2(context.dragGroup, delta.x, delta.y);
47882 
47883 	    // update resize previews
47884 	    forEach(context.frames, function(frame) {
47885 	      var element = frame.element,
47886 	          initialBounds = frame.initialBounds,
47887 	          width,
47888 	          height;
47889 
47890 	      if (context.direction === 'e') {
47891 	        attr(element, {
47892 	          width: max(initialBounds.width + delta.x, 5)
47893 	        });
47894 	      } else {
47895 	        width = max(initialBounds.width - delta.x, 5);
47896 
47897 	        attr(element, {
47898 	          width: width,
47899 	          x: initialBounds.x + initialBounds.width - width
47900 	        });
47901 	      }
47902 
47903 	      if (context.direction === 's') {
47904 	        attr(element, {
47905 	          height: max(initialBounds.height + delta.y, 5)
47906 	        });
47907 	      } else {
47908 	        height = max(initialBounds.height - delta.y, 5);
47909 
47910 	        attr(element, {
47911 	          height: height,
47912 	          y: initialBounds.y + initialBounds.height - height
47913 	        });
47914 	      }
47915 	    });
47916 
47917 	  });
47918 
47919 	  // remove move/resize previews
47920 	  eventBus.on('spaceTool.cleanup', function(event) {
47921 
47922 	    var context = event.context,
47923 	        movingShapes = context.movingShapes,
47924 	        movingConnections = context.movingConnections,
47925 	        resizingShapes = context.resizingShapes,
47926 	        line = context.line,
47927 	        dragGroup = context.dragGroup,
47928 	        frameGroup = context.frameGroup;
47929 
47930 	    // moving shapes
47931 	    forEach(movingShapes, function(shape) {
47932 	      canvas.removeMarker(shape, MARKER_DRAGGING$1);
47933 	    });
47934 
47935 	    // moving connections
47936 	    forEach(movingConnections, function(connection) {
47937 	      canvas.removeMarker(connection, MARKER_DRAGGING$1);
47938 	    });
47939 
47940 	    if (dragGroup) {
47941 	      remove$1(line);
47942 	      remove$1(dragGroup);
47943 	    }
47944 
47945 	    forEach(resizingShapes, function(shape) {
47946 	      canvas.removeMarker(shape, MARKER_RESIZING);
47947 	    });
47948 
47949 	    if (frameGroup) {
47950 	      remove$1(frameGroup);
47951 	    }
47952 	  });
47953 	}
47954 
47955 	SpaceToolPreview.$inject = [
47956 	  'eventBus',
47957 	  'elementRegistry',
47958 	  'canvas',
47959 	  'styles',
47960 	  'previewSupport'
47961 	];
47962 
47963 
47964 	// helpers //////////////////////
47965 
47966 	/**
47967 	 * Checks if an element is a connection.
47968 	 */
47969 	function isConnection$6(element) {
47970 	  return element.waypoints;
47971 	}
47972 
47973 	var SpaceToolModule = {
47974 	  __init__: ['spaceToolPreview'],
47975 	  __depends__: [
47976 	    DraggingModule,
47977 	    RulesModule$1,
47978 	    ToolManagerModule,
47979 	    PreviewSupportModule,
47980 	    MouseModule
47981 	  ],
47982 	  spaceTool: ['type', SpaceTool ],
47983 	  spaceToolPreview: ['type', SpaceToolPreview ]
47984 	};
47985 
47986 	function BpmnFactory(moddle) {
47987 	  this._model = moddle;
47988 	}
47989 
47990 	BpmnFactory.$inject = [ 'moddle' ];
47991 
47992 
47993 	BpmnFactory.prototype._needsId = function(element) {
47994 	  return isAny(element, [
47995 	    'bpmn:RootElement',
47996 	    'bpmn:FlowElement',
47997 	    'bpmn:MessageFlow',
47998 	    'bpmn:DataAssociation',
47999 	    'bpmn:Artifact',
48000 	    'bpmn:Participant',
48001 	    'bpmn:Lane',
48002 	    'bpmn:LaneSet',
48003 	    'bpmn:Process',
48004 	    'bpmn:Collaboration',
48005 	    'bpmndi:BPMNShape',
48006 	    'bpmndi:BPMNEdge',
48007 	    'bpmndi:BPMNDiagram',
48008 	    'bpmndi:BPMNPlane',
48009 	    'bpmn:Property',
48010 	    'bpmn:CategoryValue'
48011 	  ]);
48012 	};
48013 
48014 	BpmnFactory.prototype._ensureId = function(element) {
48015 
48016 	  // generate semantic ids for elements
48017 	  // bpmn:SequenceFlow -> SequenceFlow_ID
48018 	  var prefix;
48019 
48020 	  if (is$1(element, 'bpmn:Activity')) {
48021 	    prefix = 'Activity';
48022 	  } else if (is$1(element, 'bpmn:Event')) {
48023 	    prefix = 'Event';
48024 	  } else if (is$1(element, 'bpmn:Gateway')) {
48025 	    prefix = 'Gateway';
48026 	  } else if (isAny(element, [ 'bpmn:SequenceFlow', 'bpmn:MessageFlow' ])) {
48027 	    prefix = 'Flow';
48028 	  } else {
48029 	    prefix = (element.$type || '').replace(/^[^:]*:/g, '');
48030 	  }
48031 
48032 	  prefix += '_';
48033 
48034 	  if (!element.id && this._needsId(element)) {
48035 	    element.id = this._model.ids.nextPrefixed(prefix, element);
48036 	  }
48037 	};
48038 
48039 
48040 	BpmnFactory.prototype.create = function(type, attrs) {
48041 	  var element = this._model.create(type, attrs || {});
48042 
48043 	  this._ensureId(element);
48044 
48045 	  return element;
48046 	};
48047 
48048 
48049 	BpmnFactory.prototype.createDiLabel = function() {
48050 	  return this.create('bpmndi:BPMNLabel', {
48051 	    bounds: this.createDiBounds()
48052 	  });
48053 	};
48054 
48055 
48056 	BpmnFactory.prototype.createDiShape = function(semantic, bounds, attrs) {
48057 
48058 	  return this.create('bpmndi:BPMNShape', assign({
48059 	    bpmnElement: semantic,
48060 	    bounds: this.createDiBounds(bounds)
48061 	  }, attrs));
48062 	};
48063 
48064 
48065 	BpmnFactory.prototype.createDiBounds = function(bounds) {
48066 	  return this.create('dc:Bounds', bounds);
48067 	};
48068 
48069 
48070 	BpmnFactory.prototype.createDiWaypoints = function(waypoints) {
48071 	  var self = this;
48072 
48073 	  return map$1(waypoints, function(pos) {
48074 	    return self.createDiWaypoint(pos);
48075 	  });
48076 	};
48077 
48078 	BpmnFactory.prototype.createDiWaypoint = function(point) {
48079 	  return this.create('dc:Point', pick(point, [ 'x', 'y' ]));
48080 	};
48081 
48082 
48083 	BpmnFactory.prototype.createDiEdge = function(semantic, waypoints, attrs) {
48084 	  return this.create('bpmndi:BPMNEdge', assign({
48085 	    bpmnElement: semantic
48086 	  }, attrs));
48087 	};
48088 
48089 	BpmnFactory.prototype.createDiPlane = function(semantic) {
48090 	  return this.create('bpmndi:BPMNPlane', {
48091 	    bpmnElement: semantic
48092 	  });
48093 	};
48094 
48095 	/**
48096 	 * A handler responsible for updating the underlying BPMN 2.0 XML + DI
48097 	 * once changes on the diagram happen
48098 	 */
48099 	function BpmnUpdater(
48100 	    eventBus, bpmnFactory, connectionDocking,
48101 	    translate) {
48102 
48103 	  CommandInterceptor.call(this, eventBus);
48104 
48105 	  this._bpmnFactory = bpmnFactory;
48106 	  this._translate = translate;
48107 
48108 	  var self = this;
48109 
48110 
48111 
48112 	  // connection cropping //////////////////////
48113 
48114 	  // crop connection ends during create/update
48115 	  function cropConnection(e) {
48116 	    var context = e.context,
48117 	        hints = context.hints || {},
48118 	        connection;
48119 
48120 	    if (!context.cropped && hints.createElementsBehavior !== false) {
48121 	      connection = context.connection;
48122 	      connection.waypoints = connectionDocking.getCroppedWaypoints(connection);
48123 	      context.cropped = true;
48124 	    }
48125 	  }
48126 
48127 	  this.executed([
48128 	    'connection.layout',
48129 	    'connection.create'
48130 	  ], cropConnection);
48131 
48132 	  this.reverted([ 'connection.layout' ], function(e) {
48133 	    delete e.context.cropped;
48134 	  });
48135 
48136 
48137 
48138 	  // BPMN + DI update //////////////////////
48139 
48140 
48141 	  // update parent
48142 	  function updateParent(e) {
48143 	    var context = e.context;
48144 
48145 	    self.updateParent(context.shape || context.connection, context.oldParent);
48146 	  }
48147 
48148 	  function reverseUpdateParent(e) {
48149 	    var context = e.context;
48150 
48151 	    var element = context.shape || context.connection,
48152 
48153 	        // oldParent is the (old) new parent, because we are undoing
48154 	        oldParent = context.parent || context.newParent;
48155 
48156 	    self.updateParent(element, oldParent);
48157 	  }
48158 
48159 	  this.executed([
48160 	    'shape.move',
48161 	    'shape.create',
48162 	    'shape.delete',
48163 	    'connection.create',
48164 	    'connection.move',
48165 	    'connection.delete'
48166 	  ], ifBpmn(updateParent));
48167 
48168 	  this.reverted([
48169 	    'shape.move',
48170 	    'shape.create',
48171 	    'shape.delete',
48172 	    'connection.create',
48173 	    'connection.move',
48174 	    'connection.delete'
48175 	  ], ifBpmn(reverseUpdateParent));
48176 
48177 	  /*
48178 	   * ## Updating Parent
48179 	   *
48180 	   * When morphing a Process into a Collaboration or vice-versa,
48181 	   * make sure that both the *semantic* and *di* parent of each element
48182 	   * is updated.
48183 	   *
48184 	   */
48185 	  function updateRoot(event) {
48186 	    var context = event.context,
48187 	        oldRoot = context.oldRoot,
48188 	        children = oldRoot.children;
48189 
48190 	    forEach(children, function(child) {
48191 	      if (is$1(child, 'bpmn:BaseElement')) {
48192 	        self.updateParent(child);
48193 	      }
48194 	    });
48195 	  }
48196 
48197 	  this.executed([ 'canvas.updateRoot' ], updateRoot);
48198 	  this.reverted([ 'canvas.updateRoot' ], updateRoot);
48199 
48200 
48201 	  // update bounds
48202 	  function updateBounds(e) {
48203 	    var shape = e.context.shape;
48204 
48205 	    if (!is$1(shape, 'bpmn:BaseElement')) {
48206 	      return;
48207 	    }
48208 
48209 	    self.updateBounds(shape);
48210 	  }
48211 
48212 	  this.executed([ 'shape.move', 'shape.create', 'shape.resize' ], ifBpmn(function(event) {
48213 
48214 	    // exclude labels because they're handled separately during shape.changed
48215 	    if (event.context.shape.type === 'label') {
48216 	      return;
48217 	    }
48218 
48219 	    updateBounds(event);
48220 	  }));
48221 
48222 	  this.reverted([ 'shape.move', 'shape.create', 'shape.resize' ], ifBpmn(function(event) {
48223 
48224 	    // exclude labels because they're handled separately during shape.changed
48225 	    if (event.context.shape.type === 'label') {
48226 	      return;
48227 	    }
48228 
48229 	    updateBounds(event);
48230 	  }));
48231 
48232 	  // Handle labels separately. This is necessary, because the label bounds have to be updated
48233 	  // every time its shape changes, not only on move, create and resize.
48234 	  eventBus.on('shape.changed', function(event) {
48235 	    if (event.element.type === 'label') {
48236 	      updateBounds({ context: { shape: event.element } });
48237 	    }
48238 	  });
48239 
48240 	  // attach / detach connection
48241 	  function updateConnection(e) {
48242 	    self.updateConnection(e.context);
48243 	  }
48244 
48245 	  this.executed([
48246 	    'connection.create',
48247 	    'connection.move',
48248 	    'connection.delete',
48249 	    'connection.reconnect'
48250 	  ], ifBpmn(updateConnection));
48251 
48252 	  this.reverted([
48253 	    'connection.create',
48254 	    'connection.move',
48255 	    'connection.delete',
48256 	    'connection.reconnect'
48257 	  ], ifBpmn(updateConnection));
48258 
48259 
48260 	  // update waypoints
48261 	  function updateConnectionWaypoints(e) {
48262 	    self.updateConnectionWaypoints(e.context.connection);
48263 	  }
48264 
48265 	  this.executed([
48266 	    'connection.layout',
48267 	    'connection.move',
48268 	    'connection.updateWaypoints',
48269 	  ], ifBpmn(updateConnectionWaypoints));
48270 
48271 	  this.reverted([
48272 	    'connection.layout',
48273 	    'connection.move',
48274 	    'connection.updateWaypoints',
48275 	  ], ifBpmn(updateConnectionWaypoints));
48276 
48277 	  // update conditional/default flows
48278 	  this.executed('connection.reconnect', ifBpmn(function(event) {
48279 	    var context = event.context,
48280 	        connection = context.connection,
48281 	        oldSource = context.oldSource,
48282 	        newSource = context.newSource,
48283 	        connectionBo = getBusinessObject(connection),
48284 	        oldSourceBo = getBusinessObject(oldSource),
48285 	        newSourceBo = getBusinessObject(newSource);
48286 
48287 	    // remove condition from connection on reconnect to new source
48288 	    // if new source can NOT have condional sequence flow
48289 	    if (connectionBo.conditionExpression && !isAny(newSourceBo, [
48290 	      'bpmn:Activity',
48291 	      'bpmn:ExclusiveGateway',
48292 	      'bpmn:InclusiveGateway'
48293 	    ])) {
48294 	      context.oldConditionExpression = connectionBo.conditionExpression;
48295 
48296 	      delete connectionBo.conditionExpression;
48297 	    }
48298 
48299 	    // remove default from old source flow on reconnect to new source
48300 	    // if source changed
48301 	    if (oldSource !== newSource && oldSourceBo.default === connectionBo) {
48302 	      context.oldDefault = oldSourceBo.default;
48303 
48304 	      delete oldSourceBo.default;
48305 	    }
48306 	  }));
48307 
48308 	  this.reverted('connection.reconnect', ifBpmn(function(event) {
48309 	    var context = event.context,
48310 	        connection = context.connection,
48311 	        oldSource = context.oldSource,
48312 	        newSource = context.newSource,
48313 	        connectionBo = getBusinessObject(connection),
48314 	        oldSourceBo = getBusinessObject(oldSource),
48315 	        newSourceBo = getBusinessObject(newSource);
48316 
48317 	    // add condition to connection on revert reconnect to new source
48318 	    if (context.oldConditionExpression) {
48319 	      connectionBo.conditionExpression = context.oldConditionExpression;
48320 	    }
48321 
48322 	    // add default to old source on revert reconnect to new source
48323 	    if (context.oldDefault) {
48324 	      oldSourceBo.default = context.oldDefault;
48325 
48326 	      delete newSourceBo.default;
48327 	    }
48328 	  }));
48329 
48330 	  // update attachments
48331 	  function updateAttachment(e) {
48332 	    self.updateAttachment(e.context);
48333 	  }
48334 
48335 	  this.executed([ 'element.updateAttachment' ], ifBpmn(updateAttachment));
48336 	  this.reverted([ 'element.updateAttachment' ], ifBpmn(updateAttachment));
48337 	}
48338 
48339 	inherits$1(BpmnUpdater, CommandInterceptor);
48340 
48341 	BpmnUpdater.$inject = [
48342 	  'eventBus',
48343 	  'bpmnFactory',
48344 	  'connectionDocking',
48345 	  'translate'
48346 	];
48347 
48348 
48349 	// implementation //////////////////////
48350 
48351 	BpmnUpdater.prototype.updateAttachment = function(context) {
48352 
48353 	  var shape = context.shape,
48354 	      businessObject = shape.businessObject,
48355 	      host = shape.host;
48356 
48357 	  businessObject.attachedToRef = host && host.businessObject;
48358 	};
48359 
48360 	BpmnUpdater.prototype.updateParent = function(element, oldParent) {
48361 
48362 	  // do not update BPMN 2.0 label parent
48363 	  if (element instanceof Label) {
48364 	    return;
48365 	  }
48366 
48367 	  // data stores in collaborations are handled separately by DataStoreBehavior
48368 	  if (is$1(element, 'bpmn:DataStoreReference') &&
48369 	      element.parent &&
48370 	      is$1(element.parent, 'bpmn:Collaboration')) {
48371 	    return;
48372 	  }
48373 
48374 	  var parentShape = element.parent;
48375 
48376 	  var businessObject = element.businessObject,
48377 	      parentBusinessObject = parentShape && parentShape.businessObject,
48378 	      parentDi = parentBusinessObject && parentBusinessObject.di;
48379 
48380 	  if (is$1(element, 'bpmn:FlowNode')) {
48381 	    this.updateFlowNodeRefs(businessObject, parentBusinessObject, oldParent && oldParent.businessObject);
48382 	  }
48383 
48384 	  if (is$1(element, 'bpmn:DataOutputAssociation')) {
48385 	    if (element.source) {
48386 	      parentBusinessObject = element.source.businessObject;
48387 	    } else {
48388 	      parentBusinessObject = null;
48389 	    }
48390 	  }
48391 
48392 	  if (is$1(element, 'bpmn:DataInputAssociation')) {
48393 	    if (element.target) {
48394 	      parentBusinessObject = element.target.businessObject;
48395 	    } else {
48396 	      parentBusinessObject = null;
48397 	    }
48398 	  }
48399 
48400 	  this.updateSemanticParent(businessObject, parentBusinessObject);
48401 
48402 	  if (is$1(element, 'bpmn:DataObjectReference') && businessObject.dataObjectRef) {
48403 	    this.updateSemanticParent(businessObject.dataObjectRef, parentBusinessObject);
48404 	  }
48405 
48406 	  this.updateDiParent(businessObject.di, parentDi);
48407 	};
48408 
48409 
48410 	BpmnUpdater.prototype.updateBounds = function(shape) {
48411 
48412 	  var di = shape.businessObject.di;
48413 
48414 	  var target = (shape instanceof Label) ? this._getLabel(di) : di;
48415 
48416 	  var bounds = target.bounds;
48417 
48418 	  if (!bounds) {
48419 	    bounds = this._bpmnFactory.createDiBounds();
48420 	    target.set('bounds', bounds);
48421 	  }
48422 
48423 	  assign(bounds, {
48424 	    x: shape.x,
48425 	    y: shape.y,
48426 	    width: shape.width,
48427 	    height: shape.height
48428 	  });
48429 	};
48430 
48431 	BpmnUpdater.prototype.updateFlowNodeRefs = function(businessObject, newContainment, oldContainment) {
48432 
48433 	  if (oldContainment === newContainment) {
48434 	    return;
48435 	  }
48436 
48437 	  var oldRefs, newRefs;
48438 
48439 	  if (is$1 (oldContainment, 'bpmn:Lane')) {
48440 	    oldRefs = oldContainment.get('flowNodeRef');
48441 	    remove(oldRefs, businessObject);
48442 	  }
48443 
48444 	  if (is$1(newContainment, 'bpmn:Lane')) {
48445 	    newRefs = newContainment.get('flowNodeRef');
48446 	    add(newRefs, businessObject);
48447 	  }
48448 	};
48449 
48450 
48451 	// update existing sourceElement and targetElement di information
48452 	BpmnUpdater.prototype.updateDiConnection = function(di, newSource, newTarget) {
48453 
48454 	  if (di.sourceElement && di.sourceElement.bpmnElement !== newSource) {
48455 	    di.sourceElement = newSource && newSource.di;
48456 	  }
48457 
48458 	  if (di.targetElement && di.targetElement.bpmnElement !== newTarget) {
48459 	    di.targetElement = newTarget && newTarget.di;
48460 	  }
48461 
48462 	};
48463 
48464 
48465 	BpmnUpdater.prototype.updateDiParent = function(di, parentDi) {
48466 
48467 	  if (parentDi && !is$1(parentDi, 'bpmndi:BPMNPlane')) {
48468 	    parentDi = parentDi.$parent;
48469 	  }
48470 
48471 	  if (di.$parent === parentDi) {
48472 	    return;
48473 	  }
48474 
48475 	  var planeElements = (parentDi || di.$parent).get('planeElement');
48476 
48477 	  if (parentDi) {
48478 	    planeElements.push(di);
48479 	    di.$parent = parentDi;
48480 	  } else {
48481 	    remove(planeElements, di);
48482 	    di.$parent = null;
48483 	  }
48484 	};
48485 
48486 	function getDefinitions(element) {
48487 	  while (element && !is$1(element, 'bpmn:Definitions')) {
48488 	    element = element.$parent;
48489 	  }
48490 
48491 	  return element;
48492 	}
48493 
48494 	BpmnUpdater.prototype.getLaneSet = function(container) {
48495 
48496 	  var laneSet, laneSets;
48497 
48498 	  // bpmn:Lane
48499 	  if (is$1(container, 'bpmn:Lane')) {
48500 	    laneSet = container.childLaneSet;
48501 
48502 	    if (!laneSet) {
48503 	      laneSet = this._bpmnFactory.create('bpmn:LaneSet');
48504 	      container.childLaneSet = laneSet;
48505 	      laneSet.$parent = container;
48506 	    }
48507 
48508 	    return laneSet;
48509 	  }
48510 
48511 	  // bpmn:Participant
48512 	  if (is$1(container, 'bpmn:Participant')) {
48513 	    container = container.processRef;
48514 	  }
48515 
48516 	  // bpmn:FlowElementsContainer
48517 	  laneSets = container.get('laneSets');
48518 	  laneSet = laneSets[0];
48519 
48520 	  if (!laneSet) {
48521 	    laneSet = this._bpmnFactory.create('bpmn:LaneSet');
48522 	    laneSet.$parent = container;
48523 	    laneSets.push(laneSet);
48524 	  }
48525 
48526 	  return laneSet;
48527 	};
48528 
48529 	BpmnUpdater.prototype.updateSemanticParent = function(businessObject, newParent, visualParent) {
48530 
48531 	  var containment,
48532 	      translate = this._translate;
48533 
48534 	  if (businessObject.$parent === newParent) {
48535 	    return;
48536 	  }
48537 
48538 	  if (is$1(businessObject, 'bpmn:DataInput') || is$1(businessObject, 'bpmn:DataOutput')) {
48539 
48540 	    if (is$1(newParent, 'bpmn:Participant') && 'processRef' in newParent) {
48541 	      newParent = newParent.processRef;
48542 	    }
48543 
48544 	    // already in correct ioSpecification
48545 	    if ('ioSpecification' in newParent && newParent.ioSpecification === businessObject.$parent) {
48546 	      return;
48547 	    }
48548 	  }
48549 
48550 	  if (is$1(businessObject, 'bpmn:Lane')) {
48551 
48552 	    if (newParent) {
48553 	      newParent = this.getLaneSet(newParent);
48554 	    }
48555 
48556 	    containment = 'lanes';
48557 	  } else
48558 
48559 	  if (is$1(businessObject, 'bpmn:FlowElement')) {
48560 
48561 	    if (newParent) {
48562 
48563 	      if (is$1(newParent, 'bpmn:Participant')) {
48564 	        newParent = newParent.processRef;
48565 	      } else
48566 
48567 	      if (is$1(newParent, 'bpmn:Lane')) {
48568 	        do {
48569 
48570 	          // unwrap Lane -> LaneSet -> (Lane | FlowElementsContainer)
48571 	          newParent = newParent.$parent.$parent;
48572 	        } while (is$1(newParent, 'bpmn:Lane'));
48573 
48574 	      }
48575 	    }
48576 
48577 	    containment = 'flowElements';
48578 
48579 	  } else
48580 
48581 	  if (is$1(businessObject, 'bpmn:Artifact')) {
48582 
48583 	    while (newParent &&
48584 	           !is$1(newParent, 'bpmn:Process') &&
48585 	           !is$1(newParent, 'bpmn:SubProcess') &&
48586 	           !is$1(newParent, 'bpmn:Collaboration')) {
48587 
48588 	      if (is$1(newParent, 'bpmn:Participant')) {
48589 	        newParent = newParent.processRef;
48590 	        break;
48591 	      } else {
48592 	        newParent = newParent.$parent;
48593 	      }
48594 	    }
48595 
48596 	    containment = 'artifacts';
48597 	  } else
48598 
48599 	  if (is$1(businessObject, 'bpmn:MessageFlow')) {
48600 	    containment = 'messageFlows';
48601 
48602 	  } else
48603 
48604 	  if (is$1(businessObject, 'bpmn:Participant')) {
48605 	    containment = 'participants';
48606 
48607 	    // make sure the participants process is properly attached / detached
48608 	    // from the XML document
48609 
48610 	    var process = businessObject.processRef,
48611 	        definitions;
48612 
48613 	    if (process) {
48614 	      definitions = getDefinitions(businessObject.$parent || newParent);
48615 
48616 	      if (businessObject.$parent) {
48617 	        remove(definitions.get('rootElements'), process);
48618 	        process.$parent = null;
48619 	      }
48620 
48621 	      if (newParent) {
48622 	        add(definitions.get('rootElements'), process);
48623 	        process.$parent = definitions;
48624 	      }
48625 	    }
48626 	  } else
48627 
48628 	  if (is$1(businessObject, 'bpmn:DataOutputAssociation')) {
48629 	    containment = 'dataOutputAssociations';
48630 	  } else
48631 
48632 	  if (is$1(businessObject, 'bpmn:DataInputAssociation')) {
48633 	    containment = 'dataInputAssociations';
48634 	  }
48635 
48636 	  if (!containment) {
48637 	    throw new Error(translate(
48638 	      'no parent for {element} in {parent}',
48639 	      {
48640 	        element: businessObject.id,
48641 	        parent: newParent.id
48642 	      }
48643 	    ));
48644 	  }
48645 
48646 	  var children;
48647 
48648 	  if (businessObject.$parent) {
48649 
48650 	    // remove from old parent
48651 	    children = businessObject.$parent.get(containment);
48652 	    remove(children, businessObject);
48653 	  }
48654 
48655 	  if (!newParent) {
48656 	    businessObject.$parent = null;
48657 	  } else {
48658 
48659 	    // add to new parent
48660 	    children = newParent.get(containment);
48661 	    children.push(businessObject);
48662 	    businessObject.$parent = newParent;
48663 	  }
48664 
48665 	  if (visualParent) {
48666 	    var diChildren = visualParent.get(containment);
48667 
48668 	    remove(children, businessObject);
48669 
48670 	    if (newParent) {
48671 
48672 	      if (!diChildren) {
48673 	        diChildren = [];
48674 	        newParent.set(containment, diChildren);
48675 	      }
48676 
48677 	      diChildren.push(businessObject);
48678 	    }
48679 	  }
48680 	};
48681 
48682 
48683 	BpmnUpdater.prototype.updateConnectionWaypoints = function(connection) {
48684 	  connection.businessObject.di.set('waypoint', this._bpmnFactory.createDiWaypoints(connection.waypoints));
48685 	};
48686 
48687 
48688 	BpmnUpdater.prototype.updateConnection = function(context) {
48689 
48690 	  var connection = context.connection,
48691 	      businessObject = getBusinessObject(connection),
48692 	      newSource = getBusinessObject(connection.source),
48693 	      newTarget = getBusinessObject(connection.target),
48694 	      visualParent;
48695 
48696 	  if (!is$1(businessObject, 'bpmn:DataAssociation')) {
48697 
48698 	    var inverseSet = is$1(businessObject, 'bpmn:SequenceFlow');
48699 
48700 	    if (businessObject.sourceRef !== newSource) {
48701 	      if (inverseSet) {
48702 	        remove(businessObject.sourceRef && businessObject.sourceRef.get('outgoing'), businessObject);
48703 
48704 	        if (newSource && newSource.get('outgoing')) {
48705 	          newSource.get('outgoing').push(businessObject);
48706 	        }
48707 	      }
48708 
48709 	      businessObject.sourceRef = newSource;
48710 	    }
48711 
48712 	    if (businessObject.targetRef !== newTarget) {
48713 	      if (inverseSet) {
48714 	        remove(businessObject.targetRef && businessObject.targetRef.get('incoming'), businessObject);
48715 
48716 	        if (newTarget && newTarget.get('incoming')) {
48717 	          newTarget.get('incoming').push(businessObject);
48718 	        }
48719 	      }
48720 
48721 	      businessObject.targetRef = newTarget;
48722 	    }
48723 	  } else
48724 
48725 	  if (is$1(businessObject, 'bpmn:DataInputAssociation')) {
48726 
48727 	    // handle obnoxious isMsome sourceRef
48728 	    businessObject.get('sourceRef')[0] = newSource;
48729 
48730 	    visualParent = context.parent || context.newParent || newTarget;
48731 
48732 	    this.updateSemanticParent(businessObject, newTarget, visualParent);
48733 	  } else
48734 
48735 	  if (is$1(businessObject, 'bpmn:DataOutputAssociation')) {
48736 	    visualParent = context.parent || context.newParent || newSource;
48737 
48738 	    this.updateSemanticParent(businessObject, newSource, visualParent);
48739 
48740 	    // targetRef = new target
48741 	    businessObject.targetRef = newTarget;
48742 	  }
48743 
48744 	  this.updateConnectionWaypoints(connection);
48745 
48746 	  this.updateDiConnection(businessObject.di, newSource, newTarget);
48747 	};
48748 
48749 
48750 	// helpers //////////////////////
48751 
48752 	BpmnUpdater.prototype._getLabel = function(di) {
48753 	  if (!di.label) {
48754 	    di.label = this._bpmnFactory.createDiLabel();
48755 	  }
48756 
48757 	  return di.label;
48758 	};
48759 
48760 
48761 	/**
48762 	 * Make sure the event listener is only called
48763 	 * if the touched element is a BPMN element.
48764 	 *
48765 	 * @param  {Function} fn
48766 	 * @return {Function} guarded function
48767 	 */
48768 	function ifBpmn(fn) {
48769 
48770 	  return function(event) {
48771 
48772 	    var context = event.context,
48773 	        element = context.shape || context.connection;
48774 
48775 	    if (is$1(element, 'bpmn:BaseElement')) {
48776 	      fn(event);
48777 	    }
48778 	  };
48779 	}
48780 
48781 	/**
48782 	 * A bpmn-aware factory for diagram-js shapes
48783 	 */
48784 	function ElementFactory(bpmnFactory, moddle, translate) {
48785 	  ElementFactory$1.call(this);
48786 
48787 	  this._bpmnFactory = bpmnFactory;
48788 	  this._moddle = moddle;
48789 	  this._translate = translate;
48790 	}
48791 
48792 	inherits$1(ElementFactory, ElementFactory$1);
48793 
48794 	ElementFactory.$inject = [
48795 	  'bpmnFactory',
48796 	  'moddle',
48797 	  'translate'
48798 	];
48799 
48800 	ElementFactory.prototype.baseCreate = ElementFactory$1.prototype.create;
48801 
48802 	ElementFactory.prototype.create = function(elementType, attrs) {
48803 
48804 	  // no special magic for labels,
48805 	  // we assume their businessObjects have already been created
48806 	  // and wired via attrs
48807 	  if (elementType === 'label') {
48808 	    return this.baseCreate(elementType, assign({ type: 'label' }, DEFAULT_LABEL_SIZE, attrs));
48809 	  }
48810 
48811 	  return this.createBpmnElement(elementType, attrs);
48812 	};
48813 
48814 	ElementFactory.prototype.createBpmnElement = function(elementType, attrs) {
48815 	  var size,
48816 	      translate = this._translate;
48817 
48818 	  attrs = attrs || {};
48819 
48820 	  var businessObject = attrs.businessObject;
48821 
48822 	  if (!businessObject) {
48823 	    if (!attrs.type) {
48824 	      throw new Error(translate('no shape type specified'));
48825 	    }
48826 
48827 	    businessObject = this._bpmnFactory.create(attrs.type);
48828 	  }
48829 
48830 	  if (!businessObject.di) {
48831 	    if (elementType === 'root') {
48832 	      businessObject.di = this._bpmnFactory.createDiPlane(businessObject, [], {
48833 	        id: businessObject.id + '_di'
48834 	      });
48835 	    } else
48836 	    if (elementType === 'connection') {
48837 	      businessObject.di = this._bpmnFactory.createDiEdge(businessObject, [], {
48838 	        id: businessObject.id + '_di'
48839 	      });
48840 	    } else {
48841 	      businessObject.di = this._bpmnFactory.createDiShape(businessObject, {}, {
48842 	        id: businessObject.id + '_di'
48843 	      });
48844 	    }
48845 	  }
48846 
48847 	  if (is$1(businessObject, 'bpmn:Group')) {
48848 	    attrs = assign({
48849 	      isFrame: true
48850 	    }, attrs);
48851 	  }
48852 
48853 	  if (attrs.di) {
48854 	    assign(businessObject.di, attrs.di);
48855 
48856 	    delete attrs.di;
48857 	  }
48858 
48859 	  applyAttributes(businessObject, attrs, [
48860 	    'processRef',
48861 	    'isInterrupting',
48862 	    'associationDirection',
48863 	    'isForCompensation'
48864 	  ]);
48865 
48866 	  if (attrs.isExpanded) {
48867 	    applyAttribute(businessObject.di, attrs, 'isExpanded');
48868 	  }
48869 
48870 	  if (is$1(businessObject, 'bpmn:ExclusiveGateway')) {
48871 	    businessObject.di.isMarkerVisible = true;
48872 	  }
48873 
48874 	  var eventDefinitions,
48875 	      newEventDefinition;
48876 
48877 	  if (attrs.eventDefinitionType) {
48878 	    eventDefinitions = businessObject.get('eventDefinitions') || [];
48879 	    newEventDefinition = this._bpmnFactory.create(attrs.eventDefinitionType, attrs.eventDefinitionAttrs);
48880 
48881 	    if (attrs.eventDefinitionType === 'bpmn:ConditionalEventDefinition') {
48882 	      newEventDefinition.condition = this._bpmnFactory.create('bpmn:FormalExpression');
48883 	    }
48884 
48885 	    eventDefinitions.push(newEventDefinition);
48886 
48887 	    newEventDefinition.$parent = businessObject;
48888 	    businessObject.eventDefinitions = eventDefinitions;
48889 
48890 	    delete attrs.eventDefinitionType;
48891 	  }
48892 
48893 	  size = this._getDefaultSize(businessObject);
48894 
48895 	  attrs = assign({
48896 	    businessObject: businessObject,
48897 	    id: businessObject.id
48898 	  }, size, attrs);
48899 
48900 	  return this.baseCreate(elementType, attrs);
48901 	};
48902 
48903 
48904 	ElementFactory.prototype._getDefaultSize = function(semantic) {
48905 
48906 	  if (is$1(semantic, 'bpmn:SubProcess')) {
48907 
48908 	    if (isExpanded(semantic)) {
48909 	      return { width: 350, height: 200 };
48910 	    } else {
48911 	      return { width: 100, height: 80 };
48912 	    }
48913 	  }
48914 
48915 	  if (is$1(semantic, 'bpmn:Task')) {
48916 	    return { width: 100, height: 80 };
48917 	  }
48918 
48919 	  if (is$1(semantic, 'bpmn:Gateway')) {
48920 	    return { width: 50, height: 50 };
48921 	  }
48922 
48923 	  if (is$1(semantic, 'bpmn:Event')) {
48924 	    return { width: 36, height: 36 };
48925 	  }
48926 
48927 	  if (is$1(semantic, 'bpmn:Participant')) {
48928 	    if (isExpanded(semantic)) {
48929 	      return { width: 600, height: 250 };
48930 	    } else {
48931 	      return { width: 400, height: 60 };
48932 	    }
48933 	  }
48934 
48935 	  if (is$1(semantic, 'bpmn:Lane')) {
48936 	    return { width: 400, height: 100 };
48937 	  }
48938 
48939 	  if (is$1(semantic, 'bpmn:DataObjectReference')) {
48940 	    return { width: 36, height: 50 };
48941 	  }
48942 
48943 	  if (is$1(semantic, 'bpmn:DataStoreReference')) {
48944 	    return { width: 50, height: 50 };
48945 	  }
48946 
48947 	  if (is$1(semantic, 'bpmn:TextAnnotation')) {
48948 	    return { width: 100, height: 30 };
48949 	  }
48950 
48951 	  if (is$1(semantic, 'bpmn:Group')) {
48952 	    return { width: 300, height: 300 };
48953 	  }
48954 
48955 	  return { width: 100, height: 80 };
48956 	};
48957 
48958 
48959 	/**
48960 	 * Create participant.
48961 	 *
48962 	 * @param {boolean|Object} [attrs] attrs
48963 	 *
48964 	 * @returns {djs.model.Shape}
48965 	 */
48966 	ElementFactory.prototype.createParticipantShape = function(attrs) {
48967 
48968 	  if (!isObject(attrs)) {
48969 	    attrs = { isExpanded: attrs };
48970 	  }
48971 
48972 	  attrs = assign({ type: 'bpmn:Participant' }, attrs || {});
48973 
48974 	  // participants are expanded by default
48975 	  if (attrs.isExpanded !== false) {
48976 	    attrs.processRef = this._bpmnFactory.create('bpmn:Process');
48977 	  }
48978 
48979 	  return this.createShape(attrs);
48980 	};
48981 
48982 
48983 	// helpers //////////////////////
48984 
48985 	/**
48986 	 * Apply attributes from a map to the given element,
48987 	 * remove attribute from the map on application.
48988 	 *
48989 	 * @param {Base} element
48990 	 * @param {Object} attrs (in/out map of attributes)
48991 	 * @param {Array<string>} attributeNames name of attributes to apply
48992 	 */
48993 	function applyAttributes(element, attrs, attributeNames) {
48994 
48995 	  forEach(attributeNames, function(property) {
48996 	    if (attrs[property] !== undefined) {
48997 	      applyAttribute(element, attrs, property);
48998 	    }
48999 	  });
49000 	}
49001 
49002 	/**
49003 	 * Apply named property to element and drain it from the attrs
49004 	 * collection.
49005 	 *
49006 	 * @param {Base} element
49007 	 * @param {Object} attrs (in/out map of attributes)
49008 	 * @param {string} attributeName to apply
49009 	 */
49010 	function applyAttribute(element, attrs, attributeName) {
49011 	  element[attributeName] = attrs[attributeName];
49012 
49013 	  delete attrs[attributeName];
49014 	}
49015 
49016 	/**
49017 	 * A handler that align elements in a certain way.
49018 	 *
49019 	 */
49020 	function AlignElements(modeling, canvas) {
49021 	  this._modeling = modeling;
49022 	  this._canvas = canvas;
49023 	}
49024 
49025 	AlignElements.$inject = [ 'modeling', 'canvas' ];
49026 
49027 
49028 	AlignElements.prototype.preExecute = function(context) {
49029 	  var modeling = this._modeling;
49030 
49031 	  var elements = context.elements,
49032 	      alignment = context.alignment;
49033 
49034 
49035 	  forEach(elements, function(element) {
49036 	    var delta = {
49037 	      x: 0,
49038 	      y: 0
49039 	    };
49040 
49041 	    if (alignment.left) {
49042 	      delta.x = alignment.left - element.x;
49043 
49044 	    } else if (alignment.right) {
49045 	      delta.x = (alignment.right - element.width) - element.x;
49046 
49047 	    } else if (alignment.center) {
49048 	      delta.x = (alignment.center - Math.round(element.width / 2)) - element.x;
49049 
49050 	    } else if (alignment.top) {
49051 	      delta.y = alignment.top - element.y;
49052 
49053 	    } else if (alignment.bottom) {
49054 	      delta.y = (alignment.bottom - element.height) - element.y;
49055 
49056 	    } else if (alignment.middle) {
49057 	      delta.y = (alignment.middle - Math.round(element.height / 2)) - element.y;
49058 	    }
49059 
49060 	    modeling.moveElements([ element ], delta, element.parent);
49061 	  });
49062 	};
49063 
49064 	AlignElements.prototype.postExecute = function(context) {
49065 
49066 	};
49067 
49068 	/**
49069 	 * A handler that implements reversible appending of shapes
49070 	 * to a source shape.
49071 	 *
49072 	 * @param {canvas} Canvas
49073 	 * @param {elementFactory} ElementFactory
49074 	 * @param {modeling} Modeling
49075 	 */
49076 	function AppendShapeHandler(modeling) {
49077 	  this._modeling = modeling;
49078 	}
49079 
49080 	AppendShapeHandler.$inject = [ 'modeling' ];
49081 
49082 
49083 	// api //////////////////////
49084 
49085 
49086 	/**
49087 	 * Creates a new shape
49088 	 *
49089 	 * @param {Object} context
49090 	 * @param {ElementDescriptor} context.shape the new shape
49091 	 * @param {ElementDescriptor} context.source the source object
49092 	 * @param {ElementDescriptor} context.parent the parent object
49093 	 * @param {Point} context.position position of the new element
49094 	 */
49095 	AppendShapeHandler.prototype.preExecute = function(context) {
49096 
49097 	  var source = context.source;
49098 
49099 	  if (!source) {
49100 	    throw new Error('source required');
49101 	  }
49102 
49103 	  var target = context.target || source.parent,
49104 	      shape = context.shape,
49105 	      hints = context.hints || {};
49106 
49107 	  shape = context.shape =
49108 	    this._modeling.createShape(
49109 	      shape,
49110 	      context.position,
49111 	      target, { attach: hints.attach });
49112 
49113 	  context.shape = shape;
49114 	};
49115 
49116 	AppendShapeHandler.prototype.postExecute = function(context) {
49117 	  var hints = context.hints || {};
49118 
49119 	  if (!existsConnection(context.source, context.shape)) {
49120 
49121 	    // create connection
49122 	    if (hints.connectionTarget === context.source) {
49123 	      this._modeling.connect(context.shape, context.source, context.connection);
49124 	    } else {
49125 	      this._modeling.connect(context.source, context.shape, context.connection);
49126 	    }
49127 	  }
49128 	};
49129 
49130 
49131 	function existsConnection(source, target) {
49132 	  return some(source.outgoing, function(c) {
49133 	    return c.target === target;
49134 	  });
49135 	}
49136 
49137 	function CreateConnectionHandler(canvas, layouter) {
49138 	  this._canvas = canvas;
49139 	  this._layouter = layouter;
49140 	}
49141 
49142 	CreateConnectionHandler.$inject = [ 'canvas', 'layouter' ];
49143 
49144 
49145 	// api //////////////////////
49146 
49147 
49148 	/**
49149 	 * Appends a shape to a target shape
49150 	 *
49151 	 * @param {Object} context
49152 	 * @param {djs.element.Base} context.source the source object
49153 	 * @param {djs.element.Base} context.target the parent object
49154 	 * @param {Point} context.position position of the new element
49155 	 */
49156 	CreateConnectionHandler.prototype.execute = function(context) {
49157 
49158 	  var connection = context.connection,
49159 	      source = context.source,
49160 	      target = context.target,
49161 	      parent = context.parent,
49162 	      parentIndex = context.parentIndex,
49163 	      hints = context.hints;
49164 
49165 	  if (!source || !target) {
49166 	    throw new Error('source and target required');
49167 	  }
49168 
49169 	  if (!parent) {
49170 	    throw new Error('parent required');
49171 	  }
49172 
49173 	  connection.source = source;
49174 	  connection.target = target;
49175 
49176 	  if (!connection.waypoints) {
49177 	    connection.waypoints = this._layouter.layoutConnection(connection, hints);
49178 	  }
49179 
49180 	  // add connection
49181 	  this._canvas.addConnection(connection, parent, parentIndex);
49182 
49183 	  return connection;
49184 	};
49185 
49186 	CreateConnectionHandler.prototype.revert = function(context) {
49187 	  var connection = context.connection;
49188 
49189 	  this._canvas.removeConnection(connection);
49190 
49191 	  connection.source = null;
49192 	  connection.target = null;
49193 
49194 	  return connection;
49195 	};
49196 
49197 	var round$3 = Math.round;
49198 
49199 	function CreateElementsHandler(modeling) {
49200 	  this._modeling = modeling;
49201 	}
49202 
49203 	CreateElementsHandler.$inject = [
49204 	  'modeling'
49205 	];
49206 
49207 	CreateElementsHandler.prototype.preExecute = function(context) {
49208 	  var elements = context.elements,
49209 	      parent = context.parent,
49210 	      parentIndex = context.parentIndex,
49211 	      position = context.position,
49212 	      hints = context.hints;
49213 
49214 	  var modeling = this._modeling;
49215 
49216 	  // make sure each element has x and y
49217 	  forEach(elements, function(element) {
49218 	    if (!isNumber(element.x)) {
49219 	      element.x = 0;
49220 	    }
49221 
49222 	    if (!isNumber(element.y)) {
49223 	      element.y = 0;
49224 	    }
49225 	  });
49226 
49227 	  var bbox = getBBox(elements);
49228 
49229 	  // center elements around position
49230 	  forEach(elements, function(element) {
49231 	    if (isConnection$5(element)) {
49232 	      element.waypoints = map$1(element.waypoints, function(waypoint) {
49233 	        return {
49234 	          x: round$3(waypoint.x - bbox.x - bbox.width / 2 + position.x),
49235 	          y: round$3(waypoint.y - bbox.y - bbox.height / 2 + position.y)
49236 	        };
49237 	      });
49238 	    }
49239 
49240 	    assign(element, {
49241 	      x: round$3(element.x - bbox.x - bbox.width / 2 + position.x),
49242 	      y: round$3(element.y - bbox.y - bbox.height / 2 + position.y)
49243 	    });
49244 	  });
49245 
49246 	  var parents = getParents$1(elements);
49247 
49248 	  var cache = {};
49249 
49250 	  forEach(elements, function(element) {
49251 	    if (isConnection$5(element)) {
49252 	      cache[ element.id ] = isNumber(parentIndex) ?
49253 	        modeling.createConnection(
49254 	          cache[ element.source.id ],
49255 	          cache[ element.target.id ],
49256 	          parentIndex,
49257 	          element,
49258 	          element.parent || parent,
49259 	          hints
49260 	        ) :
49261 	        modeling.createConnection(
49262 	          cache[ element.source.id ],
49263 	          cache[ element.target.id ],
49264 	          element,
49265 	          element.parent || parent,
49266 	          hints
49267 	        );
49268 
49269 	      return;
49270 	    }
49271 
49272 	    var createShapeHints = assign({}, hints);
49273 
49274 	    if (parents.indexOf(element) === -1) {
49275 	      createShapeHints.autoResize = false;
49276 	    }
49277 
49278 	    cache[ element.id ] = isNumber(parentIndex) ?
49279 	      modeling.createShape(
49280 	        element,
49281 	        pick(element, [ 'x', 'y', 'width', 'height' ]),
49282 	        element.parent || parent,
49283 	        parentIndex,
49284 	        createShapeHints
49285 	      ) :
49286 	      modeling.createShape(
49287 	        element,
49288 	        pick(element, [ 'x', 'y', 'width', 'height' ]),
49289 	        element.parent || parent,
49290 	        createShapeHints
49291 	      );
49292 	  });
49293 
49294 	  context.elements = values(cache);
49295 	};
49296 
49297 	// helpers //////////
49298 
49299 	function isConnection$5(element) {
49300 	  return !!element.waypoints;
49301 	}
49302 
49303 	var round$2 = Math.round;
49304 
49305 
49306 	/**
49307 	 * A handler that implements reversible addition of shapes.
49308 	 *
49309 	 * @param {canvas} Canvas
49310 	 */
49311 	function CreateShapeHandler(canvas) {
49312 	  this._canvas = canvas;
49313 	}
49314 
49315 	CreateShapeHandler.$inject = [ 'canvas' ];
49316 
49317 
49318 	// api //////////////////////
49319 
49320 
49321 	/**
49322 	 * Appends a shape to a target shape
49323 	 *
49324 	 * @param {Object} context
49325 	 * @param {djs.model.Base} context.parent the parent object
49326 	 * @param {Point} context.position position of the new element
49327 	 */
49328 	CreateShapeHandler.prototype.execute = function(context) {
49329 
49330 	  var shape = context.shape,
49331 	      positionOrBounds = context.position,
49332 	      parent = context.parent,
49333 	      parentIndex = context.parentIndex;
49334 
49335 	  if (!parent) {
49336 	    throw new Error('parent required');
49337 	  }
49338 
49339 	  if (!positionOrBounds) {
49340 	    throw new Error('position required');
49341 	  }
49342 
49343 	  // (1) add at event center position _or_ at given bounds
49344 	  if (positionOrBounds.width !== undefined) {
49345 	    assign(shape, positionOrBounds);
49346 	  } else {
49347 	    assign(shape, {
49348 	      x: positionOrBounds.x - round$2(shape.width / 2),
49349 	      y: positionOrBounds.y - round$2(shape.height / 2)
49350 	    });
49351 	  }
49352 
49353 	  // (2) add to canvas
49354 	  this._canvas.addShape(shape, parent, parentIndex);
49355 
49356 	  return shape;
49357 	};
49358 
49359 
49360 	/**
49361 	 * Undo append by removing the shape
49362 	 */
49363 	CreateShapeHandler.prototype.revert = function(context) {
49364 
49365 	  var shape = context.shape;
49366 
49367 	  // (3) remove form canvas
49368 	  this._canvas.removeShape(shape);
49369 
49370 	  return shape;
49371 	};
49372 
49373 	/**
49374 	 * A handler that attaches a label to a given target shape.
49375 	 *
49376 	 * @param {Canvas} canvas
49377 	 */
49378 	function CreateLabelHandler(canvas) {
49379 	  CreateShapeHandler.call(this, canvas);
49380 	}
49381 
49382 	inherits$1(CreateLabelHandler, CreateShapeHandler);
49383 
49384 	CreateLabelHandler.$inject = [ 'canvas' ];
49385 
49386 
49387 	// api //////////////////////
49388 
49389 
49390 	var originalExecute = CreateShapeHandler.prototype.execute;
49391 
49392 	/**
49393 	 * Appends a label to a target shape.
49394 	 *
49395 	 * @method CreateLabelHandler#execute
49396 	 *
49397 	 * @param {Object} context
49398 	 * @param {ElementDescriptor} context.target the element the label is attached to
49399 	 * @param {ElementDescriptor} context.parent the parent object
49400 	 * @param {Point} context.position position of the new element
49401 	 */
49402 	CreateLabelHandler.prototype.execute = function(context) {
49403 
49404 	  var label = context.shape;
49405 
49406 	  ensureValidDimensions(label);
49407 
49408 	  label.labelTarget = context.labelTarget;
49409 
49410 	  return originalExecute.call(this, context);
49411 	};
49412 
49413 	var originalRevert = CreateShapeHandler.prototype.revert;
49414 
49415 	/**
49416 	 * Undo append by removing the shape
49417 	 */
49418 	CreateLabelHandler.prototype.revert = function(context) {
49419 	  context.shape.labelTarget = null;
49420 
49421 	  return originalRevert.call(this, context);
49422 	};
49423 
49424 
49425 	// helpers //////////////////////
49426 
49427 	function ensureValidDimensions(label) {
49428 
49429 	  // make sure a label has valid { width, height } dimensions
49430 	  [ 'width', 'height' ].forEach(function(prop) {
49431 	    if (typeof label[prop] === 'undefined') {
49432 	      label[prop] = 0;
49433 	    }
49434 	  });
49435 	}
49436 
49437 	/**
49438 	 * A handler that implements reversible deletion of Connections.
49439 	 */
49440 	function DeleteConnectionHandler(canvas, modeling) {
49441 	  this._canvas = canvas;
49442 	  this._modeling = modeling;
49443 	}
49444 
49445 	DeleteConnectionHandler.$inject = [
49446 	  'canvas',
49447 	  'modeling'
49448 	];
49449 
49450 
49451 	DeleteConnectionHandler.prototype.execute = function(context) {
49452 
49453 	  var connection = context.connection,
49454 	      parent = connection.parent;
49455 
49456 	  context.parent = parent;
49457 
49458 	  // remember containment
49459 	  context.parentIndex = indexOf(parent.children, connection);
49460 
49461 	  context.source = connection.source;
49462 	  context.target = connection.target;
49463 
49464 	  this._canvas.removeConnection(connection);
49465 
49466 	  connection.source = null;
49467 	  connection.target = null;
49468 
49469 	  return connection;
49470 	};
49471 
49472 	/**
49473 	 * Command revert implementation.
49474 	 */
49475 	DeleteConnectionHandler.prototype.revert = function(context) {
49476 
49477 	  var connection = context.connection,
49478 	      parent = context.parent,
49479 	      parentIndex = context.parentIndex;
49480 
49481 	  connection.source = context.source;
49482 	  connection.target = context.target;
49483 
49484 	  // restore containment
49485 	  add(parent.children, connection, parentIndex);
49486 
49487 	  this._canvas.addConnection(connection, parent);
49488 
49489 	  return connection;
49490 	};
49491 
49492 	function DeleteElementsHandler(modeling, elementRegistry) {
49493 	  this._modeling = modeling;
49494 	  this._elementRegistry = elementRegistry;
49495 	}
49496 
49497 	DeleteElementsHandler.$inject = [
49498 	  'modeling',
49499 	  'elementRegistry'
49500 	];
49501 
49502 
49503 	DeleteElementsHandler.prototype.postExecute = function(context) {
49504 
49505 	  var modeling = this._modeling,
49506 	      elementRegistry = this._elementRegistry,
49507 	      elements = context.elements;
49508 
49509 	  forEach(elements, function(element) {
49510 
49511 	    // element may have been removed with previous
49512 	    // remove operations already (e.g. in case of nesting)
49513 	    if (!elementRegistry.get(element.id)) {
49514 	      return;
49515 	    }
49516 
49517 	    if (element.waypoints) {
49518 	      modeling.removeConnection(element);
49519 	    } else {
49520 	      modeling.removeShape(element);
49521 	    }
49522 	  });
49523 	};
49524 
49525 	/**
49526 	 * A handler that implements reversible deletion of shapes.
49527 	 *
49528 	 */
49529 	function DeleteShapeHandler(canvas, modeling) {
49530 	  this._canvas = canvas;
49531 	  this._modeling = modeling;
49532 	}
49533 
49534 	DeleteShapeHandler.$inject = [ 'canvas', 'modeling' ];
49535 
49536 
49537 	/**
49538 	 * - Remove connections
49539 	 * - Remove all direct children
49540 	 */
49541 	DeleteShapeHandler.prototype.preExecute = function(context) {
49542 
49543 	  var modeling = this._modeling;
49544 
49545 	  var shape = context.shape;
49546 
49547 	  // remove connections
49548 	  saveClear(shape.incoming, function(connection) {
49549 
49550 	    // To make sure that the connection isn't removed twice
49551 	    // For example if a container is removed
49552 	    modeling.removeConnection(connection, { nested: true });
49553 	  });
49554 
49555 	  saveClear(shape.outgoing, function(connection) {
49556 	    modeling.removeConnection(connection, { nested: true });
49557 	  });
49558 
49559 	  // remove child shapes and connections
49560 	  saveClear(shape.children, function(child) {
49561 	    if (isConnection$4(child)) {
49562 	      modeling.removeConnection(child, { nested: true });
49563 	    } else {
49564 	      modeling.removeShape(child, { nested: true });
49565 	    }
49566 	  });
49567 	};
49568 
49569 	/**
49570 	 * Remove shape and remember the parent
49571 	 */
49572 	DeleteShapeHandler.prototype.execute = function(context) {
49573 	  var canvas = this._canvas;
49574 
49575 	  var shape = context.shape,
49576 	      oldParent = shape.parent;
49577 
49578 	  context.oldParent = oldParent;
49579 
49580 	  // remove containment
49581 	  context.oldParentIndex = indexOf(oldParent.children, shape);
49582 
49583 	  // remove shape
49584 	  canvas.removeShape(shape);
49585 
49586 	  return shape;
49587 	};
49588 
49589 
49590 	/**
49591 	 * Command revert implementation
49592 	 */
49593 	DeleteShapeHandler.prototype.revert = function(context) {
49594 
49595 	  var canvas = this._canvas;
49596 
49597 	  var shape = context.shape,
49598 	      oldParent = context.oldParent,
49599 	      oldParentIndex = context.oldParentIndex;
49600 
49601 	  // restore containment
49602 	  add(oldParent.children, shape, oldParentIndex);
49603 
49604 	  canvas.addShape(shape, oldParent);
49605 
49606 	  return shape;
49607 	};
49608 
49609 	function isConnection$4(element) {
49610 	  return element.waypoints;
49611 	}
49612 
49613 	/**
49614 	 * A handler that distributes elements evenly.
49615 	 */
49616 	function DistributeElements(modeling) {
49617 	  this._modeling = modeling;
49618 	}
49619 
49620 	DistributeElements.$inject = [ 'modeling' ];
49621 
49622 	var OFF_AXIS = {
49623 	  x: 'y',
49624 	  y: 'x'
49625 	};
49626 
49627 	DistributeElements.prototype.preExecute = function(context) {
49628 	  var modeling = this._modeling;
49629 
49630 	  var groups = context.groups,
49631 	      axis = context.axis,
49632 	      dimension = context.dimension;
49633 
49634 	  function updateRange(group, element) {
49635 	    group.range.min = Math.min(element[axis], group.range.min);
49636 	    group.range.max = Math.max(element[axis] + element[dimension], group.range.max);
49637 	  }
49638 
49639 	  function center(element) {
49640 	    return element[axis] + element[dimension] / 2;
49641 	  }
49642 
49643 	  function lastIdx(arr) {
49644 	    return arr.length - 1;
49645 	  }
49646 
49647 	  function rangeDiff(range) {
49648 	    return range.max - range.min;
49649 	  }
49650 
49651 	  function centerElement(refCenter, element) {
49652 	    var delta = { y: 0 };
49653 
49654 	    delta[axis] = refCenter - center(element);
49655 
49656 	    if (delta[axis]) {
49657 
49658 	      delta[OFF_AXIS[axis]] = 0;
49659 
49660 	      modeling.moveElements([ element ], delta, element.parent);
49661 	    }
49662 	  }
49663 
49664 	  var firstGroup = groups[0],
49665 	      lastGroupIdx = lastIdx(groups),
49666 	      lastGroup = groups[ lastGroupIdx ];
49667 
49668 	  var margin,
49669 	      spaceInBetween,
49670 	      groupsSize = 0; // the size of each range
49671 
49672 	  forEach(groups, function(group, idx) {
49673 	    var sortedElements,
49674 	        refElem,
49675 	        refCenter;
49676 
49677 	    if (group.elements.length < 2) {
49678 	      if (idx && idx !== groups.length - 1) {
49679 	        updateRange(group, group.elements[0]);
49680 
49681 	        groupsSize += rangeDiff(group.range);
49682 	      }
49683 	      return;
49684 	    }
49685 
49686 	    sortedElements = sortBy(group.elements, axis);
49687 
49688 	    refElem = sortedElements[0];
49689 
49690 	    if (idx === lastGroupIdx) {
49691 	      refElem = sortedElements[lastIdx(sortedElements)];
49692 	    }
49693 
49694 	    refCenter = center(refElem);
49695 
49696 	    // wanna update the ranges after the shapes have been centered
49697 	    group.range = null;
49698 
49699 	    forEach(sortedElements, function(element) {
49700 
49701 	      centerElement(refCenter, element);
49702 
49703 	      if (group.range === null) {
49704 	        group.range = {
49705 	          min: element[axis],
49706 	          max: element[axis] + element[dimension]
49707 	        };
49708 
49709 	        return;
49710 	      }
49711 
49712 	      // update group's range after centering the range elements
49713 	      updateRange(group, element);
49714 	    });
49715 
49716 	    if (idx && idx !== groups.length - 1) {
49717 	      groupsSize += rangeDiff(group.range);
49718 	    }
49719 	  });
49720 
49721 	  spaceInBetween = Math.abs(lastGroup.range.min - firstGroup.range.max);
49722 
49723 	  margin = Math.round((spaceInBetween - groupsSize) / (groups.length - 1));
49724 
49725 	  if (margin < groups.length - 1) {
49726 	    return;
49727 	  }
49728 
49729 	  forEach(groups, function(group, groupIdx) {
49730 	    var delta = {},
49731 	        prevGroup;
49732 
49733 	    if (group === firstGroup || group === lastGroup) {
49734 	      return;
49735 	    }
49736 
49737 	    prevGroup = groups[groupIdx - 1];
49738 
49739 	    group.range.max = 0;
49740 
49741 	    forEach(group.elements, function(element, idx) {
49742 	      delta[OFF_AXIS[axis]] = 0;
49743 	      delta[axis] = (prevGroup.range.max - element[axis]) + margin;
49744 
49745 	      if (group.range.min !== element[axis]) {
49746 	        delta[axis] += element[axis] - group.range.min;
49747 	      }
49748 
49749 	      if (delta[axis]) {
49750 	        modeling.moveElements([ element ], delta, element.parent);
49751 	      }
49752 
49753 	      group.range.max = Math.max(element[axis] + element[dimension], idx ? group.range.max : 0);
49754 	    });
49755 	  });
49756 	};
49757 
49758 	DistributeElements.prototype.postExecute = function(context) {
49759 
49760 	};
49761 
49762 	/**
49763 	 * A handler that implements reversible moving of shapes.
49764 	 */
49765 	function LayoutConnectionHandler(layouter, canvas) {
49766 	  this._layouter = layouter;
49767 	  this._canvas = canvas;
49768 	}
49769 
49770 	LayoutConnectionHandler.$inject = [ 'layouter', 'canvas' ];
49771 
49772 	LayoutConnectionHandler.prototype.execute = function(context) {
49773 
49774 	  var connection = context.connection;
49775 
49776 	  var oldWaypoints = connection.waypoints;
49777 
49778 	  assign(context, {
49779 	    oldWaypoints: oldWaypoints
49780 	  });
49781 
49782 	  connection.waypoints = this._layouter.layoutConnection(connection, context.hints);
49783 
49784 	  return connection;
49785 	};
49786 
49787 	LayoutConnectionHandler.prototype.revert = function(context) {
49788 
49789 	  var connection = context.connection;
49790 
49791 	  connection.waypoints = context.oldWaypoints;
49792 
49793 	  return connection;
49794 	};
49795 
49796 	/**
49797 	 * A handler that implements reversible moving of connections.
49798 	 *
49799 	 * The handler differs from the layout connection handler in a sense
49800 	 * that it preserves the connection layout.
49801 	 */
49802 	function MoveConnectionHandler() { }
49803 
49804 
49805 	MoveConnectionHandler.prototype.execute = function(context) {
49806 
49807 	  var connection = context.connection,
49808 	      delta = context.delta;
49809 
49810 	  var newParent = context.newParent || connection.parent,
49811 	      newParentIndex = context.newParentIndex,
49812 	      oldParent = connection.parent;
49813 
49814 	  // save old parent in context
49815 	  context.oldParent = oldParent;
49816 	  context.oldParentIndex = remove(oldParent.children, connection);
49817 
49818 	  // add to new parent at position
49819 	  add(newParent.children, connection, newParentIndex);
49820 
49821 	  // update parent
49822 	  connection.parent = newParent;
49823 
49824 	  // update waypoint positions
49825 	  forEach(connection.waypoints, function(p) {
49826 	    p.x += delta.x;
49827 	    p.y += delta.y;
49828 
49829 	    if (p.original) {
49830 	      p.original.x += delta.x;
49831 	      p.original.y += delta.y;
49832 	    }
49833 	  });
49834 
49835 	  return connection;
49836 	};
49837 
49838 	MoveConnectionHandler.prototype.revert = function(context) {
49839 
49840 	  var connection = context.connection,
49841 	      newParent = connection.parent,
49842 	      oldParent = context.oldParent,
49843 	      oldParentIndex = context.oldParentIndex,
49844 	      delta = context.delta;
49845 
49846 	  // remove from newParent
49847 	  remove(newParent.children, connection);
49848 
49849 	  // restore previous location in old parent
49850 	  add(oldParent.children, connection, oldParentIndex);
49851 
49852 	  // restore parent
49853 	  connection.parent = oldParent;
49854 
49855 	  // revert to old waypoint positions
49856 	  forEach(connection.waypoints, function(p) {
49857 	    p.x -= delta.x;
49858 	    p.y -= delta.y;
49859 
49860 	    if (p.original) {
49861 	      p.original.x -= delta.x;
49862 	      p.original.y -= delta.y;
49863 	    }
49864 	  });
49865 
49866 	  return connection;
49867 	};
49868 
49869 	function MoveClosure() {
49870 
49871 	  this.allShapes = {};
49872 	  this.allConnections = {};
49873 
49874 	  this.enclosedElements = {};
49875 	  this.enclosedConnections = {};
49876 
49877 	  this.topLevel = {};
49878 	}
49879 
49880 
49881 	MoveClosure.prototype.add = function(element, isTopLevel) {
49882 	  return this.addAll([ element ], isTopLevel);
49883 	};
49884 
49885 
49886 	MoveClosure.prototype.addAll = function(elements, isTopLevel) {
49887 
49888 	  var newClosure = getClosure(elements, !!isTopLevel, this);
49889 
49890 	  assign(this, newClosure);
49891 
49892 	  return this;
49893 	};
49894 
49895 	/**
49896 	 * A helper that is able to carry out serialized move
49897 	 * operations on multiple elements.
49898 	 *
49899 	 * @param {Modeling} modeling
49900 	 */
49901 	function MoveHelper(modeling) {
49902 	  this._modeling = modeling;
49903 	}
49904 
49905 	/**
49906 	 * Move the specified elements and all children by the given delta.
49907 	 *
49908 	 * This moves all enclosed connections, too and layouts all affected
49909 	 * external connections.
49910 	 *
49911 	 * @param  {Array<djs.model.Base>} elements
49912 	 * @param  {Point} delta
49913 	 * @param  {djs.model.Base} newParent applied to the first level of shapes
49914 	 *
49915 	 * @return {Array<djs.model.Base>} list of touched elements
49916 	 */
49917 	MoveHelper.prototype.moveRecursive = function(elements, delta, newParent) {
49918 	  if (!elements) {
49919 	    return [];
49920 	  } else {
49921 	    return this.moveClosure(this.getClosure(elements), delta, newParent);
49922 	  }
49923 	};
49924 
49925 	/**
49926 	 * Move the given closure of elmements.
49927 	 *
49928 	 * @param {Object} closure
49929 	 * @param {Point} delta
49930 	 * @param {djs.model.Base} [newParent]
49931 	 * @param {djs.model.Base} [newHost]
49932 	 */
49933 	MoveHelper.prototype.moveClosure = function(closure, delta, newParent, newHost, primaryShape) {
49934 	  var modeling = this._modeling;
49935 
49936 	  var allShapes = closure.allShapes,
49937 	      allConnections = closure.allConnections,
49938 	      enclosedConnections = closure.enclosedConnections,
49939 	      topLevel = closure.topLevel,
49940 	      keepParent = false;
49941 
49942 	  if (primaryShape && primaryShape.parent === newParent) {
49943 	    keepParent = true;
49944 	  }
49945 
49946 	  // move all shapes
49947 	  forEach(allShapes, function(shape) {
49948 
49949 	    // move the element according to the given delta
49950 	    modeling.moveShape(shape, delta, topLevel[shape.id] && !keepParent && newParent, {
49951 	      recurse: false,
49952 	      layout: false
49953 	    });
49954 	  });
49955 
49956 	  // move all child connections / layout external connections
49957 	  forEach(allConnections, function(c) {
49958 
49959 	    var sourceMoved = !!allShapes[c.source.id],
49960 	        targetMoved = !!allShapes[c.target.id];
49961 
49962 	    if (enclosedConnections[c.id] && sourceMoved && targetMoved) {
49963 	      modeling.moveConnection(c, delta, topLevel[c.id] && !keepParent && newParent);
49964 	    } else {
49965 	      modeling.layoutConnection(c, {
49966 	        connectionStart: sourceMoved && getMovedSourceAnchor(c, c.source, delta),
49967 	        connectionEnd: targetMoved && getMovedTargetAnchor(c, c.target, delta)
49968 	      });
49969 	    }
49970 	  });
49971 	};
49972 
49973 	/**
49974 	 * Returns the closure for the selected elements
49975 	 *
49976 	 * @param  {Array<djs.model.Base>} elements
49977 	 * @return {MoveClosure} closure
49978 	 */
49979 	MoveHelper.prototype.getClosure = function(elements) {
49980 	  return new MoveClosure().addAll(elements, true);
49981 	};
49982 
49983 	/**
49984 	 * A handler that implements reversible moving of shapes.
49985 	 */
49986 	function MoveElementsHandler(modeling) {
49987 	  this._helper = new MoveHelper(modeling);
49988 	}
49989 
49990 	MoveElementsHandler.$inject = [ 'modeling' ];
49991 
49992 	MoveElementsHandler.prototype.preExecute = function(context) {
49993 	  context.closure = this._helper.getClosure(context.shapes);
49994 	};
49995 
49996 	MoveElementsHandler.prototype.postExecute = function(context) {
49997 
49998 	  var hints = context.hints,
49999 	      primaryShape;
50000 
50001 	  if (hints && hints.primaryShape) {
50002 	    primaryShape = hints.primaryShape;
50003 	    hints.oldParent = primaryShape.parent;
50004 	  }
50005 
50006 	  this._helper.moveClosure(
50007 	    context.closure,
50008 	    context.delta,
50009 	    context.newParent,
50010 	    context.newHost,
50011 	    primaryShape
50012 	  );
50013 	};
50014 
50015 	/**
50016 	 * A handler that implements reversible moving of shapes.
50017 	 */
50018 	function MoveShapeHandler(modeling) {
50019 	  this._modeling = modeling;
50020 
50021 	  this._helper = new MoveHelper(modeling);
50022 	}
50023 
50024 	MoveShapeHandler.$inject = [ 'modeling' ];
50025 
50026 
50027 	MoveShapeHandler.prototype.execute = function(context) {
50028 
50029 	  var shape = context.shape,
50030 	      delta = context.delta,
50031 	      newParent = context.newParent || shape.parent,
50032 	      newParentIndex = context.newParentIndex,
50033 	      oldParent = shape.parent;
50034 
50035 	  context.oldBounds = pick(shape, [ 'x', 'y', 'width', 'height']);
50036 
50037 	  // save old parent in context
50038 	  context.oldParent = oldParent;
50039 	  context.oldParentIndex = remove(oldParent.children, shape);
50040 
50041 	  // add to new parent at position
50042 	  add(newParent.children, shape, newParentIndex);
50043 
50044 	  // update shape parent + position
50045 	  assign(shape, {
50046 	    parent: newParent,
50047 	    x: shape.x + delta.x,
50048 	    y: shape.y + delta.y
50049 	  });
50050 
50051 	  return shape;
50052 	};
50053 
50054 	MoveShapeHandler.prototype.postExecute = function(context) {
50055 
50056 	  var shape = context.shape,
50057 	      delta = context.delta,
50058 	      hints = context.hints;
50059 
50060 	  var modeling = this._modeling;
50061 
50062 	  if (hints.layout !== false) {
50063 
50064 	    forEach(shape.incoming, function(c) {
50065 	      modeling.layoutConnection(c, {
50066 	        connectionEnd: getMovedTargetAnchor(c, shape, delta)
50067 	      });
50068 	    });
50069 
50070 	    forEach(shape.outgoing, function(c) {
50071 	      modeling.layoutConnection(c, {
50072 	        connectionStart: getMovedSourceAnchor(c, shape, delta)
50073 	      });
50074 	    });
50075 	  }
50076 
50077 	  if (hints.recurse !== false) {
50078 	    this.moveChildren(context);
50079 	  }
50080 	};
50081 
50082 	MoveShapeHandler.prototype.revert = function(context) {
50083 
50084 	  var shape = context.shape,
50085 	      oldParent = context.oldParent,
50086 	      oldParentIndex = context.oldParentIndex,
50087 	      delta = context.delta;
50088 
50089 	  // restore previous location in old parent
50090 	  add(oldParent.children, shape, oldParentIndex);
50091 
50092 	  // revert to old position and parent
50093 	  assign(shape, {
50094 	    parent: oldParent,
50095 	    x: shape.x - delta.x,
50096 	    y: shape.y - delta.y
50097 	  });
50098 
50099 	  return shape;
50100 	};
50101 
50102 	MoveShapeHandler.prototype.moveChildren = function(context) {
50103 
50104 	  var delta = context.delta,
50105 	      shape = context.shape;
50106 
50107 	  this._helper.moveRecursive(shape.children, delta, null);
50108 	};
50109 
50110 	MoveShapeHandler.prototype.getNewParent = function(context) {
50111 	  return context.newParent || context.shape.parent;
50112 	};
50113 
50114 	/**
50115 	 * Reconnect connection handler
50116 	 */
50117 	function ReconnectConnectionHandler(modeling) {
50118 	  this._modeling = modeling;
50119 	}
50120 
50121 	ReconnectConnectionHandler.$inject = [ 'modeling' ];
50122 
50123 	ReconnectConnectionHandler.prototype.execute = function(context) {
50124 	  var newSource = context.newSource,
50125 	      newTarget = context.newTarget,
50126 	      connection = context.connection,
50127 	      dockingOrPoints = context.dockingOrPoints;
50128 
50129 	  if (!newSource && !newTarget) {
50130 	    throw new Error('newSource or newTarget required');
50131 	  }
50132 
50133 	  if (isArray$2(dockingOrPoints)) {
50134 	    context.oldWaypoints = connection.waypoints;
50135 	    connection.waypoints = dockingOrPoints;
50136 	  }
50137 
50138 	  if (newSource) {
50139 	    context.oldSource = connection.source;
50140 	    connection.source = newSource;
50141 	  }
50142 
50143 	  if (newTarget) {
50144 	    context.oldTarget = connection.target;
50145 	    connection.target = newTarget;
50146 	  }
50147 
50148 	  return connection;
50149 	};
50150 
50151 	ReconnectConnectionHandler.prototype.postExecute = function(context) {
50152 	  var connection = context.connection,
50153 	      newSource = context.newSource,
50154 	      newTarget = context.newTarget,
50155 	      dockingOrPoints = context.dockingOrPoints,
50156 	      hints = context.hints || {};
50157 
50158 	  var layoutConnectionHints = {};
50159 
50160 	  if (hints.connectionStart) {
50161 	    layoutConnectionHints.connectionStart = hints.connectionStart;
50162 	  }
50163 
50164 	  if (hints.connectionEnd) {
50165 	    layoutConnectionHints.connectionEnd = hints.connectionEnd;
50166 	  }
50167 
50168 	  if (hints.layoutConnection === false) {
50169 	    return;
50170 	  }
50171 
50172 	  if (newSource && (!newTarget || hints.docking === 'source')) {
50173 	    layoutConnectionHints.connectionStart = layoutConnectionHints.connectionStart
50174 	      || getDocking(isArray$2(dockingOrPoints) ? dockingOrPoints[ 0 ] : dockingOrPoints);
50175 	  }
50176 
50177 	  if (newTarget && (!newSource || hints.docking === 'target')) {
50178 	    layoutConnectionHints.connectionEnd = layoutConnectionHints.connectionEnd
50179 	      || getDocking(isArray$2(dockingOrPoints) ? dockingOrPoints[ dockingOrPoints.length - 1 ] : dockingOrPoints);
50180 	  }
50181 
50182 	  if (hints.newWaypoints) {
50183 	    layoutConnectionHints.waypoints = hints.newWaypoints;
50184 	  }
50185 
50186 	  this._modeling.layoutConnection(connection, layoutConnectionHints);
50187 	};
50188 
50189 	ReconnectConnectionHandler.prototype.revert = function(context) {
50190 	  var oldSource = context.oldSource,
50191 	      oldTarget = context.oldTarget,
50192 	      oldWaypoints = context.oldWaypoints,
50193 	      connection = context.connection;
50194 
50195 	  if (oldSource) {
50196 	    connection.source = oldSource;
50197 	  }
50198 
50199 	  if (oldTarget) {
50200 	    connection.target = oldTarget;
50201 	  }
50202 
50203 	  if (oldWaypoints) {
50204 	    connection.waypoints = oldWaypoints;
50205 	  }
50206 
50207 	  return connection;
50208 	};
50209 
50210 
50211 
50212 	// helpers //////////
50213 
50214 	function getDocking(point) {
50215 	  return point.original || point;
50216 	}
50217 
50218 	/**
50219 	 * Replace shape by adding new shape and removing old shape. Incoming and outgoing connections will
50220 	 * be kept if possible.
50221 	 *
50222 	 * @class
50223 	 * @constructor
50224 	 *
50225 	 * @param {Modeling} modeling
50226 	 * @param {Rules} rules
50227 	 */
50228 	function ReplaceShapeHandler(modeling, rules) {
50229 	  this._modeling = modeling;
50230 	  this._rules = rules;
50231 	}
50232 
50233 	ReplaceShapeHandler.$inject = [ 'modeling', 'rules' ];
50234 
50235 
50236 	/**
50237 	 * Add new shape.
50238 	 *
50239 	 * @param {Object} context
50240 	 * @param {djs.model.Shape} context.oldShape
50241 	 * @param {Object} context.newData
50242 	 * @param {string} context.newData.type
50243 	 * @param {number} context.newData.x
50244 	 * @param {number} context.newData.y
50245 	 * @param {Object} [hints]
50246 	 */
50247 	ReplaceShapeHandler.prototype.preExecute = function(context) {
50248 	  var self = this,
50249 	      modeling = this._modeling,
50250 	      rules = this._rules;
50251 
50252 	  var oldShape = context.oldShape,
50253 	      newData = context.newData,
50254 	      hints = context.hints || {},
50255 	      newShape;
50256 
50257 	  function canReconnect(source, target, connection) {
50258 	    return rules.allowed('connection.reconnect', {
50259 	      connection: connection,
50260 	      source: source,
50261 	      target: target
50262 	    });
50263 	  }
50264 
50265 	  // (1) add new shape at given position
50266 	  var position = {
50267 	    x: newData.x,
50268 	    y: newData.y
50269 	  };
50270 
50271 	  var oldBounds = {
50272 	    x: oldShape.x,
50273 	    y: oldShape.y,
50274 	    width: oldShape.width,
50275 	    height: oldShape.height
50276 	  };
50277 
50278 	  newShape = context.newShape =
50279 	    context.newShape ||
50280 	    self.createShape(newData, position, oldShape.parent, hints);
50281 
50282 	  // (2) update host
50283 	  if (oldShape.host) {
50284 	    modeling.updateAttachment(newShape, oldShape.host);
50285 	  }
50286 
50287 	  // (3) adopt all children from old shape
50288 	  var children;
50289 
50290 	  if (hints.moveChildren !== false) {
50291 	    children = oldShape.children.slice();
50292 
50293 	    modeling.moveElements(children, { x: 0, y: 0 }, newShape, hints);
50294 	  }
50295 
50296 	  // (4) reconnect connections to new shape if possible
50297 	  var incoming = oldShape.incoming.slice(),
50298 	      outgoing = oldShape.outgoing.slice();
50299 
50300 	  forEach(incoming, function(connection) {
50301 	    var source = connection.source,
50302 	        allowed = canReconnect(source, newShape, connection);
50303 
50304 	    if (allowed) {
50305 	      self.reconnectEnd(
50306 	        connection, newShape,
50307 	        getResizedTargetAnchor(connection, newShape, oldBounds),
50308 	        hints
50309 	      );
50310 	    }
50311 	  });
50312 
50313 	  forEach(outgoing, function(connection) {
50314 	    var target = connection.target,
50315 	        allowed = canReconnect(newShape, target, connection);
50316 
50317 	    if (allowed) {
50318 	      self.reconnectStart(
50319 	        connection, newShape,
50320 	        getResizedSourceAnchor(connection, newShape, oldBounds),
50321 	        hints
50322 	      );
50323 	    }
50324 	  });
50325 	};
50326 
50327 
50328 	/**
50329 	 * Remove old shape.
50330 	 */
50331 	ReplaceShapeHandler.prototype.postExecute = function(context) {
50332 	  var oldShape = context.oldShape;
50333 
50334 	  this._modeling.removeShape(oldShape);
50335 	};
50336 
50337 
50338 	ReplaceShapeHandler.prototype.execute = function(context) {};
50339 
50340 
50341 	ReplaceShapeHandler.prototype.revert = function(context) {};
50342 
50343 
50344 	ReplaceShapeHandler.prototype.createShape = function(shape, position, target, hints) {
50345 	  return this._modeling.createShape(shape, position, target, hints);
50346 	};
50347 
50348 
50349 	ReplaceShapeHandler.prototype.reconnectStart = function(connection, newSource, dockingPoint, hints) {
50350 	  this._modeling.reconnectStart(connection, newSource, dockingPoint, hints);
50351 	};
50352 
50353 
50354 	ReplaceShapeHandler.prototype.reconnectEnd = function(connection, newTarget, dockingPoint, hints) {
50355 	  this._modeling.reconnectEnd(connection, newTarget, dockingPoint, hints);
50356 	};
50357 
50358 	/**
50359 	 * A handler that implements reversible resizing of shapes.
50360 	 *
50361 	 * @param {Modeling} modeling
50362 	 */
50363 	function ResizeShapeHandler(modeling) {
50364 	  this._modeling = modeling;
50365 	}
50366 
50367 	ResizeShapeHandler.$inject = [ 'modeling' ];
50368 
50369 	/**
50370 	 * {
50371 	 *   shape: {....}
50372 	 *   newBounds: {
50373 	 *     width:  20,
50374 	 *     height: 40,
50375 	 *     x:       5,
50376 	 *     y:      10
50377 	 *   }
50378 	 *
50379 	 * }
50380 	 */
50381 	ResizeShapeHandler.prototype.execute = function(context) {
50382 	  var shape = context.shape,
50383 	      newBounds = context.newBounds,
50384 	      minBounds = context.minBounds;
50385 
50386 	  if (newBounds.x === undefined || newBounds.y === undefined ||
50387 	      newBounds.width === undefined || newBounds.height === undefined) {
50388 	    throw new Error('newBounds must have {x, y, width, height} properties');
50389 	  }
50390 
50391 	  if (minBounds && (newBounds.width < minBounds.width
50392 	    || newBounds.height < minBounds.height)) {
50393 	    throw new Error('width and height cannot be less than minimum height and width');
50394 	  } else if (!minBounds
50395 	    && newBounds.width < 10 || newBounds.height < 10) {
50396 	    throw new Error('width and height cannot be less than 10px');
50397 	  }
50398 
50399 	  // save old bbox in context
50400 	  context.oldBounds = {
50401 	    width:  shape.width,
50402 	    height: shape.height,
50403 	    x:      shape.x,
50404 	    y:      shape.y
50405 	  };
50406 
50407 	  // update shape
50408 	  assign(shape, {
50409 	    width:  newBounds.width,
50410 	    height: newBounds.height,
50411 	    x:      newBounds.x,
50412 	    y:      newBounds.y
50413 	  });
50414 
50415 	  return shape;
50416 	};
50417 
50418 	ResizeShapeHandler.prototype.postExecute = function(context) {
50419 	  var modeling = this._modeling;
50420 
50421 	  var shape = context.shape,
50422 	      oldBounds = context.oldBounds,
50423 	      hints = context.hints || {};
50424 
50425 	  if (hints.layout === false) {
50426 	    return;
50427 	  }
50428 
50429 	  forEach(shape.incoming, function(c) {
50430 	    modeling.layoutConnection(c, {
50431 	      connectionEnd: getResizedTargetAnchor(c, shape, oldBounds)
50432 	    });
50433 	  });
50434 
50435 	  forEach(shape.outgoing, function(c) {
50436 	    modeling.layoutConnection(c, {
50437 	      connectionStart: getResizedSourceAnchor(c, shape, oldBounds)
50438 	    });
50439 	  });
50440 
50441 	};
50442 
50443 	ResizeShapeHandler.prototype.revert = function(context) {
50444 
50445 	  var shape = context.shape,
50446 	      oldBounds = context.oldBounds;
50447 
50448 	  // restore previous bbox
50449 	  assign(shape, {
50450 	    width:  oldBounds.width,
50451 	    height: oldBounds.height,
50452 	    x:      oldBounds.x,
50453 	    y:      oldBounds.y
50454 	  });
50455 
50456 	  return shape;
50457 	};
50458 
50459 	/**
50460 	 * Add or remove space by moving and resizing shapes and updating connection waypoints.
50461 	 */
50462 	function SpaceToolHandler(modeling) {
50463 	  this._modeling = modeling;
50464 	}
50465 
50466 	SpaceToolHandler.$inject = [ 'modeling' ];
50467 
50468 	SpaceToolHandler.prototype.preExecute = function(context) {
50469 	  var delta = context.delta,
50470 	      direction = context.direction,
50471 	      movingShapes = context.movingShapes,
50472 	      resizingShapes = context.resizingShapes,
50473 	      start = context.start,
50474 	      oldBounds = {};
50475 
50476 	  // (1) move shapes
50477 	  this.moveShapes(movingShapes, delta);
50478 
50479 	  // (2a) save old bounds of resized shapes
50480 	  forEach(resizingShapes, function(shape) {
50481 	    oldBounds[shape.id] = getBounds(shape);
50482 	  });
50483 
50484 	  // (2b) resize shapes
50485 	  this.resizeShapes(resizingShapes, delta, direction);
50486 
50487 	  // (3) update connection waypoints
50488 	  this.updateConnectionWaypoints(
50489 	    getWaypointsUpdatingConnections(movingShapes, resizingShapes),
50490 	    delta,
50491 	    direction,
50492 	    start,
50493 	    movingShapes,
50494 	    resizingShapes,
50495 	    oldBounds
50496 	  );
50497 	};
50498 
50499 	SpaceToolHandler.prototype.execute = function() {};
50500 	SpaceToolHandler.prototype.revert = function() {};
50501 
50502 	SpaceToolHandler.prototype.moveShapes = function(shapes, delta) {
50503 	  var self = this;
50504 
50505 	  forEach(shapes, function(element) {
50506 	    self._modeling.moveShape(element, delta, null, {
50507 	      autoResize: false,
50508 	      layout: false,
50509 	      recurse: false
50510 	    });
50511 	  });
50512 	};
50513 
50514 	SpaceToolHandler.prototype.resizeShapes = function(shapes, delta, direction) {
50515 	  var self = this;
50516 
50517 	  forEach(shapes, function(shape) {
50518 	    var newBounds = resizeBounds(shape, direction, delta);
50519 
50520 	    self._modeling.resizeShape(shape, newBounds, null, {
50521 	      attachSupport: false,
50522 	      autoResize: false,
50523 	      layout: false
50524 	    });
50525 	  });
50526 	};
50527 
50528 	/**
50529 	 * Update connections waypoints according to the rules:
50530 	 *   1. Both source and target are moved/resized => move waypoints by the delta
50531 	 *   2. Only one of source and target is moved/resized => re-layout connection with moved start/end
50532 	 */
50533 	SpaceToolHandler.prototype.updateConnectionWaypoints = function(
50534 	    connections,
50535 	    delta,
50536 	    direction,
50537 	    start,
50538 	    movingShapes,
50539 	    resizingShapes,
50540 	    oldBounds
50541 	) {
50542 	  var self = this,
50543 	      affectedShapes = movingShapes.concat(resizingShapes);
50544 
50545 	  forEach(connections, function(connection) {
50546 	    var source = connection.source,
50547 	        target = connection.target,
50548 	        waypoints = copyWaypoints(connection),
50549 	        axis = getAxisFromDirection(direction),
50550 	        layoutHints = {
50551 	          labelBehavior: false
50552 	        };
50553 
50554 	    if (includes$1(affectedShapes, source) && includes$1(affectedShapes, target)) {
50555 
50556 	      // move waypoints
50557 	      waypoints = map$1(waypoints, function(waypoint) {
50558 	        if (shouldMoveWaypoint(waypoint, start, direction)) {
50559 
50560 	          // move waypoint
50561 	          waypoint[ axis ] = waypoint[ axis ] + delta[ axis ];
50562 	        }
50563 
50564 	        if (waypoint.original && shouldMoveWaypoint(waypoint.original, start, direction)) {
50565 
50566 	          // move waypoint original
50567 	          waypoint.original[ axis ] = waypoint.original[ axis ] + delta[ axis ];
50568 	        }
50569 
50570 	        return waypoint;
50571 	      });
50572 
50573 	      self._modeling.updateWaypoints(connection, waypoints, {
50574 	        labelBehavior: false
50575 	      });
50576 	    } else if (includes$1(affectedShapes, source) || includes$1(affectedShapes, target)) {
50577 
50578 	      // re-layout connection with moved start/end
50579 	      if (includes$1(movingShapes, source)) {
50580 	        layoutHints.connectionStart = getMovedSourceAnchor(connection, source, delta);
50581 	      } else if (includes$1(movingShapes, target)) {
50582 	        layoutHints.connectionEnd = getMovedTargetAnchor(connection, target, delta);
50583 	      } else if (includes$1(resizingShapes, source)) {
50584 	        layoutHints.connectionStart = getResizedSourceAnchor(
50585 	          connection, source, oldBounds[source.id]
50586 	        );
50587 	      } else if (includes$1(resizingShapes, target)) {
50588 	        layoutHints.connectionEnd = getResizedTargetAnchor(
50589 	          connection, target, oldBounds[target.id]
50590 	        );
50591 	      }
50592 
50593 	      self._modeling.layoutConnection(connection, layoutHints);
50594 	    }
50595 	  });
50596 	};
50597 
50598 
50599 	// helpers //////////
50600 
50601 	function copyWaypoint(waypoint) {
50602 	  return assign({}, waypoint);
50603 	}
50604 
50605 	function copyWaypoints(connection) {
50606 	  return map$1(connection.waypoints, function(waypoint) {
50607 
50608 	    waypoint = copyWaypoint(waypoint);
50609 
50610 	    if (waypoint.original) {
50611 	      waypoint.original = copyWaypoint(waypoint.original);
50612 	    }
50613 
50614 	    return waypoint;
50615 	  });
50616 	}
50617 
50618 	function getAxisFromDirection(direction) {
50619 	  switch (direction) {
50620 	  case 'n':
50621 	    return 'y';
50622 	  case 'w':
50623 	    return 'x';
50624 	  case 's':
50625 	    return 'y';
50626 	  case 'e':
50627 	    return 'x';
50628 	  }
50629 	}
50630 
50631 	function shouldMoveWaypoint(waypoint, start, direction) {
50632 	  var relevantAxis = getAxisFromDirection(direction);
50633 
50634 	  if (/e|s/.test(direction)) {
50635 	    return waypoint[ relevantAxis ] > start;
50636 	  } else if (/n|w/.test(direction)) {
50637 	    return waypoint[ relevantAxis ] < start;
50638 	  }
50639 	}
50640 
50641 	function includes$1(array, item) {
50642 	  return array.indexOf(item) !== -1;
50643 	}
50644 
50645 	function getBounds(shape) {
50646 	  return {
50647 	    x: shape.x,
50648 	    y: shape.y,
50649 	    height: shape.height,
50650 	    width: shape.width
50651 	  };
50652 	}
50653 
50654 	/**
50655 	 * A handler that toggles the collapsed state of an element
50656 	 * and the visibility of all its children.
50657 	 *
50658 	 * @param {Modeling} modeling
50659 	 */
50660 	function ToggleShapeCollapseHandler(modeling) {
50661 	  this._modeling = modeling;
50662 	}
50663 
50664 	ToggleShapeCollapseHandler.$inject = [ 'modeling' ];
50665 
50666 
50667 	ToggleShapeCollapseHandler.prototype.execute = function(context) {
50668 
50669 	  var shape = context.shape,
50670 	      children = shape.children;
50671 
50672 	  // recursively remember previous visibility of children
50673 	  context.oldChildrenVisibility = getElementsVisibilityRecursive(children);
50674 
50675 	  // toggle state
50676 	  shape.collapsed = !shape.collapsed;
50677 
50678 	  // recursively hide/show children
50679 	  var result = setHiddenRecursive(children, shape.collapsed);
50680 
50681 	  return [shape].concat(result);
50682 	};
50683 
50684 
50685 	ToggleShapeCollapseHandler.prototype.revert = function(context) {
50686 
50687 	  var shape = context.shape,
50688 	      oldChildrenVisibility = context.oldChildrenVisibility;
50689 
50690 	  var children = shape.children;
50691 
50692 	  // recursively set old visability of children
50693 	  var result = restoreVisibilityRecursive(children, oldChildrenVisibility);
50694 
50695 	  // retoggle state
50696 	  shape.collapsed = !shape.collapsed;
50697 
50698 	  return [shape].concat(result);
50699 	};
50700 
50701 
50702 	// helpers //////////////////////
50703 
50704 	/**
50705 	 * Return a map { elementId -> hiddenState}.
50706 	 *
50707 	 * @param {Array<djs.model.Shape>} elements
50708 	 *
50709 	 * @return {Object}
50710 	 */
50711 	function getElementsVisibilityRecursive(elements) {
50712 
50713 	  var result = {};
50714 
50715 	  forEach(elements, function(element) {
50716 	    result[element.id] = element.hidden;
50717 
50718 	    if (element.children) {
50719 	      result = assign({}, result, getElementsVisibilityRecursive(element.children));
50720 	    }
50721 	  });
50722 
50723 	  return result;
50724 	}
50725 
50726 
50727 	function setHiddenRecursive(elements, newHidden) {
50728 	  var result = [];
50729 	  forEach(elements, function(element) {
50730 	    element.hidden = newHidden;
50731 
50732 	    result = result.concat(element);
50733 
50734 	    if (element.children) {
50735 	      result = result.concat(setHiddenRecursive(element.children, element.collapsed || newHidden));
50736 	    }
50737 	  });
50738 
50739 	  return result;
50740 	}
50741 
50742 	function restoreVisibilityRecursive(elements, lastState) {
50743 	  var result = [];
50744 	  forEach(elements, function(element) {
50745 	    element.hidden = lastState[element.id];
50746 
50747 	    result = result.concat(element);
50748 
50749 	    if (element.children) {
50750 	      result = result.concat(restoreVisibilityRecursive(element.children, lastState));
50751 	    }
50752 	  });
50753 
50754 	  return result;
50755 	}
50756 
50757 	/**
50758 	 * A handler that implements reversible attaching/detaching of shapes.
50759 	 */
50760 	function UpdateAttachmentHandler(modeling) {
50761 	  this._modeling = modeling;
50762 	}
50763 
50764 	UpdateAttachmentHandler.$inject = [ 'modeling' ];
50765 
50766 
50767 	UpdateAttachmentHandler.prototype.execute = function(context) {
50768 	  var shape = context.shape,
50769 	      newHost = context.newHost,
50770 	      oldHost = shape.host;
50771 
50772 	  // (0) detach from old host
50773 	  context.oldHost = oldHost;
50774 	  context.attacherIdx = removeAttacher(oldHost, shape);
50775 
50776 	  // (1) attach to new host
50777 	  addAttacher(newHost, shape);
50778 
50779 	  // (2) update host
50780 	  shape.host = newHost;
50781 
50782 	  return shape;
50783 	};
50784 
50785 	UpdateAttachmentHandler.prototype.revert = function(context) {
50786 	  var shape = context.shape,
50787 	      newHost = context.newHost,
50788 	      oldHost = context.oldHost,
50789 	      attacherIdx = context.attacherIdx;
50790 
50791 	  // (2) update host
50792 	  shape.host = oldHost;
50793 
50794 	  // (1) attach to new host
50795 	  removeAttacher(newHost, shape);
50796 
50797 	  // (0) detach from old host
50798 	  addAttacher(oldHost, shape, attacherIdx);
50799 
50800 	  return shape;
50801 	};
50802 
50803 
50804 	function removeAttacher(host, attacher) {
50805 
50806 	  // remove attacher from host
50807 	  return remove(host && host.attachers, attacher);
50808 	}
50809 
50810 	function addAttacher(host, attacher, idx) {
50811 
50812 	  if (!host) {
50813 	    return;
50814 	  }
50815 
50816 	  var attachers = host.attachers;
50817 
50818 	  if (!attachers) {
50819 	    host.attachers = attachers = [];
50820 	  }
50821 
50822 	  add(attachers, attacher, idx);
50823 	}
50824 
50825 	function UpdateWaypointsHandler() { }
50826 
50827 	UpdateWaypointsHandler.prototype.execute = function(context) {
50828 
50829 	  var connection = context.connection,
50830 	      newWaypoints = context.newWaypoints;
50831 
50832 	  context.oldWaypoints = connection.waypoints;
50833 
50834 	  connection.waypoints = newWaypoints;
50835 
50836 	  return connection;
50837 	};
50838 
50839 	UpdateWaypointsHandler.prototype.revert = function(context) {
50840 
50841 	  var connection = context.connection,
50842 	      oldWaypoints = context.oldWaypoints;
50843 
50844 	  connection.waypoints = oldWaypoints;
50845 
50846 	  return connection;
50847 	};
50848 
50849 	/**
50850 	 * The basic modeling entry point.
50851 	 *
50852 	 * @param {EventBus} eventBus
50853 	 * @param {ElementFactory} elementFactory
50854 	 * @param {CommandStack} commandStack
50855 	 */
50856 	function Modeling$1(eventBus, elementFactory, commandStack) {
50857 	  this._eventBus = eventBus;
50858 	  this._elementFactory = elementFactory;
50859 	  this._commandStack = commandStack;
50860 
50861 	  var self = this;
50862 
50863 	  eventBus.on('diagram.init', function() {
50864 
50865 	    // register modeling handlers
50866 	    self.registerHandlers(commandStack);
50867 	  });
50868 	}
50869 
50870 	Modeling$1.$inject = [ 'eventBus', 'elementFactory', 'commandStack' ];
50871 
50872 
50873 	Modeling$1.prototype.getHandlers = function() {
50874 	  return {
50875 	    'shape.append': AppendShapeHandler,
50876 	    'shape.create': CreateShapeHandler,
50877 	    'shape.delete': DeleteShapeHandler,
50878 	    'shape.move': MoveShapeHandler,
50879 	    'shape.resize': ResizeShapeHandler,
50880 	    'shape.replace': ReplaceShapeHandler,
50881 	    'shape.toggleCollapse': ToggleShapeCollapseHandler,
50882 
50883 	    'spaceTool': SpaceToolHandler,
50884 
50885 	    'label.create': CreateLabelHandler,
50886 
50887 	    'connection.create': CreateConnectionHandler,
50888 	    'connection.delete': DeleteConnectionHandler,
50889 	    'connection.move': MoveConnectionHandler,
50890 	    'connection.layout': LayoutConnectionHandler,
50891 
50892 	    'connection.updateWaypoints': UpdateWaypointsHandler,
50893 
50894 	    'connection.reconnect': ReconnectConnectionHandler,
50895 
50896 	    'elements.create': CreateElementsHandler,
50897 	    'elements.move': MoveElementsHandler,
50898 	    'elements.delete': DeleteElementsHandler,
50899 
50900 	    'elements.distribute': DistributeElements,
50901 	    'elements.align': AlignElements,
50902 
50903 	    'element.updateAttachment': UpdateAttachmentHandler
50904 	  };
50905 	};
50906 
50907 	/**
50908 	 * Register handlers with the command stack
50909 	 *
50910 	 * @param {CommandStack} commandStack
50911 	 */
50912 	Modeling$1.prototype.registerHandlers = function(commandStack) {
50913 	  forEach(this.getHandlers(), function(handler, id) {
50914 	    commandStack.registerHandler(id, handler);
50915 	  });
50916 	};
50917 
50918 
50919 	// modeling helpers //////////////////////
50920 
50921 	Modeling$1.prototype.moveShape = function(shape, delta, newParent, newParentIndex, hints) {
50922 
50923 	  if (typeof newParentIndex === 'object') {
50924 	    hints = newParentIndex;
50925 	    newParentIndex = null;
50926 	  }
50927 
50928 	  var context = {
50929 	    shape: shape,
50930 	    delta:  delta,
50931 	    newParent: newParent,
50932 	    newParentIndex: newParentIndex,
50933 	    hints: hints || {}
50934 	  };
50935 
50936 	  this._commandStack.execute('shape.move', context);
50937 	};
50938 
50939 
50940 	/**
50941 	 * Update the attachment of the given shape.
50942 	 *
50943 	 * @param {djs.mode.Base} shape
50944 	 * @param {djs.model.Base} [newHost]
50945 	 */
50946 	Modeling$1.prototype.updateAttachment = function(shape, newHost) {
50947 	  var context = {
50948 	    shape: shape,
50949 	    newHost: newHost
50950 	  };
50951 
50952 	  this._commandStack.execute('element.updateAttachment', context);
50953 	};
50954 
50955 
50956 	/**
50957 	 * Move a number of shapes to a new target, either setting it as
50958 	 * the new parent or attaching it.
50959 	 *
50960 	 * @param {Array<djs.mode.Base>} shapes
50961 	 * @param {Point} delta
50962 	 * @param {djs.model.Base} [target]
50963 	 * @param {Object} [hints]
50964 	 * @param {boolean} [hints.attach=false]
50965 	 */
50966 	Modeling$1.prototype.moveElements = function(shapes, delta, target, hints) {
50967 
50968 	  hints = hints || {};
50969 
50970 	  var attach = hints.attach;
50971 
50972 	  var newParent = target,
50973 	      newHost;
50974 
50975 	  if (attach === true) {
50976 	    newHost = target;
50977 	    newParent = target.parent;
50978 	  } else
50979 
50980 	  if (attach === false) {
50981 	    newHost = null;
50982 	  }
50983 
50984 	  var context = {
50985 	    shapes: shapes,
50986 	    delta: delta,
50987 	    newParent: newParent,
50988 	    newHost: newHost,
50989 	    hints: hints
50990 	  };
50991 
50992 	  this._commandStack.execute('elements.move', context);
50993 	};
50994 
50995 
50996 	Modeling$1.prototype.moveConnection = function(connection, delta, newParent, newParentIndex, hints) {
50997 
50998 	  if (typeof newParentIndex === 'object') {
50999 	    hints = newParentIndex;
51000 	    newParentIndex = undefined;
51001 	  }
51002 
51003 	  var context = {
51004 	    connection: connection,
51005 	    delta: delta,
51006 	    newParent: newParent,
51007 	    newParentIndex: newParentIndex,
51008 	    hints: hints || {}
51009 	  };
51010 
51011 	  this._commandStack.execute('connection.move', context);
51012 	};
51013 
51014 
51015 	Modeling$1.prototype.layoutConnection = function(connection, hints) {
51016 	  var context = {
51017 	    connection: connection,
51018 	    hints: hints || {}
51019 	  };
51020 
51021 	  this._commandStack.execute('connection.layout', context);
51022 	};
51023 
51024 
51025 	/**
51026 	 * Create connection.
51027 	 *
51028 	 * @param {djs.model.Base} source
51029 	 * @param {djs.model.Base} target
51030 	 * @param {number} [parentIndex]
51031 	 * @param {Object|djs.model.Connection} connection
51032 	 * @param {djs.model.Base} parent
51033 	 * @param {Object} hints
51034 	 *
51035 	 * @return {djs.model.Connection} the created connection.
51036 	 */
51037 	Modeling$1.prototype.createConnection = function(source, target, parentIndex, connection, parent, hints) {
51038 
51039 	  if (typeof parentIndex === 'object') {
51040 	    hints = parent;
51041 	    parent = connection;
51042 	    connection = parentIndex;
51043 	    parentIndex = undefined;
51044 	  }
51045 
51046 	  connection = this._create('connection', connection);
51047 
51048 	  var context = {
51049 	    source: source,
51050 	    target: target,
51051 	    parent: parent,
51052 	    parentIndex: parentIndex,
51053 	    connection: connection,
51054 	    hints: hints
51055 	  };
51056 
51057 	  this._commandStack.execute('connection.create', context);
51058 
51059 	  return context.connection;
51060 	};
51061 
51062 
51063 	/**
51064 	 * Create a shape at the specified position.
51065 	 *
51066 	 * @param {djs.model.Shape|Object} shape
51067 	 * @param {Point} position
51068 	 * @param {djs.model.Shape|djs.model.Root} target
51069 	 * @param {number} [parentIndex] position in parents children list
51070 	 * @param {Object} [hints]
51071 	 * @param {boolean} [hints.attach] whether to attach to target or become a child
51072 	 *
51073 	 * @return {djs.model.Shape} the created shape
51074 	 */
51075 	Modeling$1.prototype.createShape = function(shape, position, target, parentIndex, hints) {
51076 
51077 	  if (typeof parentIndex !== 'number') {
51078 	    hints = parentIndex;
51079 	    parentIndex = undefined;
51080 	  }
51081 
51082 	  hints = hints || {};
51083 
51084 	  var attach = hints.attach,
51085 	      parent,
51086 	      host;
51087 
51088 	  shape = this._create('shape', shape);
51089 
51090 	  if (attach) {
51091 	    parent = target.parent;
51092 	    host = target;
51093 	  } else {
51094 	    parent = target;
51095 	  }
51096 
51097 	  var context = {
51098 	    position: position,
51099 	    shape: shape,
51100 	    parent: parent,
51101 	    parentIndex: parentIndex,
51102 	    host: host,
51103 	    hints: hints
51104 	  };
51105 
51106 	  this._commandStack.execute('shape.create', context);
51107 
51108 	  return context.shape;
51109 	};
51110 
51111 
51112 	Modeling$1.prototype.createElements = function(elements, position, parent, parentIndex, hints) {
51113 	  if (!isArray$2(elements)) {
51114 	    elements = [ elements ];
51115 	  }
51116 
51117 	  if (typeof parentIndex !== 'number') {
51118 	    hints = parentIndex;
51119 	    parentIndex = undefined;
51120 	  }
51121 
51122 	  hints = hints || {};
51123 
51124 	  var context = {
51125 	    position: position,
51126 	    elements: elements,
51127 	    parent: parent,
51128 	    parentIndex: parentIndex,
51129 	    hints: hints
51130 	  };
51131 
51132 	  this._commandStack.execute('elements.create', context);
51133 
51134 	  return context.elements;
51135 	};
51136 
51137 
51138 	Modeling$1.prototype.createLabel = function(labelTarget, position, label, parent) {
51139 
51140 	  label = this._create('label', label);
51141 
51142 	  var context = {
51143 	    labelTarget: labelTarget,
51144 	    position: position,
51145 	    parent: parent || labelTarget.parent,
51146 	    shape: label
51147 	  };
51148 
51149 	  this._commandStack.execute('label.create', context);
51150 
51151 	  return context.shape;
51152 	};
51153 
51154 
51155 	/**
51156 	 * Append shape to given source, drawing a connection
51157 	 * between source and the newly created shape.
51158 	 *
51159 	 * @param {djs.model.Shape} source
51160 	 * @param {djs.model.Shape|Object} shape
51161 	 * @param {Point} position
51162 	 * @param {djs.model.Shape} target
51163 	 * @param {Object} [hints]
51164 	 * @param {boolean} [hints.attach]
51165 	 * @param {djs.model.Connection|Object} [hints.connection]
51166 	 * @param {djs.model.Base} [hints.connectionParent]
51167 	 *
51168 	 * @return {djs.model.Shape} the newly created shape
51169 	 */
51170 	Modeling$1.prototype.appendShape = function(source, shape, position, target, hints) {
51171 
51172 	  hints = hints || {};
51173 
51174 	  shape = this._create('shape', shape);
51175 
51176 	  var context = {
51177 	    source: source,
51178 	    position: position,
51179 	    target: target,
51180 	    shape: shape,
51181 	    connection: hints.connection,
51182 	    connectionParent: hints.connectionParent,
51183 	    hints: hints
51184 	  };
51185 
51186 	  this._commandStack.execute('shape.append', context);
51187 
51188 	  return context.shape;
51189 	};
51190 
51191 
51192 	Modeling$1.prototype.removeElements = function(elements) {
51193 	  var context = {
51194 	    elements: elements
51195 	  };
51196 
51197 	  this._commandStack.execute('elements.delete', context);
51198 	};
51199 
51200 
51201 	Modeling$1.prototype.distributeElements = function(groups, axis, dimension) {
51202 	  var context = {
51203 	    groups: groups,
51204 	    axis: axis,
51205 	    dimension: dimension
51206 	  };
51207 
51208 	  this._commandStack.execute('elements.distribute', context);
51209 	};
51210 
51211 
51212 	Modeling$1.prototype.removeShape = function(shape, hints) {
51213 	  var context = {
51214 	    shape: shape,
51215 	    hints: hints || {}
51216 	  };
51217 
51218 	  this._commandStack.execute('shape.delete', context);
51219 	};
51220 
51221 
51222 	Modeling$1.prototype.removeConnection = function(connection, hints) {
51223 	  var context = {
51224 	    connection: connection,
51225 	    hints: hints || {}
51226 	  };
51227 
51228 	  this._commandStack.execute('connection.delete', context);
51229 	};
51230 
51231 	Modeling$1.prototype.replaceShape = function(oldShape, newShape, hints) {
51232 	  var context = {
51233 	    oldShape: oldShape,
51234 	    newData: newShape,
51235 	    hints: hints || {}
51236 	  };
51237 
51238 	  this._commandStack.execute('shape.replace', context);
51239 
51240 	  return context.newShape;
51241 	};
51242 
51243 	Modeling$1.prototype.alignElements = function(elements, alignment) {
51244 	  var context = {
51245 	    elements: elements,
51246 	    alignment: alignment
51247 	  };
51248 
51249 	  this._commandStack.execute('elements.align', context);
51250 	};
51251 
51252 	Modeling$1.prototype.resizeShape = function(shape, newBounds, minBounds, hints) {
51253 	  var context = {
51254 	    shape: shape,
51255 	    newBounds: newBounds,
51256 	    minBounds: minBounds,
51257 	    hints: hints
51258 	  };
51259 
51260 	  this._commandStack.execute('shape.resize', context);
51261 	};
51262 
51263 	Modeling$1.prototype.createSpace = function(movingShapes, resizingShapes, delta, direction, start) {
51264 	  var context = {
51265 	    delta: delta,
51266 	    direction: direction,
51267 	    movingShapes: movingShapes,
51268 	    resizingShapes: resizingShapes,
51269 	    start: start
51270 	  };
51271 
51272 	  this._commandStack.execute('spaceTool', context);
51273 	};
51274 
51275 	Modeling$1.prototype.updateWaypoints = function(connection, newWaypoints, hints) {
51276 	  var context = {
51277 	    connection: connection,
51278 	    newWaypoints: newWaypoints,
51279 	    hints: hints || {}
51280 	  };
51281 
51282 	  this._commandStack.execute('connection.updateWaypoints', context);
51283 	};
51284 
51285 	Modeling$1.prototype.reconnect = function(connection, source, target, dockingOrPoints, hints) {
51286 	  var context = {
51287 	    connection: connection,
51288 	    newSource: source,
51289 	    newTarget: target,
51290 	    dockingOrPoints: dockingOrPoints,
51291 	    hints: hints || {}
51292 	  };
51293 
51294 	  this._commandStack.execute('connection.reconnect', context);
51295 	};
51296 
51297 	Modeling$1.prototype.reconnectStart = function(connection, newSource, dockingOrPoints, hints) {
51298 	  if (!hints) {
51299 	    hints = {};
51300 	  }
51301 
51302 	  this.reconnect(connection, newSource, connection.target, dockingOrPoints, assign(hints, {
51303 	    docking: 'source'
51304 	  }));
51305 	};
51306 
51307 	Modeling$1.prototype.reconnectEnd = function(connection, newTarget, dockingOrPoints, hints) {
51308 	  if (!hints) {
51309 	    hints = {};
51310 	  }
51311 
51312 	  this.reconnect(connection, connection.source, newTarget, dockingOrPoints, assign(hints, {
51313 	    docking: 'target'
51314 	  }));
51315 	};
51316 
51317 	Modeling$1.prototype.connect = function(source, target, attrs, hints) {
51318 	  return this.createConnection(source, target, attrs || {}, source.parent, hints);
51319 	};
51320 
51321 	Modeling$1.prototype._create = function(type, attrs) {
51322 	  if (attrs instanceof Base$1) {
51323 	    return attrs;
51324 	  } else {
51325 	    return this._elementFactory.create(type, attrs);
51326 	  }
51327 	};
51328 
51329 	Modeling$1.prototype.toggleCollapse = function(shape, hints) {
51330 	  var context = {
51331 	    shape: shape,
51332 	    hints: hints || {}
51333 	  };
51334 
51335 	  this._commandStack.execute('shape.toggleCollapse', context);
51336 	};
51337 
51338 	function UpdateModdlePropertiesHandler(elementRegistry) {
51339 	  this._elementRegistry = elementRegistry;
51340 	}
51341 
51342 	UpdateModdlePropertiesHandler.$inject = ['elementRegistry'];
51343 
51344 	UpdateModdlePropertiesHandler.prototype.execute = function(context) {
51345 
51346 	  var element = context.element,
51347 	      moddleElement = context.moddleElement,
51348 	      properties = context.properties;
51349 
51350 	  if (!moddleElement) {
51351 	    throw new Error('<moddleElement> required');
51352 	  }
51353 
51354 	  var changed = context.changed || this.getVisualReferences(moddleElement).concat(element);
51355 	  var oldProperties = context.oldProperties || getModdleProperties(moddleElement, keys(properties));
51356 
51357 	  setModdleProperties(moddleElement, properties);
51358 
51359 	  context.oldProperties = oldProperties;
51360 	  context.changed = changed;
51361 
51362 	  return changed;
51363 	};
51364 
51365 	UpdateModdlePropertiesHandler.prototype.revert = function(context) {
51366 	  var oldProperties = context.oldProperties,
51367 	      moddleElement = context.moddleElement,
51368 	      changed = context.changed;
51369 
51370 	  setModdleProperties(moddleElement, oldProperties);
51371 
51372 	  return changed;
51373 	};
51374 
51375 	/**
51376 	 * Return visual references of given moddle element within the diagram.
51377 	 *
51378 	 * @param {ModdleElement} moddleElement
51379 	 *
51380 	 * @return {Array<djs.model.Element>}
51381 	 */
51382 	UpdateModdlePropertiesHandler.prototype.getVisualReferences = function(moddleElement) {
51383 
51384 	  var elementRegistry = this._elementRegistry;
51385 
51386 	  if (is$1(moddleElement, 'bpmn:DataObject')) {
51387 	    return getAllDataObjectReferences(moddleElement, elementRegistry);
51388 	  }
51389 
51390 	  return [];
51391 	};
51392 
51393 
51394 	// helpers /////////////////
51395 
51396 	function getModdleProperties(moddleElement, propertyNames) {
51397 	  return reduce(propertyNames, function(result, key) {
51398 	    result[key] = moddleElement.get(key);
51399 	    return result;
51400 	  }, {});
51401 	}
51402 
51403 	function setModdleProperties(moddleElement, properties) {
51404 	  forEach(properties, function(value, key) {
51405 	    moddleElement.set(key, value);
51406 	  });
51407 	}
51408 
51409 	function getAllDataObjectReferences(dataObject, elementRegistry) {
51410 	  return elementRegistry.filter(function(element) {
51411 	    return (
51412 	      is$1(element, 'bpmn:DataObjectReference') &&
51413 	          getBusinessObject(element).dataObjectRef === dataObject
51414 	    );
51415 	  });
51416 	}
51417 
51418 	var DEFAULT_FLOW = 'default',
51419 	    ID = 'id',
51420 	    DI = 'di';
51421 
51422 	var NULL_DIMENSIONS$1 = {
51423 	  width: 0,
51424 	  height: 0
51425 	};
51426 
51427 	/**
51428 	 * A handler that implements a BPMN 2.0 property update.
51429 	 *
51430 	 * This should be used to set simple properties on elements with
51431 	 * an underlying BPMN business object.
51432 	 *
51433 	 * Use respective diagram-js provided handlers if you would
51434 	 * like to perform automated modeling.
51435 	 */
51436 	function UpdatePropertiesHandler(
51437 	    elementRegistry, moddle, translate,
51438 	    modeling, textRenderer) {
51439 
51440 	  this._elementRegistry = elementRegistry;
51441 	  this._moddle = moddle;
51442 	  this._translate = translate;
51443 	  this._modeling = modeling;
51444 	  this._textRenderer = textRenderer;
51445 	}
51446 
51447 	UpdatePropertiesHandler.$inject = [
51448 	  'elementRegistry',
51449 	  'moddle',
51450 	  'translate',
51451 	  'modeling',
51452 	  'textRenderer'
51453 	];
51454 
51455 
51456 	// api //////////////////////
51457 
51458 	/**
51459 	 * Updates a BPMN element with a list of new properties
51460 	 *
51461 	 * @param {Object} context
51462 	 * @param {djs.model.Base} context.element the element to update
51463 	 * @param {Object} context.properties a list of properties to set on the element's
51464 	 *                                    businessObject (the BPMN model element)
51465 	 *
51466 	 * @return {Array<djs.model.Base>} the updated element
51467 	 */
51468 	UpdatePropertiesHandler.prototype.execute = function(context) {
51469 
51470 	  var element = context.element,
51471 	      changed = [ element ],
51472 	      translate = this._translate;
51473 
51474 	  if (!element) {
51475 	    throw new Error(translate('element required'));
51476 	  }
51477 
51478 	  var elementRegistry = this._elementRegistry,
51479 	      ids = this._moddle.ids;
51480 
51481 	  var businessObject = element.businessObject,
51482 	      properties = unwrapBusinessObjects(context.properties),
51483 	      oldProperties = context.oldProperties || getProperties(businessObject, properties);
51484 
51485 	  if (isIdChange(properties, businessObject)) {
51486 	    ids.unclaim(businessObject[ID]);
51487 
51488 	    elementRegistry.updateId(element, properties[ID]);
51489 
51490 	    ids.claim(properties[ID], businessObject);
51491 	  }
51492 
51493 	  // correctly indicate visual changes on default flow updates
51494 	  if (DEFAULT_FLOW in properties) {
51495 
51496 	    if (properties[DEFAULT_FLOW]) {
51497 	      changed.push(elementRegistry.get(properties[DEFAULT_FLOW].id));
51498 	    }
51499 
51500 	    if (businessObject[DEFAULT_FLOW]) {
51501 	      changed.push(elementRegistry.get(businessObject[DEFAULT_FLOW].id));
51502 	    }
51503 	  }
51504 
51505 	  // update properties
51506 	  setProperties(businessObject, properties);
51507 
51508 	  // store old values
51509 	  context.oldProperties = oldProperties;
51510 	  context.changed = changed;
51511 
51512 	  // indicate changed on objects affected by the update
51513 	  return changed;
51514 	};
51515 
51516 
51517 	UpdatePropertiesHandler.prototype.postExecute = function(context) {
51518 	  var element = context.element,
51519 	      label = element.label;
51520 
51521 	  var text = label && getBusinessObject(label).name;
51522 
51523 	  if (!text) {
51524 	    return;
51525 	  }
51526 
51527 	  // get layouted text bounds and resize external
51528 	  // external label accordingly
51529 	  var newLabelBounds = this._textRenderer.getExternalLabelBounds(label, text);
51530 
51531 	  this._modeling.resizeShape(label, newLabelBounds, NULL_DIMENSIONS$1);
51532 	};
51533 
51534 	/**
51535 	 * Reverts the update on a BPMN elements properties.
51536 	 *
51537 	 * @param  {Object} context
51538 	 *
51539 	 * @return {djs.model.Base} the updated element
51540 	 */
51541 	UpdatePropertiesHandler.prototype.revert = function(context) {
51542 
51543 	  var element = context.element,
51544 	      properties = context.properties,
51545 	      oldProperties = context.oldProperties,
51546 	      businessObject = element.businessObject,
51547 	      elementRegistry = this._elementRegistry,
51548 	      ids = this._moddle.ids;
51549 
51550 	  // update properties
51551 	  setProperties(businessObject, oldProperties);
51552 
51553 	  if (isIdChange(properties, businessObject)) {
51554 	    ids.unclaim(properties[ID]);
51555 
51556 	    elementRegistry.updateId(element, oldProperties[ID]);
51557 
51558 	    ids.claim(oldProperties[ID], businessObject);
51559 	  }
51560 
51561 	  return context.changed;
51562 	};
51563 
51564 
51565 	function isIdChange(properties, businessObject) {
51566 	  return ID in properties && properties[ID] !== businessObject[ID];
51567 	}
51568 
51569 
51570 	function getProperties(businessObject, properties) {
51571 	  var propertyNames = keys(properties);
51572 
51573 	  return reduce(propertyNames, function(result, key) {
51574 
51575 	    // handle DI separately
51576 	    if (key !== DI) {
51577 	      result[key] = businessObject.get(key);
51578 	    } else {
51579 	      result[key] = getDiProperties(businessObject.di, keys(properties.di));
51580 	    }
51581 
51582 	    return result;
51583 	  }, {});
51584 	}
51585 
51586 
51587 	function getDiProperties(di, propertyNames) {
51588 	  return reduce(propertyNames, function(result, key) {
51589 	    result[key] = di.get(key);
51590 
51591 	    return result;
51592 	  }, {});
51593 	}
51594 
51595 
51596 	function setProperties(businessObject, properties) {
51597 	  forEach(properties, function(value, key) {
51598 
51599 	    if (key !== DI) {
51600 	      businessObject.set(key, value);
51601 	    } else {
51602 
51603 	      // only update, if businessObject.di exists
51604 	      if (businessObject.di) {
51605 	        setDiProperties(businessObject.di, value);
51606 	      }
51607 	    }
51608 	  });
51609 	}
51610 
51611 
51612 	function setDiProperties(di, properties) {
51613 	  forEach(properties, function(value, key) {
51614 	    di.set(key, value);
51615 	  });
51616 	}
51617 
51618 
51619 	var referencePropertyNames = [ 'default' ];
51620 
51621 	/**
51622 	 * Make sure we unwrap the actual business object
51623 	 * behind diagram element that may have been
51624 	 * passed as arguments.
51625 	 *
51626 	 * @param  {Object} properties
51627 	 *
51628 	 * @return {Object} unwrappedProps
51629 	 */
51630 	function unwrapBusinessObjects(properties) {
51631 
51632 	  var unwrappedProps = assign({}, properties);
51633 
51634 	  referencePropertyNames.forEach(function(name) {
51635 	    if (name in properties) {
51636 	      unwrappedProps[name] = getBusinessObject(unwrappedProps[name]);
51637 	    }
51638 	  });
51639 
51640 	  return unwrappedProps;
51641 	}
51642 
51643 	function UpdateCanvasRootHandler(canvas, modeling) {
51644 	  this._canvas = canvas;
51645 	  this._modeling = modeling;
51646 	}
51647 
51648 	UpdateCanvasRootHandler.$inject = [
51649 	  'canvas',
51650 	  'modeling'
51651 	];
51652 
51653 
51654 	UpdateCanvasRootHandler.prototype.execute = function(context) {
51655 
51656 	  var canvas = this._canvas;
51657 
51658 	  var newRoot = context.newRoot,
51659 	      newRootBusinessObject = newRoot.businessObject,
51660 	      oldRoot = canvas.getRootElement(),
51661 	      oldRootBusinessObject = oldRoot.businessObject,
51662 	      bpmnDefinitions = oldRootBusinessObject.$parent,
51663 	      diPlane = oldRootBusinessObject.di;
51664 
51665 	  // (1) replace process old <> new root
51666 	  canvas.setRootElement(newRoot, true);
51667 
51668 	  // (2) update root elements
51669 	  add(bpmnDefinitions.rootElements, newRootBusinessObject);
51670 	  newRootBusinessObject.$parent = bpmnDefinitions;
51671 
51672 	  remove(bpmnDefinitions.rootElements, oldRootBusinessObject);
51673 	  oldRootBusinessObject.$parent = null;
51674 
51675 	  // (3) wire di
51676 	  oldRootBusinessObject.di = null;
51677 
51678 	  diPlane.bpmnElement = newRootBusinessObject;
51679 	  newRootBusinessObject.di = diPlane;
51680 
51681 	  context.oldRoot = oldRoot;
51682 
51683 	  // TODO(nikku): return changed elements?
51684 	  // return [ newRoot, oldRoot ];
51685 	};
51686 
51687 
51688 	UpdateCanvasRootHandler.prototype.revert = function(context) {
51689 
51690 	  var canvas = this._canvas;
51691 
51692 	  var newRoot = context.newRoot,
51693 	      newRootBusinessObject = newRoot.businessObject,
51694 	      oldRoot = context.oldRoot,
51695 	      oldRootBusinessObject = oldRoot.businessObject,
51696 	      bpmnDefinitions = newRootBusinessObject.$parent,
51697 	      diPlane = newRootBusinessObject.di;
51698 
51699 	  // (1) replace process old <> new root
51700 	  canvas.setRootElement(oldRoot, true);
51701 
51702 	  // (2) update root elements
51703 	  remove(bpmnDefinitions.rootElements, newRootBusinessObject);
51704 	  newRootBusinessObject.$parent = null;
51705 
51706 	  add(bpmnDefinitions.rootElements, oldRootBusinessObject);
51707 	  oldRootBusinessObject.$parent = bpmnDefinitions;
51708 
51709 	  // (3) wire di
51710 	  newRootBusinessObject.di = null;
51711 
51712 	  diPlane.bpmnElement = oldRootBusinessObject;
51713 	  oldRootBusinessObject.di = diPlane;
51714 
51715 	  // TODO(nikku): return changed elements?
51716 	  // return [ newRoot, oldRoot ];
51717 	};
51718 
51719 	/**
51720 	 * A handler that allows us to add a new lane
51721 	 * above or below an existing one.
51722 	 *
51723 	 * @param {Modeling} modeling
51724 	 * @param {SpaceTool} spaceTool
51725 	 */
51726 	function AddLaneHandler(modeling, spaceTool) {
51727 	  this._modeling = modeling;
51728 	  this._spaceTool = spaceTool;
51729 	}
51730 
51731 	AddLaneHandler.$inject = [
51732 	  'modeling',
51733 	  'spaceTool'
51734 	];
51735 
51736 
51737 	AddLaneHandler.prototype.preExecute = function(context) {
51738 
51739 	  var spaceTool = this._spaceTool,
51740 	      modeling = this._modeling;
51741 
51742 	  var shape = context.shape,
51743 	      location = context.location;
51744 
51745 	  var lanesRoot = getLanesRoot(shape);
51746 
51747 	  var isRoot = lanesRoot === shape,
51748 	      laneParent = isRoot ? shape : shape.parent;
51749 
51750 	  var existingChildLanes = getChildLanes(laneParent);
51751 
51752 	  // (0) add a lane if we currently got none and are adding to root
51753 	  if (!existingChildLanes.length) {
51754 	    modeling.createShape({ type: 'bpmn:Lane' }, {
51755 	      x: shape.x + LANE_INDENTATION,
51756 	      y: shape.y,
51757 	      width: shape.width - LANE_INDENTATION,
51758 	      height: shape.height
51759 	    }, laneParent);
51760 	  }
51761 
51762 	  // (1) collect affected elements to create necessary space
51763 	  var allAffected = [];
51764 
51765 	  eachElement(lanesRoot, function(element) {
51766 	    allAffected.push(element);
51767 
51768 	    // handle element labels in the diagram root
51769 	    if (element.label) {
51770 	      allAffected.push(element.label);
51771 	    }
51772 
51773 	    if (element === shape) {
51774 	      return [];
51775 	    }
51776 
51777 	    return filter(element.children, function(c) {
51778 	      return c !== shape;
51779 	    });
51780 	  });
51781 
51782 	  var offset = location === 'top' ? -120 : 120,
51783 	      lanePosition = location === 'top' ? shape.y : shape.y + shape.height,
51784 	      spacePos = lanePosition + (location === 'top' ? 10 : -10),
51785 	      direction = location === 'top' ? 'n' : 's';
51786 
51787 	  var adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos);
51788 
51789 	  spaceTool.makeSpace(
51790 	    adjustments.movingShapes,
51791 	    adjustments.resizingShapes,
51792 	    { x: 0, y: offset },
51793 	    direction,
51794 	    spacePos
51795 	  );
51796 
51797 	  // (2) create new lane at open space
51798 	  context.newLane = modeling.createShape({ type: 'bpmn:Lane' }, {
51799 	    x: shape.x + (isRoot ? LANE_INDENTATION : 0),
51800 	    y: lanePosition - (location === 'top' ? 120 : 0),
51801 	    width: shape.width - (isRoot ? LANE_INDENTATION : 0),
51802 	    height: 120
51803 	  }, laneParent);
51804 	};
51805 
51806 	/**
51807 	 * A handler that splits a lane into a number of sub-lanes,
51808 	 * creating new sub lanes, if necessary.
51809 	 *
51810 	 * @param {Modeling} modeling
51811 	 */
51812 	function SplitLaneHandler(modeling, translate) {
51813 	  this._modeling = modeling;
51814 	  this._translate = translate;
51815 	}
51816 
51817 	SplitLaneHandler.$inject = [
51818 	  'modeling',
51819 	  'translate'
51820 	];
51821 
51822 
51823 	SplitLaneHandler.prototype.preExecute = function(context) {
51824 
51825 	  var modeling = this._modeling,
51826 	      translate = this._translate;
51827 
51828 	  var shape = context.shape,
51829 	      newLanesCount = context.count;
51830 
51831 	  var childLanes = getChildLanes(shape),
51832 	      existingLanesCount = childLanes.length;
51833 
51834 	  if (existingLanesCount > newLanesCount) {
51835 	    throw new Error(translate('more than {count} child lanes', { count: newLanesCount }));
51836 	  }
51837 
51838 	  var newLanesHeight = Math.round(shape.height / newLanesCount);
51839 
51840 	  // Iterate from top to bottom in child lane order,
51841 	  // resizing existing lanes and creating new ones
51842 	  // so that they split the parent proportionally.
51843 	  //
51844 	  // Due to rounding related errors, the bottom lane
51845 	  // needs to take up all the remaining space.
51846 	  var laneY,
51847 	      laneHeight,
51848 	      laneBounds,
51849 	      newLaneAttrs,
51850 	      idx;
51851 
51852 	  for (idx = 0; idx < newLanesCount; idx++) {
51853 
51854 	    laneY = shape.y + idx * newLanesHeight;
51855 
51856 	    // if bottom lane
51857 	    if (idx === newLanesCount - 1) {
51858 	      laneHeight = shape.height - (newLanesHeight * idx);
51859 	    } else {
51860 	      laneHeight = newLanesHeight;
51861 	    }
51862 
51863 	    laneBounds = {
51864 	      x: shape.x + LANE_INDENTATION,
51865 	      y: laneY,
51866 	      width: shape.width - LANE_INDENTATION,
51867 	      height: laneHeight
51868 	    };
51869 
51870 	    if (idx < existingLanesCount) {
51871 
51872 	      // resize existing lane
51873 	      modeling.resizeShape(childLanes[idx], laneBounds);
51874 	    } else {
51875 
51876 	      // create a new lane at position
51877 	      newLaneAttrs = {
51878 	        type: 'bpmn:Lane'
51879 	      };
51880 
51881 	      modeling.createShape(newLaneAttrs, laneBounds, shape);
51882 	    }
51883 	  }
51884 	};
51885 
51886 	/**
51887 	 * A handler that resizes a lane.
51888 	 *
51889 	 * @param {Modeling} modeling
51890 	 */
51891 	function ResizeLaneHandler(modeling, spaceTool) {
51892 	  this._modeling = modeling;
51893 	  this._spaceTool = spaceTool;
51894 	}
51895 
51896 	ResizeLaneHandler.$inject = [
51897 	  'modeling',
51898 	  'spaceTool'
51899 	];
51900 
51901 
51902 	ResizeLaneHandler.prototype.preExecute = function(context) {
51903 
51904 	  var shape = context.shape,
51905 	      newBounds = context.newBounds,
51906 	      balanced = context.balanced;
51907 
51908 	  if (balanced !== false) {
51909 	    this.resizeBalanced(shape, newBounds);
51910 	  } else {
51911 	    this.resizeSpace(shape, newBounds);
51912 	  }
51913 	};
51914 
51915 
51916 	/**
51917 	 * Resize balanced, adjusting next / previous lane sizes.
51918 	 *
51919 	 * @param {djs.model.Shape} shape
51920 	 * @param {Bounds} newBounds
51921 	 */
51922 	ResizeLaneHandler.prototype.resizeBalanced = function(shape, newBounds) {
51923 
51924 	  var modeling = this._modeling;
51925 
51926 	  var resizeNeeded = computeLanesResize(shape, newBounds);
51927 
51928 	  // resize the lane
51929 	  modeling.resizeShape(shape, newBounds);
51930 
51931 	  // resize other lanes as needed
51932 	  resizeNeeded.forEach(function(r) {
51933 	    modeling.resizeShape(r.shape, r.newBounds);
51934 	  });
51935 	};
51936 
51937 
51938 	/**
51939 	 * Resize, making actual space and moving below / above elements.
51940 	 *
51941 	 * @param {djs.model.Shape} shape
51942 	 * @param {Bounds} newBounds
51943 	 */
51944 	ResizeLaneHandler.prototype.resizeSpace = function(shape, newBounds) {
51945 	  var spaceTool = this._spaceTool;
51946 
51947 	  var shapeTrbl = asTRBL(shape),
51948 	      newTrbl = asTRBL(newBounds);
51949 
51950 	  var trblDiff = substractTRBL(newTrbl, shapeTrbl);
51951 
51952 	  var lanesRoot = getLanesRoot(shape);
51953 
51954 	  var allAffected = [],
51955 	      allLanes = [];
51956 
51957 	  eachElement(lanesRoot, function(element) {
51958 	    allAffected.push(element);
51959 
51960 	    if (is$1(element, 'bpmn:Lane') || is$1(element, 'bpmn:Participant')) {
51961 	      allLanes.push(element);
51962 	    }
51963 
51964 	    return element.children;
51965 	  });
51966 
51967 	  var change,
51968 	      spacePos,
51969 	      direction,
51970 	      offset,
51971 	      adjustments;
51972 
51973 	  if (trblDiff.bottom || trblDiff.top) {
51974 
51975 	    change = trblDiff.bottom || trblDiff.top;
51976 	    spacePos = shape.y + (trblDiff.bottom ? shape.height : 0) + (trblDiff.bottom ? -10 : 10);
51977 	    direction = trblDiff.bottom ? 's' : 'n';
51978 
51979 	    offset = trblDiff.top > 0 || trblDiff.bottom < 0 ? -change : change;
51980 
51981 	    adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos);
51982 
51983 	    spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: 0, y: change }, direction);
51984 	  }
51985 
51986 
51987 	  if (trblDiff.left || trblDiff.right) {
51988 
51989 	    change = trblDiff.right || trblDiff.left;
51990 	    spacePos = shape.x + (trblDiff.right ? shape.width : 0) + (trblDiff.right ? -10 : 100);
51991 	    direction = trblDiff.right ? 'e' : 'w';
51992 
51993 	    offset = trblDiff.left > 0 || trblDiff.right < 0 ? -change : change;
51994 
51995 	    adjustments = spaceTool.calculateAdjustments(allLanes, 'x', offset, spacePos);
51996 
51997 	    spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: change, y: 0 }, direction);
51998 	  }
51999 	};
52000 
52001 	var FLOW_NODE_REFS_ATTR = 'flowNodeRef',
52002 	    LANES_ATTR = 'lanes';
52003 
52004 
52005 	/**
52006 	 * A handler that updates lane refs on changed elements
52007 	 */
52008 	function UpdateFlowNodeRefsHandler(elementRegistry) {
52009 	  this._elementRegistry = elementRegistry;
52010 	}
52011 
52012 	UpdateFlowNodeRefsHandler.$inject = [
52013 	  'elementRegistry'
52014 	];
52015 
52016 
52017 	UpdateFlowNodeRefsHandler.prototype.computeUpdates = function(flowNodeShapes, laneShapes) {
52018 
52019 	  var handledNodes = [];
52020 
52021 	  var updates = [];
52022 
52023 	  var participantCache = {};
52024 
52025 	  var allFlowNodeShapes = [];
52026 
52027 	  function isInLaneShape(element, laneShape) {
52028 
52029 	    var laneTrbl = asTRBL(laneShape);
52030 
52031 	    var elementMid = {
52032 	      x: element.x + element.width / 2,
52033 	      y: element.y + element.height / 2
52034 	    };
52035 
52036 	    return elementMid.x > laneTrbl.left &&
52037 	           elementMid.x < laneTrbl.right &&
52038 	           elementMid.y > laneTrbl.top &&
52039 	           elementMid.y < laneTrbl.bottom;
52040 	  }
52041 
52042 	  function addFlowNodeShape(flowNodeShape) {
52043 	    if (handledNodes.indexOf(flowNodeShape) === -1) {
52044 	      allFlowNodeShapes.push(flowNodeShape);
52045 	      handledNodes.push(flowNodeShape);
52046 	    }
52047 	  }
52048 
52049 	  function getAllLaneShapes(flowNodeShape) {
52050 
52051 	    var root = getLanesRoot(flowNodeShape);
52052 
52053 	    if (!participantCache[root.id]) {
52054 	      participantCache[root.id] = collectLanes(root);
52055 	    }
52056 
52057 	    return participantCache[root.id];
52058 	  }
52059 
52060 	  function getNewLanes(flowNodeShape) {
52061 	    if (!flowNodeShape.parent) {
52062 	      return [];
52063 	    }
52064 
52065 	    var allLaneShapes = getAllLaneShapes(flowNodeShape);
52066 
52067 	    return allLaneShapes.filter(function(l) {
52068 	      return isInLaneShape(flowNodeShape, l);
52069 	    }).map(function(shape) {
52070 	      return shape.businessObject;
52071 	    });
52072 	  }
52073 
52074 	  laneShapes.forEach(function(laneShape) {
52075 	    var root = getLanesRoot(laneShape);
52076 
52077 	    if (!root || handledNodes.indexOf(root) !== -1) {
52078 	      return;
52079 	    }
52080 
52081 	    var children = root.children.filter(function(c) {
52082 	      return is$1(c, 'bpmn:FlowNode');
52083 	    });
52084 
52085 	    children.forEach(addFlowNodeShape);
52086 
52087 	    handledNodes.push(root);
52088 	  });
52089 
52090 	  flowNodeShapes.forEach(addFlowNodeShape);
52091 
52092 
52093 	  allFlowNodeShapes.forEach(function(flowNodeShape) {
52094 
52095 	    var flowNode = flowNodeShape.businessObject;
52096 
52097 	    var lanes = flowNode.get(LANES_ATTR),
52098 	        remove = lanes.slice(),
52099 	        add = getNewLanes(flowNodeShape);
52100 
52101 	    updates.push({ flowNode: flowNode, remove: remove, add: add });
52102 	  });
52103 
52104 	  laneShapes.forEach(function(laneShape) {
52105 
52106 	    var lane = laneShape.businessObject;
52107 
52108 	    // lane got removed XX-)
52109 	    if (!laneShape.parent) {
52110 	      lane.get(FLOW_NODE_REFS_ATTR).forEach(function(flowNode) {
52111 	        updates.push({ flowNode: flowNode, remove: [ lane ], add: [] });
52112 	      });
52113 	    }
52114 	  });
52115 
52116 	  return updates;
52117 	};
52118 
52119 	UpdateFlowNodeRefsHandler.prototype.execute = function(context) {
52120 
52121 	  var updates = context.updates;
52122 
52123 	  if (!updates) {
52124 	    updates = context.updates = this.computeUpdates(context.flowNodeShapes, context.laneShapes);
52125 	  }
52126 
52127 
52128 	  updates.forEach(function(update) {
52129 
52130 	    var flowNode = update.flowNode,
52131 	        lanes = flowNode.get(LANES_ATTR);
52132 
52133 	    // unwire old
52134 	    update.remove.forEach(function(oldLane) {
52135 	      remove(lanes, oldLane);
52136 	      remove(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode);
52137 	    });
52138 
52139 	    // wire new
52140 	    update.add.forEach(function(newLane) {
52141 	      add(lanes, newLane);
52142 	      add(newLane.get(FLOW_NODE_REFS_ATTR), flowNode);
52143 	    });
52144 	  });
52145 
52146 	  // TODO(nikku): return changed elements
52147 	  // return [ ... ];
52148 	};
52149 
52150 
52151 	UpdateFlowNodeRefsHandler.prototype.revert = function(context) {
52152 
52153 	  var updates = context.updates;
52154 
52155 	  updates.forEach(function(update) {
52156 
52157 	    var flowNode = update.flowNode,
52158 	        lanes = flowNode.get(LANES_ATTR);
52159 
52160 	    // unwire new
52161 	    update.add.forEach(function(newLane) {
52162 	      remove(lanes, newLane);
52163 	      remove(newLane.get(FLOW_NODE_REFS_ATTR), flowNode);
52164 	    });
52165 
52166 	    // wire old
52167 	    update.remove.forEach(function(oldLane) {
52168 	      add(lanes, oldLane);
52169 	      add(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode);
52170 	    });
52171 	  });
52172 
52173 	  // TODO(nikku): return changed elements
52174 	  // return [ ... ];
52175 	};
52176 
52177 	function IdClaimHandler(moddle) {
52178 	  this._moddle = moddle;
52179 	}
52180 
52181 	IdClaimHandler.$inject = [ 'moddle' ];
52182 
52183 
52184 	IdClaimHandler.prototype.execute = function(context) {
52185 	  var ids = this._moddle.ids,
52186 	      id = context.id,
52187 	      element = context.element,
52188 	      claiming = context.claiming;
52189 
52190 	  if (claiming) {
52191 	    ids.claim(id, element);
52192 	  } else {
52193 	    ids.unclaim(id);
52194 	  }
52195 	};
52196 
52197 	/**
52198 	 * Command revert implementation.
52199 	 */
52200 	IdClaimHandler.prototype.revert = function(context) {
52201 	  var ids = this._moddle.ids,
52202 	      id = context.id,
52203 	      element = context.element,
52204 	      claiming = context.claiming;
52205 
52206 	  if (claiming) {
52207 	    ids.unclaim(id);
52208 	  } else {
52209 	    ids.claim(id, element);
52210 	  }
52211 	};
52212 
52213 	var DEFAULT_COLORS = {
52214 	  fill: undefined,
52215 	  stroke: undefined
52216 	};
52217 
52218 
52219 	function SetColorHandler(commandStack) {
52220 	  this._commandStack = commandStack;
52221 
52222 	  this._normalizeColor = function(color) {
52223 
52224 	    // Remove color for falsy values.
52225 	    if (!color) {
52226 	      return undefined;
52227 	    }
52228 
52229 	    if (isString(color)) {
52230 	      var hexColor = colorToHex(color);
52231 
52232 	      if (hexColor) {
52233 	        return hexColor;
52234 	      }
52235 	    }
52236 
52237 	    throw new Error('invalid color value: ' + color);
52238 	  };
52239 	}
52240 
52241 	SetColorHandler.$inject = [
52242 	  'commandStack'
52243 	];
52244 
52245 
52246 	SetColorHandler.prototype.postExecute = function(context) {
52247 	  var elements = context.elements,
52248 	      colors = context.colors || DEFAULT_COLORS;
52249 
52250 	  var self = this;
52251 
52252 	  var di = {};
52253 
52254 	  if ('fill' in colors) {
52255 	    assign(di, {
52256 	      'background-color': this._normalizeColor(colors.fill) });
52257 	  }
52258 
52259 	  if ('stroke' in colors) {
52260 	    assign(di, {
52261 	      'border-color': this._normalizeColor(colors.stroke) });
52262 	  }
52263 
52264 	  forEach(elements, function(element) {
52265 	    var assignedDi = isConnection$3(element) ? pick(di, [ 'border-color' ]) : di;
52266 
52267 	    // TODO @barmac: remove once we drop bpmn.io properties
52268 	    ensureLegacySupport(assignedDi);
52269 
52270 	    self._commandStack.execute('element.updateProperties', {
52271 	      element: element,
52272 	      properties: {
52273 	        di: assignedDi
52274 	      }
52275 	    });
52276 	  });
52277 
52278 	};
52279 
52280 	/**
52281 	 * Convert color from rgb(a)/hsl to hex. Returns `null` for unknown color names and for colors
52282 	 * with alpha less than 1.0. This depends on `<canvas>` serialization of the `context.fillStyle`.
52283 	 * Cf. https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle
52284 	 *
52285 	 * @example
52286 	 * ```js
52287 	 * var color = 'fuchsia';
52288 	 * console.log(colorToHex(color));
52289 	 * // "#ff00ff"
52290 	 * color = 'rgba(1,2,3,0.4)';
52291 	 * console.log(colorToHex(color));
52292 	 * // null
52293 	 * ```
52294 	 *
52295 	 * @param {string} color
52296 	 * @returns {string|null}
52297 	 */
52298 	function colorToHex(color) {
52299 	  var context = document.createElement('canvas').getContext('2d');
52300 
52301 	  // (0) Start with transparent to account for browser default values.
52302 	  context.fillStyle = 'transparent';
52303 
52304 	  // (1) Assign color so that it's serialized.
52305 	  context.fillStyle = color;
52306 
52307 	  // (2) Return null for non-hex serialization result.
52308 	  return /^#[0-9a-fA-F]{6}$/.test(context.fillStyle) ? context.fillStyle : null;
52309 	}
52310 
52311 	function isConnection$3(element) {
52312 	  return !!element.waypoints;
52313 	}
52314 
52315 	/**
52316 	 * Add legacy properties if required.
52317 	 * @param {{ 'border-color': string?, 'background-color': string? }} di
52318 	 */
52319 	function ensureLegacySupport(di) {
52320 	  if ('border-color' in di) {
52321 	    di.stroke = di['border-color'];
52322 	  }
52323 
52324 	  if ('background-color' in di) {
52325 	    di.fill = di['background-color'];
52326 	  }
52327 	}
52328 
52329 	var NULL_DIMENSIONS = {
52330 	  width: 0,
52331 	  height: 0
52332 	};
52333 
52334 
52335 	/**
52336 	 * A handler that updates the text of a BPMN element.
52337 	 */
52338 	function UpdateLabelHandler(modeling, textRenderer) {
52339 
52340 	  /**
52341 	   * Set the label and return the changed elements.
52342 	   *
52343 	   * Element parameter can be label itself or connection (i.e. sequence flow).
52344 	   *
52345 	   * @param {djs.model.Base} element
52346 	   * @param {string} text
52347 	   */
52348 	  function setText(element, text) {
52349 
52350 	    // external label if present
52351 	    var label = element.label || element;
52352 
52353 	    var labelTarget = element.labelTarget || element;
52354 
52355 	    setLabel(label, text);
52356 
52357 	    return [ label, labelTarget ];
52358 	  }
52359 
52360 	  function preExecute(ctx) {
52361 	    var element = ctx.element,
52362 	        businessObject = element.businessObject,
52363 	        newLabel = ctx.newLabel;
52364 
52365 	    if (!isLabel$6(element)
52366 	        && isLabelExternal(element)
52367 	        && !hasExternalLabel(element)
52368 	        && !isEmptyText(newLabel)) {
52369 
52370 	      // create label
52371 	      var paddingTop = 7;
52372 
52373 	      var labelCenter = getExternalLabelMid(element);
52374 
52375 	      labelCenter = {
52376 	        x: labelCenter.x,
52377 	        y: labelCenter.y + paddingTop
52378 	      };
52379 
52380 	      modeling.createLabel(element, labelCenter, {
52381 	        id: businessObject.id + '_label',
52382 	        businessObject: businessObject
52383 	      });
52384 	    }
52385 	  }
52386 
52387 	  function execute(ctx) {
52388 	    ctx.oldLabel = getLabel(ctx.element);
52389 	    return setText(ctx.element, ctx.newLabel);
52390 	  }
52391 
52392 	  function revert(ctx) {
52393 	    return setText(ctx.element, ctx.oldLabel);
52394 	  }
52395 
52396 	  function postExecute(ctx) {
52397 	    var element = ctx.element,
52398 	        label = element.label || element,
52399 	        newLabel = ctx.newLabel,
52400 	        newBounds = ctx.newBounds,
52401 	        hints = ctx.hints || {};
52402 
52403 	    // ignore internal labels for elements except text annotations
52404 	    if (!isLabel$6(label) && !is$1(label, 'bpmn:TextAnnotation')) {
52405 	      return;
52406 	    }
52407 
52408 	    if (isLabel$6(label) && isEmptyText(newLabel)) {
52409 
52410 	      if (hints.removeShape !== false) {
52411 	        modeling.removeShape(label, { unsetLabel: false });
52412 	      }
52413 
52414 	      return;
52415 	    }
52416 
52417 	    var text = getLabel(label);
52418 
52419 	    // resize element based on label _or_ pre-defined bounds
52420 	    if (typeof newBounds === 'undefined') {
52421 	      newBounds = textRenderer.getExternalLabelBounds(label, text);
52422 	    }
52423 
52424 	    // setting newBounds to false or _null_ will
52425 	    // disable the postExecute resize operation
52426 	    if (newBounds) {
52427 	      modeling.resizeShape(label, newBounds, NULL_DIMENSIONS);
52428 	    }
52429 	  }
52430 
52431 	  // API
52432 
52433 	  this.preExecute = preExecute;
52434 	  this.execute = execute;
52435 	  this.revert = revert;
52436 	  this.postExecute = postExecute;
52437 	}
52438 
52439 	UpdateLabelHandler.$inject = [
52440 	  'modeling',
52441 	  'textRenderer'
52442 	];
52443 
52444 
52445 	// helpers ///////////////////////
52446 
52447 	function isEmptyText(label) {
52448 	  return !label || !label.trim();
52449 	}
52450 
52451 	/**
52452 	 * BPMN 2.0 modeling features activator
52453 	 *
52454 	 * @param {EventBus} eventBus
52455 	 * @param {ElementFactory} elementFactory
52456 	 * @param {CommandStack} commandStack
52457 	 * @param {BpmnRules} bpmnRules
52458 	 */
52459 	function Modeling(
52460 	    eventBus, elementFactory, commandStack,
52461 	    bpmnRules) {
52462 
52463 	  Modeling$1.call(this, eventBus, elementFactory, commandStack);
52464 
52465 	  this._bpmnRules = bpmnRules;
52466 	}
52467 
52468 	inherits$1(Modeling, Modeling$1);
52469 
52470 	Modeling.$inject = [
52471 	  'eventBus',
52472 	  'elementFactory',
52473 	  'commandStack',
52474 	  'bpmnRules'
52475 	];
52476 
52477 
52478 	Modeling.prototype.getHandlers = function() {
52479 	  var handlers = Modeling$1.prototype.getHandlers.call(this);
52480 
52481 	  handlers['element.updateModdleProperties'] = UpdateModdlePropertiesHandler;
52482 	  handlers['element.updateProperties'] = UpdatePropertiesHandler;
52483 	  handlers['canvas.updateRoot'] = UpdateCanvasRootHandler;
52484 	  handlers['lane.add'] = AddLaneHandler;
52485 	  handlers['lane.resize'] = ResizeLaneHandler;
52486 	  handlers['lane.split'] = SplitLaneHandler;
52487 	  handlers['lane.updateRefs'] = UpdateFlowNodeRefsHandler;
52488 	  handlers['id.updateClaim'] = IdClaimHandler;
52489 	  handlers['element.setColor'] = SetColorHandler;
52490 	  handlers['element.updateLabel'] = UpdateLabelHandler;
52491 
52492 	  return handlers;
52493 	};
52494 
52495 
52496 	Modeling.prototype.updateLabel = function(element, newLabel, newBounds, hints) {
52497 	  this._commandStack.execute('element.updateLabel', {
52498 	    element: element,
52499 	    newLabel: newLabel,
52500 	    newBounds: newBounds,
52501 	    hints: hints || {}
52502 	  });
52503 	};
52504 
52505 
52506 	Modeling.prototype.connect = function(source, target, attrs, hints) {
52507 
52508 	  var bpmnRules = this._bpmnRules;
52509 
52510 	  if (!attrs) {
52511 	    attrs = bpmnRules.canConnect(source, target);
52512 	  }
52513 
52514 	  if (!attrs) {
52515 	    return;
52516 	  }
52517 
52518 	  return this.createConnection(source, target, attrs, source.parent, hints);
52519 	};
52520 
52521 
52522 	Modeling.prototype.updateModdleProperties = function(element, moddleElement, properties) {
52523 	  this._commandStack.execute('element.updateModdleProperties', {
52524 	    element: element,
52525 	    moddleElement: moddleElement,
52526 	    properties: properties
52527 	  });
52528 	};
52529 
52530 	Modeling.prototype.updateProperties = function(element, properties) {
52531 	  this._commandStack.execute('element.updateProperties', {
52532 	    element: element,
52533 	    properties: properties
52534 	  });
52535 	};
52536 
52537 	Modeling.prototype.resizeLane = function(laneShape, newBounds, balanced) {
52538 	  this._commandStack.execute('lane.resize', {
52539 	    shape: laneShape,
52540 	    newBounds: newBounds,
52541 	    balanced: balanced
52542 	  });
52543 	};
52544 
52545 	Modeling.prototype.addLane = function(targetLaneShape, location) {
52546 	  var context = {
52547 	    shape: targetLaneShape,
52548 	    location: location
52549 	  };
52550 
52551 	  this._commandStack.execute('lane.add', context);
52552 
52553 	  return context.newLane;
52554 	};
52555 
52556 	Modeling.prototype.splitLane = function(targetLane, count) {
52557 	  this._commandStack.execute('lane.split', {
52558 	    shape: targetLane,
52559 	    count: count
52560 	  });
52561 	};
52562 
52563 	/**
52564 	 * Transform the current diagram into a collaboration.
52565 	 *
52566 	 * @return {djs.model.Root} the new root element
52567 	 */
52568 	Modeling.prototype.makeCollaboration = function() {
52569 
52570 	  var collaborationElement = this._create('root', {
52571 	    type: 'bpmn:Collaboration'
52572 	  });
52573 
52574 	  var context = {
52575 	    newRoot: collaborationElement
52576 	  };
52577 
52578 	  this._commandStack.execute('canvas.updateRoot', context);
52579 
52580 	  return collaborationElement;
52581 	};
52582 
52583 	Modeling.prototype.updateLaneRefs = function(flowNodeShapes, laneShapes) {
52584 
52585 	  this._commandStack.execute('lane.updateRefs', {
52586 	    flowNodeShapes: flowNodeShapes,
52587 	    laneShapes: laneShapes
52588 	  });
52589 	};
52590 
52591 	/**
52592 	 * Transform the current diagram into a process.
52593 	 *
52594 	 * @return {djs.model.Root} the new root element
52595 	 */
52596 	Modeling.prototype.makeProcess = function() {
52597 
52598 	  var processElement = this._create('root', {
52599 	    type: 'bpmn:Process'
52600 	  });
52601 
52602 	  var context = {
52603 	    newRoot: processElement
52604 	  };
52605 
52606 	  this._commandStack.execute('canvas.updateRoot', context);
52607 	};
52608 
52609 
52610 	Modeling.prototype.claimId = function(id, moddleElement) {
52611 	  this._commandStack.execute('id.updateClaim', {
52612 	    id: id,
52613 	    element: moddleElement,
52614 	    claiming: true
52615 	  });
52616 	};
52617 
52618 
52619 	Modeling.prototype.unclaimId = function(id, moddleElement) {
52620 	  this._commandStack.execute('id.updateClaim', {
52621 	    id: id,
52622 	    element: moddleElement
52623 	  });
52624 	};
52625 
52626 	Modeling.prototype.setColor = function(elements, colors) {
52627 	  if (!elements.length) {
52628 	    elements = [ elements ];
52629 	  }
52630 
52631 	  this._commandStack.execute('element.setColor', {
52632 	    elements: elements,
52633 	    colors: colors
52634 	  });
52635 	};
52636 
52637 	/**
52638 	 * A base connection layouter implementation
52639 	 * that layouts the connection by directly connecting
52640 	 * mid(source) + mid(target).
52641 	 */
52642 	function BaseLayouter() {}
52643 
52644 
52645 	/**
52646 	 * Return the new layouted waypoints for the given connection.
52647 	 *
52648 	 * The connection passed is still unchanged; you may figure out about
52649 	 * the new connection start / end via the layout hints provided.
52650 	 *
52651 	 * @param {djs.model.Connection} connection
52652 	 * @param {Object} [hints]
52653 	 * @param {Point} [hints.connectionStart]
52654 	 * @param {Point} [hints.connectionEnd]
52655 	 * @param {Point} [hints.source]
52656 	 * @param {Point} [hints.target]
52657 	 *
52658 	 * @return {Array<Point>} the layouted connection waypoints
52659 	 */
52660 	BaseLayouter.prototype.layoutConnection = function(connection, hints) {
52661 
52662 	  hints = hints || {};
52663 
52664 	  return [
52665 	    hints.connectionStart || getMid(hints.source || connection.source),
52666 	    hints.connectionEnd || getMid(hints.target || connection.target)
52667 	  ];
52668 	};
52669 
52670 	var MIN_SEGMENT_LENGTH = 20,
52671 	    POINT_ORIENTATION_PADDING = 5;
52672 
52673 	var round$1 = Math.round;
52674 
52675 	var INTERSECTION_THRESHOLD = 20,
52676 	    ORIENTATION_THRESHOLD = {
52677 	      'h:h': 20,
52678 	      'v:v': 20,
52679 	      'h:v': -10,
52680 	      'v:h': -10
52681 	    };
52682 
52683 	function needsTurn(orientation, startDirection) {
52684 	  return !{
52685 	    t: /top/,
52686 	    r: /right/,
52687 	    b: /bottom/,
52688 	    l: /left/,
52689 	    h: /./,
52690 	    v: /./
52691 	  }[startDirection].test(orientation);
52692 	}
52693 
52694 	function canLayoutStraight(direction, targetOrientation) {
52695 	  return {
52696 	    t: /top/,
52697 	    r: /right/,
52698 	    b: /bottom/,
52699 	    l: /left/,
52700 	    h: /left|right/,
52701 	    v: /top|bottom/
52702 	  }[direction].test(targetOrientation);
52703 	}
52704 
52705 	function getSegmentBendpoints(a, b, directions) {
52706 	  var orientation = getOrientation(b, a, POINT_ORIENTATION_PADDING);
52707 
52708 	  var startDirection = directions.split(':')[0];
52709 
52710 	  var xmid = round$1((b.x - a.x) / 2 + a.x),
52711 	      ymid = round$1((b.y - a.y) / 2 + a.y);
52712 
52713 	  var segmentEnd, segmentDirections;
52714 
52715 	  var layoutStraight = canLayoutStraight(startDirection, orientation),
52716 	      layoutHorizontal = /h|r|l/.test(startDirection),
52717 	      layoutTurn = false;
52718 
52719 	  var turnNextDirections = false;
52720 
52721 	  if (layoutStraight) {
52722 	    segmentEnd = layoutHorizontal ? { x: xmid, y: a.y } : { x: a.x, y: ymid };
52723 
52724 	    segmentDirections = layoutHorizontal ? 'h:h' : 'v:v';
52725 	  } else {
52726 	    layoutTurn = needsTurn(orientation, startDirection);
52727 
52728 	    segmentDirections = layoutHorizontal ? 'h:v' : 'v:h';
52729 
52730 	    if (layoutTurn) {
52731 
52732 	      if (layoutHorizontal) {
52733 	        turnNextDirections = ymid === a.y;
52734 
52735 	        segmentEnd = {
52736 	          x: a.x + MIN_SEGMENT_LENGTH * (/l/.test(startDirection) ? -1 : 1),
52737 	          y: turnNextDirections ? ymid + MIN_SEGMENT_LENGTH : ymid
52738 	        };
52739 	      } else {
52740 	        turnNextDirections = xmid === a.x;
52741 
52742 	        segmentEnd = {
52743 	          x: turnNextDirections ? xmid + MIN_SEGMENT_LENGTH : xmid,
52744 	          y: a.y + MIN_SEGMENT_LENGTH * (/t/.test(startDirection) ? -1 : 1)
52745 	        };
52746 	      }
52747 
52748 	    } else {
52749 	      segmentEnd = {
52750 	        x: xmid,
52751 	        y: ymid
52752 	      };
52753 	    }
52754 	  }
52755 
52756 	  return {
52757 	    waypoints: getBendpoints(a, segmentEnd, segmentDirections).concat(segmentEnd),
52758 	    directions:  segmentDirections,
52759 	    turnNextDirections: turnNextDirections
52760 	  };
52761 	}
52762 
52763 	function getStartSegment(a, b, directions) {
52764 	  return getSegmentBendpoints(a, b, directions);
52765 	}
52766 
52767 	function getEndSegment(a, b, directions) {
52768 	  var invertedSegment = getSegmentBendpoints(b, a, invertDirections(directions));
52769 
52770 	  return {
52771 	    waypoints: invertedSegment.waypoints.slice().reverse(),
52772 	    directions: invertDirections(invertedSegment.directions),
52773 	    turnNextDirections: invertedSegment.turnNextDirections
52774 	  };
52775 	}
52776 
52777 	function getMidSegment(startSegment, endSegment) {
52778 
52779 	  var startDirection = startSegment.directions.split(':')[1],
52780 	      endDirection = endSegment.directions.split(':')[0];
52781 
52782 	  if (startSegment.turnNextDirections) {
52783 	    startDirection = startDirection == 'h' ? 'v' : 'h';
52784 	  }
52785 
52786 	  if (endSegment.turnNextDirections) {
52787 	    endDirection = endDirection == 'h' ? 'v' : 'h';
52788 	  }
52789 
52790 	  var directions = startDirection + ':' + endDirection;
52791 
52792 	  var bendpoints = getBendpoints(
52793 	    startSegment.waypoints[startSegment.waypoints.length - 1],
52794 	    endSegment.waypoints[0],
52795 	    directions
52796 	  );
52797 
52798 	  return {
52799 	    waypoints: bendpoints,
52800 	    directions: directions
52801 	  };
52802 	}
52803 
52804 	function invertDirections(directions) {
52805 	  return directions.split(':').reverse().join(':');
52806 	}
52807 
52808 	/**
52809 	 * Handle simple layouts with maximum two bendpoints.
52810 	 */
52811 	function getSimpleBendpoints(a, b, directions) {
52812 
52813 	  var xmid = round$1((b.x - a.x) / 2 + a.x),
52814 	      ymid = round$1((b.y - a.y) / 2 + a.y);
52815 
52816 	  // one point, right or left from a
52817 	  if (directions === 'h:v') {
52818 	    return [ { x: b.x, y: a.y } ];
52819 	  }
52820 
52821 	  // one point, above or below a
52822 	  if (directions === 'v:h') {
52823 	    return [ { x: a.x, y: b.y } ];
52824 	  }
52825 
52826 	  // vertical segment between a and b
52827 	  if (directions === 'h:h') {
52828 	    return [
52829 	      { x: xmid, y: a.y },
52830 	      { x: xmid, y: b.y }
52831 	    ];
52832 	  }
52833 
52834 	  // horizontal segment between a and b
52835 	  if (directions === 'v:v') {
52836 	    return [
52837 	      { x: a.x, y: ymid },
52838 	      { x: b.x, y: ymid }
52839 	    ];
52840 	  }
52841 
52842 	  throw new Error('invalid directions: can only handle varians of [hv]:[hv]');
52843 	}
52844 
52845 
52846 	/**
52847 	 * Returns the mid points for a manhattan connection between two points.
52848 	 *
52849 	 * @example h:h (horizontal:horizontal)
52850 	 *
52851 	 * [a]----[x]
52852 	 *         |
52853 	 *        [x]----[b]
52854 	 *
52855 	 * @example h:v (horizontal:vertical)
52856 	 *
52857 	 * [a]----[x]
52858 	 *         |
52859 	 *        [b]
52860 	 *
52861 	 * @example h:r (horizontal:right)
52862 	 *
52863 	 * [a]----[x]
52864 	 *         |
52865 	 *    [b]-[x]
52866 	 *
52867 	 * @param  {Point} a
52868 	 * @param  {Point} b
52869 	 * @param  {string} directions
52870 	 *
52871 	 * @return {Array<Point>}
52872 	 */
52873 	function getBendpoints(a, b, directions) {
52874 	  directions = directions || 'h:h';
52875 
52876 	  if (!isValidDirections(directions)) {
52877 	    throw new Error(
52878 	      'unknown directions: <' + directions + '>: ' +
52879 	      'must be specified as <start>:<end> ' +
52880 	      'with start/end in { h,v,t,r,b,l }'
52881 	    );
52882 	  }
52883 
52884 	  // compute explicit directions, involving trbl dockings
52885 	  // using a three segmented layouting algorithm
52886 	  if (isExplicitDirections(directions)) {
52887 	    var startSegment = getStartSegment(a, b, directions),
52888 	        endSegment = getEndSegment(a, b, directions),
52889 	        midSegment = getMidSegment(startSegment, endSegment);
52890 
52891 	    return [].concat(
52892 	      startSegment.waypoints,
52893 	      midSegment.waypoints,
52894 	      endSegment.waypoints
52895 	    );
52896 	  }
52897 
52898 	  // handle simple [hv]:[hv] cases that can be easily computed
52899 	  return getSimpleBendpoints(a, b, directions);
52900 	}
52901 
52902 	/**
52903 	 * Create a connection between the two points according
52904 	 * to the manhattan layout (only horizontal and vertical) edges.
52905 	 *
52906 	 * @param {Point} a
52907 	 * @param {Point} b
52908 	 *
52909 	 * @param {string} [directions='h:h'] specifies manhattan directions for each point as {adirection}:{bdirection}.
52910 	                   A directionfor a point is either `h` (horizontal) or `v` (vertical)
52911 	 *
52912 	 * @return {Array<Point>}
52913 	 */
52914 	function connectPoints(a, b, directions) {
52915 
52916 	  var points = getBendpoints(a, b, directions);
52917 
52918 	  points.unshift(a);
52919 	  points.push(b);
52920 
52921 	  return withoutRedundantPoints(points);
52922 	}
52923 
52924 
52925 	/**
52926 	 * Connect two rectangles using a manhattan layouted connection.
52927 	 *
52928 	 * @param {Bounds} source source rectangle
52929 	 * @param {Bounds} target target rectangle
52930 	 * @param {Point} [start] source docking
52931 	 * @param {Point} [end] target docking
52932 	 *
52933 	 * @param {Object} [hints]
52934 	 * @param {string} [hints.preserveDocking=source] preserve docking on selected side
52935 	 * @param {Array<string>} [hints.preferredLayouts]
52936 	 * @param {Point|boolean} [hints.connectionStart] whether the start changed
52937 	 * @param {Point|boolean} [hints.connectionEnd] whether the end changed
52938 	 *
52939 	 * @return {Array<Point>} connection points
52940 	 */
52941 	function connectRectangles(source, target, start, end, hints) {
52942 
52943 	  var preferredLayouts = hints && hints.preferredLayouts || [];
52944 
52945 	  var preferredLayout = without(preferredLayouts, 'straight')[0] || 'h:h';
52946 
52947 	  var threshold = ORIENTATION_THRESHOLD[preferredLayout] || 0;
52948 
52949 	  var orientation = getOrientation(source, target, threshold);
52950 
52951 	  var directions = getDirections(orientation, preferredLayout);
52952 
52953 	  start = start || getMid(source);
52954 	  end = end || getMid(target);
52955 
52956 	  var directionSplit = directions.split(':');
52957 
52958 	  // compute actual docking points for start / end
52959 	  // this ensures we properly layout only parts of the
52960 	  // connection that lies in between the two rectangles
52961 	  var startDocking = getDockingPoint(start, source, directionSplit[0], invertOrientation(orientation)),
52962 	      endDocking = getDockingPoint(end, target, directionSplit[1], orientation);
52963 
52964 	  return connectPoints(startDocking, endDocking, directions);
52965 	}
52966 
52967 
52968 	/**
52969 	 * Repair the connection between two rectangles, of which one has been updated.
52970 	 *
52971 	 * @param {Bounds} source
52972 	 * @param {Bounds} target
52973 	 * @param {Point} [start]
52974 	 * @param {Point} [end]
52975 	 * @param {Array<Point>} [waypoints]
52976 	 * @param {Object} [hints]
52977 	 * @param {Array<string>} [hints.preferredLayouts] list of preferred layouts
52978 	 * @param {boolean} [hints.connectionStart]
52979 	 * @param {boolean} [hints.connectionEnd]
52980 	 *
52981 	 * @return {Array<Point>} repaired waypoints
52982 	 */
52983 	function repairConnection(source, target, start, end, waypoints, hints) {
52984 
52985 	  if (isArray$2(start)) {
52986 	    waypoints = start;
52987 	    hints = end;
52988 
52989 	    start = getMid(source);
52990 	    end = getMid(target);
52991 	  }
52992 
52993 	  hints = assign({ preferredLayouts: [] }, hints);
52994 	  waypoints = waypoints || [];
52995 
52996 	  var preferredLayouts = hints.preferredLayouts,
52997 	      preferStraight = preferredLayouts.indexOf('straight') !== -1,
52998 	      repairedWaypoints;
52999 
53000 	  // just layout non-existing or simple connections
53001 	  // attempt to render straight lines, if required
53002 
53003 	  // attempt to layout a straight line
53004 	  repairedWaypoints = preferStraight && tryLayoutStraight(source, target, start, end, hints);
53005 
53006 	  if (repairedWaypoints) {
53007 	    return repairedWaypoints;
53008 	  }
53009 
53010 	  // try to layout from end
53011 	  repairedWaypoints = hints.connectionEnd && tryRepairConnectionEnd(target, source, end, waypoints);
53012 
53013 	  if (repairedWaypoints) {
53014 	    return repairedWaypoints;
53015 	  }
53016 
53017 	  // try to layout from start
53018 	  repairedWaypoints = hints.connectionStart && tryRepairConnectionStart(source, target, start, waypoints);
53019 
53020 	  if (repairedWaypoints) {
53021 	    return repairedWaypoints;
53022 	  }
53023 
53024 	  // or whether nothing seems to have changed
53025 	  if (!hints.connectionStart && !hints.connectionEnd && waypoints && waypoints.length) {
53026 	    return waypoints;
53027 	  }
53028 
53029 	  // simply reconnect if nothing else worked
53030 	  return connectRectangles(source, target, start, end, hints);
53031 	}
53032 
53033 
53034 	function inRange(a, start, end) {
53035 	  return a >= start && a <= end;
53036 	}
53037 
53038 	function isInRange(axis, a, b) {
53039 	  var size = {
53040 	    x: 'width',
53041 	    y: 'height'
53042 	  };
53043 
53044 	  return inRange(a[axis], b[axis], b[axis] + b[size[axis]]);
53045 	}
53046 
53047 	/**
53048 	 * Layout a straight connection
53049 	 *
53050 	 * @param {Bounds} source
53051 	 * @param {Bounds} target
53052 	 * @param {Point} start
53053 	 * @param {Point} end
53054 	 * @param {Object} [hints]
53055 	 *
53056 	 * @return {Array<Point>|null} waypoints if straight layout worked
53057 	 */
53058 	function tryLayoutStraight(source, target, start, end, hints) {
53059 	  var axis = {},
53060 	      primaryAxis,
53061 	      orientation;
53062 
53063 	  orientation = getOrientation(source, target);
53064 
53065 	  // only layout a straight connection if shapes are
53066 	  // horizontally or vertically aligned
53067 	  if (!/^(top|bottom|left|right)$/.test(orientation)) {
53068 	    return null;
53069 	  }
53070 
53071 	  if (/top|bottom/.test(orientation)) {
53072 	    primaryAxis = 'x';
53073 	  }
53074 
53075 	  if (/left|right/.test(orientation)) {
53076 	    primaryAxis = 'y';
53077 	  }
53078 
53079 	  if (hints.preserveDocking === 'target') {
53080 
53081 	    if (!isInRange(primaryAxis, end, source)) {
53082 	      return null;
53083 	    }
53084 
53085 	    axis[primaryAxis] = end[primaryAxis];
53086 
53087 	    return [
53088 	      {
53089 	        x: axis.x !== undefined ? axis.x : start.x,
53090 	        y: axis.y !== undefined ? axis.y : start.y,
53091 	        original: {
53092 	          x: axis.x !== undefined ? axis.x : start.x,
53093 	          y: axis.y !== undefined ? axis.y : start.y
53094 	        }
53095 	      },
53096 	      {
53097 	        x: end.x,
53098 	        y: end.y
53099 	      }
53100 	    ];
53101 
53102 	  } else {
53103 
53104 	    if (!isInRange(primaryAxis, start, target)) {
53105 	      return null;
53106 	    }
53107 
53108 	    axis[primaryAxis] = start[primaryAxis];
53109 
53110 	    return [
53111 	      {
53112 	        x: start.x,
53113 	        y: start.y
53114 	      },
53115 	      {
53116 	        x: axis.x !== undefined ? axis.x : end.x,
53117 	        y: axis.y !== undefined ? axis.y : end.y,
53118 	        original: {
53119 	          x: axis.x !== undefined ? axis.x : end.x,
53120 	          y: axis.y !== undefined ? axis.y : end.y
53121 	        }
53122 	      }
53123 	    ];
53124 	  }
53125 
53126 	}
53127 
53128 	/**
53129 	 * Repair a connection from start.
53130 	 *
53131 	 * @param {Bounds} moved
53132 	 * @param {Bounds} other
53133 	 * @param {Point} newDocking
53134 	 * @param {Array<Point>} points originalPoints from moved to other
53135 	 *
53136 	 * @return {Array<Point>|null} the repaired points between the two rectangles
53137 	 */
53138 	function tryRepairConnectionStart(moved, other, newDocking, points) {
53139 	  return _tryRepairConnectionSide(moved, other, newDocking, points);
53140 	}
53141 
53142 	/**
53143 	 * Repair a connection from end.
53144 	 *
53145 	 * @param {Bounds} moved
53146 	 * @param {Bounds} other
53147 	 * @param {Point} newDocking
53148 	 * @param {Array<Point>} points originalPoints from moved to other
53149 	 *
53150 	 * @return {Array<Point>|null} the repaired points between the two rectangles
53151 	 */
53152 	function tryRepairConnectionEnd(moved, other, newDocking, points) {
53153 	  var waypoints = points.slice().reverse();
53154 
53155 	  waypoints = _tryRepairConnectionSide(moved, other, newDocking, waypoints);
53156 
53157 	  return waypoints ? waypoints.reverse() : null;
53158 	}
53159 
53160 	/**
53161 	 * Repair a connection from one side that moved.
53162 	 *
53163 	 * @param {Bounds} moved
53164 	 * @param {Bounds} other
53165 	 * @param {Point} newDocking
53166 	 * @param {Array<Point>} points originalPoints from moved to other
53167 	 *
53168 	 * @return {Array<Point>} the repaired points between the two rectangles
53169 	 */
53170 	function _tryRepairConnectionSide(moved, other, newDocking, points) {
53171 
53172 	  function needsRelayout(points) {
53173 	    if (points.length < 3) {
53174 	      return true;
53175 	    }
53176 
53177 	    if (points.length > 4) {
53178 	      return false;
53179 	    }
53180 
53181 	    // relayout if two points overlap
53182 	    // this is most likely due to
53183 	    return !!find(points, function(p, idx) {
53184 	      var q = points[idx - 1];
53185 
53186 	      return q && pointDistance(p, q) < 3;
53187 	    });
53188 	  }
53189 
53190 	  function repairBendpoint(candidate, oldPeer, newPeer) {
53191 
53192 	    var alignment = pointsAligned(oldPeer, candidate);
53193 
53194 	    switch (alignment) {
53195 	    case 'v':
53196 
53197 	      // repair horizontal alignment
53198 	      return { x: newPeer.x, y: candidate.y };
53199 	    case 'h':
53200 
53201 	      // repair vertical alignment
53202 	      return { x: candidate.x, y: newPeer.y };
53203 	    }
53204 
53205 	    return { x: candidate.x, y: candidate. y };
53206 	  }
53207 
53208 	  function removeOverlapping(points, a, b) {
53209 	    var i;
53210 
53211 	    for (i = points.length - 2; i !== 0; i--) {
53212 
53213 	      // intersects (?) break, remove all bendpoints up to this one and relayout
53214 	      if (pointInRect(points[i], a, INTERSECTION_THRESHOLD) ||
53215 	          pointInRect(points[i], b, INTERSECTION_THRESHOLD)) {
53216 
53217 	        // return sliced old connection
53218 	        return points.slice(i);
53219 	      }
53220 	    }
53221 
53222 	    return points;
53223 	  }
53224 
53225 	  // (0) only repair what has layoutable bendpoints
53226 
53227 	  // (1) if only one bendpoint and on shape moved onto other shapes axis
53228 	  //     (horizontally / vertically), relayout
53229 
53230 	  if (needsRelayout(points)) {
53231 	    return null;
53232 	  }
53233 
53234 	  var oldDocking = points[0],
53235 	      newPoints = points.slice(),
53236 	      slicedPoints;
53237 
53238 	  // (2) repair only last line segment and only if it was layouted before
53239 
53240 	  newPoints[0] = newDocking;
53241 	  newPoints[1] = repairBendpoint(newPoints[1], oldDocking, newDocking);
53242 
53243 
53244 	  // (3) if shape intersects with any bendpoint after repair,
53245 	  //     remove all segments up to this bendpoint and repair from there
53246 	  slicedPoints = removeOverlapping(newPoints, moved, other);
53247 
53248 	  if (slicedPoints !== newPoints) {
53249 	    newPoints = _tryRepairConnectionSide(moved, other, newDocking, slicedPoints);
53250 	  }
53251 
53252 	  // (4) do NOT repair if repaired bendpoints are aligned
53253 	  if (newPoints && pointsAligned(newPoints)) {
53254 	    return null;
53255 	  }
53256 
53257 	  return newPoints;
53258 	}
53259 
53260 
53261 	/**
53262 	 * Returns the manhattan directions connecting two rectangles
53263 	 * with the given orientation.
53264 	 *
53265 	 * Will always return the default layout, if it is specific
53266 	 * regarding sides already (trbl).
53267 	 *
53268 	 * @example
53269 	 *
53270 	 * getDirections('top'); // -> 'v:v'
53271 	 * getDirections('intersect'); // -> 't:t'
53272 	 *
53273 	 * getDirections('top-right', 'v:h'); // -> 'v:h'
53274 	 * getDirections('top-right', 'h:h'); // -> 'h:h'
53275 	 *
53276 	 *
53277 	 * @param {string} orientation
53278 	 * @param {string} defaultLayout
53279 	 *
53280 	 * @return {string}
53281 	 */
53282 	function getDirections(orientation, defaultLayout) {
53283 
53284 	  // don't override specific trbl directions
53285 	  if (isExplicitDirections(defaultLayout)) {
53286 	    return defaultLayout;
53287 	  }
53288 
53289 	  switch (orientation) {
53290 	  case 'intersect':
53291 	    return 't:t';
53292 
53293 	  case 'top':
53294 	  case 'bottom':
53295 	    return 'v:v';
53296 
53297 	  case 'left':
53298 	  case 'right':
53299 	    return 'h:h';
53300 
53301 	  // 'top-left'
53302 	  // 'top-right'
53303 	  // 'bottom-left'
53304 	  // 'bottom-right'
53305 	  default:
53306 	    return defaultLayout;
53307 	  }
53308 	}
53309 
53310 	function isValidDirections(directions) {
53311 	  return directions && /^h|v|t|r|b|l:h|v|t|r|b|l$/.test(directions);
53312 	}
53313 
53314 	function isExplicitDirections(directions) {
53315 	  return directions && /t|r|b|l/.test(directions);
53316 	}
53317 
53318 	function invertOrientation(orientation) {
53319 	  return {
53320 	    'top': 'bottom',
53321 	    'bottom': 'top',
53322 	    'left': 'right',
53323 	    'right': 'left',
53324 	    'top-left': 'bottom-right',
53325 	    'bottom-right': 'top-left',
53326 	    'top-right': 'bottom-left',
53327 	    'bottom-left': 'top-right',
53328 	  }[orientation];
53329 	}
53330 
53331 	function getDockingPoint(point, rectangle, dockingDirection, targetOrientation) {
53332 
53333 	  // ensure we end up with a specific docking direction
53334 	  // based on the targetOrientation, if <h|v> is being passed
53335 
53336 	  if (dockingDirection === 'h') {
53337 	    dockingDirection = /left/.test(targetOrientation) ? 'l' : 'r';
53338 	  }
53339 
53340 	  if (dockingDirection === 'v') {
53341 	    dockingDirection = /top/.test(targetOrientation) ? 't' : 'b';
53342 	  }
53343 
53344 	  if (dockingDirection === 't') {
53345 	    return { original: point, x: point.x, y: rectangle.y };
53346 	  }
53347 
53348 	  if (dockingDirection === 'r') {
53349 	    return { original: point, x: rectangle.x + rectangle.width, y: point.y };
53350 	  }
53351 
53352 	  if (dockingDirection === 'b') {
53353 	    return { original: point, x: point.x, y: rectangle.y + rectangle.height };
53354 	  }
53355 
53356 	  if (dockingDirection === 'l') {
53357 	    return { original: point, x: rectangle.x, y: point.y };
53358 	  }
53359 
53360 	  throw new Error('unexpected dockingDirection: <' + dockingDirection + '>');
53361 	}
53362 
53363 
53364 	/**
53365 	 * Return list of waypoints with redundant ones filtered out.
53366 	 *
53367 	 * @example
53368 	 *
53369 	 * Original points:
53370 	 *
53371 	 *   [x] ----- [x] ------ [x]
53372 	 *                         |
53373 	 *                        [x] ----- [x] - [x]
53374 	 *
53375 	 * Filtered:
53376 	 *
53377 	 *   [x] ---------------- [x]
53378 	 *                         |
53379 	 *                        [x] ----------- [x]
53380 	 *
53381 	 * @param  {Array<Point>} waypoints
53382 	 *
53383 	 * @return {Array<Point>}
53384 	 */
53385 	function withoutRedundantPoints(waypoints) {
53386 	  return waypoints.reduce(function(points, p, idx) {
53387 
53388 	    var previous = points[points.length - 1],
53389 	        next = waypoints[idx + 1];
53390 
53391 	    if (!pointsOnLine(previous, next, p, 0)) {
53392 	      points.push(p);
53393 	    }
53394 
53395 	    return points;
53396 	  }, []);
53397 	}
53398 
53399 	var ATTACH_ORIENTATION_PADDING = -10,
53400 	    BOUNDARY_TO_HOST_THRESHOLD$1 = 40;
53401 
53402 	var oppositeOrientationMapping = {
53403 	  'top': 'bottom',
53404 	  'top-right': 'bottom-left',
53405 	  'top-left': 'bottom-right',
53406 	  'right': 'left',
53407 	  'bottom': 'top',
53408 	  'bottom-right': 'top-left',
53409 	  'bottom-left': 'top-right',
53410 	  'left': 'right'
53411 	};
53412 
53413 	var orientationDirectionMapping = {
53414 	  top: 't',
53415 	  right: 'r',
53416 	  bottom: 'b',
53417 	  left: 'l'
53418 	};
53419 
53420 
53421 	function BpmnLayouter() {}
53422 
53423 	inherits$1(BpmnLayouter, BaseLayouter);
53424 
53425 
53426 	BpmnLayouter.prototype.layoutConnection = function(connection, hints) {
53427 	  if (!hints) {
53428 	    hints = {};
53429 	  }
53430 
53431 	  var source = hints.source || connection.source,
53432 	      target = hints.target || connection.target,
53433 	      waypoints = hints.waypoints || connection.waypoints,
53434 	      connectionStart = hints.connectionStart,
53435 	      connectionEnd = hints.connectionEnd;
53436 
53437 	  var manhattanOptions,
53438 	      updatedWaypoints;
53439 
53440 	  if (!connectionStart) {
53441 	    connectionStart = getConnectionDocking(waypoints && waypoints[ 0 ], source);
53442 	  }
53443 
53444 	  if (!connectionEnd) {
53445 	    connectionEnd = getConnectionDocking(waypoints && waypoints[ waypoints.length - 1 ], target);
53446 	  }
53447 
53448 	  // TODO(nikku): support vertical modeling
53449 	  // and invert preferredLayouts accordingly
53450 
53451 	  if (is$1(connection, 'bpmn:Association') ||
53452 	      is$1(connection, 'bpmn:DataAssociation')) {
53453 
53454 	    if (waypoints && !isCompensationAssociation(source, target)) {
53455 	      return [].concat([ connectionStart ], waypoints.slice(1, -1), [ connectionEnd ]);
53456 	    }
53457 	  }
53458 
53459 	  if (is$1(connection, 'bpmn:MessageFlow')) {
53460 	    manhattanOptions = getMessageFlowManhattanOptions(source, target);
53461 	  } else if (is$1(connection, 'bpmn:SequenceFlow') || isCompensationAssociation(source, target)) {
53462 
53463 	    // layout all connection between flow elements h:h, except for
53464 	    // (1) outgoing of boundary events -> layout based on attach orientation and target orientation
53465 	    // (2) incoming/outgoing of gateways -> v:h for outgoing, h:v for incoming
53466 	    // (3) loops
53467 	    if (source === target) {
53468 	      manhattanOptions = {
53469 	        preferredLayouts: getLoopPreferredLayout(source, connection)
53470 	      };
53471 	    } else if (is$1(source, 'bpmn:BoundaryEvent')) {
53472 	      manhattanOptions = {
53473 	        preferredLayouts: getBoundaryEventPreferredLayouts(source, target, connectionEnd)
53474 	      };
53475 	    } else if (isExpandedSubProcess(source) || isExpandedSubProcess(target)) {
53476 	      manhattanOptions = getSubProcessManhattanOptions(source);
53477 	    } else if (is$1(source, 'bpmn:Gateway')) {
53478 	      manhattanOptions = {
53479 	        preferredLayouts: [ 'v:h' ]
53480 	      };
53481 	    } else if (is$1(target, 'bpmn:Gateway')) {
53482 	      manhattanOptions = {
53483 	        preferredLayouts: [ 'h:v' ]
53484 	      };
53485 	    } else {
53486 	      manhattanOptions = {
53487 	        preferredLayouts: [ 'h:h' ]
53488 	      };
53489 	    }
53490 	  }
53491 
53492 	  if (manhattanOptions) {
53493 	    manhattanOptions = assign(manhattanOptions, hints);
53494 
53495 	    updatedWaypoints = withoutRedundantPoints(repairConnection(
53496 	      source,
53497 	      target,
53498 	      connectionStart,
53499 	      connectionEnd,
53500 	      waypoints,
53501 	      manhattanOptions
53502 	    ));
53503 	  }
53504 
53505 	  return updatedWaypoints || [ connectionStart, connectionEnd ];
53506 	};
53507 
53508 
53509 	// helpers //////////
53510 
53511 	function getAttachOrientation(attachedElement) {
53512 	  var hostElement = attachedElement.host;
53513 
53514 	  return getOrientation(getMid(attachedElement), hostElement, ATTACH_ORIENTATION_PADDING);
53515 	}
53516 
53517 	function getMessageFlowManhattanOptions(source, target) {
53518 	  return {
53519 	    preferredLayouts: [ 'straight', 'v:v' ],
53520 	    preserveDocking: getMessageFlowPreserveDocking(source, target)
53521 	  };
53522 	}
53523 
53524 	function getMessageFlowPreserveDocking(source, target) {
53525 
53526 	  // (1) docking element connected to participant has precedence
53527 	  if (is$1(target, 'bpmn:Participant')) {
53528 	    return 'source';
53529 	  }
53530 
53531 	  if (is$1(source, 'bpmn:Participant')) {
53532 	    return 'target';
53533 	  }
53534 
53535 	  // (2) docking element connected to expanded sub-process has precedence
53536 	  if (isExpandedSubProcess(target)) {
53537 	    return 'source';
53538 	  }
53539 
53540 	  if (isExpandedSubProcess(source)) {
53541 	    return 'target';
53542 	  }
53543 
53544 	  // (3) docking event has precedence
53545 	  if (is$1(target, 'bpmn:Event')) {
53546 	    return 'target';
53547 	  }
53548 
53549 	  if (is$1(source, 'bpmn:Event')) {
53550 	    return 'source';
53551 	  }
53552 
53553 	  return null;
53554 	}
53555 
53556 	function getSubProcessManhattanOptions(source) {
53557 	  return {
53558 	    preferredLayouts: [ 'straight', 'h:h' ],
53559 	    preserveDocking: getSubProcessPreserveDocking(source)
53560 	  };
53561 	}
53562 
53563 	function getSubProcessPreserveDocking(source) {
53564 	  return isExpandedSubProcess(source) ? 'target' : 'source';
53565 	}
53566 
53567 	function getConnectionDocking(point, shape) {
53568 	  return point ? (point.original || point) : getMid(shape);
53569 	}
53570 
53571 	function isCompensationAssociation(source, target) {
53572 	  return is$1(target, 'bpmn:Activity') &&
53573 	    is$1(source, 'bpmn:BoundaryEvent') &&
53574 	    target.businessObject.isForCompensation;
53575 	}
53576 
53577 	function isExpandedSubProcess(element) {
53578 	  return is$1(element, 'bpmn:SubProcess') && isExpanded(element);
53579 	}
53580 
53581 	function isSame(a, b) {
53582 	  return a === b;
53583 	}
53584 
53585 	function isAnyOrientation(orientation, orientations) {
53586 	  return orientations.indexOf(orientation) !== -1;
53587 	}
53588 
53589 	function getHorizontalOrientation(orientation) {
53590 	  var matches = /right|left/.exec(orientation);
53591 
53592 	  return matches && matches[0];
53593 	}
53594 
53595 	function getVerticalOrientation(orientation) {
53596 	  var matches = /top|bottom/.exec(orientation);
53597 
53598 	  return matches && matches[0];
53599 	}
53600 
53601 	function isOppositeOrientation(a, b) {
53602 	  return oppositeOrientationMapping[a] === b;
53603 	}
53604 
53605 	function isOppositeHorizontalOrientation(a, b) {
53606 	  var horizontalOrientation = getHorizontalOrientation(a);
53607 
53608 	  var oppositeHorizontalOrientation = oppositeOrientationMapping[horizontalOrientation];
53609 
53610 	  return b.indexOf(oppositeHorizontalOrientation) !== -1;
53611 	}
53612 
53613 	function isOppositeVerticalOrientation(a, b) {
53614 	  var verticalOrientation = getVerticalOrientation(a);
53615 
53616 	  var oppositeVerticalOrientation = oppositeOrientationMapping[verticalOrientation];
53617 
53618 	  return b.indexOf(oppositeVerticalOrientation) !== -1;
53619 	}
53620 
53621 	function isHorizontalOrientation(orientation) {
53622 	  return orientation === 'right' || orientation === 'left';
53623 	}
53624 
53625 	function getLoopPreferredLayout(source, connection) {
53626 	  var waypoints = connection.waypoints;
53627 
53628 	  var orientation = waypoints && waypoints.length && getOrientation(waypoints[0], source);
53629 
53630 	  if (orientation === 'top') {
53631 	    return [ 't:r' ];
53632 	  } else if (orientation === 'right') {
53633 	    return [ 'r:b' ];
53634 	  } else if (orientation === 'left') {
53635 	    return [ 'l:t' ];
53636 	  }
53637 
53638 	  return [ 'b:l' ];
53639 	}
53640 
53641 	function getBoundaryEventPreferredLayouts(source, target, end) {
53642 	  var sourceMid = getMid(source),
53643 	      targetMid = getMid(target),
53644 	      attachOrientation = getAttachOrientation(source),
53645 	      sourceLayout,
53646 	      targetLayout;
53647 
53648 	  var isLoop = isSame(source.host, target);
53649 
53650 	  var attachedToSide = isAnyOrientation(attachOrientation, [ 'top', 'right', 'bottom', 'left' ]);
53651 
53652 	  var targetOrientation = getOrientation(targetMid, sourceMid, {
53653 	    x: source.width / 2 + target.width / 2,
53654 	    y: source.height / 2 + target.height / 2
53655 	  });
53656 
53657 	  if (isLoop) {
53658 	    return getBoundaryEventLoopLayout(attachOrientation, attachedToSide, source, target, end);
53659 	  }
53660 
53661 	  // source layout
53662 	  sourceLayout = getBoundaryEventSourceLayout(attachOrientation, targetOrientation, attachedToSide);
53663 
53664 	  // target layout
53665 	  targetLayout = getBoundaryEventTargetLayout(attachOrientation, targetOrientation, attachedToSide);
53666 
53667 	  return [ sourceLayout + ':' + targetLayout ];
53668 	}
53669 
53670 	function getBoundaryEventLoopLayout(attachOrientation, attachedToSide, source, target, end) {
53671 	  var orientation = attachedToSide ? attachOrientation : getVerticalOrientation(attachOrientation),
53672 	      sourceLayout = orientationDirectionMapping[ orientation ],
53673 	      targetLayout;
53674 
53675 	  if (attachedToSide) {
53676 	    if (isHorizontalOrientation(attachOrientation)) {
53677 	      targetLayout = shouldConnectToSameSide('y', source, target, end) ? 'h' : 'b';
53678 	    } else {
53679 	      targetLayout = shouldConnectToSameSide('x', source, target, end) ? 'v' : 'l';
53680 	    }
53681 	  } else {
53682 	    targetLayout = 'v';
53683 	  }
53684 
53685 	  return [ sourceLayout + ':' + targetLayout ];
53686 	}
53687 
53688 	function shouldConnectToSameSide(axis, source, target, end) {
53689 	  var threshold = BOUNDARY_TO_HOST_THRESHOLD$1;
53690 
53691 	  return !(
53692 	    areCloseOnAxis(axis, end, target, threshold) ||
53693 	    areCloseOnAxis(axis, end, {
53694 	      x: target.x + target.width,
53695 	      y: target.y + target.height
53696 	    }, threshold) ||
53697 	    areCloseOnAxis(axis, end, getMid(source), threshold)
53698 	  );
53699 	}
53700 
53701 	function areCloseOnAxis(axis, a, b, threshold) {
53702 	  return Math.abs(a[ axis ] - b[ axis ]) < threshold;
53703 	}
53704 
53705 	function getBoundaryEventSourceLayout(attachOrientation, targetOrientation, attachedToSide) {
53706 
53707 	  // attached to either top, right, bottom or left side
53708 	  if (attachedToSide) {
53709 	    return orientationDirectionMapping[ attachOrientation ];
53710 	  }
53711 
53712 	  // attached to either top-right, top-left, bottom-right or bottom-left corner
53713 
53714 	  // same vertical or opposite horizontal orientation
53715 	  if (isSame(
53716 	    getVerticalOrientation(attachOrientation), getVerticalOrientation(targetOrientation)
53717 	  ) || isOppositeOrientation(
53718 	    getHorizontalOrientation(attachOrientation), getHorizontalOrientation(targetOrientation)
53719 	  )) {
53720 	    return orientationDirectionMapping[ getVerticalOrientation(attachOrientation) ];
53721 	  }
53722 
53723 	  // fallback
53724 	  return orientationDirectionMapping[ getHorizontalOrientation(attachOrientation) ];
53725 	}
53726 
53727 	function getBoundaryEventTargetLayout(attachOrientation, targetOrientation, attachedToSide) {
53728 
53729 	  // attached to either top, right, bottom or left side
53730 	  if (attachedToSide) {
53731 	    if (isHorizontalOrientation(attachOrientation)) {
53732 
53733 	      // orientation is right or left
53734 
53735 	      // opposite horizontal orientation or same orientation
53736 	      if (
53737 	        isOppositeHorizontalOrientation(attachOrientation, targetOrientation) ||
53738 	        isSame(attachOrientation, targetOrientation)
53739 	      ) {
53740 	        return 'h';
53741 	      }
53742 
53743 	      // fallback
53744 	      return 'v';
53745 	    } else {
53746 
53747 	      // orientation is top or bottom
53748 
53749 	      // opposite vertical orientation or same orientation
53750 	      if (
53751 	        isOppositeVerticalOrientation(attachOrientation, targetOrientation) ||
53752 	        isSame(attachOrientation, targetOrientation)
53753 	      ) {
53754 	        return 'v';
53755 	      }
53756 
53757 	      // fallback
53758 	      return 'h';
53759 	    }
53760 	  }
53761 
53762 	  // attached to either top-right, top-left, bottom-right or bottom-left corner
53763 
53764 	  // orientation is right, left
53765 	  // or same vertical orientation but also right or left
53766 	  if (isHorizontalOrientation(targetOrientation) ||
53767 	    (isSame(getVerticalOrientation(attachOrientation), getVerticalOrientation(targetOrientation)) &&
53768 	      getHorizontalOrientation(targetOrientation))) {
53769 	    return 'h';
53770 	  } else {
53771 	    return 'v';
53772 	  }
53773 	}
53774 
53775 	function dockingToPoint(docking) {
53776 
53777 	  // use the dockings actual point and
53778 	  // retain the original docking
53779 	  return assign({ original: docking.point.original || docking.point }, docking.actual);
53780 	}
53781 
53782 
53783 	/**
53784 	 * A {@link ConnectionDocking} that crops connection waypoints based on
53785 	 * the path(s) of the connection source and target.
53786 	 *
53787 	 * @param {djs.core.ElementRegistry} elementRegistry
53788 	 */
53789 	function CroppingConnectionDocking(elementRegistry, graphicsFactory) {
53790 	  this._elementRegistry = elementRegistry;
53791 	  this._graphicsFactory = graphicsFactory;
53792 	}
53793 
53794 	CroppingConnectionDocking.$inject = [ 'elementRegistry', 'graphicsFactory' ];
53795 
53796 
53797 	/**
53798 	 * @inheritDoc ConnectionDocking#getCroppedWaypoints
53799 	 */
53800 	CroppingConnectionDocking.prototype.getCroppedWaypoints = function(connection, source, target) {
53801 
53802 	  source = source || connection.source;
53803 	  target = target || connection.target;
53804 
53805 	  var sourceDocking = this.getDockingPoint(connection, source, true),
53806 	      targetDocking = this.getDockingPoint(connection, target);
53807 
53808 	  var croppedWaypoints = connection.waypoints.slice(sourceDocking.idx + 1, targetDocking.idx);
53809 
53810 	  croppedWaypoints.unshift(dockingToPoint(sourceDocking));
53811 	  croppedWaypoints.push(dockingToPoint(targetDocking));
53812 
53813 	  return croppedWaypoints;
53814 	};
53815 
53816 	/**
53817 	 * Return the connection docking point on the specified shape
53818 	 *
53819 	 * @inheritDoc ConnectionDocking#getDockingPoint
53820 	 */
53821 	CroppingConnectionDocking.prototype.getDockingPoint = function(connection, shape, dockStart) {
53822 
53823 	  var waypoints = connection.waypoints,
53824 	      dockingIdx,
53825 	      dockingPoint,
53826 	      croppedPoint;
53827 
53828 	  dockingIdx = dockStart ? 0 : waypoints.length - 1;
53829 	  dockingPoint = waypoints[dockingIdx];
53830 
53831 	  croppedPoint = this._getIntersection(shape, connection, dockStart);
53832 
53833 	  return {
53834 	    point: dockingPoint,
53835 	    actual: croppedPoint || dockingPoint,
53836 	    idx: dockingIdx
53837 	  };
53838 	};
53839 
53840 
53841 	// helpers //////////////////////
53842 
53843 	CroppingConnectionDocking.prototype._getIntersection = function(shape, connection, takeFirst) {
53844 
53845 	  var shapePath = this._getShapePath(shape),
53846 	      connectionPath = this._getConnectionPath(connection);
53847 
53848 	  return getElementLineIntersection(shapePath, connectionPath, takeFirst);
53849 	};
53850 
53851 	CroppingConnectionDocking.prototype._getConnectionPath = function(connection) {
53852 	  return this._graphicsFactory.getConnectionPath(connection);
53853 	};
53854 
53855 	CroppingConnectionDocking.prototype._getShapePath = function(shape) {
53856 	  return this._graphicsFactory.getShapePath(shape);
53857 	};
53858 
53859 	CroppingConnectionDocking.prototype._getGfx = function(element) {
53860 	  return this._elementRegistry.getGraphics(element);
53861 	};
53862 
53863 	var ModelingModule = {
53864 	  __init__: [
53865 	    'modeling',
53866 	    'bpmnUpdater'
53867 	  ],
53868 	  __depends__: [
53869 	    BehaviorModule,
53870 	    RulesModule,
53871 	    DiOrderingModule,
53872 	    OrderingModule,
53873 	    ReplaceModule,
53874 	    CommandModule,
53875 	    TooltipsModule,
53876 	    LabelSupportModule,
53877 	    AttachSupportModule,
53878 	    SelectionModule,
53879 	    ChangeSupportModule,
53880 	    SpaceToolModule
53881 	  ],
53882 	  bpmnFactory: [ 'type', BpmnFactory ],
53883 	  bpmnUpdater: [ 'type', BpmnUpdater ],
53884 	  elementFactory: [ 'type', ElementFactory ],
53885 	  modeling: [ 'type', Modeling ],
53886 	  layouter: [ 'type', BpmnLayouter ],
53887 	  connectionDocking: [ 'type', CroppingConnectionDocking ]
53888 	};
53889 
53890 	var LOW_PRIORITY$2 = 500,
53891 	    MEDIUM_PRIORITY = 1250,
53892 	    HIGH_PRIORITY$2 = 1500;
53893 
53894 	var round = Math.round;
53895 
53896 	function mid(element) {
53897 	  return {
53898 	    x: element.x + round(element.width / 2),
53899 	    y: element.y + round(element.height / 2)
53900 	  };
53901 	}
53902 
53903 	/**
53904 	 * A plugin that makes shapes draggable / droppable.
53905 	 *
53906 	 * @param {EventBus} eventBus
53907 	 * @param {Dragging} dragging
53908 	 * @param {Modeling} modeling
53909 	 * @param {Selection} selection
53910 	 * @param {Rules} rules
53911 	 */
53912 	function MoveEvents(
53913 	    eventBus, dragging, modeling,
53914 	    selection, rules) {
53915 
53916 	  // rules
53917 
53918 	  function canMove(shapes, delta, position, target) {
53919 
53920 	    return rules.allowed('elements.move', {
53921 	      shapes: shapes,
53922 	      delta: delta,
53923 	      position: position,
53924 	      target: target
53925 	    });
53926 	  }
53927 
53928 
53929 	  // move events
53930 
53931 	  // assign a high priority to this handler to setup the environment
53932 	  // others may hook up later, e.g. at default priority and modify
53933 	  // the move environment.
53934 	  //
53935 	  // This sets up the context with
53936 	  //
53937 	  // * shape: the primary shape being moved
53938 	  // * shapes: a list of shapes to be moved
53939 	  // * validatedShapes: a list of shapes that are being checked
53940 	  //                    against the rules before and during move
53941 	  //
53942 	  eventBus.on('shape.move.start', HIGH_PRIORITY$2, function(event) {
53943 
53944 	    var context = event.context,
53945 	        shape = event.shape,
53946 	        shapes = selection.get().slice();
53947 
53948 	    // move only single shape if the dragged element
53949 	    // is not part of the current selection
53950 	    if (shapes.indexOf(shape) === -1) {
53951 	      shapes = [ shape ];
53952 	    }
53953 
53954 	    // ensure we remove nested elements in the collection
53955 	    // and add attachers for a proper dragger
53956 	    shapes = removeNested(shapes);
53957 
53958 	    // attach shapes to drag context
53959 	    assign(context, {
53960 	      shapes: shapes,
53961 	      validatedShapes: shapes,
53962 	      shape: shape
53963 	    });
53964 	  });
53965 
53966 
53967 	  // assign a high priority to this handler to setup the environment
53968 	  // others may hook up later, e.g. at default priority and modify
53969 	  // the move environment
53970 	  //
53971 	  eventBus.on('shape.move.start', MEDIUM_PRIORITY, function(event) {
53972 
53973 	    var context = event.context,
53974 	        validatedShapes = context.validatedShapes,
53975 	        canExecute;
53976 
53977 	    canExecute = context.canExecute = canMove(validatedShapes);
53978 
53979 	    // check if we can move the elements
53980 	    if (!canExecute) {
53981 	      return false;
53982 	    }
53983 	  });
53984 
53985 	  // assign a low priority to this handler
53986 	  // to let others modify the move event before we update
53987 	  // the context
53988 	  //
53989 	  eventBus.on('shape.move.move', LOW_PRIORITY$2, function(event) {
53990 
53991 	    var context = event.context,
53992 	        validatedShapes = context.validatedShapes,
53993 	        hover = event.hover,
53994 	        delta = { x: event.dx, y: event.dy },
53995 	        position = { x: event.x, y: event.y },
53996 	        canExecute;
53997 
53998 	    // check if we can move the elements
53999 	    canExecute = canMove(validatedShapes, delta, position, hover);
54000 
54001 	    context.delta = delta;
54002 	    context.canExecute = canExecute;
54003 
54004 	    // simply ignore move over
54005 	    if (canExecute === null) {
54006 	      context.target = null;
54007 
54008 	      return;
54009 	    }
54010 
54011 	    context.target = hover;
54012 	  });
54013 
54014 	  eventBus.on('shape.move.end', function(event) {
54015 
54016 	    var context = event.context;
54017 
54018 	    var delta = context.delta,
54019 	        canExecute = context.canExecute,
54020 	        isAttach = canExecute === 'attach',
54021 	        shapes = context.shapes;
54022 
54023 	    if (canExecute === false) {
54024 	      return false;
54025 	    }
54026 
54027 	    // ensure we have actual pixel values deltas
54028 	    // (important when zoom level was > 1 during move)
54029 	    delta.x = round(delta.x);
54030 	    delta.y = round(delta.y);
54031 
54032 	    if (delta.x === 0 && delta.y === 0) {
54033 
54034 	      // didn't move
54035 	      return;
54036 	    }
54037 
54038 	    modeling.moveElements(shapes, delta, context.target, {
54039 	      primaryShape: context.shape,
54040 	      attach: isAttach
54041 	    });
54042 	  });
54043 
54044 
54045 	  // move activation
54046 
54047 	  eventBus.on('element.mousedown', function(event) {
54048 
54049 	    if (!isPrimaryButton(event)) {
54050 	      return;
54051 	    }
54052 
54053 	    var originalEvent = getOriginal$1(event);
54054 
54055 	    if (!originalEvent) {
54056 	      throw new Error('must supply DOM mousedown event');
54057 	    }
54058 
54059 	    return start(originalEvent, event.element);
54060 	  });
54061 
54062 	  /**
54063 	   * Start move.
54064 	   *
54065 	   * @param {MouseEvent} event
54066 	   * @param {djs.model.Shape} shape
54067 	   * @param {boolean} [activate]
54068 	   * @param {Object} [context]
54069 	   */
54070 	  function start(event, element, activate, context) {
54071 	    if (isObject(activate)) {
54072 	      context = activate;
54073 	      activate = false;
54074 	    }
54075 
54076 	    // do not move connections or the root element
54077 	    if (element.waypoints || !element.parent) {
54078 	      return;
54079 	    }
54080 
54081 	    var referencePoint = mid(element);
54082 
54083 	    dragging.init(event, referencePoint, 'shape.move', {
54084 	      cursor: 'grabbing',
54085 	      autoActivate: activate,
54086 	      data: {
54087 	        shape: element,
54088 	        context: context || {}
54089 	      }
54090 	    });
54091 
54092 	    // we've handled the event
54093 	    return true;
54094 	  }
54095 
54096 	  // API
54097 
54098 	  this.start = start;
54099 	}
54100 
54101 	MoveEvents.$inject = [
54102 	  'eventBus',
54103 	  'dragging',
54104 	  'modeling',
54105 	  'selection',
54106 	  'rules'
54107 	];
54108 
54109 
54110 	/**
54111 	 * Return a filtered list of elements that do not contain
54112 	 * those nested into others.
54113 	 *
54114 	 * @param  {Array<djs.model.Base>} elements
54115 	 *
54116 	 * @return {Array<djs.model.Base>} filtered
54117 	 */
54118 	function removeNested(elements) {
54119 
54120 	  var ids = groupBy(elements, 'id');
54121 
54122 	  return filter(elements, function(element) {
54123 	    while ((element = element.parent)) {
54124 
54125 	      // parent in selection
54126 	      if (ids[element.id]) {
54127 	        return false;
54128 	      }
54129 	    }
54130 
54131 	    return true;
54132 	  });
54133 	}
54134 
54135 	var LOW_PRIORITY$1 = 499;
54136 
54137 	var MARKER_DRAGGING = 'djs-dragging',
54138 	    MARKER_OK$1 = 'drop-ok',
54139 	    MARKER_NOT_OK$1 = 'drop-not-ok',
54140 	    MARKER_NEW_PARENT = 'new-parent',
54141 	    MARKER_ATTACH = 'attach-ok';
54142 
54143 
54144 	/**
54145 	 * Provides previews for moving shapes when moving.
54146 	 *
54147 	 * @param {EventBus} eventBus
54148 	 * @param {ElementRegistry} elementRegistry
54149 	 * @param {Canvas} canvas
54150 	 * @param {Styles} styles
54151 	 */
54152 	function MovePreview(
54153 	    eventBus, canvas, styles, previewSupport) {
54154 
54155 	  function getVisualDragShapes(shapes) {
54156 	    var elements = getAllDraggedElements(shapes);
54157 
54158 	    var filteredElements = removeEdges(elements);
54159 
54160 	    return filteredElements;
54161 	  }
54162 
54163 	  function getAllDraggedElements(shapes) {
54164 	    var allShapes = selfAndAllChildren(shapes, true);
54165 
54166 	    var allConnections = map$1(allShapes, function(shape) {
54167 	      return (shape.incoming || []).concat(shape.outgoing || []);
54168 	    });
54169 
54170 	    return flatten(allShapes.concat(allConnections));
54171 	  }
54172 
54173 	  /**
54174 	   * Sets drop marker on an element.
54175 	   */
54176 	  function setMarker(element, marker) {
54177 
54178 	    [ MARKER_ATTACH, MARKER_OK$1, MARKER_NOT_OK$1, MARKER_NEW_PARENT ].forEach(function(m) {
54179 
54180 	      if (m === marker) {
54181 	        canvas.addMarker(element, m);
54182 	      } else {
54183 	        canvas.removeMarker(element, m);
54184 	      }
54185 	    });
54186 	  }
54187 
54188 	  /**
54189 	   * Make an element draggable.
54190 	   *
54191 	   * @param {Object} context
54192 	   * @param {djs.model.Base} element
54193 	   * @param {boolean} addMarker
54194 	   */
54195 	  function makeDraggable(context, element, addMarker) {
54196 
54197 	    previewSupport.addDragger(element, context.dragGroup);
54198 
54199 	    if (addMarker) {
54200 	      canvas.addMarker(element, MARKER_DRAGGING);
54201 	    }
54202 
54203 	    if (context.allDraggedElements) {
54204 	      context.allDraggedElements.push(element);
54205 	    } else {
54206 	      context.allDraggedElements = [ element ];
54207 	    }
54208 	  }
54209 
54210 	  // assign a low priority to this handler
54211 	  // to let others modify the move context before
54212 	  // we draw things
54213 	  eventBus.on('shape.move.start', LOW_PRIORITY$1, function(event) {
54214 	    var context = event.context,
54215 	        dragShapes = context.shapes,
54216 	        allDraggedElements = context.allDraggedElements;
54217 
54218 	    var visuallyDraggedShapes = getVisualDragShapes(dragShapes);
54219 
54220 	    if (!context.dragGroup) {
54221 	      var dragGroup = create$1('g');
54222 
54223 	      attr(dragGroup, styles.cls('djs-drag-group', [ 'no-events' ]));
54224 
54225 	      var activeLayer = canvas.getActiveLayer();
54226 
54227 	      append(activeLayer, dragGroup);
54228 
54229 	      context.dragGroup = dragGroup;
54230 	    }
54231 
54232 	    // add previews
54233 	    visuallyDraggedShapes.forEach(function(shape) {
54234 	      previewSupport.addDragger(shape, context.dragGroup);
54235 	    });
54236 
54237 	    // cache all dragged elements / gfx
54238 	    // so that we can quickly undo their state changes later
54239 	    if (!allDraggedElements) {
54240 	      allDraggedElements = getAllDraggedElements(dragShapes);
54241 	    } else {
54242 	      allDraggedElements = flatten([
54243 	        allDraggedElements,
54244 	        getAllDraggedElements(dragShapes)
54245 	      ]);
54246 	    }
54247 
54248 	    // add dragging marker
54249 	    forEach(allDraggedElements, function(e) {
54250 	      canvas.addMarker(e, MARKER_DRAGGING);
54251 	    });
54252 
54253 	    context.allDraggedElements = allDraggedElements;
54254 
54255 	    // determine, if any of the dragged elements have different parents
54256 	    context.differentParents = haveDifferentParents(dragShapes);
54257 	  });
54258 
54259 	  // update previews
54260 	  eventBus.on('shape.move.move', LOW_PRIORITY$1, function(event) {
54261 
54262 	    var context = event.context,
54263 	        dragGroup = context.dragGroup,
54264 	        target = context.target,
54265 	        parent = context.shape.parent,
54266 	        canExecute = context.canExecute;
54267 
54268 	    if (target) {
54269 	      if (canExecute === 'attach') {
54270 	        setMarker(target, MARKER_ATTACH);
54271 	      } else if (context.canExecute && target && target.id !== parent.id) {
54272 	        setMarker(target, MARKER_NEW_PARENT);
54273 	      } else {
54274 	        setMarker(target, context.canExecute ? MARKER_OK$1 : MARKER_NOT_OK$1);
54275 	      }
54276 	    }
54277 
54278 	    translate$2(dragGroup, event.dx, event.dy);
54279 	  });
54280 
54281 	  eventBus.on([ 'shape.move.out', 'shape.move.cleanup' ], function(event) {
54282 	    var context = event.context,
54283 	        target = context.target;
54284 
54285 	    if (target) {
54286 	      setMarker(target, null);
54287 	    }
54288 	  });
54289 
54290 	  // remove previews
54291 	  eventBus.on('shape.move.cleanup', function(event) {
54292 
54293 	    var context = event.context,
54294 	        allDraggedElements = context.allDraggedElements,
54295 	        dragGroup = context.dragGroup;
54296 
54297 
54298 	    // remove dragging marker
54299 	    forEach(allDraggedElements, function(e) {
54300 	      canvas.removeMarker(e, MARKER_DRAGGING);
54301 	    });
54302 
54303 	    if (dragGroup) {
54304 	      remove$1(dragGroup);
54305 	    }
54306 	  });
54307 
54308 
54309 	  // API //////////////////////
54310 
54311 	  /**
54312 	   * Make an element draggable.
54313 	   *
54314 	   * @param {Object} context
54315 	   * @param {djs.model.Base} element
54316 	   * @param {boolean} addMarker
54317 	   */
54318 	  this.makeDraggable = makeDraggable;
54319 	}
54320 
54321 	MovePreview.$inject = [
54322 	  'eventBus',
54323 	  'canvas',
54324 	  'styles',
54325 	  'previewSupport'
54326 	];
54327 
54328 
54329 	// helpers //////////////////////
54330 
54331 	/**
54332 	 * returns elements minus all connections
54333 	 * where source or target is not elements
54334 	 */
54335 	function removeEdges(elements) {
54336 
54337 	  var filteredElements = filter(elements, function(element) {
54338 
54339 	    if (!isConnection$2(element)) {
54340 	      return true;
54341 	    } else {
54342 
54343 	      return (
54344 	        find(elements, matchPattern({ id: element.source.id })) &&
54345 	        find(elements, matchPattern({ id: element.target.id }))
54346 	      );
54347 	    }
54348 	  });
54349 
54350 	  return filteredElements;
54351 	}
54352 
54353 	function haveDifferentParents(elements) {
54354 	  return size(groupBy(elements, function(e) { return e.parent && e.parent.id; })) !== 1;
54355 	}
54356 
54357 	/**
54358 	 * Checks if an element is a connection.
54359 	 */
54360 	function isConnection$2(element) {
54361 	  return element.waypoints;
54362 	}
54363 
54364 	var MoveModule = {
54365 	  __depends__: [
54366 	    InteractionEventsModule$1,
54367 	    SelectionModule,
54368 	    OutlineModule,
54369 	    RulesModule$1,
54370 	    DraggingModule,
54371 	    PreviewSupportModule
54372 	  ],
54373 	  __init__: [
54374 	    'move',
54375 	    'movePreview'
54376 	  ],
54377 	  move: [ 'type', MoveEvents ],
54378 	  movePreview: [ 'type', MovePreview ]
54379 	};
54380 
54381 	var TOGGLE_SELECTOR = '.djs-palette-toggle',
54382 	    ENTRY_SELECTOR = '.entry',
54383 	    ELEMENT_SELECTOR = TOGGLE_SELECTOR + ', ' + ENTRY_SELECTOR;
54384 
54385 	var PALETTE_OPEN_CLS = 'open',
54386 	    PALETTE_TWO_COLUMN_CLS = 'two-column';
54387 
54388 	var DEFAULT_PRIORITY = 1000;
54389 
54390 
54391 	/**
54392 	 * A palette containing modeling elements.
54393 	 */
54394 	function Palette(eventBus, canvas) {
54395 
54396 	  this._eventBus = eventBus;
54397 	  this._canvas = canvas;
54398 
54399 	  var self = this;
54400 
54401 	  eventBus.on('tool-manager.update', function(event) {
54402 	    var tool = event.tool;
54403 
54404 	    self.updateToolHighlight(tool);
54405 	  });
54406 
54407 	  eventBus.on('i18n.changed', function() {
54408 	    self._update();
54409 	  });
54410 
54411 	  eventBus.on('diagram.init', function() {
54412 
54413 	    self._diagramInitialized = true;
54414 
54415 	    self._rebuild();
54416 	  });
54417 	}
54418 
54419 	Palette.$inject = [ 'eventBus', 'canvas' ];
54420 
54421 
54422 	/**
54423 	 * Register a provider with the palette
54424 	 *
54425 	 * @param  {number} [priority=1000]
54426 	 * @param  {PaletteProvider} provider
54427 	 *
54428 	 * @example
54429 	 * const paletteProvider = {
54430 	 *   getPaletteEntries: function() {
54431 	 *     return function(entries) {
54432 	 *       return {
54433 	 *         ...entries,
54434 	 *         'entry-1': {
54435 	 *           label: 'My Entry',
54436 	 *           action: function() { alert("I have been clicked!"); }
54437 	 *         }
54438 	 *       };
54439 	 *     }
54440 	 *   }
54441 	 * };
54442 	 *
54443 	 * palette.registerProvider(800, paletteProvider);
54444 	 */
54445 	Palette.prototype.registerProvider = function(priority, provider) {
54446 	  if (!provider) {
54447 	    provider = priority;
54448 	    priority = DEFAULT_PRIORITY;
54449 	  }
54450 
54451 	  this._eventBus.on('palette.getProviders', priority, function(event) {
54452 	    event.providers.push(provider);
54453 	  });
54454 
54455 	  this._rebuild();
54456 	};
54457 
54458 
54459 	/**
54460 	 * Returns the palette entries
54461 	 *
54462 	 * @return {Object<string, PaletteEntryDescriptor>} map of entries
54463 	 */
54464 	Palette.prototype.getEntries = function() {
54465 	  var providers = this._getProviders();
54466 
54467 	  return providers.reduce(addPaletteEntries, {});
54468 	};
54469 
54470 	Palette.prototype._rebuild = function() {
54471 
54472 	  if (!this._diagramInitialized) {
54473 	    return;
54474 	  }
54475 
54476 	  var providers = this._getProviders();
54477 
54478 	  if (!providers.length) {
54479 	    return;
54480 	  }
54481 
54482 	  if (!this._container) {
54483 	    this._init();
54484 	  }
54485 
54486 	  this._update();
54487 	};
54488 
54489 	/**
54490 	 * Initialize
54491 	 */
54492 	Palette.prototype._init = function() {
54493 
54494 	  var self = this;
54495 
54496 	  var eventBus = this._eventBus;
54497 
54498 	  var parentContainer = this._getParentContainer();
54499 
54500 	  var container = this._container = domify(Palette.HTML_MARKUP);
54501 
54502 	  parentContainer.appendChild(container);
54503 
54504 	  delegate.bind(container, ELEMENT_SELECTOR, 'click', function(event) {
54505 
54506 	    var target = event.delegateTarget;
54507 
54508 	    if (matchesSelector(target, TOGGLE_SELECTOR)) {
54509 	      return self.toggle();
54510 	    }
54511 
54512 	    self.trigger('click', event);
54513 	  });
54514 
54515 	  // prevent drag propagation
54516 	  componentEvent.bind(container, 'mousedown', function(event) {
54517 	    event.stopPropagation();
54518 	  });
54519 
54520 	  // prevent drag propagation
54521 	  delegate.bind(container, ENTRY_SELECTOR, 'dragstart', function(event) {
54522 	    self.trigger('dragstart', event);
54523 	  });
54524 
54525 	  eventBus.on('canvas.resized', this._layoutChanged, this);
54526 
54527 	  eventBus.fire('palette.create', {
54528 	    container: container
54529 	  });
54530 	};
54531 
54532 	Palette.prototype._getProviders = function(id) {
54533 
54534 	  var event = this._eventBus.createEvent({
54535 	    type: 'palette.getProviders',
54536 	    providers: []
54537 	  });
54538 
54539 	  this._eventBus.fire(event);
54540 
54541 	  return event.providers;
54542 	};
54543 
54544 	/**
54545 	 * Update palette state.
54546 	 *
54547 	 * @param  {Object} [state] { open, twoColumn }
54548 	 */
54549 	Palette.prototype._toggleState = function(state) {
54550 
54551 	  state = state || {};
54552 
54553 	  var parent = this._getParentContainer(),
54554 	      container = this._container;
54555 
54556 	  var eventBus = this._eventBus;
54557 
54558 	  var twoColumn;
54559 
54560 	  var cls = classes$1(container);
54561 
54562 	  if ('twoColumn' in state) {
54563 	    twoColumn = state.twoColumn;
54564 	  } else {
54565 	    twoColumn = this._needsCollapse(parent.clientHeight, this._entries || {});
54566 	  }
54567 
54568 	  // always update two column
54569 	  cls.toggle(PALETTE_TWO_COLUMN_CLS, twoColumn);
54570 
54571 	  if ('open' in state) {
54572 	    cls.toggle(PALETTE_OPEN_CLS, state.open);
54573 	  }
54574 
54575 	  eventBus.fire('palette.changed', {
54576 	    twoColumn: twoColumn,
54577 	    open: this.isOpen()
54578 	  });
54579 	};
54580 
54581 	Palette.prototype._update = function() {
54582 
54583 	  var entriesContainer = query('.djs-palette-entries', this._container),
54584 	      entries = this._entries = this.getEntries();
54585 
54586 	  clear$1(entriesContainer);
54587 
54588 	  forEach(entries, function(entry, id) {
54589 
54590 	    var grouping = entry.group || 'default';
54591 
54592 	    var container = query('[data-group=' + grouping + ']', entriesContainer);
54593 	    if (!container) {
54594 	      container = domify('<div class="group" data-group="' + grouping + '"></div>');
54595 	      entriesContainer.appendChild(container);
54596 	    }
54597 
54598 	    var html = entry.html || (
54599 	      entry.separator ?
54600 	        '<hr class="separator" />' :
54601 	        '<div class="entry" draggable="true"></div>');
54602 
54603 
54604 	    var control = domify(html);
54605 	    container.appendChild(control);
54606 
54607 	    if (!entry.separator) {
54608 	      attr$1(control, 'data-action', id);
54609 
54610 	      if (entry.title) {
54611 	        attr$1(control, 'title', entry.title);
54612 	      }
54613 
54614 	      if (entry.className) {
54615 	        addClasses(control, entry.className);
54616 	      }
54617 
54618 	      if (entry.imageUrl) {
54619 	        control.appendChild(domify('<img src="' + entry.imageUrl + '">'));
54620 	      }
54621 	    }
54622 	  });
54623 
54624 	  // open after update
54625 	  this.open();
54626 	};
54627 
54628 
54629 	/**
54630 	 * Trigger an action available on the palette
54631 	 *
54632 	 * @param  {string} action
54633 	 * @param  {Event} event
54634 	 */
54635 	Palette.prototype.trigger = function(action, event, autoActivate) {
54636 	  var entries = this._entries,
54637 	      entry,
54638 	      handler,
54639 	      originalEvent,
54640 	      button = event.delegateTarget || event.target;
54641 
54642 	  if (!button) {
54643 	    return event.preventDefault();
54644 	  }
54645 
54646 	  entry = entries[attr$1(button, 'data-action')];
54647 
54648 	  // when user clicks on the palette and not on an action
54649 	  if (!entry) {
54650 	    return;
54651 	  }
54652 
54653 	  handler = entry.action;
54654 
54655 	  originalEvent = event.originalEvent || event;
54656 
54657 	  // simple action (via callback function)
54658 	  if (isFunction(handler)) {
54659 	    if (action === 'click') {
54660 	      handler(originalEvent, autoActivate);
54661 	    }
54662 	  } else {
54663 	    if (handler[action]) {
54664 	      handler[action](originalEvent, autoActivate);
54665 	    }
54666 	  }
54667 
54668 	  // silence other actions
54669 	  event.preventDefault();
54670 	};
54671 
54672 	Palette.prototype._layoutChanged = function() {
54673 	  this._toggleState({});
54674 	};
54675 
54676 	/**
54677 	 * Do we need to collapse to two columns?
54678 	 *
54679 	 * @param {number} availableHeight
54680 	 * @param {Object} entries
54681 	 *
54682 	 * @return {boolean}
54683 	 */
54684 	Palette.prototype._needsCollapse = function(availableHeight, entries) {
54685 
54686 	  // top margin + bottom toggle + bottom margin
54687 	  // implementors must override this method if they
54688 	  // change the palette styles
54689 	  var margin = 20 + 10 + 20;
54690 
54691 	  var entriesHeight = Object.keys(entries).length * 46;
54692 
54693 	  return availableHeight < entriesHeight + margin;
54694 	};
54695 
54696 	/**
54697 	 * Close the palette
54698 	 */
54699 	Palette.prototype.close = function() {
54700 
54701 	  this._toggleState({
54702 	    open: false,
54703 	    twoColumn: false
54704 	  });
54705 	};
54706 
54707 
54708 	/**
54709 	 * Open the palette
54710 	 */
54711 	Palette.prototype.open = function() {
54712 	  this._toggleState({ open: true });
54713 	};
54714 
54715 
54716 	Palette.prototype.toggle = function(open) {
54717 	  if (this.isOpen()) {
54718 	    this.close();
54719 	  } else {
54720 	    this.open();
54721 	  }
54722 	};
54723 
54724 	Palette.prototype.isActiveTool = function(tool) {
54725 	  return tool && this._activeTool === tool;
54726 	};
54727 
54728 	Palette.prototype.updateToolHighlight = function(name) {
54729 	  var entriesContainer,
54730 	      toolsContainer;
54731 
54732 	  if (!this._toolsContainer) {
54733 	    entriesContainer = query('.djs-palette-entries', this._container);
54734 
54735 	    this._toolsContainer = query('[data-group=tools]', entriesContainer);
54736 	  }
54737 
54738 	  toolsContainer = this._toolsContainer;
54739 
54740 	  forEach(toolsContainer.children, function(tool) {
54741 	    var actionName = tool.getAttribute('data-action');
54742 
54743 	    if (!actionName) {
54744 	      return;
54745 	    }
54746 
54747 	    var toolClasses = classes$1(tool);
54748 
54749 	    actionName = actionName.replace('-tool', '');
54750 
54751 	    if (toolClasses.contains('entry') && actionName === name) {
54752 	      toolClasses.add('highlighted-entry');
54753 	    } else {
54754 	      toolClasses.remove('highlighted-entry');
54755 	    }
54756 	  });
54757 	};
54758 
54759 
54760 	/**
54761 	 * Return true if the palette is opened.
54762 	 *
54763 	 * @example
54764 	 *
54765 	 * palette.open();
54766 	 *
54767 	 * if (palette.isOpen()) {
54768 	 *   // yes, we are open
54769 	 * }
54770 	 *
54771 	 * @return {boolean} true if palette is opened
54772 	 */
54773 	Palette.prototype.isOpen = function() {
54774 	  return classes$1(this._container).has(PALETTE_OPEN_CLS);
54775 	};
54776 
54777 	/**
54778 	 * Get container the palette lives in.
54779 	 *
54780 	 * @return {Element}
54781 	 */
54782 	Palette.prototype._getParentContainer = function() {
54783 	  return this._canvas.getContainer();
54784 	};
54785 
54786 
54787 	/* markup definition */
54788 
54789 	Palette.HTML_MARKUP =
54790 	  '<div class="djs-palette">' +
54791 	    '<div class="djs-palette-entries"></div>' +
54792 	    '<div class="djs-palette-toggle"></div>' +
54793 	  '</div>';
54794 
54795 
54796 	// helpers //////////////////////
54797 
54798 	function addClasses(element, classNames) {
54799 
54800 	  var classes = classes$1(element);
54801 
54802 	  var actualClassNames = isArray$2(classNames) ? classNames : classNames.split(/\s+/g);
54803 	  actualClassNames.forEach(function(cls) {
54804 	    classes.add(cls);
54805 	  });
54806 	}
54807 
54808 	function addPaletteEntries(entries, provider) {
54809 
54810 	  var entriesOrUpdater = provider.getPaletteEntries();
54811 
54812 	  if (isFunction(entriesOrUpdater)) {
54813 	    return entriesOrUpdater(entries);
54814 	  }
54815 
54816 	  forEach(entriesOrUpdater, function(entry, id) {
54817 	    entries[id] = entry;
54818 	  });
54819 
54820 	  return entries;
54821 	}
54822 
54823 	var PaletteModule$1 = {
54824 	  __init__: [ 'palette' ],
54825 	  palette: [ 'type', Palette ]
54826 	};
54827 
54828 	var LASSO_TOOL_CURSOR = 'crosshair';
54829 
54830 
54831 	function LassoTool(
54832 	    eventBus, canvas, dragging,
54833 	    elementRegistry, selection, toolManager,
54834 	    mouse) {
54835 
54836 	  this._selection = selection;
54837 	  this._dragging = dragging;
54838 	  this._mouse = mouse;
54839 
54840 	  var self = this;
54841 
54842 	  // lasso visuals implementation
54843 
54844 	  /**
54845 	  * A helper that realizes the selection box visual
54846 	  */
54847 	  var visuals = {
54848 
54849 	    create: function(context) {
54850 	      var container = canvas.getActiveLayer(),
54851 	          frame;
54852 
54853 	      frame = context.frame = create$1('rect');
54854 	      attr(frame, {
54855 	        class: 'djs-lasso-overlay',
54856 	        width:  1,
54857 	        height: 1,
54858 	        x: 0,
54859 	        y: 0
54860 	      });
54861 
54862 	      append(container, frame);
54863 	    },
54864 
54865 	    update: function(context) {
54866 	      var frame = context.frame,
54867 	          bbox = context.bbox;
54868 
54869 	      attr(frame, {
54870 	        x: bbox.x,
54871 	        y: bbox.y,
54872 	        width: bbox.width,
54873 	        height: bbox.height
54874 	      });
54875 	    },
54876 
54877 	    remove: function(context) {
54878 
54879 	      if (context.frame) {
54880 	        remove$1(context.frame);
54881 	      }
54882 	    }
54883 	  };
54884 
54885 	  toolManager.registerTool('lasso', {
54886 	    tool: 'lasso.selection',
54887 	    dragging: 'lasso'
54888 	  });
54889 
54890 	  eventBus.on('lasso.selection.end', function(event) {
54891 	    var target = event.originalEvent.target;
54892 
54893 	    // only reactive on diagram click
54894 	    // on some occasions, event.hover is not set and we have to check if the target is an svg
54895 	    if (!event.hover && !(target instanceof SVGElement)) {
54896 	      return;
54897 	    }
54898 
54899 	    eventBus.once('lasso.selection.ended', function() {
54900 	      self.activateLasso(event.originalEvent, true);
54901 	    });
54902 	  });
54903 
54904 	  // lasso interaction implementation
54905 
54906 	  eventBus.on('lasso.end', function(event) {
54907 
54908 	    var bbox = toBBox(event);
54909 
54910 	    var elements = elementRegistry.filter(function(element) {
54911 	      return element;
54912 	    });
54913 
54914 	    self.select(elements, bbox);
54915 	  });
54916 
54917 	  eventBus.on('lasso.start', function(event) {
54918 
54919 	    var context = event.context;
54920 
54921 	    context.bbox = toBBox(event);
54922 	    visuals.create(context);
54923 	  });
54924 
54925 	  eventBus.on('lasso.move', function(event) {
54926 
54927 	    var context = event.context;
54928 
54929 	    context.bbox = toBBox(event);
54930 	    visuals.update(context);
54931 	  });
54932 
54933 	  eventBus.on('lasso.cleanup', function(event) {
54934 
54935 	    var context = event.context;
54936 
54937 	    visuals.remove(context);
54938 	  });
54939 
54940 
54941 	  // event integration
54942 
54943 	  eventBus.on('element.mousedown', 1500, function(event) {
54944 
54945 	    if (!hasSecondaryModifier(event)) {
54946 	      return;
54947 	    }
54948 
54949 	    self.activateLasso(event.originalEvent);
54950 
54951 	    // we've handled the event
54952 	    return true;
54953 	  });
54954 	}
54955 
54956 	LassoTool.$inject = [
54957 	  'eventBus',
54958 	  'canvas',
54959 	  'dragging',
54960 	  'elementRegistry',
54961 	  'selection',
54962 	  'toolManager',
54963 	  'mouse'
54964 	];
54965 
54966 
54967 	LassoTool.prototype.activateLasso = function(event, autoActivate) {
54968 
54969 	  this._dragging.init(event, 'lasso', {
54970 	    autoActivate: autoActivate,
54971 	    cursor: LASSO_TOOL_CURSOR,
54972 	    data: {
54973 	      context: {}
54974 	    }
54975 	  });
54976 	};
54977 
54978 	LassoTool.prototype.activateSelection = function(event, autoActivate) {
54979 
54980 	  this._dragging.init(event, 'lasso.selection', {
54981 	    trapClick: false,
54982 	    autoActivate: autoActivate,
54983 	    cursor: LASSO_TOOL_CURSOR,
54984 	    data: {
54985 	      context: {}
54986 	    }
54987 	  });
54988 	};
54989 
54990 	LassoTool.prototype.select = function(elements, bbox) {
54991 	  var selectedElements = getEnclosedElements(elements, bbox);
54992 
54993 	  this._selection.select(values(selectedElements));
54994 	};
54995 
54996 	LassoTool.prototype.toggle = function() {
54997 	  if (this.isActive()) {
54998 	    return this._dragging.cancel();
54999 	  }
55000 
55001 	  var mouseEvent = this._mouse.getLastMoveEvent();
55002 
55003 	  this.activateSelection(mouseEvent, !!mouseEvent);
55004 	};
55005 
55006 	LassoTool.prototype.isActive = function() {
55007 	  var context = this._dragging.context();
55008 
55009 	  return context && /^lasso/.test(context.prefix);
55010 	};
55011 
55012 
55013 
55014 	function toBBox(event) {
55015 
55016 	  var start = {
55017 
55018 	    x: event.x - event.dx,
55019 	    y: event.y - event.dy
55020 	  };
55021 
55022 	  var end = {
55023 	    x: event.x,
55024 	    y: event.y
55025 	  };
55026 
55027 	  var bbox;
55028 
55029 	  if ((start.x <= end.x && start.y < end.y) ||
55030 	      (start.x < end.x && start.y <= end.y)) {
55031 
55032 	    bbox = {
55033 	      x: start.x,
55034 	      y: start.y,
55035 	      width:  end.x - start.x,
55036 	      height: end.y - start.y
55037 	    };
55038 	  } else if ((start.x >= end.x && start.y < end.y) ||
55039 	             (start.x > end.x && start.y <= end.y)) {
55040 
55041 	    bbox = {
55042 	      x: end.x,
55043 	      y: start.y,
55044 	      width:  start.x - end.x,
55045 	      height: end.y - start.y
55046 	    };
55047 	  } else if ((start.x <= end.x && start.y > end.y) ||
55048 	             (start.x < end.x && start.y >= end.y)) {
55049 
55050 	    bbox = {
55051 	      x: start.x,
55052 	      y: end.y,
55053 	      width:  end.x - start.x,
55054 	      height: start.y - end.y
55055 	    };
55056 	  } else if ((start.x >= end.x && start.y > end.y) ||
55057 	             (start.x > end.x && start.y >= end.y)) {
55058 
55059 	    bbox = {
55060 	      x: end.x,
55061 	      y: end.y,
55062 	      width:  start.x - end.x,
55063 	      height: start.y - end.y
55064 	    };
55065 	  } else {
55066 
55067 	    bbox = {
55068 	      x: end.x,
55069 	      y: end.y,
55070 	      width:  0,
55071 	      height: 0
55072 	    };
55073 	  }
55074 	  return bbox;
55075 	}
55076 
55077 	var LassoToolModule = {
55078 	  __depends__: [
55079 	    ToolManagerModule,
55080 	    MouseModule
55081 	  ],
55082 	  __init__: [ 'lassoTool' ],
55083 	  lassoTool: [ 'type', LassoTool ]
55084 	};
55085 
55086 	var HIGH_PRIORITY$1 = 1500;
55087 	var HAND_CURSOR = 'grab';
55088 
55089 
55090 	function HandTool(
55091 	    eventBus, canvas, dragging,
55092 	    injector, toolManager, mouse) {
55093 
55094 	  this._dragging = dragging;
55095 	  this._mouse = mouse;
55096 
55097 	  var self = this,
55098 	      keyboard = injector.get('keyboard', false);
55099 
55100 	  toolManager.registerTool('hand', {
55101 	    tool: 'hand',
55102 	    dragging: 'hand.move'
55103 	  });
55104 
55105 	  eventBus.on('element.mousedown', HIGH_PRIORITY$1, function(event) {
55106 
55107 	    if (!hasPrimaryModifier(event)) {
55108 	      return;
55109 	    }
55110 
55111 	    self.activateMove(event.originalEvent, true);
55112 
55113 	    return false;
55114 	  });
55115 
55116 	  keyboard && keyboard.addListener(HIGH_PRIORITY$1, function(e) {
55117 	    if (!isSpace(e.keyEvent) || self.isActive()) {
55118 	      return;
55119 	    }
55120 
55121 	    var mouseEvent = self._mouse.getLastMoveEvent();
55122 
55123 	    self.activateMove(mouseEvent, !!mouseEvent);
55124 	  }, 'keyboard.keydown');
55125 
55126 	  keyboard && keyboard.addListener(HIGH_PRIORITY$1, function(e) {
55127 	    if (!isSpace(e.keyEvent) || !self.isActive()) {
55128 	      return;
55129 	    }
55130 
55131 	    self.toggle();
55132 	  }, 'keyboard.keyup');
55133 
55134 	  eventBus.on('hand.end', function(event) {
55135 	    var target = event.originalEvent.target;
55136 
55137 	    // only reactive on diagram click
55138 	    // on some occasions, event.hover is not set and we have to check if the target is an svg
55139 	    if (!event.hover && !(target instanceof SVGElement)) {
55140 	      return false;
55141 	    }
55142 
55143 	    eventBus.once('hand.ended', function() {
55144 	      self.activateMove(event.originalEvent, { reactivate: true });
55145 	    });
55146 
55147 	  });
55148 
55149 	  eventBus.on('hand.move.move', function(event) {
55150 	    var scale = canvas.viewbox().scale;
55151 
55152 	    canvas.scroll({
55153 	      dx: event.dx * scale,
55154 	      dy: event.dy * scale
55155 	    });
55156 	  });
55157 
55158 	  eventBus.on('hand.move.end', function(event) {
55159 	    var context = event.context,
55160 	        reactivate = context.reactivate;
55161 
55162 	    // Don't reactivate if the user is using the keyboard keybinding
55163 	    if (!hasPrimaryModifier(event) && reactivate) {
55164 
55165 	      eventBus.once('hand.move.ended', function(event) {
55166 	        self.activateHand(event.originalEvent, true, true);
55167 	      });
55168 
55169 	    }
55170 
55171 	    return false;
55172 	  });
55173 
55174 	}
55175 
55176 	HandTool.$inject = [
55177 	  'eventBus',
55178 	  'canvas',
55179 	  'dragging',
55180 	  'injector',
55181 	  'toolManager',
55182 	  'mouse'
55183 	];
55184 
55185 
55186 	HandTool.prototype.activateMove = function(event, autoActivate, context) {
55187 	  if (typeof autoActivate === 'object') {
55188 	    context = autoActivate;
55189 	    autoActivate = false;
55190 	  }
55191 
55192 	  this._dragging.init(event, 'hand.move', {
55193 	    autoActivate: autoActivate,
55194 	    cursor: HAND_CURSOR,
55195 	    data: {
55196 	      context: context || {}
55197 	    }
55198 	  });
55199 	};
55200 
55201 	HandTool.prototype.activateHand = function(event, autoActivate, reactivate) {
55202 	  this._dragging.init(event, 'hand', {
55203 	    trapClick: false,
55204 	    autoActivate: autoActivate,
55205 	    cursor: HAND_CURSOR,
55206 	    data: {
55207 	      context: {
55208 	        reactivate: reactivate
55209 	      }
55210 	    }
55211 	  });
55212 	};
55213 
55214 	HandTool.prototype.toggle = function() {
55215 	  if (this.isActive()) {
55216 	    return this._dragging.cancel();
55217 	  }
55218 
55219 	  var mouseEvent = this._mouse.getLastMoveEvent();
55220 
55221 	  this.activateHand(mouseEvent, !!mouseEvent);
55222 	};
55223 
55224 	HandTool.prototype.isActive = function() {
55225 	  var context = this._dragging.context();
55226 
55227 	  if (context) {
55228 	    return /^(hand|hand\.move)$/.test(context.prefix);
55229 	  }
55230 
55231 	  return false;
55232 	};
55233 
55234 	// helpers //////////
55235 
55236 	function isSpace(keyEvent) {
55237 	  return isKey(' ', keyEvent);
55238 	}
55239 
55240 	var HandToolModule = {
55241 	  __depends__: [
55242 	    ToolManagerModule,
55243 	    MouseModule
55244 	  ],
55245 	  __init__: [ 'handTool' ],
55246 	  handTool: [ 'type', HandTool ]
55247 	};
55248 
55249 	var MARKER_OK = 'connect-ok',
55250 	    MARKER_NOT_OK = 'connect-not-ok';
55251 
55252 	/**
55253 	 * @class
55254 	 * @constructor
55255 	 *
55256 	 * @param {EventBus} eventBus
55257 	 * @param {Dragging} dragging
55258 	 * @param {Connect} connect
55259 	 * @param {Canvas} canvas
55260 	 * @param {ToolManager} toolManager
55261 	 * @param {Rules} rules
55262 	 * @param {Mouse} mouse
55263 	 */
55264 	function GlobalConnect(
55265 	    eventBus, dragging, connect,
55266 	    canvas, toolManager, rules,
55267 	    mouse) {
55268 
55269 	  var self = this;
55270 
55271 	  this._dragging = dragging;
55272 	  this._rules = rules;
55273 	  this._mouse = mouse;
55274 
55275 	  toolManager.registerTool('global-connect', {
55276 	    tool: 'global-connect',
55277 	    dragging: 'global-connect.drag'
55278 	  });
55279 
55280 	  eventBus.on('global-connect.hover', function(event) {
55281 	    var context = event.context,
55282 	        startTarget = event.hover;
55283 
55284 	    var canStartConnect = context.canStartConnect = self.canStartConnect(startTarget);
55285 
55286 	    // simply ignore hover
55287 	    if (canStartConnect === null) {
55288 	      return;
55289 	    }
55290 
55291 	    context.startTarget = startTarget;
55292 
55293 	    canvas.addMarker(startTarget, canStartConnect ? MARKER_OK : MARKER_NOT_OK);
55294 	  });
55295 
55296 
55297 	  eventBus.on([ 'global-connect.out', 'global-connect.cleanup' ], function(event) {
55298 	    var startTarget = event.context.startTarget,
55299 	        canStartConnect = event.context.canStartConnect;
55300 
55301 	    if (startTarget) {
55302 	      canvas.removeMarker(startTarget, canStartConnect ? MARKER_OK : MARKER_NOT_OK);
55303 	    }
55304 	  });
55305 
55306 
55307 	  eventBus.on([ 'global-connect.ended' ], function(event) {
55308 	    var context = event.context,
55309 	        startTarget = context.startTarget,
55310 	        startPosition = {
55311 	          x: event.x,
55312 	          y: event.y
55313 	        };
55314 
55315 	    var canStartConnect = self.canStartConnect(startTarget);
55316 
55317 	    if (!canStartConnect) {
55318 	      return;
55319 	    }
55320 
55321 	    eventBus.once('element.out', function() {
55322 	      eventBus.once([ 'connect.ended', 'connect.canceled' ], function() {
55323 	        eventBus.fire('global-connect.drag.ended');
55324 	      });
55325 
55326 	      connect.start(null, startTarget, startPosition);
55327 	    });
55328 
55329 	    return false;
55330 	  });
55331 	}
55332 
55333 	GlobalConnect.$inject = [
55334 	  'eventBus',
55335 	  'dragging',
55336 	  'connect',
55337 	  'canvas',
55338 	  'toolManager',
55339 	  'rules',
55340 	  'mouse'
55341 	];
55342 
55343 	/**
55344 	 * Initiates tool activity.
55345 	 */
55346 	GlobalConnect.prototype.start = function(event, autoActivate) {
55347 	  this._dragging.init(event, 'global-connect', {
55348 	    autoActivate: autoActivate,
55349 	    trapClick: false,
55350 	    data: {
55351 	      context: {}
55352 	    }
55353 	  });
55354 	};
55355 
55356 	GlobalConnect.prototype.toggle = function() {
55357 
55358 	  if (this.isActive()) {
55359 	    return this._dragging.cancel();
55360 	  }
55361 
55362 	  var mouseEvent = this._mouse.getLastMoveEvent();
55363 
55364 	  return this.start(mouseEvent, !!mouseEvent);
55365 	};
55366 
55367 	GlobalConnect.prototype.isActive = function() {
55368 	  var context = this._dragging.context();
55369 
55370 	  return context && /^global-connect/.test(context.prefix);
55371 	};
55372 
55373 	/**
55374 	 * Check if source shape can initiate connection.
55375 	 *
55376 	 * @param  {Shape} startTarget
55377 	 * @return {boolean}
55378 	 */
55379 	GlobalConnect.prototype.canStartConnect = function(startTarget) {
55380 	  return this._rules.allowed('connection.start', { source: startTarget });
55381 	};
55382 
55383 	var GlobalConnectModule = {
55384 	  __depends__: [
55385 	    ConnectModule,
55386 	    RulesModule$1,
55387 	    DraggingModule,
55388 	    ToolManagerModule,
55389 	    MouseModule
55390 	  ],
55391 	  globalConnect: [ 'type', GlobalConnect ]
55392 	};
55393 
55394 	/**
55395 	 * A palette provider for BPMN 2.0 elements.
55396 	 */
55397 	function PaletteProvider(
55398 	    palette, create, elementFactory,
55399 	    spaceTool, lassoTool, handTool,
55400 	    globalConnect, translate) {
55401 
55402 	  this._palette = palette;
55403 	  this._create = create;
55404 	  this._elementFactory = elementFactory;
55405 	  this._spaceTool = spaceTool;
55406 	  this._lassoTool = lassoTool;
55407 	  this._handTool = handTool;
55408 	  this._globalConnect = globalConnect;
55409 	  this._translate = translate;
55410 
55411 	  palette.registerProvider(this);
55412 	}
55413 
55414 	PaletteProvider.$inject = [
55415 	  'palette',
55416 	  'create',
55417 	  'elementFactory',
55418 	  'spaceTool',
55419 	  'lassoTool',
55420 	  'handTool',
55421 	  'globalConnect',
55422 	  'translate'
55423 	];
55424 
55425 
55426 	PaletteProvider.prototype.getPaletteEntries = function(element) {
55427 
55428 	  var actions = {},
55429 	      create = this._create,
55430 	      elementFactory = this._elementFactory,
55431 	      spaceTool = this._spaceTool,
55432 	      lassoTool = this._lassoTool,
55433 	      handTool = this._handTool,
55434 	      globalConnect = this._globalConnect,
55435 	      translate = this._translate;
55436 
55437 	  function createAction(type, group, className, title, options) {
55438 
55439 	    function createListener(event) {
55440 	      var shape = elementFactory.createShape(assign({ type: type }, options));
55441 
55442 	      if (options) {
55443 	        shape.businessObject.di.isExpanded = options.isExpanded;
55444 	      }
55445 
55446 	      create.start(event, shape);
55447 	    }
55448 
55449 	    var shortType = type.replace(/^bpmn:/, '');
55450 
55451 	    return {
55452 	      group: group,
55453 	      className: className,
55454 	      title: title || translate('Create {type}', { type: shortType }),
55455 	      action: {
55456 	        dragstart: createListener,
55457 	        click: createListener
55458 	      }
55459 	    };
55460 	  }
55461 
55462 	  function createSubprocess(event) {
55463 	    var subProcess = elementFactory.createShape({
55464 	      type: 'bpmn:SubProcess',
55465 	      x: 0,
55466 	      y: 0,
55467 	      isExpanded: true
55468 	    });
55469 
55470 	    var startEvent = elementFactory.createShape({
55471 	      type: 'bpmn:StartEvent',
55472 	      x: 40,
55473 	      y: 82,
55474 	      parent: subProcess
55475 	    });
55476 
55477 	    create.start(event, [ subProcess, startEvent ], {
55478 	      hints: {
55479 	        autoSelect: [ startEvent ]
55480 	      }
55481 	    });
55482 	  }
55483 
55484 	  function createParticipant(event) {
55485 	    create.start(event, elementFactory.createParticipantShape());
55486 	  }
55487 
55488 	  assign(actions, {
55489 	    'hand-tool': {
55490 	      group: 'tools',
55491 	      className: 'bpmn-icon-hand-tool',
55492 	      title: translate('Activate the hand tool'),
55493 	      action: {
55494 	        click: function(event) {
55495 	          handTool.activateHand(event);
55496 	        }
55497 	      }
55498 	    },
55499 	    'lasso-tool': {
55500 	      group: 'tools',
55501 	      className: 'bpmn-icon-lasso-tool',
55502 	      title: translate('Activate the lasso tool'),
55503 	      action: {
55504 	        click: function(event) {
55505 	          lassoTool.activateSelection(event);
55506 	        }
55507 	      }
55508 	    },
55509 	    'space-tool': {
55510 	      group: 'tools',
55511 	      className: 'bpmn-icon-space-tool',
55512 	      title: translate('Activate the create/remove space tool'),
55513 	      action: {
55514 	        click: function(event) {
55515 	          spaceTool.activateSelection(event);
55516 	        }
55517 	      }
55518 	    },
55519 	    'global-connect-tool': {
55520 	      group: 'tools',
55521 	      className: 'bpmn-icon-connection-multi',
55522 	      title: translate('Activate the global connect tool'),
55523 	      action: {
55524 	        click: function(event) {
55525 	          globalConnect.start(event);
55526 	        }
55527 	      }
55528 	    },
55529 	    'tool-separator': {
55530 	      group: 'tools',
55531 	      separator: true
55532 	    },
55533 	    'create.start-event': createAction(
55534 	      'bpmn:StartEvent', 'event', 'bpmn-icon-start-event-none',
55535 	      translate('Create StartEvent')
55536 	    ),
55537 	    'create.intermediate-event': createAction(
55538 	      'bpmn:IntermediateThrowEvent', 'event', 'bpmn-icon-intermediate-event-none',
55539 	      translate('Create Intermediate/Boundary Event')
55540 	    ),
55541 	    'create.end-event': createAction(
55542 	      'bpmn:EndEvent', 'event', 'bpmn-icon-end-event-none',
55543 	      translate('Create EndEvent')
55544 	    ),
55545 	    'create.exclusive-gateway': createAction(
55546 	      'bpmn:ExclusiveGateway', 'gateway', 'bpmn-icon-gateway-none',
55547 	      translate('Create Gateway')
55548 	    ),
55549 	    'create.task': createAction(
55550 	      'bpmn:Task', 'activity', 'bpmn-icon-task',
55551 	      translate('Create Task')
55552 	    ),
55553 	    'create.data-object': createAction(
55554 	      'bpmn:DataObjectReference', 'data-object', 'bpmn-icon-data-object',
55555 	      translate('Create DataObjectReference')
55556 	    ),
55557 	    'create.data-store': createAction(
55558 	      'bpmn:DataStoreReference', 'data-store', 'bpmn-icon-data-store',
55559 	      translate('Create DataStoreReference')
55560 	    ),
55561 	    'create.subprocess-expanded': {
55562 	      group: 'activity',
55563 	      className: 'bpmn-icon-subprocess-expanded',
55564 	      title: translate('Create expanded SubProcess'),
55565 	      action: {
55566 	        dragstart: createSubprocess,
55567 	        click: createSubprocess
55568 	      }
55569 	    },
55570 	    'create.participant-expanded': {
55571 	      group: 'collaboration',
55572 	      className: 'bpmn-icon-participant',
55573 	      title: translate('Create Pool/Participant'),
55574 	      action: {
55575 	        dragstart: createParticipant,
55576 	        click: createParticipant
55577 	      }
55578 	    },
55579 	    'create.group': createAction(
55580 	      'bpmn:Group', 'artifact', 'bpmn-icon-group',
55581 	      translate('Create Group')
55582 	    ),
55583 	  });
55584 
55585 	  return actions;
55586 	};
55587 
55588 	var PaletteModule = {
55589 	  __depends__: [
55590 	    PaletteModule$1,
55591 	    CreateModule,
55592 	    SpaceToolModule,
55593 	    LassoToolModule,
55594 	    HandToolModule,
55595 	    GlobalConnectModule,
55596 	    translate
55597 	  ],
55598 	  __init__: [ 'paletteProvider' ],
55599 	  paletteProvider: [ 'type', PaletteProvider ]
55600 	};
55601 
55602 	var LOW_PRIORITY = 250;
55603 
55604 
55605 	function BpmnReplacePreview(
55606 	    eventBus, elementRegistry, elementFactory,
55607 	    canvas, previewSupport) {
55608 
55609 	  CommandInterceptor.call(this, eventBus);
55610 
55611 	  /**
55612 	   * Replace the visuals of all elements in the context which can be replaced
55613 	   *
55614 	   * @param  {Object} context
55615 	   */
55616 	  function replaceVisual(context) {
55617 
55618 	    var replacements = context.canExecute.replacements;
55619 
55620 	    forEach(replacements, function(replacement) {
55621 
55622 	      var id = replacement.oldElementId;
55623 
55624 	      var newElement = {
55625 	        type: replacement.newElementType
55626 	      };
55627 
55628 	      // if the visual of the element is already replaced
55629 	      if (context.visualReplacements[id]) {
55630 	        return;
55631 	      }
55632 
55633 	      var element = elementRegistry.get(id);
55634 
55635 	      assign(newElement, { x: element.x, y: element.y });
55636 
55637 	      // create a temporary shape
55638 	      var tempShape = elementFactory.createShape(newElement);
55639 
55640 	      canvas.addShape(tempShape, element.parent);
55641 
55642 	      // select the original SVG element related to the element and hide it
55643 	      var gfx = query('[data-element-id="' + cssEscape(element.id) + '"]', context.dragGroup);
55644 
55645 	      if (gfx) {
55646 	        attr(gfx, { display: 'none' });
55647 	      }
55648 
55649 	      // clone the gfx of the temporary shape and add it to the drag group
55650 	      var dragger = previewSupport.addDragger(tempShape, context.dragGroup);
55651 
55652 	      context.visualReplacements[id] = dragger;
55653 
55654 	      canvas.removeShape(tempShape);
55655 	    });
55656 	  }
55657 
55658 	  /**
55659 	   * Restore the original visuals of the previously replaced elements
55660 	   *
55661 	   * @param  {Object} context
55662 	   */
55663 	  function restoreVisual(context) {
55664 
55665 	    var visualReplacements = context.visualReplacements;
55666 
55667 	    forEach(visualReplacements, function(dragger, id) {
55668 
55669 	      var originalGfx = query('[data-element-id="' + cssEscape(id) + '"]', context.dragGroup);
55670 
55671 	      if (originalGfx) {
55672 	        attr(originalGfx, { display: 'inline' });
55673 	      }
55674 
55675 	      dragger.remove();
55676 
55677 	      if (visualReplacements[id]) {
55678 	        delete visualReplacements[id];
55679 	      }
55680 	    });
55681 	  }
55682 
55683 	  eventBus.on('shape.move.move', LOW_PRIORITY, function(event) {
55684 
55685 	    var context = event.context,
55686 	        canExecute = context.canExecute;
55687 
55688 	    if (!context.visualReplacements) {
55689 	      context.visualReplacements = {};
55690 	    }
55691 
55692 	    if (canExecute && canExecute.replacements) {
55693 	      replaceVisual(context);
55694 	    } else {
55695 	      restoreVisual(context);
55696 	    }
55697 	  });
55698 	}
55699 
55700 	BpmnReplacePreview.$inject = [
55701 	  'eventBus',
55702 	  'elementRegistry',
55703 	  'elementFactory',
55704 	  'canvas',
55705 	  'previewSupport'
55706 	];
55707 
55708 	inherits$1(BpmnReplacePreview, CommandInterceptor);
55709 
55710 	var ReplacePreviewModule = {
55711 	  __depends__: [
55712 	    PreviewSupportModule
55713 	  ],
55714 	  __init__: [ 'bpmnReplacePreview' ],
55715 	  bpmnReplacePreview: [ 'type', BpmnReplacePreview ]
55716 	};
55717 
55718 	var HIGHER_PRIORITY$2 = 1250;
55719 
55720 	var BOUNDARY_TO_HOST_THRESHOLD = 40;
55721 
55722 	var TARGET_BOUNDS_PADDING = 20,
55723 	    TASK_BOUNDS_PADDING = 10;
55724 
55725 	var TARGET_CENTER_PADDING = 20;
55726 
55727 	var AXES = [ 'x', 'y' ];
55728 
55729 	var abs = Math.abs;
55730 
55731 	/**
55732 	 * Snap during connect.
55733 	 *
55734 	 * @param {EventBus} eventBus
55735 	 */
55736 	function BpmnConnectSnapping(eventBus) {
55737 	  eventBus.on([
55738 	    'connect.hover',
55739 	    'connect.move',
55740 	    'connect.end',
55741 	  ], HIGHER_PRIORITY$2, function(event) {
55742 	    var context = event.context,
55743 	        canExecute = context.canExecute,
55744 	        start = context.start,
55745 	        hover = context.hover,
55746 	        source = context.source,
55747 	        target = context.target;
55748 
55749 	    // do NOT snap on CMD
55750 	    if (event.originalEvent && isCmd(event.originalEvent)) {
55751 	      return;
55752 	    }
55753 
55754 	    if (!context.initialConnectionStart) {
55755 	      context.initialConnectionStart = context.connectionStart;
55756 	    }
55757 
55758 	    // snap hover
55759 	    if (canExecute && hover) {
55760 	      snapToShape(event, hover, getTargetBoundsPadding(hover));
55761 	    }
55762 
55763 	    if (hover && isAnyType(canExecute, [
55764 	      'bpmn:Association',
55765 	      'bpmn:DataInputAssociation',
55766 	      'bpmn:DataOutputAssociation',
55767 	      'bpmn:SequenceFlow'
55768 	    ])) {
55769 	      context.connectionStart = mid$2(start);
55770 
55771 	      // snap hover
55772 	      if (isAny(hover, [ 'bpmn:Event', 'bpmn:Gateway' ])) {
55773 	        snapToPosition(event, mid$2(hover));
55774 	      }
55775 
55776 	      // snap hover
55777 	      if (isAny(hover, [ 'bpmn:Task', 'bpmn:SubProcess' ])) {
55778 	        snapToTargetMid(event, hover);
55779 	      }
55780 
55781 	      // snap source and target
55782 	      if (is$1(source, 'bpmn:BoundaryEvent') && target === source.host) {
55783 	        snapBoundaryEventLoop(event);
55784 	      }
55785 
55786 	    } else if (isType(canExecute, 'bpmn:MessageFlow')) {
55787 
55788 	      if (is$1(start, 'bpmn:Event')) {
55789 
55790 	        // snap start
55791 	        context.connectionStart = mid$2(start);
55792 	      }
55793 
55794 	      if (is$1(hover, 'bpmn:Event')) {
55795 
55796 	        // snap hover
55797 	        snapToPosition(event, mid$2(hover));
55798 	      }
55799 
55800 	    } else {
55801 
55802 	      // un-snap source
55803 	      context.connectionStart = context.initialConnectionStart;
55804 	    }
55805 	  });
55806 	}
55807 
55808 	BpmnConnectSnapping.$inject = [ 'eventBus' ];
55809 
55810 
55811 	// helpers //////////
55812 
55813 	// snap to target if event in target
55814 	function snapToShape(event, target, padding) {
55815 	  AXES.forEach(function(axis) {
55816 	    var dimensionForAxis = getDimensionForAxis(axis, target);
55817 
55818 	    if (event[ axis ] < target[ axis ] + padding) {
55819 	      setSnapped(event, axis, target[ axis ] + padding);
55820 	    } else if (event[ axis ] > target[ axis ] + dimensionForAxis - padding) {
55821 	      setSnapped(event, axis, target[ axis ] + dimensionForAxis - padding);
55822 	    }
55823 	  });
55824 	}
55825 
55826 	// snap to target mid if event in target mid
55827 	function snapToTargetMid(event, target) {
55828 	  var targetMid = mid$2(target);
55829 
55830 	  AXES.forEach(function(axis) {
55831 	    if (isMid(event, target, axis)) {
55832 	      setSnapped(event, axis, targetMid[ axis ]);
55833 	    }
55834 	  });
55835 	}
55836 
55837 	// snap to prevent loop overlapping boundary event
55838 	function snapBoundaryEventLoop(event) {
55839 	  var context = event.context,
55840 	      source = context.source,
55841 	      target = context.target;
55842 
55843 	  if (isReverse(context)) {
55844 	    return;
55845 	  }
55846 
55847 	  var sourceMid = mid$2(source),
55848 	      orientation = getOrientation(sourceMid, target, -10),
55849 	      axes = [];
55850 
55851 	  if (/top|bottom/.test(orientation)) {
55852 	    axes.push('x');
55853 	  }
55854 
55855 	  if (/left|right/.test(orientation)) {
55856 	    axes.push('y');
55857 	  }
55858 
55859 	  axes.forEach(function(axis) {
55860 	    var coordinate = event[ axis ], newCoordinate;
55861 
55862 	    if (abs(coordinate - sourceMid[ axis ]) < BOUNDARY_TO_HOST_THRESHOLD) {
55863 	      if (coordinate > sourceMid[ axis ]) {
55864 	        newCoordinate = sourceMid[ axis ] + BOUNDARY_TO_HOST_THRESHOLD;
55865 	      }
55866 	      else {
55867 	        newCoordinate = sourceMid[ axis ] - BOUNDARY_TO_HOST_THRESHOLD;
55868 	      }
55869 
55870 	      setSnapped(event, axis, newCoordinate);
55871 	    }
55872 	  });
55873 	}
55874 
55875 	function snapToPosition(event, position) {
55876 	  setSnapped(event, 'x', position.x);
55877 	  setSnapped(event, 'y', position.y);
55878 	}
55879 
55880 	function isType(attrs, type) {
55881 	  return attrs && attrs.type === type;
55882 	}
55883 
55884 	function isAnyType(attrs, types) {
55885 	  return some(types, function(type) {
55886 	    return isType(attrs, type);
55887 	  });
55888 	}
55889 
55890 	function getDimensionForAxis(axis, element) {
55891 	  return axis === 'x' ? element.width : element.height;
55892 	}
55893 
55894 	function getTargetBoundsPadding(target) {
55895 	  if (is$1(target, 'bpmn:Task')) {
55896 	    return TASK_BOUNDS_PADDING;
55897 	  } else {
55898 	    return TARGET_BOUNDS_PADDING;
55899 	  }
55900 	}
55901 
55902 	function isMid(event, target, axis) {
55903 	  return event[ axis ] > target[ axis ] + TARGET_CENTER_PADDING
55904 	    && event[ axis ] < target[ axis ] + getDimensionForAxis(axis, target) - TARGET_CENTER_PADDING;
55905 	}
55906 
55907 	function isReverse(context) {
55908 	  var hover = context.hover,
55909 	      source = context.source;
55910 
55911 	  return hover && source && hover === source;
55912 	}
55913 
55914 	/**
55915 	 * A snap context, containing the (possibly incomplete)
55916 	 * mappings of drop targets (to identify the snapping)
55917 	 * to computed snap points.
55918 	 */
55919 	function SnapContext() {
55920 
55921 	  /**
55922 	   * Map<String, SnapPoints> mapping drop targets to
55923 	   * a list of possible snappings.
55924 	   *
55925 	   * @type {Object}
55926 	   */
55927 	  this._targets = {};
55928 
55929 	  /**
55930 	   * Map<String, Point> initial positioning of element
55931 	   * regarding various snap directions.
55932 	   *
55933 	   * @type {Object}
55934 	   */
55935 	  this._snapOrigins = {};
55936 
55937 	  /**
55938 	   * List of snap locations
55939 	   *
55940 	   * @type {Array<string>}
55941 	   */
55942 	  this._snapLocations = [];
55943 
55944 	  /**
55945 	   * Map<String, Array<Point>> of default snapping locations
55946 	   *
55947 	   * @type {Object}
55948 	   */
55949 	  this._defaultSnaps = {};
55950 	}
55951 
55952 
55953 	SnapContext.prototype.getSnapOrigin = function(snapLocation) {
55954 	  return this._snapOrigins[snapLocation];
55955 	};
55956 
55957 
55958 	SnapContext.prototype.setSnapOrigin = function(snapLocation, initialValue) {
55959 	  this._snapOrigins[snapLocation] = initialValue;
55960 
55961 	  if (this._snapLocations.indexOf(snapLocation) === -1) {
55962 	    this._snapLocations.push(snapLocation);
55963 	  }
55964 	};
55965 
55966 
55967 	SnapContext.prototype.addDefaultSnap = function(type, point) {
55968 
55969 	  var snapValues = this._defaultSnaps[type];
55970 
55971 	  if (!snapValues) {
55972 	    snapValues = this._defaultSnaps[type] = [];
55973 	  }
55974 
55975 	  snapValues.push(point);
55976 	};
55977 
55978 	/**
55979 	 * Return a number of initialized snaps, i.e. snap locations such as
55980 	 * top-left, mid, bottom-right and so forth.
55981 	 *
55982 	 * @return {Array<string>} snapLocations
55983 	 */
55984 	SnapContext.prototype.getSnapLocations = function() {
55985 	  return this._snapLocations;
55986 	};
55987 
55988 	/**
55989 	 * Set the snap locations for this context.
55990 	 *
55991 	 * The order of locations determines precedence.
55992 	 *
55993 	 * @param {Array<string>} snapLocations
55994 	 */
55995 	SnapContext.prototype.setSnapLocations = function(snapLocations) {
55996 	  this._snapLocations = snapLocations;
55997 	};
55998 
55999 	/**
56000 	 * Get snap points for a given target
56001 	 *
56002 	 * @param {Element|string} target
56003 	 */
56004 	SnapContext.prototype.pointsForTarget = function(target) {
56005 
56006 	  var targetId = target.id || target;
56007 
56008 	  var snapPoints = this._targets[targetId];
56009 
56010 	  if (!snapPoints) {
56011 	    snapPoints = this._targets[targetId] = new SnapPoints();
56012 	    snapPoints.initDefaults(this._defaultSnaps);
56013 	  }
56014 
56015 	  return snapPoints;
56016 	};
56017 
56018 
56019 	/**
56020 	 * Creates the snap points and initializes them with the
56021 	 * given default values.
56022 	 *
56023 	 * @param {Object<string, Array<Point>>} [defaultPoints]
56024 	 */
56025 	function SnapPoints(defaultSnaps) {
56026 
56027 	  /**
56028 	   * Map<String, Map<(x|y), Array<number>>> mapping snap locations,
56029 	   * i.e. top-left, bottom-right, center to actual snap values.
56030 	   *
56031 	   * @type {Object}
56032 	   */
56033 	  this._snapValues = {};
56034 	}
56035 
56036 	SnapPoints.prototype.add = function(snapLocation, point) {
56037 
56038 	  var snapValues = this._snapValues[snapLocation];
56039 
56040 	  if (!snapValues) {
56041 	    snapValues = this._snapValues[snapLocation] = { x: [], y: [] };
56042 	  }
56043 
56044 	  if (snapValues.x.indexOf(point.x) === -1) {
56045 	    snapValues.x.push(point.x);
56046 	  }
56047 
56048 	  if (snapValues.y.indexOf(point.y) === -1) {
56049 	    snapValues.y.push(point.y);
56050 	  }
56051 	};
56052 
56053 
56054 	SnapPoints.prototype.snap = function(point, snapLocation, axis, tolerance) {
56055 	  var snappingValues = this._snapValues[snapLocation];
56056 
56057 	  return snappingValues && snapTo(point[axis], snappingValues[axis], tolerance);
56058 	};
56059 
56060 	/**
56061 	 * Initialize a number of default snapping points.
56062 	 *
56063 	 * @param  {Object} defaultSnaps
56064 	 */
56065 	SnapPoints.prototype.initDefaults = function(defaultSnaps) {
56066 
56067 	  var self = this;
56068 
56069 	  forEach(defaultSnaps || {}, function(snapPoints, snapLocation) {
56070 	    forEach(snapPoints, function(point) {
56071 	      self.add(snapLocation, point);
56072 	    });
56073 	  });
56074 	};
56075 
56076 	var HIGHER_PRIORITY$1 = 1250;
56077 
56078 
56079 	/**
56080 	 * Snap during create and move.
56081 	 *
56082 	 * @param {EventBus} elementRegistry
56083 	 * @param {EventBus} eventBus
56084 	 * @param {Snapping} snapping
56085 	 */
56086 	function CreateMoveSnapping(elementRegistry, eventBus, snapping) {
56087 	  var self = this;
56088 
56089 	  this._elementRegistry = elementRegistry;
56090 
56091 	  eventBus.on([
56092 	    'create.start',
56093 	    'shape.move.start'
56094 	  ], function(event) {
56095 	    self.initSnap(event);
56096 	  });
56097 
56098 	  eventBus.on([
56099 	    'create.move',
56100 	    'create.end',
56101 	    'shape.move.move',
56102 	    'shape.move.end'
56103 	  ], HIGHER_PRIORITY$1, function(event) {
56104 	    var context = event.context,
56105 	        shape = context.shape,
56106 	        snapContext = context.snapContext,
56107 	        target = context.target;
56108 
56109 	    if (event.originalEvent && isCmd(event.originalEvent)) {
56110 	      return;
56111 	    }
56112 
56113 	    if (isSnapped(event) || !target) {
56114 	      return;
56115 	    }
56116 
56117 	    var snapPoints = snapContext.pointsForTarget(target);
56118 
56119 	    if (!snapPoints.initialized) {
56120 	      snapPoints = self.addSnapTargetPoints(snapPoints, shape, target);
56121 
56122 	      snapPoints.initialized = true;
56123 	    }
56124 
56125 	    snapping.snap(event, snapPoints);
56126 	  });
56127 
56128 	  eventBus.on([
56129 	    'create.cleanup',
56130 	    'shape.move.cleanup'
56131 	  ], function() {
56132 	    snapping.hide();
56133 	  });
56134 	}
56135 
56136 	CreateMoveSnapping.$inject = [
56137 	  'elementRegistry',
56138 	  'eventBus',
56139 	  'snapping'
56140 	];
56141 
56142 	CreateMoveSnapping.prototype.initSnap = function(event) {
56143 	  var elementRegistry = this._elementRegistry;
56144 
56145 	  var context = event.context,
56146 	      shape = context.shape,
56147 	      snapContext = context.snapContext;
56148 
56149 	  if (!snapContext) {
56150 	    snapContext = context.snapContext = new SnapContext();
56151 	  }
56152 
56153 	  var shapeMid;
56154 
56155 	  if (elementRegistry.get(shape.id)) {
56156 
56157 	    // move
56158 	    shapeMid = mid$2(shape, event);
56159 	  } else {
56160 
56161 	    // create
56162 	    shapeMid = {
56163 	      x: event.x + mid$2(shape).x,
56164 	      y: event.y + mid$2(shape).y
56165 	    };
56166 	  }
56167 
56168 	  var shapeTopLeft = {
56169 	        x: shapeMid.x - shape.width / 2,
56170 	        y: shapeMid.y - shape.height / 2
56171 	      },
56172 	      shapeBottomRight = {
56173 	        x: shapeMid.x + shape.width / 2,
56174 	        y: shapeMid.y + shape.height / 2
56175 	      };
56176 
56177 	  snapContext.setSnapOrigin('mid', {
56178 	    x: shapeMid.x - event.x,
56179 	    y: shapeMid.y - event.y
56180 	  });
56181 
56182 	  // snap labels to mid only
56183 	  if (isLabel$1(shape)) {
56184 	    return snapContext;
56185 	  }
56186 
56187 	  snapContext.setSnapOrigin('top-left', {
56188 	    x: shapeTopLeft.x - event.x,
56189 	    y: shapeTopLeft.y - event.y
56190 	  });
56191 
56192 	  snapContext.setSnapOrigin('bottom-right', {
56193 	    x: shapeBottomRight.x - event.x,
56194 	    y: shapeBottomRight.y - event.y
56195 	  });
56196 
56197 	  return snapContext;
56198 	};
56199 
56200 	CreateMoveSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target) {
56201 	  var snapTargets = this.getSnapTargets(shape, target);
56202 
56203 	  forEach(snapTargets, function(snapTarget) {
56204 
56205 	    // handle labels
56206 	    if (isLabel$1(snapTarget)) {
56207 
56208 	      if (isLabel$1(shape)) {
56209 	        snapPoints.add('mid', mid$2(snapTarget));
56210 	      }
56211 
56212 	      return;
56213 	    }
56214 
56215 	    // handle connections
56216 	    if (isConnection$1(snapTarget)) {
56217 
56218 	      // ignore single segment connections
56219 	      if (snapTarget.waypoints.length < 3) {
56220 	        return;
56221 	      }
56222 
56223 	      // ignore first and last waypoint
56224 	      var waypoints = snapTarget.waypoints.slice(1, -1);
56225 
56226 	      forEach(waypoints, function(waypoint) {
56227 	        snapPoints.add('mid', waypoint);
56228 	      });
56229 
56230 	      return;
56231 	    }
56232 
56233 	    // handle shapes
56234 	    snapPoints.add('mid', mid$2(snapTarget));
56235 	  });
56236 
56237 	  if (!isNumber(shape.x) || !isNumber(shape.y)) {
56238 	    return snapPoints;
56239 	  }
56240 
56241 	  // snap to original position when moving
56242 	  if (this._elementRegistry.get(shape.id)) {
56243 	    snapPoints.add('mid', mid$2(shape));
56244 	  }
56245 
56246 	  return snapPoints;
56247 	};
56248 
56249 	CreateMoveSnapping.prototype.getSnapTargets = function(shape, target) {
56250 	  return getChildren(target).filter(function(child) {
56251 	    return !isHidden$1(child);
56252 	  });
56253 	};
56254 
56255 	// helpers //////////
56256 
56257 	function isConnection$1(element) {
56258 	  return !!element.waypoints;
56259 	}
56260 
56261 	function isHidden$1(element) {
56262 	  return !!element.hidden;
56263 	}
56264 
56265 	function isLabel$1(element) {
56266 	  return !!element.labelTarget;
56267 	}
56268 
56269 	var HIGH_PRIORITY = 1500;
56270 
56271 
56272 	/**
56273 	 * Snap during create and move.
56274 	 *
56275 	 * @param {EventBus} eventBus
56276 	 * @param {Injector} injector
56277 	 */
56278 	function BpmnCreateMoveSnapping(eventBus, injector) {
56279 	  injector.invoke(CreateMoveSnapping, this);
56280 
56281 	  // creating first participant
56282 	  eventBus.on([ 'create.move', 'create.end' ], HIGH_PRIORITY, setSnappedIfConstrained);
56283 
56284 	  // snap boundary events
56285 	  eventBus.on([
56286 	    'create.move',
56287 	    'create.end',
56288 	    'shape.move.move',
56289 	    'shape.move.end'
56290 	  ], HIGH_PRIORITY, function(event) {
56291 	    var context = event.context,
56292 	        canExecute = context.canExecute,
56293 	        target = context.target;
56294 
56295 	    var canAttach = canExecute && (canExecute === 'attach' || canExecute.attach);
56296 
56297 	    if (canAttach && !isSnapped(event)) {
56298 	      snapBoundaryEvent(event, target);
56299 	    }
56300 	  });
56301 	}
56302 
56303 	inherits$1(BpmnCreateMoveSnapping, CreateMoveSnapping);
56304 
56305 	BpmnCreateMoveSnapping.$inject = [
56306 	  'eventBus',
56307 	  'injector'
56308 	];
56309 
56310 	BpmnCreateMoveSnapping.prototype.initSnap = function(event) {
56311 	  var snapContext = CreateMoveSnapping.prototype.initSnap.call(this, event);
56312 
56313 	  var shape = event.shape;
56314 
56315 	  var isMove = !!this._elementRegistry.get(shape.id);
56316 
56317 	  // snap to docking points
56318 	  forEach(shape.outgoing, function(connection) {
56319 	    var docking = connection.waypoints[0];
56320 
56321 	    docking = docking.original || docking;
56322 
56323 	    snapContext.setSnapOrigin(connection.id + '-docking', getDockingSnapOrigin(docking, isMove, event));
56324 	  });
56325 
56326 	  forEach(shape.incoming, function(connection) {
56327 	    var docking = connection.waypoints[connection.waypoints.length - 1];
56328 
56329 	    docking = docking.original || docking;
56330 
56331 	    snapContext.setSnapOrigin(connection.id + '-docking', getDockingSnapOrigin(docking, isMove, event));
56332 	  });
56333 
56334 	  if (is$1(shape, 'bpmn:Participant')) {
56335 
56336 	    // snap to borders with higher priority
56337 	    snapContext.setSnapLocations([ 'top-left', 'bottom-right', 'mid' ]);
56338 	  }
56339 
56340 	  return snapContext;
56341 	};
56342 
56343 	BpmnCreateMoveSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target) {
56344 	  CreateMoveSnapping.prototype.addSnapTargetPoints.call(this, snapPoints, shape, target);
56345 
56346 	  var snapTargets = this.getSnapTargets(shape, target);
56347 
56348 	  forEach(snapTargets, function(snapTarget) {
56349 
56350 	    // handle TRBL alignment
56351 	    //
56352 	    // * with container elements
56353 	    // * with text annotations
56354 	    if (isContainer(snapTarget) || areAll([ shape, snapTarget ], 'bpmn:TextAnnotation')) {
56355 	      snapPoints.add('top-left', topLeft(snapTarget));
56356 	      snapPoints.add('bottom-right', bottomRight(snapTarget));
56357 	    }
56358 	  });
56359 
56360 	  var elementRegistry = this._elementRegistry;
56361 
56362 	  // snap to docking points if not create mode
56363 	  forEach(shape.incoming, function(connection) {
56364 	    if (elementRegistry.get(shape.id)) {
56365 
56366 	      if (!includes(snapTargets, connection.source)) {
56367 	        snapPoints.add('mid', getMid(connection.source));
56368 	      }
56369 
56370 	      var docking = connection.waypoints[0];
56371 	      snapPoints.add(connection.id + '-docking', docking.original || docking);
56372 	    }
56373 	  });
56374 
56375 	  forEach(shape.outgoing, function(connection) {
56376 	    if (elementRegistry.get(shape.id)) {
56377 
56378 	      if (!includes(snapTargets, connection.target)) {
56379 	        snapPoints.add('mid', getMid(connection.target));
56380 	      }
56381 
56382 	      var docking = connection.waypoints[ connection.waypoints.length - 1 ];
56383 
56384 	      snapPoints.add(connection.id + '-docking', docking.original || docking);
56385 	    }
56386 	  });
56387 
56388 	  // add sequence flow parents as snap targets
56389 	  if (is$1(target, 'bpmn:SequenceFlow')) {
56390 	    snapPoints = this.addSnapTargetPoints(snapPoints, shape, target.parent);
56391 	  }
56392 
56393 	  return snapPoints;
56394 	};
56395 
56396 	BpmnCreateMoveSnapping.prototype.getSnapTargets = function(shape, target) {
56397 	  return CreateMoveSnapping.prototype.getSnapTargets.call(this, shape, target)
56398 	    .filter(function(snapTarget) {
56399 
56400 	      // do not snap to lanes
56401 	      return !is$1(snapTarget, 'bpmn:Lane');
56402 	    });
56403 	};
56404 
56405 	// helpers //////////
56406 
56407 	function snapBoundaryEvent(event, target) {
56408 	  var targetTRBL = asTRBL(target);
56409 
56410 	  var direction = getBoundaryAttachment(event, target);
56411 
56412 	  var context = event.context,
56413 	      shape = context.shape;
56414 
56415 	  var offset;
56416 
56417 	  if (shape.parent) {
56418 	    offset = { x: 0, y: 0 };
56419 	  } else {
56420 	    offset = getMid(shape);
56421 	  }
56422 
56423 	  if (/top/.test(direction)) {
56424 	    setSnapped(event, 'y', targetTRBL.top - offset.y);
56425 	  } else if (/bottom/.test(direction)) {
56426 	    setSnapped(event, 'y', targetTRBL.bottom - offset.y);
56427 	  }
56428 
56429 	  if (/left/.test(direction)) {
56430 	    setSnapped(event, 'x', targetTRBL.left - offset.x);
56431 	  } else if (/right/.test(direction)) {
56432 	    setSnapped(event, 'x', targetTRBL.right - offset.x);
56433 	  }
56434 	}
56435 
56436 	function areAll(elements, type) {
56437 	  return elements.every(function(el) {
56438 	    return is$1(el, type);
56439 	  });
56440 	}
56441 
56442 	function isContainer(element) {
56443 	  if (is$1(element, 'bpmn:SubProcess') && isExpanded(element)) {
56444 	    return true;
56445 	  }
56446 
56447 	  return is$1(element, 'bpmn:Participant');
56448 	}
56449 
56450 
56451 	function setSnappedIfConstrained(event) {
56452 	  var context = event.context,
56453 	      createConstraints = context.createConstraints;
56454 
56455 	  if (!createConstraints) {
56456 	    return;
56457 	  }
56458 
56459 	  var top = createConstraints.top,
56460 	      right = createConstraints.right,
56461 	      bottom = createConstraints.bottom,
56462 	      left = createConstraints.left;
56463 
56464 	  if ((left && left >= event.x) || (right && right <= event.x)) {
56465 	    setSnapped(event, 'x', event.x);
56466 	  }
56467 
56468 	  if ((top && top >= event.y) || (bottom && bottom <= event.y)) {
56469 	    setSnapped(event, 'y', event.y);
56470 	  }
56471 	}
56472 
56473 	function includes(array, value) {
56474 	  return array.indexOf(value) !== -1;
56475 	}
56476 
56477 	function getDockingSnapOrigin(docking, isMove, event) {
56478 	  return isMove ? (
56479 	    {
56480 	      x: docking.x - event.x,
56481 	      y: docking.y - event.y
56482 	    }
56483 	  ) : {
56484 	    x: docking.x,
56485 	    y: docking.y
56486 	  };
56487 	}
56488 
56489 	var HIGHER_PRIORITY = 1250;
56490 
56491 
56492 	/**
56493 	 * Snap during resize.
56494 	 *
56495 	 * @param {EventBus} eventBus
56496 	 * @param {Snapping} snapping
56497 	 */
56498 	function ResizeSnapping(eventBus, snapping) {
56499 	  var self = this;
56500 
56501 	  eventBus.on([ 'resize.start' ], function(event) {
56502 	    self.initSnap(event);
56503 	  });
56504 
56505 	  eventBus.on([
56506 	    'resize.move',
56507 	    'resize.end',
56508 	  ], HIGHER_PRIORITY, function(event) {
56509 	    var context = event.context,
56510 	        shape = context.shape,
56511 	        parent = shape.parent,
56512 	        direction = context.direction,
56513 	        snapContext = context.snapContext;
56514 
56515 	    if (event.originalEvent && isCmd(event.originalEvent)) {
56516 	      return;
56517 	    }
56518 
56519 	    if (isSnapped(event)) {
56520 	      return;
56521 	    }
56522 
56523 	    var snapPoints = snapContext.pointsForTarget(parent);
56524 
56525 	    if (!snapPoints.initialized) {
56526 	      snapPoints = self.addSnapTargetPoints(snapPoints, shape, parent, direction);
56527 
56528 	      snapPoints.initialized = true;
56529 	    }
56530 
56531 	    if (isHorizontal(direction)) {
56532 	      setSnapped(event, 'x', event.x);
56533 	    }
56534 
56535 	    if (isVertical(direction)) {
56536 	      setSnapped(event, 'y', event.y);
56537 	    }
56538 
56539 	    snapping.snap(event, snapPoints);
56540 	  });
56541 
56542 	  eventBus.on([ 'resize.cleanup' ], function() {
56543 	    snapping.hide();
56544 	  });
56545 	}
56546 
56547 	ResizeSnapping.prototype.initSnap = function(event) {
56548 	  var context = event.context,
56549 	      shape = context.shape,
56550 	      direction = context.direction,
56551 	      snapContext = context.snapContext;
56552 
56553 	  if (!snapContext) {
56554 	    snapContext = context.snapContext = new SnapContext();
56555 	  }
56556 
56557 	  var snapOrigin = getSnapOrigin(shape, direction);
56558 
56559 	  snapContext.setSnapOrigin('corner', {
56560 	    x: snapOrigin.x - event.x,
56561 	    y: snapOrigin.y - event.y
56562 	  });
56563 
56564 	  return snapContext;
56565 	};
56566 
56567 	ResizeSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target, direction) {
56568 	  var snapTargets = this.getSnapTargets(shape, target);
56569 
56570 	  forEach(snapTargets, function(snapTarget) {
56571 	    snapPoints.add('corner', bottomRight(snapTarget));
56572 	    snapPoints.add('corner', topLeft(snapTarget));
56573 	  });
56574 
56575 	  snapPoints.add('corner', getSnapOrigin(shape, direction));
56576 
56577 	  return snapPoints;
56578 	};
56579 
56580 	ResizeSnapping.$inject = [
56581 	  'eventBus',
56582 	  'snapping'
56583 	];
56584 
56585 	ResizeSnapping.prototype.getSnapTargets = function(shape, target) {
56586 	  return getChildren(target).filter(function(child) {
56587 	    return !isAttached(child, shape)
56588 	      && !isConnection(child)
56589 	      && !isHidden(child)
56590 	      && !isLabel(child);
56591 	  });
56592 	};
56593 
56594 	// helpers //////////
56595 
56596 	function getSnapOrigin(shape, direction) {
56597 	  var mid = getMid(shape),
56598 	      trbl = asTRBL(shape);
56599 
56600 	  var snapOrigin = {
56601 	    x: mid.x,
56602 	    y: mid.y
56603 	  };
56604 
56605 	  if (direction.indexOf('n') !== -1) {
56606 	    snapOrigin.y = trbl.top;
56607 	  } else if (direction.indexOf('s') !== -1) {
56608 	    snapOrigin.y = trbl.bottom;
56609 	  }
56610 
56611 	  if (direction.indexOf('e') !== -1) {
56612 	    snapOrigin.x = trbl.right;
56613 	  } else if (direction.indexOf('w') !== -1) {
56614 	    snapOrigin.x = trbl.left;
56615 	  }
56616 
56617 	  return snapOrigin;
56618 	}
56619 
56620 	function isAttached(element, host) {
56621 	  return element.host === host;
56622 	}
56623 
56624 	function isConnection(element) {
56625 	  return !!element.waypoints;
56626 	}
56627 
56628 	function isHidden(element) {
56629 	  return !!element.hidden;
56630 	}
56631 
56632 	function isLabel(element) {
56633 	  return !!element.labelTarget;
56634 	}
56635 
56636 	function isHorizontal(direction) {
56637 	  return direction === 'n' || direction === 's';
56638 	}
56639 
56640 	function isVertical(direction) {
56641 	  return direction === 'e' || direction === 'w';
56642 	}
56643 
56644 	var SNAP_TOLERANCE = 7;
56645 
56646 	var SNAP_LINE_HIDE_DELAY = 1000;
56647 
56648 
56649 	/**
56650 	 * Generic snapping feature.
56651 	 *
56652 	 * @param {EventBus} eventBus
56653 	 * @param {Canvas} canvas
56654 	 */
56655 	function Snapping(canvas) {
56656 	  this._canvas = canvas;
56657 
56658 	  // delay hide by 1000 seconds since last snap
56659 	  this._asyncHide = debounce(bind$2(this.hide, this), SNAP_LINE_HIDE_DELAY);
56660 	}
56661 
56662 	Snapping.$inject = [ 'canvas' ];
56663 
56664 	/**
56665 	 * Snap an event to given snap points.
56666 	 *
56667 	 * @param {Event} event
56668 	 * @param {SnapPoints} snapPoints
56669 	 */
56670 	Snapping.prototype.snap = function(event, snapPoints) {
56671 	  var context = event.context,
56672 	      snapContext = context.snapContext,
56673 	      snapLocations = snapContext.getSnapLocations();
56674 
56675 	  var snapping = {
56676 	    x: isSnapped(event, 'x'),
56677 	    y: isSnapped(event, 'y')
56678 	  };
56679 
56680 	  forEach(snapLocations, function(location) {
56681 	    var snapOrigin = snapContext.getSnapOrigin(location);
56682 
56683 	    var snapCurrent = {
56684 	      x: event.x + snapOrigin.x,
56685 	      y: event.y + snapOrigin.y
56686 	    };
56687 
56688 	    // snap both axis if not snapped already
56689 	    forEach([ 'x', 'y' ], function(axis) {
56690 	      var locationSnapping;
56691 
56692 	      if (!snapping[axis]) {
56693 	        locationSnapping = snapPoints.snap(snapCurrent, location, axis, SNAP_TOLERANCE);
56694 
56695 	        if (locationSnapping !== undefined) {
56696 	          snapping[axis] = {
56697 	            value: locationSnapping,
56698 	            originValue: locationSnapping - snapOrigin[axis]
56699 	          };
56700 	        }
56701 	      }
56702 	    });
56703 
56704 	    // no need to continue snapping
56705 	    if (snapping.x && snapping.y) {
56706 	      return false;
56707 	    }
56708 	  });
56709 
56710 	  // show snap lines
56711 	  this.showSnapLine('vertical', snapping.x && snapping.x.value);
56712 	  this.showSnapLine('horizontal', snapping.y && snapping.y.value);
56713 
56714 	  // snap event
56715 	  forEach([ 'x', 'y' ], function(axis) {
56716 	    var axisSnapping = snapping[axis];
56717 
56718 	    if (isObject(axisSnapping)) {
56719 	      setSnapped(event, axis, axisSnapping.originValue);
56720 	    }
56721 	  });
56722 	};
56723 
56724 	Snapping.prototype._createLine = function(orientation) {
56725 	  var root = this._canvas.getLayer('snap');
56726 
56727 	  var line = create$1('path');
56728 
56729 	  attr(line, { d: 'M0,0 L0,0' });
56730 
56731 	  classes(line).add('djs-snap-line');
56732 
56733 	  append(root, line);
56734 
56735 	  return {
56736 	    update: function(position) {
56737 
56738 	      if (!isNumber(position)) {
56739 	        attr(line, { display: 'none' });
56740 	      } else {
56741 	        if (orientation === 'horizontal') {
56742 	          attr(line, {
56743 	            d: 'M-100000,' + position + ' L+100000,' + position,
56744 	            display: ''
56745 	          });
56746 	        } else {
56747 	          attr(line, {
56748 	            d: 'M ' + position + ',-100000 L ' + position + ', +100000',
56749 	            display: ''
56750 	          });
56751 	        }
56752 	      }
56753 	    }
56754 	  };
56755 	};
56756 
56757 	Snapping.prototype._createSnapLines = function() {
56758 	  this._snapLines = {
56759 	    horizontal: this._createLine('horizontal'),
56760 	    vertical: this._createLine('vertical')
56761 	  };
56762 	};
56763 
56764 	Snapping.prototype.showSnapLine = function(orientation, position) {
56765 
56766 	  var line = this.getSnapLine(orientation);
56767 
56768 	  if (line) {
56769 	    line.update(position);
56770 	  }
56771 
56772 	  this._asyncHide();
56773 	};
56774 
56775 	Snapping.prototype.getSnapLine = function(orientation) {
56776 	  if (!this._snapLines) {
56777 	    this._createSnapLines();
56778 	  }
56779 
56780 	  return this._snapLines[orientation];
56781 	};
56782 
56783 	Snapping.prototype.hide = function() {
56784 	  forEach(this._snapLines, function(snapLine) {
56785 	    snapLine.update();
56786 	  });
56787 	};
56788 
56789 	var SnappingModule$1 = {
56790 	  __init__: [
56791 	    'createMoveSnapping',
56792 	    'resizeSnapping',
56793 	    'snapping'
56794 	  ],
56795 	  createMoveSnapping: [ 'type', CreateMoveSnapping ],
56796 	  resizeSnapping: [ 'type', ResizeSnapping ],
56797 	  snapping: [ 'type', Snapping ]
56798 	};
56799 
56800 	var SnappingModule = {
56801 	  __depends__: [ SnappingModule$1 ],
56802 	  __init__: [
56803 	    'connectSnapping',
56804 	    'createMoveSnapping'
56805 	  ],
56806 	  connectSnapping: [ 'type', BpmnConnectSnapping ],
56807 	  createMoveSnapping: [ 'type', BpmnCreateMoveSnapping ]
56808 	};
56809 
56810 	/**
56811 	 * Provides searching infrastructure
56812 	 */
56813 	function SearchPad(canvas, eventBus, overlays, selection) {
56814 	  this._open = false;
56815 	  this._results = [];
56816 	  this._eventMaps = [];
56817 
56818 	  this._canvas = canvas;
56819 	  this._eventBus = eventBus;
56820 	  this._overlays = overlays;
56821 	  this._selection = selection;
56822 
56823 	  // setup elements
56824 	  this._container = domify(SearchPad.BOX_HTML);
56825 	  this._searchInput = query(SearchPad.INPUT_SELECTOR, this._container);
56826 	  this._resultsContainer = query(SearchPad.RESULTS_CONTAINER_SELECTOR, this._container);
56827 
56828 	  // attach search pad
56829 	  this._canvas.getContainer().appendChild(this._container);
56830 
56831 	  // cleanup on destroy
56832 	  eventBus.on([ 'canvas.destroy', 'diagram.destroy' ], this.close, this);
56833 	}
56834 
56835 
56836 	SearchPad.$inject = [
56837 	  'canvas',
56838 	  'eventBus',
56839 	  'overlays',
56840 	  'selection'
56841 	];
56842 
56843 
56844 	/**
56845 	 * Binds and keeps track of all event listereners
56846 	 */
56847 	SearchPad.prototype._bindEvents = function() {
56848 	  var self = this;
56849 
56850 	  function listen(el, selector, type, fn) {
56851 	    self._eventMaps.push({
56852 	      el: el,
56853 	      type: type,
56854 	      listener: delegate.bind(el, selector, type, fn)
56855 	    });
56856 	  }
56857 
56858 	  // close search on clicking anywhere outside
56859 	  listen(document, 'html', 'click', function(e) {
56860 	    self.close();
56861 	  });
56862 
56863 	  // stop event from propagating and closing search
56864 	  // focus on input
56865 	  listen(this._container, SearchPad.INPUT_SELECTOR, 'click', function(e) {
56866 	    e.stopPropagation();
56867 	    e.delegateTarget.focus();
56868 	  });
56869 
56870 	  // preselect result on hover
56871 	  listen(this._container, SearchPad.RESULT_SELECTOR, 'mouseover', function(e) {
56872 	    e.stopPropagation();
56873 	    self._scrollToNode(e.delegateTarget);
56874 	    self._preselect(e.delegateTarget);
56875 	  });
56876 
56877 	  // selects desired result on mouse click
56878 	  listen(this._container, SearchPad.RESULT_SELECTOR, 'click', function(e) {
56879 	    e.stopPropagation();
56880 	    self._select(e.delegateTarget);
56881 	  });
56882 
56883 	  // prevent cursor in input from going left and right when using up/down to
56884 	  // navigate results
56885 	  listen(this._container, SearchPad.INPUT_SELECTOR, 'keydown', function(e) {
56886 
56887 	    // up
56888 	    if (e.keyCode === 38) {
56889 	      e.preventDefault();
56890 	    }
56891 
56892 	    // down
56893 	    if (e.keyCode === 40) {
56894 	      e.preventDefault();
56895 	    }
56896 	  });
56897 
56898 	  // handle keyboard input
56899 	  listen(this._container, SearchPad.INPUT_SELECTOR, 'keyup', function(e) {
56900 
56901 	    // escape
56902 	    if (e.keyCode === 27) {
56903 	      return self.close();
56904 	    }
56905 
56906 	    // enter
56907 	    if (e.keyCode === 13) {
56908 	      var selected = self._getCurrentResult();
56909 
56910 	      return selected ? self._select(selected) : self.close();
56911 	    }
56912 
56913 	    // up
56914 	    if (e.keyCode === 38) {
56915 	      return self._scrollToDirection(true);
56916 	    }
56917 
56918 	    // down
56919 	    if (e.keyCode === 40) {
56920 	      return self._scrollToDirection();
56921 	    }
56922 
56923 	    // left && right
56924 	    // do not search while navigating text input
56925 	    if (e.keyCode === 37 || e.keyCode === 39) {
56926 	      return;
56927 	    }
56928 
56929 	    // anything else
56930 	    self._search(e.delegateTarget.value);
56931 	  });
56932 	};
56933 
56934 
56935 	/**
56936 	 * Unbinds all previously established listeners
56937 	 */
56938 	SearchPad.prototype._unbindEvents = function() {
56939 	  this._eventMaps.forEach(function(m) {
56940 	    delegate.unbind(m.el, m.type, m.listener);
56941 	  });
56942 	};
56943 
56944 
56945 	/**
56946 	 * Performs a search for the given pattern.
56947 	 *
56948 	 * @param  {string} pattern
56949 	 */
56950 	SearchPad.prototype._search = function(pattern) {
56951 	  var self = this;
56952 
56953 	  this._clearResults();
56954 
56955 	  // do not search on empty query
56956 	  if (!pattern || pattern === '') {
56957 	    return;
56958 	  }
56959 
56960 	  var searchResults = this._searchProvider.find(pattern);
56961 
56962 	  if (!searchResults.length) {
56963 	    return;
56964 	  }
56965 
56966 	  // append new results
56967 	  searchResults.forEach(function(result) {
56968 	    var id = result.element.id;
56969 	    var node = self._createResultNode(result, id);
56970 	    self._results[id] = {
56971 	      element: result.element,
56972 	      node: node
56973 	    };
56974 	  });
56975 
56976 	  // preselect first result
56977 	  var node = query(SearchPad.RESULT_SELECTOR, this._resultsContainer);
56978 	  this._scrollToNode(node);
56979 	  this._preselect(node);
56980 	};
56981 
56982 
56983 	/**
56984 	 * Navigate to the previous/next result. Defaults to next result.
56985 	 * @param  {boolean} previous
56986 	 */
56987 	SearchPad.prototype._scrollToDirection = function(previous) {
56988 	  var selected = this._getCurrentResult();
56989 	  if (!selected) {
56990 	    return;
56991 	  }
56992 
56993 	  var node = previous ? selected.previousElementSibling : selected.nextElementSibling;
56994 	  if (node) {
56995 	    this._scrollToNode(node);
56996 	    this._preselect(node);
56997 	  }
56998 	};
56999 
57000 
57001 	/**
57002 	 * Scroll to the node if it is not visible.
57003 	 *
57004 	 * @param  {Element} node
57005 	 */
57006 	SearchPad.prototype._scrollToNode = function(node) {
57007 	  if (!node || node === this._getCurrentResult()) {
57008 	    return;
57009 	  }
57010 
57011 	  var nodeOffset = node.offsetTop;
57012 	  var containerScroll = this._resultsContainer.scrollTop;
57013 
57014 	  var bottomScroll = nodeOffset - this._resultsContainer.clientHeight + node.clientHeight;
57015 
57016 	  if (nodeOffset < containerScroll) {
57017 	    this._resultsContainer.scrollTop = nodeOffset;
57018 	  } else if (containerScroll < bottomScroll) {
57019 	    this._resultsContainer.scrollTop = bottomScroll;
57020 	  }
57021 	};
57022 
57023 
57024 	/**
57025 	 * Clears all results data.
57026 	 */
57027 	SearchPad.prototype._clearResults = function() {
57028 	  clear$1(this._resultsContainer);
57029 
57030 	  this._results = [];
57031 
57032 	  this._resetOverlay();
57033 
57034 	  this._eventBus.fire('searchPad.cleared');
57035 	};
57036 
57037 
57038 	/**
57039 	 * Get currently selected result.
57040 	 *
57041 	 * @return {Element}
57042 	 */
57043 	SearchPad.prototype._getCurrentResult = function() {
57044 	  return query(SearchPad.RESULT_SELECTED_SELECTOR, this._resultsContainer);
57045 	};
57046 
57047 
57048 	/**
57049 	 * Create result DOM element within results container
57050 	 * that corresponds to a search result.
57051 	 *
57052 	 * 'result' : one of the elements returned by SearchProvider
57053 	 * 'id' : id attribute value to assign to the new DOM node
57054 	 * return : created DOM element
57055 	 *
57056 	 * @param  {SearchResult} result
57057 	 * @param  {string} id
57058 	 * @return {Element}
57059 	 */
57060 	SearchPad.prototype._createResultNode = function(result, id) {
57061 	  var node = domify(SearchPad.RESULT_HTML);
57062 
57063 	  // create only if available
57064 	  if (result.primaryTokens.length > 0) {
57065 	    createInnerTextNode(node, result.primaryTokens, SearchPad.RESULT_PRIMARY_HTML);
57066 	  }
57067 
57068 	  // secondary tokens (represent element ID) are allways available
57069 	  createInnerTextNode(node, result.secondaryTokens, SearchPad.RESULT_SECONDARY_HTML);
57070 
57071 	  attr$1(node, SearchPad.RESULT_ID_ATTRIBUTE, id);
57072 
57073 	  this._resultsContainer.appendChild(node);
57074 
57075 	  return node;
57076 	};
57077 
57078 
57079 	/**
57080 	 * Register search element provider.
57081 	 *
57082 	 * SearchProvider.find - provides search function over own elements
57083 	 *  (pattern) => [{ text: <String>, element: <Element>}, ...]
57084 	 *
57085 	 * @param  {SearchProvider} provider
57086 	 */
57087 	SearchPad.prototype.registerProvider = function(provider) {
57088 	  this._searchProvider = provider;
57089 	};
57090 
57091 
57092 	/**
57093 	 * Open search pad.
57094 	 */
57095 	SearchPad.prototype.open = function() {
57096 	  if (!this._searchProvider) {
57097 	    throw new Error('no search provider registered');
57098 	  }
57099 
57100 	  if (this.isOpen()) {
57101 	    return;
57102 	  }
57103 
57104 	  this._bindEvents();
57105 
57106 	  this._open = true;
57107 
57108 	  classes$1(this._container).add('open');
57109 
57110 	  this._searchInput.focus();
57111 
57112 	  this._eventBus.fire('searchPad.opened');
57113 	};
57114 
57115 
57116 	/**
57117 	 * Close search pad.
57118 	 */
57119 	SearchPad.prototype.close = function() {
57120 	  if (!this.isOpen()) {
57121 	    return;
57122 	  }
57123 
57124 	  this._unbindEvents();
57125 
57126 	  this._open = false;
57127 
57128 	  classes$1(this._container).remove('open');
57129 
57130 	  this._clearResults();
57131 
57132 	  this._searchInput.value = '';
57133 	  this._searchInput.blur();
57134 
57135 	  this._resetOverlay();
57136 
57137 	  this._eventBus.fire('searchPad.closed');
57138 	};
57139 
57140 
57141 	/**
57142 	 * Toggles search pad on/off.
57143 	 */
57144 	SearchPad.prototype.toggle = function() {
57145 	  this.isOpen() ? this.close() : this.open();
57146 	};
57147 
57148 
57149 	/**
57150 	 * Report state of search pad.
57151 	 */
57152 	SearchPad.prototype.isOpen = function() {
57153 	  return this._open;
57154 	};
57155 
57156 
57157 	/**
57158 	 * Preselect result entry.
57159 	 *
57160 	 * @param  {Element} element
57161 	 */
57162 	SearchPad.prototype._preselect = function(node) {
57163 	  var selectedNode = this._getCurrentResult();
57164 
57165 	  // already selected
57166 	  if (node === selectedNode) {
57167 	    return;
57168 	  }
57169 
57170 	  // removing preselection from current node
57171 	  if (selectedNode) {
57172 	    classes$1(selectedNode).remove(SearchPad.RESULT_SELECTED_CLASS);
57173 	  }
57174 
57175 	  var id = attr$1(node, SearchPad.RESULT_ID_ATTRIBUTE);
57176 	  var element = this._results[id].element;
57177 
57178 	  classes$1(node).add(SearchPad.RESULT_SELECTED_CLASS);
57179 
57180 	  this._resetOverlay(element);
57181 
57182 	  this._canvas.scrollToElement(element, { top: 400 });
57183 
57184 	  this._selection.select(element);
57185 
57186 	  this._eventBus.fire('searchPad.preselected', element);
57187 	};
57188 
57189 
57190 	/**
57191 	 * Select result node.
57192 	 *
57193 	 * @param  {Element} element
57194 	 */
57195 	SearchPad.prototype._select = function(node) {
57196 	  var id = attr$1(node, SearchPad.RESULT_ID_ATTRIBUTE);
57197 	  var element = this._results[id].element;
57198 
57199 	  this.close();
57200 
57201 	  this._resetOverlay();
57202 
57203 	  this._canvas.scrollToElement(element, { top: 400 });
57204 
57205 	  this._selection.select(element);
57206 
57207 	  this._eventBus.fire('searchPad.selected', element);
57208 	};
57209 
57210 
57211 	/**
57212 	 * Reset overlay removes and, optionally, set
57213 	 * overlay to a new element.
57214 	 *
57215 	 * @param  {Element} element
57216 	 */
57217 	SearchPad.prototype._resetOverlay = function(element) {
57218 	  if (this._overlayId) {
57219 	    this._overlays.remove(this._overlayId);
57220 	  }
57221 
57222 	  if (element) {
57223 	    var box = getBBox(element);
57224 	    var overlay = constructOverlay(box);
57225 	    this._overlayId = this._overlays.add(element, overlay);
57226 	  }
57227 	};
57228 
57229 
57230 	/**
57231 	 * Construct overlay object for the given bounding box.
57232 	 *
57233 	 * @param  {BoundingBox} box
57234 	 * @return {Object}
57235 	 */
57236 	function constructOverlay(box) {
57237 
57238 	  var offset = 6;
57239 	  var w = box.width + offset * 2;
57240 	  var h = box.height + offset * 2;
57241 
57242 	  var styles = [
57243 	    'width: '+ w +'px',
57244 	    'height: '+ h + 'px'
57245 	  ].join('; ');
57246 
57247 	  return {
57248 	    position: {
57249 	      bottom: h - offset,
57250 	      right: w - offset
57251 	    },
57252 	    show: true,
57253 	    html: '<div style="' + styles + '" class="' + SearchPad.OVERLAY_CLASS + '"></div>'
57254 	  };
57255 	}
57256 
57257 
57258 	/**
57259 	 * Creates and appends child node from result tokens and HTML template.
57260 	 *
57261 	 * @param  {Element} node
57262 	 * @param  {Array<Object>} tokens
57263 	 * @param  {string} template
57264 	 */
57265 	function createInnerTextNode(parentNode, tokens, template) {
57266 	  var text = createHtmlText(tokens);
57267 	  var childNode = domify(template);
57268 	  childNode.innerHTML = text;
57269 	  parentNode.appendChild(childNode);
57270 	}
57271 
57272 	/**
57273 	 * Create internal HTML markup from result tokens.
57274 	 * Caters for highlighting pattern matched tokens.
57275 	 *
57276 	 * @param  {Array<Object>} tokens
57277 	 * @return {string}
57278 	 */
57279 	function createHtmlText(tokens) {
57280 	  var htmlText = '';
57281 
57282 	  tokens.forEach(function(t) {
57283 	    if (t.matched) {
57284 	      htmlText += '<strong class="' + SearchPad.RESULT_HIGHLIGHT_CLASS + '">' + escapeHTML(t.matched) + '</strong>';
57285 	    } else {
57286 	      htmlText += escapeHTML(t.normal);
57287 	    }
57288 	  });
57289 
57290 	  return htmlText !== '' ? htmlText : null;
57291 	}
57292 
57293 
57294 	/**
57295 	 * CONSTANTS
57296 	 */
57297 	SearchPad.CONTAINER_SELECTOR = '.djs-search-container';
57298 	SearchPad.INPUT_SELECTOR = '.djs-search-input input';
57299 	SearchPad.RESULTS_CONTAINER_SELECTOR = '.djs-search-results';
57300 	SearchPad.RESULT_SELECTOR = '.djs-search-result';
57301 	SearchPad.RESULT_SELECTED_CLASS = 'djs-search-result-selected';
57302 	SearchPad.RESULT_SELECTED_SELECTOR = '.' + SearchPad.RESULT_SELECTED_CLASS;
57303 	SearchPad.RESULT_ID_ATTRIBUTE = 'data-result-id';
57304 	SearchPad.RESULT_HIGHLIGHT_CLASS = 'djs-search-highlight';
57305 	SearchPad.OVERLAY_CLASS = 'djs-search-overlay';
57306 
57307 	SearchPad.BOX_HTML =
57308 	  '<div class="djs-search-container djs-draggable djs-scrollable">' +
57309 	    '<div class="djs-search-input">' +
57310 	      '<input type="text"/>' +
57311 	    '</div>' +
57312 	    '<div class="djs-search-results"></div>' +
57313 	  '</div>';
57314 
57315 	SearchPad.RESULT_HTML =
57316 	  '<div class="djs-search-result"></div>';
57317 
57318 	SearchPad.RESULT_PRIMARY_HTML =
57319 	  '<div class="djs-search-result-primary"></div>';
57320 
57321 	SearchPad.RESULT_SECONDARY_HTML =
57322 	  '<p class="djs-search-result-secondary"></p>';
57323 
57324 	var SearchPadModule = {
57325 	  __depends__: [
57326 	    OverlaysModule,
57327 	    SelectionModule
57328 	  ],
57329 	  searchPad: [ 'type', SearchPad ]
57330 	};
57331 
57332 	/**
57333 	 * Provides ability to search through BPMN elements
57334 	 */
57335 	function BpmnSearchProvider(elementRegistry, searchPad, canvas) {
57336 
57337 	  this._elementRegistry = elementRegistry;
57338 	  this._canvas = canvas;
57339 
57340 	  searchPad.registerProvider(this);
57341 	}
57342 
57343 	BpmnSearchProvider.$inject = [
57344 	  'elementRegistry',
57345 	  'searchPad',
57346 	  'canvas'
57347 	];
57348 
57349 
57350 	/**
57351 	 * Finds all elements that match given pattern
57352 	 *
57353 	 * <Result> :
57354 	 *  {
57355 	 *    primaryTokens: <Array<Token>>,
57356 	 *    secondaryTokens: <Array<Token>>,
57357 	 *    element: <Element>
57358 	 *  }
57359 	 *
57360 	 * <Token> :
57361 	 *  {
57362 	 *    normal|matched: <string>
57363 	 *  }
57364 	 *
57365 	 * @param  {string} pattern
57366 	 * @return {Array<Result>}
57367 	 */
57368 	BpmnSearchProvider.prototype.find = function(pattern) {
57369 	  var rootElement = this._canvas.getRootElement();
57370 
57371 	  var elements = this._elementRegistry.filter(function(element) {
57372 	    if (element.labelTarget) {
57373 	      return false;
57374 	    }
57375 	    return true;
57376 	  });
57377 
57378 	  // do not include root element
57379 	  elements = filter(elements, function(element) {
57380 	    return element !== rootElement;
57381 	  });
57382 
57383 	  elements = map$1(elements, function(element) {
57384 	    return {
57385 	      primaryTokens: matchAndSplit(getLabel(element), pattern),
57386 	      secondaryTokens: matchAndSplit(element.id, pattern),
57387 	      element: element
57388 	    };
57389 	  });
57390 
57391 	  // exclude non-matched elements
57392 	  elements = filter(elements, function(element) {
57393 	    return hasMatched(element.primaryTokens) || hasMatched(element.secondaryTokens);
57394 	  });
57395 
57396 	  elements = sortBy(elements, function(element) {
57397 	    return getLabel(element.element) + element.element.id;
57398 	  });
57399 
57400 	  return elements;
57401 	};
57402 
57403 
57404 	function hasMatched(tokens) {
57405 	  var matched = filter(tokens, function(t) {
57406 	    return !!t.matched;
57407 	  });
57408 
57409 	  return matched.length > 0;
57410 	}
57411 
57412 
57413 	function matchAndSplit(text, pattern) {
57414 	  var tokens = [],
57415 	      originalText = text;
57416 
57417 	  if (!text) {
57418 	    return tokens;
57419 	  }
57420 
57421 	  text = text.toLowerCase();
57422 	  pattern = pattern.toLowerCase();
57423 
57424 	  var i = text.indexOf(pattern);
57425 
57426 	  if (i > -1) {
57427 	    if (i !== 0) {
57428 	      tokens.push({
57429 	        normal: originalText.substr(0, i)
57430 	      });
57431 	    }
57432 
57433 	    tokens.push({
57434 	      matched: originalText.substr(i, pattern.length)
57435 	    });
57436 
57437 	    if (pattern.length + i < text.length) {
57438 	      tokens.push({
57439 	        normal: originalText.substr(pattern.length + i, text.length)
57440 	      });
57441 	    }
57442 	  } else {
57443 	    tokens.push({
57444 	      normal: originalText
57445 	    });
57446 	  }
57447 
57448 	  return tokens;
57449 	}
57450 
57451 	var SearchModule = {
57452 	  __depends__: [
57453 	    SearchPadModule
57454 	  ],
57455 	  __init__: [ 'bpmnSearch'],
57456 	  bpmnSearch: [ 'type', BpmnSearchProvider ]
57457 	};
57458 
57459 	var initialDiagram =
57460 	  '<?xml version="1.0" encoding="UTF-8"?>' +
57461 	  '<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
57462 	                    'xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" ' +
57463 	                    'xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" ' +
57464 	                    'xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" ' +
57465 	                    'targetNamespace="http://bpmn.io/schema/bpmn" ' +
57466 	                    'id="Definitions_1">' +
57467 	    '<bpmn:process id="Process_1" isExecutable="false">' +
57468 	      '<bpmn:startEvent id="StartEvent_1"/>' +
57469 	    '</bpmn:process>' +
57470 	    '<bpmndi:BPMNDiagram id="BPMNDiagram_1">' +
57471 	      '<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">' +
57472 	        '<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">' +
57473 	          '<dc:Bounds height="36.0" width="36.0" x="173.0" y="102.0"/>' +
57474 	        '</bpmndi:BPMNShape>' +
57475 	      '</bpmndi:BPMNPlane>' +
57476 	    '</bpmndi:BPMNDiagram>' +
57477 	  '</bpmn:definitions>';
57478 
57479 
57480 	/**
57481 	 * A modeler for BPMN 2.0 diagrams.
57482 	 *
57483 	 *
57484 	 * ## Extending the Modeler
57485 	 *
57486 	 * In order to extend the viewer pass extension modules to bootstrap via the
57487 	 * `additionalModules` option. An extension module is an object that exposes
57488 	 * named services.
57489 	 *
57490 	 * The following example depicts the integration of a simple
57491 	 * logging component that integrates with interaction events:
57492 	 *
57493 	 *
57494 	 * ```javascript
57495 	 *
57496 	 * // logging component
57497 	 * function InteractionLogger(eventBus) {
57498 	 *   eventBus.on('element.hover', function(event) {
57499 	 *     console.log()
57500 	 *   })
57501 	 * }
57502 	 *
57503 	 * InteractionLogger.$inject = [ 'eventBus' ]; // minification save
57504 	 *
57505 	 * // extension module
57506 	 * var extensionModule = {
57507 	 *   __init__: [ 'interactionLogger' ],
57508 	 *   interactionLogger: [ 'type', InteractionLogger ]
57509 	 * };
57510 	 *
57511 	 * // extend the viewer
57512 	 * var bpmnModeler = new Modeler({ additionalModules: [ extensionModule ] });
57513 	 * bpmnModeler.importXML(...);
57514 	 * ```
57515 	 *
57516 	 *
57517 	 * ## Customizing / Replacing Components
57518 	 *
57519 	 * You can replace individual diagram components by redefining them in override modules.
57520 	 * This works for all components, including those defined in the core.
57521 	 *
57522 	 * Pass in override modules via the `options.additionalModules` flag like this:
57523 	 *
57524 	 * ```javascript
57525 	 * function CustomContextPadProvider(contextPad) {
57526 	 *
57527 	 *   contextPad.registerProvider(this);
57528 	 *
57529 	 *   this.getContextPadEntries = function(element) {
57530 	 *     // no entries, effectively disable the context pad
57531 	 *     return {};
57532 	 *   };
57533 	 * }
57534 	 *
57535 	 * CustomContextPadProvider.$inject = [ 'contextPad' ];
57536 	 *
57537 	 * var overrideModule = {
57538 	 *   contextPadProvider: [ 'type', CustomContextPadProvider ]
57539 	 * };
57540 	 *
57541 	 * var bpmnModeler = new Modeler({ additionalModules: [ overrideModule ]});
57542 	 * ```
57543 	 *
57544 	 * @param {Object} [options] configuration options to pass to the viewer
57545 	 * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
57546 	 * @param {string|number} [options.width] the width of the viewer
57547 	 * @param {string|number} [options.height] the height of the viewer
57548 	 * @param {Object} [options.moddleExtensions] extension packages to provide
57549 	 * @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
57550 	 * @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
57551 	 */
57552 	function Modeler(options) {
57553 	  BaseModeler.call(this, options);
57554 	}
57555 
57556 	inherits$1(Modeler, BaseModeler);
57557 
57558 
57559 	Modeler.Viewer = Viewer;
57560 	Modeler.NavigatedViewer = NavigatedViewer;
57561 
57562 	/**
57563 	* The createDiagram result.
57564 	*
57565 	* @typedef {Object} CreateDiagramResult
57566 	*
57567 	* @property {Array<string>} warnings
57568 	*/
57569 
57570 	/**
57571 	* The createDiagram error.
57572 	*
57573 	* @typedef {Error} CreateDiagramError
57574 	*
57575 	* @property {Array<string>} warnings
57576 	*/
57577 
57578 	/**
57579 	 * Create a new diagram to start modeling.
57580 	 *
57581 	 * Returns {Promise<CreateDiagramResult, CreateDiagramError>}
57582 	 */
57583 	Modeler.prototype.createDiagram = wrapForCompatibility(function createDiagram() {
57584 	  return this.importXML(initialDiagram);
57585 	});
57586 
57587 
57588 	Modeler.prototype._interactionModules = [
57589 
57590 	  // non-modeling components
57591 	  KeyboardMoveModule,
57592 	  MoveCanvasModule,
57593 	  TouchModule,
57594 	  ZoomScrollModule
57595 	];
57596 
57597 	Modeler.prototype._modelingModules = [
57598 
57599 	  // modeling components
57600 	  AlignElementsModule,
57601 	  AutoPlaceModule,
57602 	  AutoScrollModule,
57603 	  AutoResizeModule,
57604 	  BendpointsModule,
57605 	  ConnectModule,
57606 	  ConnectionPreviewModule,
57607 	  ContextPadModule,
57608 	  CopyPasteModule,
57609 	  CreateModule,
57610 	  DistributeElementsModule,
57611 	  EditorActionsModule,
57612 	  GridSnappingModule,
57613 	  InteractionEventsModule,
57614 	  KeyboardModule,
57615 	  KeyboardMoveSelectionModule,
57616 	  LabelEditingModule,
57617 	  ModelingModule,
57618 	  MoveModule,
57619 	  PaletteModule,
57620 	  ReplacePreviewModule,
57621 	  ResizeModule,
57622 	  SnappingModule,
57623 	  SearchModule
57624 	];
57625 
57626 
57627 	// modules the modeler is composed of
57628 	//
57629 	// - viewer modules
57630 	// - interaction modules
57631 	// - modeling modules
57632 
57633 	Modeler.prototype._modules = [].concat(
57634 	  Viewer.prototype._modules,
57635 	  Modeler.prototype._interactionModules,
57636 	  Modeler.prototype._modelingModules
57637 	);
57638 
57639 	return Modeler;
57640 
57641 })));
57642