UNPKG

52.3 kBJavaScriptView Raw
1import inherits from 'inherits';
2
3import {
4 isObject,
5 assign,
6 forEach
7} from 'min-dash';
8
9import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
10
11import {
12 isExpanded,
13 isEventSubProcess
14} from '../util/DiUtil';
15
16import { is } from '../util/ModelUtil';
17
18import {
19 createLine
20} from 'diagram-js/lib/util/RenderUtil';
21
22import {
23 isTypedEvent,
24 isThrowEvent,
25 isCollection,
26 getDi,
27 getSemantic,
28 getCirclePath,
29 getRoundRectPath,
30 getDiamondPath,
31 getRectPath,
32 getFillColor,
33 getStrokeColor
34} from './BpmnRenderUtil';
35
36import {
37 query as domQuery
38} from 'min-dom';
39
40import {
41 append as svgAppend,
42 attr as svgAttr,
43 create as svgCreate,
44 classes as svgClasses
45} from 'tiny-svg';
46
47import {
48 rotate,
49 transform,
50 translate
51} from 'diagram-js/lib/util/SvgTransformUtil';
52
53import Ids from 'ids';
54
55var RENDERER_IDS = new Ids();
56
57var TASK_BORDER_RADIUS = 10;
58var INNER_OUTER_DIST = 3;
59
60var DEFAULT_FILL_OPACITY = .95,
61 HIGH_FILL_OPACITY = .35;
62
63
64export default function BpmnRenderer(
65 config, eventBus, styles, pathMap,
66 canvas, textRenderer, priority) {
67
68 BaseRenderer.call(this, eventBus, priority);
69
70 var defaultFillColor = config && config.defaultFillColor,
71 defaultStrokeColor = config && config.defaultStrokeColor;
72
73 var rendererId = RENDERER_IDS.next();
74
75 var markers = {};
76
77 var computeStyle = styles.computeStyle;
78
79 function addMarker(id, options) {
80 var attrs = assign({
81 fill: 'black',
82 strokeWidth: 1,
83 strokeLinecap: 'round',
84 strokeDasharray: 'none'
85 }, options.attrs);
86
87 var ref = options.ref || { x: 0, y: 0 };
88
89 var scale = options.scale || 1;
90
91 // fix for safari / chrome / firefox bug not correctly
92 // resetting stroke dash array
93 if (attrs.strokeDasharray === 'none') {
94 attrs.strokeDasharray = [10000, 1];
95 }
96
97 var marker = svgCreate('marker');
98
99 svgAttr(options.element, attrs);
100
101 svgAppend(marker, options.element);
102
103 svgAttr(marker, {
104 id: id,
105 viewBox: '0 0 20 20',
106 refX: ref.x,
107 refY: ref.y,
108 markerWidth: 20 * scale,
109 markerHeight: 20 * scale,
110 orient: 'auto'
111 });
112
113 var defs = domQuery('defs', canvas._svg);
114
115 if (!defs) {
116 defs = svgCreate('defs');
117
118 svgAppend(canvas._svg, defs);
119 }
120
121 svgAppend(defs, marker);
122
123 markers[id] = marker;
124 }
125
126 function marker(type, fill, stroke) {
127 var id = type + '-' + fill + '-' + stroke + '-' + rendererId;
128
129 if (!markers[id]) {
130 createMarker(type, fill, stroke);
131 }
132
133 return 'url(#' + id + ')';
134 }
135
136 function createMarker(type, fill, stroke) {
137 var id = type + '-' + fill + '-' + stroke + '-' + rendererId;
138
139 if (type === 'sequenceflow-end') {
140 var sequenceflowEnd = svgCreate('path');
141 svgAttr(sequenceflowEnd, { d: 'M 1 5 L 11 10 L 1 15 Z' });
142
143 addMarker(id, {
144 element: sequenceflowEnd,
145 ref: { x: 11, y: 10 },
146 scale: 0.5,
147 attrs: {
148 fill: stroke,
149 stroke: stroke
150 }
151 });
152 }
153
154 if (type === 'messageflow-start') {
155 var messageflowStart = svgCreate('circle');
156 svgAttr(messageflowStart, { cx: 6, cy: 6, r: 3.5 });
157
158 addMarker(id, {
159 element: messageflowStart,
160 attrs: {
161 fill: fill,
162 stroke: stroke
163 },
164 ref: { x: 6, y: 6 }
165 });
166 }
167
168 if (type === 'messageflow-end') {
169 var messageflowEnd = svgCreate('path');
170 svgAttr(messageflowEnd, { d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z' });
171
172 addMarker(id, {
173 element: messageflowEnd,
174 attrs: {
175 fill: fill,
176 stroke: stroke,
177 strokeLinecap: 'butt'
178 },
179 ref: { x: 8.5, y: 5 }
180 });
181 }
182
183 if (type === 'association-start') {
184 var associationStart = svgCreate('path');
185 svgAttr(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
186
187 addMarker(id, {
188 element: associationStart,
189 attrs: {
190 fill: 'none',
191 stroke: stroke,
192 strokeWidth: 1.5
193 },
194 ref: { x: 1, y: 10 },
195 scale: 0.5
196 });
197 }
198
199 if (type === 'association-end') {
200 var associationEnd = svgCreate('path');
201 svgAttr(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
202
203 addMarker(id, {
204 element: associationEnd,
205 attrs: {
206 fill: 'none',
207 stroke: stroke,
208 strokeWidth: 1.5
209 },
210 ref: { x: 12, y: 10 },
211 scale: 0.5
212 });
213 }
214
215 if (type === 'conditional-flow-marker') {
216 var conditionalflowMarker = svgCreate('path');
217 svgAttr(conditionalflowMarker, { d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z' });
218
219 addMarker(id, {
220 element: conditionalflowMarker,
221 attrs: {
222 fill: fill,
223 stroke: stroke
224 },
225 ref: { x: -1, y: 10 },
226 scale: 0.5
227 });
228 }
229
230 if (type === 'conditional-default-flow-marker') {
231 var conditionaldefaultflowMarker = svgCreate('path');
232 svgAttr(conditionaldefaultflowMarker, { d: 'M 6 4 L 10 16' });
233
234 addMarker(id, {
235 element: conditionaldefaultflowMarker,
236 attrs: {
237 stroke: stroke
238 },
239 ref: { x: 0, y: 10 },
240 scale: 0.5
241 });
242 }
243 }
244
245 function drawCircle(parentGfx, width, height, offset, attrs) {
246
247 if (isObject(offset)) {
248 attrs = offset;
249 offset = 0;
250 }
251
252 offset = offset || 0;
253
254 attrs = computeStyle(attrs, {
255 stroke: 'black',
256 strokeWidth: 2,
257 fill: 'white'
258 });
259
260 if (attrs.fill === 'none') {
261 delete attrs.fillOpacity;
262 }
263
264 var cx = width / 2,
265 cy = height / 2;
266
267 var circle = svgCreate('circle');
268 svgAttr(circle, {
269 cx: cx,
270 cy: cy,
271 r: Math.round((width + height) / 4 - offset)
272 });
273 svgAttr(circle, attrs);
274
275 svgAppend(parentGfx, circle);
276
277 return circle;
278 }
279
280 function drawRect(parentGfx, width, height, r, offset, attrs) {
281
282 if (isObject(offset)) {
283 attrs = offset;
284 offset = 0;
285 }
286
287 offset = offset || 0;
288
289 attrs = computeStyle(attrs, {
290 stroke: 'black',
291 strokeWidth: 2,
292 fill: 'white'
293 });
294
295 var rect = svgCreate('rect');
296 svgAttr(rect, {
297 x: offset,
298 y: offset,
299 width: width - offset * 2,
300 height: height - offset * 2,
301 rx: r,
302 ry: r
303 });
304 svgAttr(rect, attrs);
305
306 svgAppend(parentGfx, rect);
307
308 return rect;
309 }
310
311 function drawDiamond(parentGfx, width, height, attrs) {
312
313 var x_2 = width / 2;
314 var y_2 = height / 2;
315
316 var points = [{ x: x_2, y: 0 }, { x: width, y: y_2 }, { x: x_2, y: height }, { x: 0, y: y_2 }];
317
318 var pointsString = points.map(function(point) {
319 return point.x + ',' + point.y;
320 }).join(' ');
321
322 attrs = computeStyle(attrs, {
323 stroke: 'black',
324 strokeWidth: 2,
325 fill: 'white'
326 });
327
328 var polygon = svgCreate('polygon');
329 svgAttr(polygon, {
330 points: pointsString
331 });
332 svgAttr(polygon, attrs);
333
334 svgAppend(parentGfx, polygon);
335
336 return polygon;
337 }
338
339 function drawLine(parentGfx, waypoints, attrs) {
340 attrs = computeStyle(attrs, [ 'no-fill' ], {
341 stroke: 'black',
342 strokeWidth: 2,
343 fill: 'none'
344 });
345
346 var line = createLine(waypoints, attrs);
347
348 svgAppend(parentGfx, line);
349
350 return line;
351 }
352
353 function drawPath(parentGfx, d, attrs) {
354
355 attrs = computeStyle(attrs, [ 'no-fill' ], {
356 strokeWidth: 2,
357 stroke: 'black'
358 });
359
360 var path = svgCreate('path');
361 svgAttr(path, { d: d });
362 svgAttr(path, attrs);
363
364 svgAppend(parentGfx, path);
365
366 return path;
367 }
368
369 function drawMarker(type, parentGfx, path, attrs) {
370 return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
371 }
372
373 function as(type) {
374 return function(parentGfx, element) {
375 return handlers[type](parentGfx, element);
376 };
377 }
378
379 function renderer(type) {
380 return handlers[type];
381 }
382
383 function renderEventContent(element, parentGfx) {
384
385 var event = getSemantic(element);
386 var isThrowing = isThrowEvent(event);
387
388 if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
389 return renderer('bpmn:MessageEventDefinition')(parentGfx, element, isThrowing);
390 }
391
392 if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
393 return renderer('bpmn:TimerEventDefinition')(parentGfx, element, isThrowing);
394 }
395
396 if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
397 return renderer('bpmn:ConditionalEventDefinition')(parentGfx, element);
398 }
399
400 if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
401 return renderer('bpmn:SignalEventDefinition')(parentGfx, element, isThrowing);
402 }
403
404 if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
405 isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) {
406 return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing);
407 }
408
409 if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
410 isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) {
411 return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing);
412 }
413
414 if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
415 return renderer('bpmn:EscalationEventDefinition')(parentGfx, element, isThrowing);
416 }
417
418 if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
419 return renderer('bpmn:LinkEventDefinition')(parentGfx, element, isThrowing);
420 }
421
422 if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
423 return renderer('bpmn:ErrorEventDefinition')(parentGfx, element, isThrowing);
424 }
425
426 if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
427 return renderer('bpmn:CancelEventDefinition')(parentGfx, element, isThrowing);
428 }
429
430 if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
431 return renderer('bpmn:CompensateEventDefinition')(parentGfx, element, isThrowing);
432 }
433
434 if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
435 return renderer('bpmn:TerminateEventDefinition')(parentGfx, element, isThrowing);
436 }
437
438 return null;
439 }
440
441 function renderLabel(parentGfx, label, options) {
442
443 options = assign({
444 size: {
445 width: 100
446 }
447 }, options);
448
449 var text = textRenderer.createText(label || '', options);
450
451 svgClasses(text).add('djs-label');
452
453 svgAppend(parentGfx, text);
454
455 return text;
456 }
457
458 function renderEmbeddedLabel(parentGfx, element, align) {
459 var semantic = getSemantic(element);
460
461 return renderLabel(parentGfx, semantic.name, {
462 box: element,
463 align: align,
464 padding: 5,
465 style: {
466 fill: getStrokeColor(element, defaultStrokeColor)
467 }
468 });
469 }
470
471 function renderExternalLabel(parentGfx, element) {
472 var semantic = getSemantic(element);
473 var box = {
474 width: 90,
475 height: 30,
476 x: element.width / 2 + element.x,
477 y: element.height / 2 + element.y
478 };
479
480 return renderLabel(parentGfx, semantic.name, {
481 box: box,
482 fitBox: true,
483 style: assign(
484 {},
485 textRenderer.getExternalStyle(),
486 {
487 fill: getStrokeColor(element, defaultStrokeColor)
488 }
489 )
490 });
491 }
492
493 function renderLaneLabel(parentGfx, text, element) {
494 var textBox = renderLabel(parentGfx, text, {
495 box: {
496 height: 30,
497 width: element.height
498 },
499 align: 'center-middle',
500 style: {
501 fill: getStrokeColor(element, defaultStrokeColor)
502 }
503 });
504
505 var top = -1 * element.height;
506
507 transform(textBox, 0, -top, 270);
508 }
509
510 function createPathFromConnection(connection) {
511 var waypoints = connection.waypoints;
512
513 var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
514 for (var i = 1; i < waypoints.length; i++) {
515 pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
516 }
517 return pathData;
518 }
519
520 var handlers = this.handlers = {
521 'bpmn:Event': function(parentGfx, element, attrs) {
522
523 if (!('fillOpacity' in attrs)) {
524 attrs.fillOpacity = DEFAULT_FILL_OPACITY;
525 }
526
527 return drawCircle(parentGfx, element.width, element.height, attrs);
528 },
529 'bpmn:StartEvent': function(parentGfx, element) {
530 var attrs = {
531 fill: getFillColor(element, defaultFillColor),
532 stroke: getStrokeColor(element, defaultStrokeColor)
533 };
534
535 var semantic = getSemantic(element);
536
537 if (!semantic.isInterrupting) {
538 attrs = {
539 strokeDasharray: '6',
540 strokeLinecap: 'round',
541 fill: getFillColor(element, defaultFillColor),
542 stroke: getStrokeColor(element, defaultStrokeColor)
543 };
544 }
545
546 var circle = renderer('bpmn:Event')(parentGfx, element, attrs);
547
548 renderEventContent(element, parentGfx);
549
550 return circle;
551 },
552 'bpmn:MessageEventDefinition': function(parentGfx, element, isThrowing) {
553 var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
554 xScaleFactor: 0.9,
555 yScaleFactor: 0.9,
556 containerWidth: element.width,
557 containerHeight: element.height,
558 position: {
559 mx: 0.235,
560 my: 0.315
561 }
562 });
563
564 var fill = isThrowing ? getStrokeColor(element, defaultStrokeColor) : getFillColor(element, defaultFillColor);
565 var stroke = isThrowing ? getFillColor(element, defaultFillColor) : getStrokeColor(element, defaultStrokeColor);
566
567 var messagePath = drawPath(parentGfx, pathData, {
568 strokeWidth: 1,
569 fill: fill,
570 stroke: stroke
571 });
572
573 return messagePath;
574 },
575 'bpmn:TimerEventDefinition': function(parentGfx, element) {
576 var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
577 strokeWidth: 2,
578 fill: getFillColor(element, defaultFillColor),
579 stroke: getStrokeColor(element, defaultStrokeColor)
580 });
581
582 var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
583 xScaleFactor: 0.75,
584 yScaleFactor: 0.75,
585 containerWidth: element.width,
586 containerHeight: element.height,
587 position: {
588 mx: 0.5,
589 my: 0.5
590 }
591 });
592
593 drawPath(parentGfx, pathData, {
594 strokeWidth: 2,
595 strokeLinecap: 'square',
596 stroke: getStrokeColor(element, defaultStrokeColor)
597 });
598
599 for (var i = 0;i < 12; i++) {
600
601 var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
602 xScaleFactor: 0.75,
603 yScaleFactor: 0.75,
604 containerWidth: element.width,
605 containerHeight: element.height,
606 position: {
607 mx: 0.5,
608 my: 0.5
609 }
610 });
611
612 var width = element.width / 2;
613 var height = element.height / 2;
614
615 drawPath(parentGfx, linePathData, {
616 strokeWidth: 1,
617 strokeLinecap: 'square',
618 transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')',
619 stroke: getStrokeColor(element, defaultStrokeColor)
620 });
621 }
622
623 return circle;
624 },
625 'bpmn:EscalationEventDefinition': function(parentGfx, event, isThrowing) {
626 var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
627 xScaleFactor: 1,
628 yScaleFactor: 1,
629 containerWidth: event.width,
630 containerHeight: event.height,
631 position: {
632 mx: 0.5,
633 my: 0.2
634 }
635 });
636
637 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
638
639 return drawPath(parentGfx, pathData, {
640 strokeWidth: 1,
641 fill: fill,
642 stroke: getStrokeColor(event, defaultStrokeColor)
643 });
644 },
645 'bpmn:ConditionalEventDefinition': function(parentGfx, event) {
646 var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
647 xScaleFactor: 1,
648 yScaleFactor: 1,
649 containerWidth: event.width,
650 containerHeight: event.height,
651 position: {
652 mx: 0.5,
653 my: 0.222
654 }
655 });
656
657 return drawPath(parentGfx, pathData, {
658 strokeWidth: 1,
659 stroke: getStrokeColor(event, defaultStrokeColor)
660 });
661 },
662 'bpmn:LinkEventDefinition': function(parentGfx, event, isThrowing) {
663 var pathData = pathMap.getScaledPath('EVENT_LINK', {
664 xScaleFactor: 1,
665 yScaleFactor: 1,
666 containerWidth: event.width,
667 containerHeight: event.height,
668 position: {
669 mx: 0.57,
670 my: 0.263
671 }
672 });
673
674 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
675
676 return drawPath(parentGfx, pathData, {
677 strokeWidth: 1,
678 fill: fill,
679 stroke: getStrokeColor(event, defaultStrokeColor)
680 });
681 },
682 'bpmn:ErrorEventDefinition': function(parentGfx, event, isThrowing) {
683 var pathData = pathMap.getScaledPath('EVENT_ERROR', {
684 xScaleFactor: 1.1,
685 yScaleFactor: 1.1,
686 containerWidth: event.width,
687 containerHeight: event.height,
688 position: {
689 mx: 0.2,
690 my: 0.722
691 }
692 });
693
694 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
695
696 return drawPath(parentGfx, pathData, {
697 strokeWidth: 1,
698 fill: fill,
699 stroke: getStrokeColor(event, defaultStrokeColor)
700 });
701 },
702 'bpmn:CancelEventDefinition': function(parentGfx, event, isThrowing) {
703 var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
704 xScaleFactor: 1.0,
705 yScaleFactor: 1.0,
706 containerWidth: event.width,
707 containerHeight: event.height,
708 position: {
709 mx: 0.638,
710 my: -0.055
711 }
712 });
713
714 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
715
716 var path = drawPath(parentGfx, pathData, {
717 strokeWidth: 1,
718 fill: fill,
719 stroke: getStrokeColor(event, defaultStrokeColor)
720 });
721
722 rotate(path, 45);
723
724 return path;
725 },
726 'bpmn:CompensateEventDefinition': function(parentGfx, event, isThrowing) {
727 var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
728 xScaleFactor: 1,
729 yScaleFactor: 1,
730 containerWidth: event.width,
731 containerHeight: event.height,
732 position: {
733 mx: 0.22,
734 my: 0.5
735 }
736 });
737
738 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
739
740 return drawPath(parentGfx, pathData, {
741 strokeWidth: 1,
742 fill: fill,
743 stroke: getStrokeColor(event, defaultStrokeColor)
744 });
745 },
746 'bpmn:SignalEventDefinition': function(parentGfx, event, isThrowing) {
747 var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
748 xScaleFactor: 0.9,
749 yScaleFactor: 0.9,
750 containerWidth: event.width,
751 containerHeight: event.height,
752 position: {
753 mx: 0.5,
754 my: 0.2
755 }
756 });
757
758 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
759
760 return drawPath(parentGfx, pathData, {
761 strokeWidth: 1,
762 fill: fill,
763 stroke: getStrokeColor(event, defaultStrokeColor)
764 });
765 },
766 'bpmn:MultipleEventDefinition': function(parentGfx, event, isThrowing) {
767 var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
768 xScaleFactor: 1.1,
769 yScaleFactor: 1.1,
770 containerWidth: event.width,
771 containerHeight: event.height,
772 position: {
773 mx: 0.222,
774 my: 0.36
775 }
776 });
777
778 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
779
780 return drawPath(parentGfx, pathData, {
781 strokeWidth: 1,
782 fill: fill
783 });
784 },
785 'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event) {
786 var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
787 xScaleFactor: 1.2,
788 yScaleFactor: 1.2,
789 containerWidth: event.width,
790 containerHeight: event.height,
791 position: {
792 mx: 0.458,
793 my: 0.194
794 }
795 });
796
797 return drawPath(parentGfx, pathData, {
798 strokeWidth: 1,
799 fill: getStrokeColor(event, defaultStrokeColor),
800 stroke: getStrokeColor(event, defaultStrokeColor)
801 });
802 },
803 'bpmn:EndEvent': function(parentGfx, element) {
804 var circle = renderer('bpmn:Event')(parentGfx, element, {
805 strokeWidth: 4,
806 fill: getFillColor(element, defaultFillColor),
807 stroke: getStrokeColor(element, defaultStrokeColor)
808 });
809
810 renderEventContent(element, parentGfx, true);
811
812 return circle;
813 },
814 'bpmn:TerminateEventDefinition': function(parentGfx, element) {
815 var circle = drawCircle(parentGfx, element.width, element.height, 8, {
816 strokeWidth: 4,
817 fill: getStrokeColor(element, defaultStrokeColor),
818 stroke: getStrokeColor(element, defaultStrokeColor)
819 });
820
821 return circle;
822 },
823 'bpmn:IntermediateEvent': function(parentGfx, element) {
824 var outer = renderer('bpmn:Event')(parentGfx, element, {
825 strokeWidth: 1,
826 fill: getFillColor(element, defaultFillColor),
827 stroke: getStrokeColor(element, defaultStrokeColor)
828 });
829
830 /* inner */
831 drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
832 strokeWidth: 1,
833 fill: getFillColor(element, 'none'),
834 stroke: getStrokeColor(element, defaultStrokeColor)
835 });
836
837 renderEventContent(element, parentGfx);
838
839 return outer;
840 },
841 'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
842 'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
843
844 'bpmn:Activity': function(parentGfx, element, attrs) {
845
846 attrs = attrs || {};
847
848 if (!('fillOpacity' in attrs)) {
849 attrs.fillOpacity = DEFAULT_FILL_OPACITY;
850 }
851
852 return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs);
853 },
854
855 'bpmn:Task': function(parentGfx, element) {
856 var attrs = {
857 fill: getFillColor(element, defaultFillColor),
858 stroke: getStrokeColor(element, defaultStrokeColor)
859 };
860
861 var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
862
863 renderEmbeddedLabel(parentGfx, element, 'center-middle');
864 attachTaskMarkers(parentGfx, element);
865
866 return rect;
867 },
868 'bpmn:ServiceTask': function(parentGfx, element) {
869 var task = renderer('bpmn:Task')(parentGfx, element);
870
871 var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
872 abspos: {
873 x: 12,
874 y: 18
875 }
876 });
877
878 /* service bg */ drawPath(parentGfx, pathDataBG, {
879 strokeWidth: 1,
880 fill: getFillColor(element, defaultFillColor),
881 stroke: getStrokeColor(element, defaultStrokeColor)
882 });
883
884 var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
885 abspos: {
886 x: 17.2,
887 y: 18
888 }
889 });
890
891 /* service fill */ drawPath(parentGfx, fillPathData, {
892 strokeWidth: 0,
893 fill: getFillColor(element, defaultFillColor)
894 });
895
896 var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
897 abspos: {
898 x: 17,
899 y: 22
900 }
901 });
902
903 /* service */ drawPath(parentGfx, pathData, {
904 strokeWidth: 1,
905 fill: getFillColor(element, defaultFillColor),
906 stroke: getStrokeColor(element, defaultStrokeColor)
907 });
908
909 return task;
910 },
911 'bpmn:UserTask': function(parentGfx, element) {
912 var task = renderer('bpmn:Task')(parentGfx, element);
913
914 var x = 15;
915 var y = 12;
916
917 var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
918 abspos: {
919 x: x,
920 y: y
921 }
922 });
923
924 /* user path */ drawPath(parentGfx, pathData, {
925 strokeWidth: 0.5,
926 fill: getFillColor(element, defaultFillColor),
927 stroke: getStrokeColor(element, defaultStrokeColor)
928 });
929
930 var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
931 abspos: {
932 x: x,
933 y: y
934 }
935 });
936
937 /* user2 path */ drawPath(parentGfx, pathData2, {
938 strokeWidth: 0.5,
939 fill: getFillColor(element, defaultFillColor),
940 stroke: getStrokeColor(element, defaultStrokeColor)
941 });
942
943 var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
944 abspos: {
945 x: x,
946 y: y
947 }
948 });
949
950 /* user3 path */ drawPath(parentGfx, pathData3, {
951 strokeWidth: 0.5,
952 fill: getStrokeColor(element, defaultStrokeColor),
953 stroke: getStrokeColor(element, defaultStrokeColor)
954 });
955
956 return task;
957 },
958 'bpmn:ManualTask': function(parentGfx, element) {
959 var task = renderer('bpmn:Task')(parentGfx, element);
960
961 var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
962 abspos: {
963 x: 17,
964 y: 15
965 }
966 });
967
968 /* manual path */ drawPath(parentGfx, pathData, {
969 strokeWidth: 0.5, // 0.25,
970 fill: getFillColor(element, defaultFillColor),
971 stroke: getStrokeColor(element, defaultStrokeColor)
972 });
973
974 return task;
975 },
976 'bpmn:SendTask': function(parentGfx, element) {
977 var task = renderer('bpmn:Task')(parentGfx, element);
978
979 var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
980 xScaleFactor: 1,
981 yScaleFactor: 1,
982 containerWidth: 21,
983 containerHeight: 14,
984 position: {
985 mx: 0.285,
986 my: 0.357
987 }
988 });
989
990 /* send path */ drawPath(parentGfx, pathData, {
991 strokeWidth: 1,
992 fill: getStrokeColor(element, defaultStrokeColor),
993 stroke: getFillColor(element, defaultFillColor)
994 });
995
996 return task;
997 },
998 'bpmn:ReceiveTask' : function(parentGfx, element) {
999 var semantic = getSemantic(element);
1000
1001 var task = renderer('bpmn:Task')(parentGfx, element);
1002 var pathData;
1003
1004 if (semantic.instantiate) {
1005 drawCircle(parentGfx, 28, 28, 20 * 0.22, { strokeWidth: 1 });
1006
1007 pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
1008 abspos: {
1009 x: 7.77,
1010 y: 9.52
1011 }
1012 });
1013 } else {
1014
1015 pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
1016 xScaleFactor: 0.9,
1017 yScaleFactor: 0.9,
1018 containerWidth: 21,
1019 containerHeight: 14,
1020 position: {
1021 mx: 0.3,
1022 my: 0.4
1023 }
1024 });
1025 }
1026
1027 /* receive path */ drawPath(parentGfx, pathData, {
1028 strokeWidth: 1,
1029 fill: getFillColor(element, defaultFillColor),
1030 stroke: getStrokeColor(element, defaultStrokeColor)
1031 });
1032
1033 return task;
1034 },
1035 'bpmn:ScriptTask': function(parentGfx, element) {
1036 var task = renderer('bpmn:Task')(parentGfx, element);
1037
1038 var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
1039 abspos: {
1040 x: 15,
1041 y: 20
1042 }
1043 });
1044
1045 /* script path */ drawPath(parentGfx, pathData, {
1046 strokeWidth: 1,
1047 stroke: getStrokeColor(element, defaultStrokeColor)
1048 });
1049
1050 return task;
1051 },
1052 'bpmn:BusinessRuleTask': function(parentGfx, element) {
1053 var task = renderer('bpmn:Task')(parentGfx, element);
1054
1055 var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
1056 abspos: {
1057 x: 8,
1058 y: 8
1059 }
1060 });
1061
1062 var businessHeaderPath = drawPath(parentGfx, headerPathData);
1063 svgAttr(businessHeaderPath, {
1064 strokeWidth: 1,
1065 fill: getFillColor(element, '#aaaaaa'),
1066 stroke: getStrokeColor(element, defaultStrokeColor)
1067 });
1068
1069 var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
1070 abspos: {
1071 x: 8,
1072 y: 8
1073 }
1074 });
1075
1076 var businessPath = drawPath(parentGfx, headerData);
1077 svgAttr(businessPath, {
1078 strokeWidth: 1,
1079 stroke: getStrokeColor(element, defaultStrokeColor)
1080 });
1081
1082 return task;
1083 },
1084 'bpmn:SubProcess': function(parentGfx, element, attrs) {
1085 attrs = assign({
1086 fill: getFillColor(element, defaultFillColor),
1087 stroke: getStrokeColor(element, defaultStrokeColor)
1088 }, attrs);
1089
1090 var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
1091
1092 var expanded = isExpanded(element);
1093
1094 if (isEventSubProcess(element)) {
1095 svgAttr(rect, {
1096 strokeDasharray: '1,2'
1097 });
1098 }
1099
1100 renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle');
1101
1102 if (expanded) {
1103 attachTaskMarkers(parentGfx, element);
1104 } else {
1105 attachTaskMarkers(parentGfx, element, ['SubProcessMarker']);
1106 }
1107
1108 return rect;
1109 },
1110 'bpmn:AdHocSubProcess': function(parentGfx, element) {
1111 return renderer('bpmn:SubProcess')(parentGfx, element);
1112 },
1113 'bpmn:Transaction': function(parentGfx, element) {
1114 var outer = renderer('bpmn:SubProcess')(parentGfx, element);
1115
1116 var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
1117 stroke: getStrokeColor(element, defaultStrokeColor)
1118 });
1119
1120 /* inner path */ drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
1121
1122 return outer;
1123 },
1124 'bpmn:CallActivity': function(parentGfx, element) {
1125 return renderer('bpmn:SubProcess')(parentGfx, element, {
1126 strokeWidth: 5
1127 });
1128 },
1129 'bpmn:Participant': function(parentGfx, element) {
1130
1131 var attrs = {
1132 fillOpacity: DEFAULT_FILL_OPACITY,
1133 fill: getFillColor(element, defaultFillColor),
1134 stroke: getStrokeColor(element, defaultStrokeColor)
1135 };
1136
1137 var lane = renderer('bpmn:Lane')(parentGfx, element, attrs);
1138
1139 var expandedPool = isExpanded(element);
1140
1141 if (expandedPool) {
1142 drawLine(parentGfx, [
1143 { x: 30, y: 0 },
1144 { x: 30, y: element.height }
1145 ], {
1146 stroke: getStrokeColor(element, defaultStrokeColor)
1147 });
1148 var text = getSemantic(element).name;
1149 renderLaneLabel(parentGfx, text, element);
1150 } else {
1151 // Collapsed pool draw text inline
1152 var text2 = getSemantic(element).name;
1153 renderLabel(parentGfx, text2, {
1154 box: element, align: 'center-middle',
1155 style: {
1156 fill: getStrokeColor(element, defaultStrokeColor)
1157 }
1158 });
1159 }
1160
1161 var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
1162
1163 if (participantMultiplicity) {
1164 renderer('ParticipantMultiplicityMarker')(parentGfx, element);
1165 }
1166
1167 return lane;
1168 },
1169 'bpmn:Lane': function(parentGfx, element, attrs) {
1170 var rect = drawRect(parentGfx, element.width, element.height, 0, assign({
1171 fill: getFillColor(element, defaultFillColor),
1172 fillOpacity: HIGH_FILL_OPACITY,
1173 stroke: getStrokeColor(element, defaultStrokeColor)
1174 }, attrs));
1175
1176 var semantic = getSemantic(element);
1177
1178 if (semantic.$type === 'bpmn:Lane') {
1179 var text = semantic.name;
1180 renderLaneLabel(parentGfx, text, element);
1181 }
1182
1183 return rect;
1184 },
1185 'bpmn:InclusiveGateway': function(parentGfx, element) {
1186 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
1187
1188 /* circle path */
1189 drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
1190 strokeWidth: 2.5,
1191 fill: getFillColor(element, defaultFillColor),
1192 stroke: getStrokeColor(element, defaultStrokeColor)
1193 });
1194
1195 return diamond;
1196 },
1197 'bpmn:ExclusiveGateway': function(parentGfx, element) {
1198 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
1199
1200 var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
1201 xScaleFactor: 0.4,
1202 yScaleFactor: 0.4,
1203 containerWidth: element.width,
1204 containerHeight: element.height,
1205 position: {
1206 mx: 0.32,
1207 my: 0.3
1208 }
1209 });
1210
1211 if ((getDi(element).isMarkerVisible)) {
1212 drawPath(parentGfx, pathData, {
1213 strokeWidth: 1,
1214 fill: getStrokeColor(element, defaultStrokeColor),
1215 stroke: getStrokeColor(element, defaultStrokeColor)
1216 });
1217 }
1218
1219 return diamond;
1220 },
1221 'bpmn:ComplexGateway': function(parentGfx, element) {
1222 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
1223
1224 var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
1225 xScaleFactor: 0.5,
1226 yScaleFactor:0.5,
1227 containerWidth: element.width,
1228 containerHeight: element.height,
1229 position: {
1230 mx: 0.46,
1231 my: 0.26
1232 }
1233 });
1234
1235 /* complex path */ drawPath(parentGfx, pathData, {
1236 strokeWidth: 1,
1237 fill: getStrokeColor(element, defaultStrokeColor),
1238 stroke: getStrokeColor(element, defaultStrokeColor)
1239 });
1240
1241 return diamond;
1242 },
1243 'bpmn:ParallelGateway': function(parentGfx, element) {
1244 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
1245
1246 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
1247 xScaleFactor: 0.6,
1248 yScaleFactor:0.6,
1249 containerWidth: element.width,
1250 containerHeight: element.height,
1251 position: {
1252 mx: 0.46,
1253 my: 0.2
1254 }
1255 });
1256
1257 /* parallel path */ drawPath(parentGfx, pathData, {
1258 strokeWidth: 1,
1259 fill: getStrokeColor(element, defaultStrokeColor),
1260 stroke: getStrokeColor(element, defaultStrokeColor)
1261 });
1262
1263 return diamond;
1264 },
1265 'bpmn:EventBasedGateway': function(parentGfx, element) {
1266
1267 var semantic = getSemantic(element);
1268
1269 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
1270
1271 /* outer circle path */ drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
1272 strokeWidth: 1,
1273 fill: 'none',
1274 stroke: getStrokeColor(element, defaultStrokeColor)
1275 });
1276
1277 var type = semantic.eventGatewayType;
1278 var instantiate = !!semantic.instantiate;
1279
1280 function drawEvent() {
1281
1282 var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
1283 xScaleFactor: 0.18,
1284 yScaleFactor: 0.18,
1285 containerWidth: element.width,
1286 containerHeight: element.height,
1287 position: {
1288 mx: 0.36,
1289 my: 0.44
1290 }
1291 });
1292
1293 var attrs = {
1294 strokeWidth: 2,
1295 fill: getFillColor(element, 'none'),
1296 stroke: getStrokeColor(element, defaultStrokeColor)
1297 };
1298
1299 /* event path */ drawPath(parentGfx, pathData, attrs);
1300 }
1301
1302 if (type === 'Parallel') {
1303
1304 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
1305 xScaleFactor: 0.4,
1306 yScaleFactor:0.4,
1307 containerWidth: element.width,
1308 containerHeight: element.height,
1309 position: {
1310 mx: 0.474,
1311 my: 0.296
1312 }
1313 });
1314
1315 var parallelPath = drawPath(parentGfx, pathData);
1316 svgAttr(parallelPath, {
1317 strokeWidth: 1,
1318 fill: 'none'
1319 });
1320 } else if (type === 'Exclusive') {
1321
1322 if (!instantiate) {
1323 var innerCircle = drawCircle(parentGfx, element.width, element.height, element.height * 0.26);
1324 svgAttr(innerCircle, {
1325 strokeWidth: 1,
1326 fill: 'none',
1327 stroke: getStrokeColor(element, defaultStrokeColor)
1328 });
1329 }
1330
1331 drawEvent();
1332 }
1333
1334
1335 return diamond;
1336 },
1337 'bpmn:Gateway': function(parentGfx, element) {
1338 var attrs = {
1339 fill: getFillColor(element, defaultFillColor),
1340 fillOpacity: DEFAULT_FILL_OPACITY,
1341 stroke: getStrokeColor(element, defaultStrokeColor)
1342 };
1343
1344 return drawDiamond(parentGfx, element.width, element.height, attrs);
1345 },
1346 'bpmn:SequenceFlow': function(parentGfx, element) {
1347 var pathData = createPathFromConnection(element);
1348
1349 var fill = getFillColor(element, defaultFillColor),
1350 stroke = getStrokeColor(element, defaultStrokeColor);
1351
1352 var attrs = {
1353 strokeLinejoin: 'round',
1354 markerEnd: marker('sequenceflow-end', fill, stroke),
1355 stroke: getStrokeColor(element, defaultStrokeColor)
1356 };
1357
1358 var path = drawPath(parentGfx, pathData, attrs);
1359
1360 var sequenceFlow = getSemantic(element);
1361
1362 var source;
1363
1364 if (element.source) {
1365 source = element.source.businessObject;
1366
1367 // conditional flow marker
1368 if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
1369 svgAttr(path, {
1370 markerStart: marker('conditional-flow-marker', fill, stroke)
1371 });
1372 }
1373
1374 // default marker
1375 if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
1376 source.default === sequenceFlow) {
1377 svgAttr(path, {
1378 markerStart: marker('conditional-default-flow-marker', fill, stroke)
1379 });
1380 }
1381 }
1382
1383 return path;
1384 },
1385 'bpmn:Association': function(parentGfx, element, attrs) {
1386
1387 var semantic = getSemantic(element);
1388
1389 var fill = getFillColor(element, defaultFillColor),
1390 stroke = getStrokeColor(element, defaultStrokeColor);
1391
1392 attrs = assign({
1393 strokeDasharray: '0.5, 5',
1394 strokeLinecap: 'round',
1395 strokeLinejoin: 'round',
1396 stroke: getStrokeColor(element, defaultStrokeColor)
1397 }, attrs || {});
1398
1399 if (semantic.associationDirection === 'One' ||
1400 semantic.associationDirection === 'Both') {
1401 attrs.markerEnd = marker('association-end', fill, stroke);
1402 }
1403
1404 if (semantic.associationDirection === 'Both') {
1405 attrs.markerStart = marker('association-start', fill, stroke);
1406 }
1407
1408 return drawLine(parentGfx, element.waypoints, attrs);
1409 },
1410 'bpmn:DataInputAssociation': function(parentGfx, element) {
1411 var fill = getFillColor(element, defaultFillColor),
1412 stroke = getStrokeColor(element, defaultStrokeColor);
1413
1414 return renderer('bpmn:Association')(parentGfx, element, {
1415 markerEnd: marker('association-end', fill, stroke)
1416 });
1417 },
1418 'bpmn:DataOutputAssociation': function(parentGfx, element) {
1419 var fill = getFillColor(element, defaultFillColor),
1420 stroke = getStrokeColor(element, defaultStrokeColor);
1421
1422 return renderer('bpmn:Association')(parentGfx, element, {
1423 markerEnd: marker('association-end', fill, stroke)
1424 });
1425 },
1426 'bpmn:MessageFlow': function(parentGfx, element) {
1427
1428 var semantic = getSemantic(element),
1429 di = getDi(element);
1430
1431 var fill = getFillColor(element, defaultFillColor),
1432 stroke = getStrokeColor(element, defaultStrokeColor);
1433
1434 var pathData = createPathFromConnection(element);
1435
1436 var attrs = {
1437 markerEnd: marker('messageflow-end', fill, stroke),
1438 markerStart: marker('messageflow-start', fill, stroke),
1439 strokeDasharray: '10, 12',
1440 strokeLinecap: 'round',
1441 strokeLinejoin: 'round',
1442 strokeWidth: '1.5px',
1443 stroke: getStrokeColor(element, defaultStrokeColor)
1444 };
1445
1446 var path = drawPath(parentGfx, pathData, attrs);
1447
1448 if (semantic.messageRef) {
1449 var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
1450
1451 var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
1452 abspos: {
1453 x: midPoint.x,
1454 y: midPoint.y
1455 }
1456 });
1457
1458 var messageAttrs = { strokeWidth: 1 };
1459
1460 if (di.messageVisibleKind === 'initiating') {
1461 messageAttrs.fill = 'white';
1462 messageAttrs.stroke = 'black';
1463 } else {
1464 messageAttrs.fill = '#888';
1465 messageAttrs.stroke = 'white';
1466 }
1467
1468 drawPath(parentGfx, markerPathData, messageAttrs);
1469 }
1470
1471 return path;
1472 },
1473 'bpmn:DataObject': function(parentGfx, element) {
1474 var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
1475 xScaleFactor: 1,
1476 yScaleFactor: 1,
1477 containerWidth: element.width,
1478 containerHeight: element.height,
1479 position: {
1480 mx: 0.474,
1481 my: 0.296
1482 }
1483 });
1484
1485 var elementObject = drawPath(parentGfx, pathData, {
1486 fill: getFillColor(element, defaultFillColor),
1487 fillOpacity: DEFAULT_FILL_OPACITY,
1488 stroke: getStrokeColor(element, defaultStrokeColor)
1489 });
1490
1491 var semantic = getSemantic(element);
1492
1493 if (isCollection(semantic)) {
1494 renderDataItemCollection(parentGfx, element);
1495 }
1496
1497 return elementObject;
1498 },
1499 'bpmn:DataObjectReference': as('bpmn:DataObject'),
1500 'bpmn:DataInput': function(parentGfx, element) {
1501
1502 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
1503
1504 // page
1505 var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
1506
1507 /* input arrow path */ drawPath(parentGfx, arrowPathData, { strokeWidth: 1 });
1508
1509 return elementObject;
1510 },
1511 'bpmn:DataOutput': function(parentGfx, element) {
1512 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
1513
1514 // page
1515 var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
1516
1517 /* output arrow path */ drawPath(parentGfx, arrowPathData, {
1518 strokeWidth: 1,
1519 fill: 'black'
1520 });
1521
1522 return elementObject;
1523 },
1524 'bpmn:DataStoreReference': function(parentGfx, element) {
1525 var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
1526 xScaleFactor: 1,
1527 yScaleFactor: 1,
1528 containerWidth: element.width,
1529 containerHeight: element.height,
1530 position: {
1531 mx: 0,
1532 my: 0.133
1533 }
1534 });
1535
1536 var elementStore = drawPath(parentGfx, DATA_STORE_PATH, {
1537 strokeWidth: 2,
1538 fill: getFillColor(element, defaultFillColor),
1539 fillOpacity: DEFAULT_FILL_OPACITY,
1540 stroke: getStrokeColor(element, defaultStrokeColor)
1541 });
1542
1543 return elementStore;
1544 },
1545 'bpmn:BoundaryEvent': function(parentGfx, element) {
1546
1547 var semantic = getSemantic(element),
1548 cancel = semantic.cancelActivity;
1549
1550 var attrs = {
1551 strokeWidth: 1,
1552 fill: getFillColor(element, defaultFillColor),
1553 stroke: getStrokeColor(element, defaultStrokeColor)
1554 };
1555
1556 if (!cancel) {
1557 attrs.strokeDasharray = '6';
1558 attrs.strokeLinecap = 'round';
1559 }
1560
1561 // apply fillOpacity
1562 var outerAttrs = assign({}, attrs, {
1563 fillOpacity: 1
1564 });
1565
1566 // apply no-fill
1567 var innerAttrs = assign({}, attrs, {
1568 fill: 'none'
1569 });
1570
1571 var outer = renderer('bpmn:Event')(parentGfx, element, outerAttrs);
1572
1573 /* inner path */ drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, innerAttrs);
1574
1575 renderEventContent(element, parentGfx);
1576
1577 return outer;
1578 },
1579 'bpmn:Group': function(parentGfx, element) {
1580 var semantic = getSemantic(element),
1581 di = getDi(element);
1582
1583 var group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
1584 strokeWidth: 1,
1585 strokeDasharray: '8,3,1,3',
1586 fill: 'none',
1587 pointerEvents: 'none'
1588 });
1589
1590 var categoryValueRef = semantic.categoryValueRef || {};
1591
1592 if (categoryValueRef.value) {
1593 var box = di.label ? di.label.bounds : element;
1594
1595 renderLabel(parentGfx, categoryValueRef.value, {
1596 box: box,
1597 style: {
1598 fill: getStrokeColor(element, defaultStrokeColor)
1599 }
1600 });
1601 }
1602
1603 return group;
1604 },
1605 'label': function(parentGfx, element) {
1606 return renderExternalLabel(parentGfx, element);
1607 },
1608 'bpmn:TextAnnotation': function(parentGfx, element) {
1609 var style = {
1610 'fill': 'none',
1611 'stroke': 'none'
1612 };
1613
1614 var textElement = drawRect(parentGfx, element.width, element.height, 0, 0, style);
1615
1616 var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
1617 xScaleFactor: 1,
1618 yScaleFactor: 1,
1619 containerWidth: element.width,
1620 containerHeight: element.height,
1621 position: {
1622 mx: 0.0,
1623 my: 0.0
1624 }
1625 });
1626
1627 drawPath(parentGfx, textPathData, {
1628 stroke: getStrokeColor(element, defaultStrokeColor)
1629 });
1630
1631 var text = getSemantic(element).text || '';
1632 renderLabel(parentGfx, text, {
1633 box: element,
1634 align: 'left-top',
1635 padding: 5,
1636 style: {
1637 fill: getStrokeColor(element, defaultStrokeColor)
1638 }
1639 });
1640
1641 return textElement;
1642 },
1643 'ParticipantMultiplicityMarker': function(parentGfx, element) {
1644 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
1645 xScaleFactor: 1,
1646 yScaleFactor: 1,
1647 containerWidth: element.width,
1648 containerHeight: element.height,
1649 position: {
1650 mx: ((element.width / 2) / element.width),
1651 my: (element.height - 15) / element.height
1652 }
1653 });
1654
1655 drawMarker('participant-multiplicity', parentGfx, markerPath, {
1656 strokeWidth: 1,
1657 fill: getFillColor(element, defaultFillColor),
1658 stroke: getStrokeColor(element, defaultStrokeColor)
1659 });
1660 },
1661 'SubProcessMarker': function(parentGfx, element) {
1662 var markerRect = drawRect(parentGfx, 14, 14, 0, {
1663 strokeWidth: 1,
1664 fill: getFillColor(element, defaultFillColor),
1665 stroke: getStrokeColor(element, defaultStrokeColor)
1666 });
1667
1668 // Process marker is placed in the middle of the box
1669 // therefore fixed values can be used here
1670 translate(markerRect, element.width / 2 - 7.5, element.height - 20);
1671
1672 var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
1673 xScaleFactor: 1.5,
1674 yScaleFactor: 1.5,
1675 containerWidth: element.width,
1676 containerHeight: element.height,
1677 position: {
1678 mx: (element.width / 2 - 7.5) / element.width,
1679 my: (element.height - 20) / element.height
1680 }
1681 });
1682
1683 drawMarker('sub-process', parentGfx, markerPath, {
1684 fill: getFillColor(element, defaultFillColor),
1685 stroke: getStrokeColor(element, defaultStrokeColor)
1686 });
1687 },
1688 'ParallelMarker': function(parentGfx, element, position) {
1689 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
1690 xScaleFactor: 1,
1691 yScaleFactor: 1,
1692 containerWidth: element.width,
1693 containerHeight: element.height,
1694 position: {
1695 mx: ((element.width / 2 + position.parallel) / element.width),
1696 my: (element.height - 20) / element.height
1697 }
1698 });
1699
1700 drawMarker('parallel', parentGfx, markerPath, {
1701 fill: getFillColor(element, defaultFillColor),
1702 stroke: getStrokeColor(element, defaultStrokeColor)
1703 });
1704 },
1705 'SequentialMarker': function(parentGfx, element, position) {
1706 var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
1707 xScaleFactor: 1,
1708 yScaleFactor: 1,
1709 containerWidth: element.width,
1710 containerHeight: element.height,
1711 position: {
1712 mx: ((element.width / 2 + position.seq) / element.width),
1713 my: (element.height - 19) / element.height
1714 }
1715 });
1716
1717 drawMarker('sequential', parentGfx, markerPath, {
1718 fill: getFillColor(element, defaultFillColor),
1719 stroke: getStrokeColor(element, defaultStrokeColor)
1720 });
1721 },
1722 'CompensationMarker': function(parentGfx, element, position) {
1723 var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
1724 xScaleFactor: 1,
1725 yScaleFactor: 1,
1726 containerWidth: element.width,
1727 containerHeight: element.height,
1728 position: {
1729 mx: ((element.width / 2 + position.compensation) / element.width),
1730 my: (element.height - 13) / element.height
1731 }
1732 });
1733
1734 drawMarker('compensation', parentGfx, markerMath, {
1735 strokeWidth: 1,
1736 fill: getFillColor(element, defaultFillColor),
1737 stroke: getStrokeColor(element, defaultStrokeColor)
1738 });
1739 },
1740 'LoopMarker': function(parentGfx, element, position) {
1741 var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
1742 xScaleFactor: 1,
1743 yScaleFactor: 1,
1744 containerWidth: element.width,
1745 containerHeight: element.height,
1746 position: {
1747 mx: ((element.width / 2 + position.loop) / element.width),
1748 my: (element.height - 7) / element.height
1749 }
1750 });
1751
1752 drawMarker('loop', parentGfx, markerPath, {
1753 strokeWidth: 1,
1754 fill: getFillColor(element, defaultFillColor),
1755 stroke: getStrokeColor(element, defaultStrokeColor),
1756 strokeLinecap: 'round',
1757 strokeMiterlimit: 0.5
1758 });
1759 },
1760 'AdhocMarker': function(parentGfx, element, position) {
1761 var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
1762 xScaleFactor: 1,
1763 yScaleFactor: 1,
1764 containerWidth: element.width,
1765 containerHeight: element.height,
1766 position: {
1767 mx: ((element.width / 2 + position.adhoc) / element.width),
1768 my: (element.height - 15) / element.height
1769 }
1770 });
1771
1772 drawMarker('adhoc', parentGfx, markerPath, {
1773 strokeWidth: 1,
1774 fill: getStrokeColor(element, defaultStrokeColor),
1775 stroke: getStrokeColor(element, defaultStrokeColor)
1776 });
1777 }
1778 };
1779
1780 function attachTaskMarkers(parentGfx, element, taskMarkers) {
1781 var obj = getSemantic(element);
1782
1783 var subprocess = taskMarkers && taskMarkers.indexOf('SubProcessMarker') !== -1;
1784 var position;
1785
1786 if (subprocess) {
1787 position = {
1788 seq: -21,
1789 parallel: -22,
1790 compensation: -42,
1791 loop: -18,
1792 adhoc: 10
1793 };
1794 } else {
1795 position = {
1796 seq: -3,
1797 parallel: -6,
1798 compensation: -27,
1799 loop: 0,
1800 adhoc: 10
1801 };
1802 }
1803
1804 forEach(taskMarkers, function(marker) {
1805 renderer(marker)(parentGfx, element, position);
1806 });
1807
1808 if (obj.isForCompensation) {
1809 renderer('CompensationMarker')(parentGfx, element, position);
1810 }
1811
1812 if (obj.$type === 'bpmn:AdHocSubProcess') {
1813 renderer('AdhocMarker')(parentGfx, element, position);
1814 }
1815
1816 var loopCharacteristics = obj.loopCharacteristics,
1817 isSequential = loopCharacteristics && loopCharacteristics.isSequential;
1818
1819 if (loopCharacteristics) {
1820
1821 if (isSequential === undefined) {
1822 renderer('LoopMarker')(parentGfx, element, position);
1823 }
1824
1825 if (isSequential === false) {
1826 renderer('ParallelMarker')(parentGfx, element, position);
1827 }
1828
1829 if (isSequential === true) {
1830 renderer('SequentialMarker')(parentGfx, element, position);
1831 }
1832 }
1833 }
1834
1835 function renderDataItemCollection(parentGfx, element) {
1836
1837 var yPosition = (element.height - 16) / element.height;
1838
1839 var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
1840 xScaleFactor: 1,
1841 yScaleFactor: 1,
1842 containerWidth: element.width,
1843 containerHeight: element.height,
1844 position: {
1845 mx: 0.451,
1846 my: yPosition
1847 }
1848 });
1849
1850 /* collection path */ drawPath(parentGfx, pathData, {
1851 strokeWidth: 2
1852 });
1853 }
1854
1855
1856 // extension API, use at your own risk
1857 this._drawPath = drawPath;
1858
1859}
1860
1861
1862inherits(BpmnRenderer, BaseRenderer);
1863
1864BpmnRenderer.$inject = [
1865 'config.bpmnRenderer',
1866 'eventBus',
1867 'styles',
1868 'pathMap',
1869 'canvas',
1870 'textRenderer'
1871];
1872
1873
1874BpmnRenderer.prototype.canRender = function(element) {
1875 return is(element, 'bpmn:BaseElement');
1876};
1877
1878BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
1879 var type = element.type;
1880 var h = this.handlers[type];
1881
1882 /* jshint -W040 */
1883 return h(parentGfx, element);
1884};
1885
1886BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
1887 var type = element.type;
1888 var h = this.handlers[type];
1889
1890 /* jshint -W040 */
1891 return h(parentGfx, element);
1892};
1893
1894BpmnRenderer.prototype.getShapePath = function(element) {
1895
1896 if (is(element, 'bpmn:Event')) {
1897 return getCirclePath(element);
1898 }
1899
1900 if (is(element, 'bpmn:Activity')) {
1901 return getRoundRectPath(element, TASK_BORDER_RADIUS);
1902 }
1903
1904 if (is(element, 'bpmn:Gateway')) {
1905 return getDiamondPath(element);
1906 }
1907
1908 return getRectPath(element);
1909};