@jylups/cmmn-js 0.0.0-stage → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/.babelrc +3 -0
  2. package/CHANGELOG.md +119 -0
  3. package/LICENSE +23 -0
  4. package/README.md +107 -2
  5. package/dist/assets/cmmn-font/css/cmmn-codes.css +41 -0
  6. package/dist/assets/cmmn-font/css/cmmn-embedded.css +94 -0
  7. package/dist/assets/cmmn-font/css/cmmn.css +97 -0
  8. package/dist/assets/cmmn-font/font/cmmn.eot +0 -0
  9. package/dist/assets/cmmn-font/font/cmmn.svg +90 -0
  10. package/dist/assets/cmmn-font/font/cmmn.ttf +0 -0
  11. package/dist/assets/cmmn-font/font/cmmn.woff +0 -0
  12. package/dist/assets/cmmn-font/font/cmmn.woff2 +0 -0
  13. package/dist/assets/diagram-js.css +713 -0
  14. package/dist/cmmn-modeler.development.js +44817 -0
  15. package/dist/cmmn-modeler.production.min.js +2 -0
  16. package/dist/cmmn-navigated-viewer.development.js +18131 -0
  17. package/dist/cmmn-navigated-viewer.production.min.js +2 -0
  18. package/dist/cmmn-viewer.development.js +17599 -0
  19. package/dist/cmmn-viewer.production.min.js +2 -0
  20. package/index.js +1 -0
  21. package/lib/Modeler.js +222 -0
  22. package/lib/NavigatedViewer.js +28 -0
  23. package/lib/Viewer.js +489 -0
  24. package/lib/core/ItemRegistry.js +316 -0
  25. package/lib/core/index.js +7 -0
  26. package/lib/draw/CmmnRenderer.js +1235 -0
  27. package/lib/draw/PathMap.js +335 -0
  28. package/lib/draw/index.js +5 -0
  29. package/lib/features/auto-resize/CmmnAutoResizeProvider.js +57 -0
  30. package/lib/features/auto-resize/index.js +7 -0
  31. package/lib/features/context-pad/ContextPadProvider.js +240 -0
  32. package/lib/features/context-pad/index.js +11 -0
  33. package/lib/features/editor-actions/CmmnEditorActions.js +105 -0
  34. package/lib/features/editor-actions/index.js +10 -0
  35. package/lib/features/keyboard/CmmnKeyboardBindings.js +159 -0
  36. package/lib/features/keyboard/index.js +7 -0
  37. package/lib/features/label-editing/LabelEditingProvider.js +221 -0
  38. package/lib/features/label-editing/LabelUtil.js +95 -0
  39. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +63 -0
  40. package/lib/features/label-editing/index.js +9 -0
  41. package/lib/features/modeling/CmmnFactory.js +166 -0
  42. package/lib/features/modeling/CmmnLayouter.js +49 -0
  43. package/lib/features/modeling/CmmnUpdater.js +511 -0
  44. package/lib/features/modeling/ElementFactory.js +215 -0
  45. package/lib/features/modeling/Modeling.js +185 -0
  46. package/lib/features/modeling/behavior/AttachCriterionBehavior.js +58 -0
  47. package/lib/features/modeling/behavior/CaseFileItemUpdater.js +324 -0
  48. package/lib/features/modeling/behavior/LabelBehavior.js +139 -0
  49. package/lib/features/modeling/behavior/PlanItemDefinitionUpdater.js +449 -0
  50. package/lib/features/modeling/behavior/PlanningTableUpdater.js +620 -0
  51. package/lib/features/modeling/behavior/ReplaceConnectionBehavior.js +320 -0
  52. package/lib/features/modeling/behavior/ReplaceElementBehavior.js +395 -0
  53. package/lib/features/modeling/behavior/ResizeCasePlanModelBehavior.js +108 -0
  54. package/lib/features/modeling/behavior/SentryUpdater.js +678 -0
  55. package/lib/features/modeling/behavior/UnclaimIdBehavior.js +28 -0
  56. package/lib/features/modeling/behavior/index.js +24 -0
  57. package/lib/features/modeling/cmd/AppendShapeHandler.js +52 -0
  58. package/lib/features/modeling/cmd/IdClaimHandler.js +38 -0
  59. package/lib/features/modeling/cmd/ReconnectConnectionHandler.js +57 -0
  60. package/lib/features/modeling/cmd/ReplaceShapeHandler.js +46 -0
  61. package/lib/features/modeling/cmd/UpdateControlsHandler.js +221 -0
  62. package/lib/features/modeling/cmd/UpdatePropertiesHandler.js +240 -0
  63. package/lib/features/modeling/cmd/UpdateSemanticParentHandler.js +94 -0
  64. package/lib/features/modeling/index.js +20 -0
  65. package/lib/features/modeling/util/ModelingUtil.js +138 -0
  66. package/lib/features/modeling/util/PlanItemDefinitionUtil.js +183 -0
  67. package/lib/features/ordering/CmmnOrderingProvider.js +146 -0
  68. package/lib/features/ordering/index.js +4 -0
  69. package/lib/features/outline/Outline.js +47 -0
  70. package/lib/features/outline/index.js +6 -0
  71. package/lib/features/palette/PaletteProvider.js +171 -0
  72. package/lib/features/palette/index.js +12 -0
  73. package/lib/features/popup-menu/ReplaceMenuProvider.js +448 -0
  74. package/lib/features/popup-menu/index.js +4 -0
  75. package/lib/features/replace/CmmnReplace.js +355 -0
  76. package/lib/features/replace/ReplaceOptions.js +241 -0
  77. package/lib/features/replace/index.js +8 -0
  78. package/lib/features/replace-preview/CmmnReplacePreview.js +247 -0
  79. package/lib/features/replace-preview/index.js +7 -0
  80. package/lib/features/rules/CmmnRules.js +1040 -0
  81. package/lib/features/rules/index.js +7 -0
  82. package/lib/features/search/CmmnSearchProvider.js +129 -0
  83. package/lib/features/search/index.js +7 -0
  84. package/lib/features/snapping/CmmnConnectSnapping.js +110 -0
  85. package/lib/features/snapping/CmmnCreateMoveSnapping.js +148 -0
  86. package/lib/features/snapping/CmmnResizeSnapping.js +42 -0
  87. package/lib/features/snapping/CmmnSnappingUtil.js +76 -0
  88. package/lib/features/snapping/index.js +17 -0
  89. package/lib/import/CmmnImporter.js +251 -0
  90. package/lib/import/CmmnTreeWalker.js +410 -0
  91. package/lib/import/Importer.js +73 -0
  92. package/lib/import/Util.js +9 -0
  93. package/lib/import/index.js +3 -0
  94. package/lib/util/DiUtil.js +39 -0
  95. package/lib/util/LabelUtil.js +124 -0
  96. package/lib/util/ModelUtil.js +257 -0
  97. package/lib/util/PoweredByUtil.js +91 -0
  98. package/package.json +88 -4
  99. package/test/helper/index.js +231 -0
  100. package/test/util/KeyEvents.js +23 -0
  101. package/test/util/MockEvents.js +55 -0
  102. package/test/util/custom-rules/CustomRules.js +19 -0
  103. package/test/util/custom-rules/index.js +4 -0
@@ -0,0 +1,1235 @@
1
+ 'use strict';
2
+
3
+ var inherits = require('inherits'),
4
+ isArray = require('min-dash').isArray,
5
+ isObject = require('min-dash').isObject,
6
+ assign = require('min-dash').assign;
7
+
8
+ var BaseRenderer = require('diagram-js/lib/draw/BaseRenderer').default,
9
+ TextUtil = require('diagram-js/lib/util/Text').default,
10
+ DiUtil = require('../util/DiUtil'),
11
+ ModelUtil = require('../util/ModelUtil');
12
+
13
+ var isStandardEventVisible = DiUtil.isStandardEventVisible;
14
+ var isPlanningTableCollapsed = DiUtil.isPlanningTableCollapsed;
15
+ var isCollapsed = DiUtil.isCollapsed;
16
+
17
+ var isCasePlanModel = ModelUtil.isCasePlanModel;
18
+ var getBusinessObject = ModelUtil.getBusinessObject;
19
+ var getDefinition = ModelUtil.getDefinition;
20
+ var isRequired = ModelUtil.isRequired;
21
+ var isRepeatable = ModelUtil.isRepeatable;
22
+ var isManualActivation = ModelUtil.isManualActivation;
23
+ var isAutoComplete = ModelUtil.isAutoComplete;
24
+ var hasPlanningTable = ModelUtil.hasPlanningTable;
25
+ var getName = ModelUtil.getName;
26
+ var is = ModelUtil.is;
27
+ var getStandardEvent = ModelUtil.getStandardEvent;
28
+
29
+ var domQuery = require('min-dom').query;
30
+
31
+ var svgAppend = require('tiny-svg').append,
32
+ svgAttr = require('tiny-svg').attr,
33
+ svgClasses = require('tiny-svg').classes,
34
+ svgCreate = require('tiny-svg').create;
35
+
36
+ var translate = require('diagram-js/lib/util/SvgTransformUtil').translate;
37
+
38
+ var createLine = require('diagram-js/lib/util/RenderUtil').createLine;
39
+
40
+
41
+ function CmmnRenderer(eventBus, styles, pathMap) {
42
+
43
+ BaseRenderer.call(this, eventBus);
44
+
45
+ var TASK_BORDER_RADIUS = 10;
46
+ var MILESTONE_BORDER_RADIUS = 24;
47
+ var STAGE_EDGE_OFFSET = 20;
48
+
49
+ var LABEL_STYLE = {
50
+ fontFamily: 'Arial, sans-serif',
51
+ fontSize: '12px'
52
+ };
53
+
54
+ var textUtil = new TextUtil({
55
+ style: LABEL_STYLE,
56
+ size: { width: 100 }
57
+ });
58
+
59
+ var markers = {};
60
+
61
+ function addMarker(id, element) {
62
+ markers[id] = element;
63
+ }
64
+
65
+ function marker(id) {
66
+ return markers[id];
67
+ }
68
+
69
+ function initMarkers(svg) {
70
+
71
+ function createMarker(id, options) {
72
+ var attrs = assign({
73
+ fill: 'black',
74
+ strokeWidth: 1,
75
+ strokeLinecap: 'round',
76
+ strokeDasharray: 'none'
77
+ }, options.attrs);
78
+
79
+ var ref = options.ref || { x: 0, y: 0 };
80
+
81
+ var scale = options.scale || 1;
82
+
83
+ // fix for safari / chrome / firefox bug not correctly
84
+ // resetting stroke dash array
85
+ if (attrs.strokeDasharray === 'none') {
86
+ attrs.strokeDasharray = [10000, 1];
87
+ }
88
+
89
+ var marker = svgCreate('marker');
90
+
91
+ svgAttr(options.element, attrs);
92
+
93
+ svgAppend(marker, options.element);
94
+
95
+ svgAttr(marker, {
96
+ id: id,
97
+ viewBox: '0 0 20 20',
98
+ refX: ref.x,
99
+ refY: ref.y,
100
+ markerWidth: 20 * scale,
101
+ markerHeight: 20 * scale,
102
+ orient: 'auto'
103
+ });
104
+
105
+ var defs = domQuery('defs', svg);
106
+
107
+ if (!defs) {
108
+ defs = svgCreate('defs');
109
+
110
+ svgAppend(svg, defs);
111
+ }
112
+
113
+ svgAppend(defs, marker);
114
+
115
+ return addMarker(id, marker);
116
+ }
117
+
118
+ var associationStart = svgCreate('path');
119
+ svgAttr(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
120
+
121
+ createMarker('association-start', {
122
+ element: associationStart,
123
+ attrs: {
124
+ fill: 'none',
125
+ stroke: 'black',
126
+ strokeWidth: 1.5
127
+ },
128
+ ref: { x: 1, y: 10 },
129
+ scale: 0.5
130
+ });
131
+
132
+ var associationEnd = svgCreate('path');
133
+ svgAttr(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
134
+
135
+ createMarker('association-end', {
136
+ element: associationEnd,
137
+ attrs: {
138
+ fill: 'none',
139
+ stroke: 'black',
140
+ strokeWidth: 1.5
141
+ },
142
+ ref: { x: 12, y: 10 },
143
+ scale: 0.5
144
+ });
145
+
146
+ }
147
+
148
+ // draw shape //////////////////////////////////////////////////////////////
149
+
150
+ function computeStyle(custom, traits, defaultStyles) {
151
+ if (!isArray(traits)) {
152
+ defaultStyles = traits;
153
+ traits = [];
154
+ }
155
+
156
+ return styles.style(traits || [], assign(defaultStyles, custom || {}));
157
+ }
158
+
159
+ function drawCircle(parentGfx, width, height, offset, attrs) {
160
+
161
+ if (isObject(offset)) {
162
+ attrs = offset;
163
+ offset = 0;
164
+ }
165
+
166
+ offset = offset || 0;
167
+
168
+ attrs = computeStyle(attrs, {
169
+ stroke: 'black',
170
+ strokeWidth: 2,
171
+ fill: 'white'
172
+ });
173
+
174
+ var cx = width / 2,
175
+ cy = height / 2;
176
+
177
+ var circle = svgCreate('circle');
178
+ svgAttr(circle, {
179
+ cx: cx,
180
+ cy: cy,
181
+ r: Math.round((width + height) / 4 - offset)
182
+ });
183
+ svgAttr(circle, attrs);
184
+
185
+ svgAppend(parentGfx, circle);
186
+
187
+ return circle;
188
+ }
189
+
190
+ function drawRect(parentGfx, width, height, r, offset, attrs) {
191
+
192
+ if (isObject(offset)) {
193
+ attrs = offset;
194
+ offset = 0;
195
+ }
196
+
197
+ offset = offset || 0;
198
+
199
+ attrs = computeStyle(attrs, {
200
+ stroke: 'black',
201
+ strokeWidth: 2,
202
+ fill: 'white'
203
+ });
204
+
205
+ var rect = svgCreate('rect');
206
+ svgAttr(rect, {
207
+ x: offset,
208
+ y: offset,
209
+ width: width - offset * 2,
210
+ height: height - offset * 2,
211
+ rx: r,
212
+ ry: r
213
+ });
214
+ svgAttr(rect, attrs);
215
+
216
+ svgAppend(parentGfx, rect);
217
+
218
+ return rect;
219
+ }
220
+
221
+ function drawDiamond(parentGfx, width, height, attrs) {
222
+
223
+ var x_2 = width / 2;
224
+ var y_2 = height / 2;
225
+
226
+ var points = [
227
+ { x: x_2, y: 0 },
228
+ { x: width, y: y_2 },
229
+ { x: x_2, y: height },
230
+ { x: 0, y: y_2 }
231
+ ];
232
+
233
+ var pointsString = points.map(function(point) {
234
+ return point.x + ',' + point.y;
235
+ }).join(' ');
236
+
237
+ attrs = computeStyle(attrs, {
238
+ stroke: 'black',
239
+ strokeWidth: 2,
240
+ fill: 'white'
241
+ });
242
+
243
+ var polygon = svgCreate('polygon');
244
+ svgAttr(polygon, {
245
+ points: pointsString
246
+ });
247
+ svgAttr(polygon, attrs);
248
+
249
+ svgAppend(parentGfx, polygon);
250
+
251
+ return polygon;
252
+ }
253
+
254
+ function drawPath(parentGfx, d, attrs) {
255
+
256
+ attrs = computeStyle(attrs, [ 'no-fill' ], {
257
+ strokeWidth: 2,
258
+ stroke: 'black'
259
+ });
260
+
261
+ var path = svgCreate('path');
262
+ svgAttr(path, { d: d });
263
+ svgAttr(path, attrs);
264
+
265
+ svgAppend(parentGfx, path);
266
+
267
+ return path;
268
+ }
269
+
270
+ function drawOctagon(parentGfx, width, height, offset, attrs) {
271
+ offset = offset || 20;
272
+
273
+ var x1 = offset;
274
+ var y1 = height;
275
+
276
+ var x2 = 0;
277
+ var y2 = height - offset;
278
+
279
+ var x3 = 0;
280
+ var y3 = offset;
281
+
282
+ var x4 = offset;
283
+ var y4 = 0;
284
+
285
+ var x5 = width - offset;
286
+ var y5 = 0;
287
+
288
+ var x6 = width;
289
+ var y6 = offset;
290
+
291
+ var x7 = width;
292
+ var y7 = height - offset;
293
+
294
+ var x8 = width - offset;
295
+ var y8 = height;
296
+
297
+ var points = [
298
+ { x: x1, y: y1 },
299
+ { x: x2, y: y2 },
300
+ { x: x3, y: y3 },
301
+ { x: x4, y: y4 },
302
+ { x: x5, y: y5 },
303
+ { x: x6, y: y6 },
304
+ { x: x7, y: y7 },
305
+ { x: x8, y: y8 }
306
+ ];
307
+
308
+ attrs = attrs || {};
309
+ attrs.fill = 'white';
310
+ attrs.stroke = 'black';
311
+ attrs.strokeWidth = 2;
312
+
313
+ return drawPolygon(parentGfx, points, attrs);
314
+ }
315
+
316
+ function drawPolygon(parentGfx, points, attrs) {
317
+ var pointsString = points.map(function(point) {
318
+ return point.x + ',' + point.y;
319
+ }).join(' ');
320
+
321
+ var polygon = svgCreate('polygon');
322
+
323
+ svgAttr(polygon, {
324
+ points: pointsString
325
+ });
326
+ svgAttr(polygon, attrs);
327
+
328
+ svgAppend(parentGfx, polygon);
329
+
330
+ return polygon;
331
+ }
332
+
333
+ // draw connection ////////////////////////////////////////////
334
+
335
+ function drawLine(parentGfx, waypoints, attrs) {
336
+ attrs = computeStyle(attrs, [ 'no-fill' ], {
337
+ stroke: 'black',
338
+ strokeWidth: 2,
339
+ fill: 'none'
340
+ });
341
+
342
+ var line = createLine(waypoints, attrs);
343
+
344
+ svgAppend(parentGfx, line);
345
+
346
+ return line;
347
+ }
348
+
349
+ function createPathFromConnection(connection) {
350
+ var waypoints = connection.waypoints;
351
+
352
+ var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
353
+ for (var i = 1; i < waypoints.length; i++) {
354
+ pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
355
+ }
356
+ return pathData;
357
+ }
358
+
359
+ // render label //////////////////////////////////////////////
360
+
361
+ function renderLabel(parentGfx, label, options) {
362
+ var text = textUtil.createText(label || '', options);
363
+ svgClasses(text).add('djs-label');
364
+ svgAppend(parentGfx, text);
365
+
366
+ return text;
367
+ }
368
+
369
+ function renderEmbeddedLabel(p, element, align) {
370
+ var name = getName(element);
371
+ return renderLabel(p, name, {
372
+ box: element,
373
+ align: align,
374
+ padding: 5
375
+ });
376
+ }
377
+
378
+ function renderExpandedStageLabel(p, element, align) {
379
+ var name = getName(element);
380
+ var textbox = renderLabel(p, name, { box: element, align: align, padding: 5 });
381
+
382
+ // reset the position of the text box
383
+ translate(textbox, STAGE_EDGE_OFFSET, 0);
384
+
385
+ return textbox;
386
+ }
387
+
388
+ function renderCasePlanModelLabel(p, element) {
389
+ var bo = getBusinessObject(element);
390
+
391
+ // default maximum textbox dimensions
392
+ var height = 18;
393
+ var width = (element.width / 2) - 60;
394
+
395
+ var label = bo.name;
396
+
397
+ // create text box
398
+ var textBox = renderLabel(p, label, {
399
+ box: { height: height, width: width },
400
+ align: 'left-top'
401
+ });
402
+
403
+ var minWidth = 60,
404
+ padding = 40,
405
+ textBoxWidth = textBox.getBBox().width;
406
+
407
+ // set polygon width based on actual textbox size
408
+ var polygonWidth = textBoxWidth + padding;
409
+
410
+ if (textBoxWidth < minWidth) {
411
+ polygonWidth = minWidth + padding;
412
+ }
413
+
414
+ var polygonPoints = [
415
+ { x: 10, y: 0 },
416
+ { x: 20, y: -height },
417
+ { x: polygonWidth, y: -height },
418
+ { x: polygonWidth + 10, y: 0 }
419
+ ];
420
+
421
+ // The pointer-events attribute is needed to allow clicks on the polygon
422
+ // which otherwise would be prevented by the parent node ('djs-visual').
423
+ var polygon = drawPolygon(p, polygonPoints, {
424
+ fill: 'white',
425
+ stroke: 'black',
426
+ strokeWidth: 2,
427
+ fillOpacity: 0.95,
428
+ 'pointer-events': 'all'
429
+ });
430
+
431
+ // make sure the textbox is visually on top of the polygon
432
+ textBox.parentNode.insertBefore(polygon, textBox);
433
+
434
+ // reset the position of the text box
435
+ translate(textBox, 25, -height + 5);
436
+
437
+ return textBox;
438
+ }
439
+
440
+ function renderExternalLabel(parentGfx, element) {
441
+ var name = getName(element),
442
+ hide = false;
443
+
444
+ var standardEvent = getStandardEvent(element);
445
+
446
+ if (standardEvent) {
447
+
448
+ var standardEventVisible = isStandardEventVisible(element);
449
+ standardEvent = '[' + standardEvent + ']';
450
+
451
+ if (!name) {
452
+ name = standardEvent;
453
+ element.hidden = hide = !standardEventVisible;
454
+ }
455
+ else {
456
+ if (standardEventVisible) {
457
+ name = name + ' ' + standardEvent;
458
+ }
459
+ }
460
+
461
+ }
462
+
463
+ var box = {
464
+ width: 90,
465
+ height: 30,
466
+ x: element.width / 2 + element.x,
467
+ y: element.height / 2 + element.y
468
+ };
469
+
470
+ element.hidden = element.labelTarget.hidden || hide || !name;
471
+
472
+ return renderLabel(parentGfx, name, { box: box, style: { fontSize: '11px' } });
473
+ }
474
+
475
+ // render elements //////////////////////////////////////////
476
+
477
+ function renderer(type) {
478
+ return handlers[type];
479
+ }
480
+
481
+ var handlers = {
482
+ 'cmmn:PlanItem': function(p, element) {
483
+ var definition = getDefinition(element);
484
+ return renderer(definition.$type)(p, element);
485
+ },
486
+
487
+ 'cmmn:DiscretionaryItem': function(p, element) {
488
+ var definition = getDefinition(element);
489
+
490
+ var attrs = {
491
+ strokeDasharray: '10, 12'
492
+ };
493
+
494
+ if (is(definition, 'cmmn:Task')) {
495
+ assign(attrs, {
496
+ strokeDasharray: '12, 12.4',
497
+ strokeDashoffset: 13.6
498
+ });
499
+ }
500
+
501
+ return renderer(definition.$type)(p, element, attrs);
502
+ },
503
+
504
+ // STAGE
505
+ 'cmmn:Stage': function(p, element, attrs) {
506
+
507
+ attrs = assign({ fillOpacity: 0.95 }, attrs);
508
+
509
+ var rect;
510
+ if (isCasePlanModel(element)) {
511
+ return handlers['cmmn:CasePlanModel'](p, element);
512
+ }
513
+
514
+ rect = drawOctagon(p, element.width, element.height, STAGE_EDGE_OFFSET, attrs);
515
+
516
+ if (!isCollapsed(element)) {
517
+ renderExpandedStageLabel(p, element, 'left-top');
518
+ }
519
+ else {
520
+ renderEmbeddedLabel(p, element, 'center-middle');
521
+ }
522
+
523
+ attachPlanningTableMarker(p, element);
524
+ attachStageMarkers(p, element);
525
+ return rect;
526
+ },
527
+
528
+ // STAGE
529
+ 'cmmn:PlanFragment': function(p, element, attrs) {
530
+
531
+ var rect = drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, {
532
+ strokeDasharray: '10, 12',
533
+ fillOpacity: 0.95
534
+ });
535
+
536
+ renderEmbeddedLabel(p, element, isCollapsed(element) ? 'center-middle' : 'left-top');
537
+
538
+ attachStageMarkers(p, element);
539
+ return rect;
540
+ },
541
+
542
+ 'cmmn:CasePlanModel': function(p, element) {
543
+ var rect = drawRect(p, element.width, element.height, 0, {
544
+ fillOpacity: 0.95
545
+ });
546
+ renderCasePlanModelLabel(p, element);
547
+ attachPlanningTableMarker(p, element);
548
+ attachCasePlanModelMarkers(p, element);
549
+ return rect;
550
+ },
551
+
552
+ // MILESTONE
553
+ 'cmmn:Milestone': function(p, element, attrs) {
554
+ var rect = drawRect(p, element.width, element.height, MILESTONE_BORDER_RADIUS, attrs);
555
+ renderEmbeddedLabel(p, element, 'center-middle');
556
+ attachTaskMarkers(p, element);
557
+ return rect;
558
+ },
559
+
560
+ // EVENT LISTENER
561
+ 'cmmn:EventListener': function(p, element, attrs) {
562
+ var outerCircle = drawCircle(p, element.width, element.height, attrs);
563
+
564
+ attrs = attrs || {};
565
+ attrs.strokeWidth = 2;
566
+
567
+ drawCircle(p, element.width, element.height, 0.1 * element.height, attrs);
568
+ return outerCircle;
569
+ },
570
+
571
+ 'cmmn:TimerEventListener': function(p, element, attrs) {
572
+ var circle = renderer('cmmn:EventListener')(p, element, attrs);
573
+
574
+ var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
575
+ xScaleFactor: 0.75,
576
+ yScaleFactor: 0.75,
577
+ containerWidth: element.width,
578
+ containerHeight: element.height,
579
+ position: {
580
+ mx: 0.5,
581
+ my: 0.5
582
+ }
583
+ });
584
+
585
+ drawPath(p, pathData, {
586
+ strokeWidth: 2,
587
+ strokeLinecap: 'square'
588
+ });
589
+
590
+ for (var i = 0;i < 12;i++) {
591
+
592
+ var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
593
+ xScaleFactor: 0.75,
594
+ yScaleFactor: 0.75,
595
+ containerWidth: element.width,
596
+ containerHeight: element.height,
597
+ position: {
598
+ mx: 0.5,
599
+ my: 0.5
600
+ }
601
+ });
602
+
603
+ var width = element.width / 2;
604
+ var height = element.height / 2;
605
+
606
+ drawPath(p, linePathData, {
607
+ strokeWidth: 1,
608
+ strokeLinecap: 'square',
609
+ transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')'
610
+ });
611
+ }
612
+
613
+
614
+ return circle;
615
+ },
616
+
617
+ 'cmmn:UserEventListener': function(p, element, attrs) {
618
+ var circle = renderer('cmmn:EventListener')(p, element, attrs);
619
+
620
+ // TODO: The user event decorator has to be
621
+ // scaled correctly!
622
+ var x = 20;
623
+ var y = 15;
624
+
625
+ var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
626
+ abspos: {
627
+ x: x,
628
+ y: y
629
+ }
630
+ });
631
+
632
+ /* user path */ drawPath(p, pathData, {
633
+ strokeWidth: 0.5,
634
+ fill: 'none'
635
+ });
636
+
637
+ var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
638
+ abspos: {
639
+ x: x,
640
+ y: y
641
+ }
642
+ });
643
+
644
+ /* user2 path */ drawPath(p, pathData2, {
645
+ strokeWidth: 0.5,
646
+ fill: 'none'
647
+ });
648
+
649
+ var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
650
+ abspos: {
651
+ x: x,
652
+ y: y
653
+ }
654
+ });
655
+
656
+ /* user3 path */ drawPath(p, pathData3, {
657
+ strokeWidth: 0.5,
658
+ fill: 'black'
659
+ });
660
+
661
+ return circle;
662
+ },
663
+
664
+ // TASK
665
+ 'cmmn:Task': function(p, element, attrs) {
666
+ var rect = drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, attrs);
667
+ renderEmbeddedLabel(p, element, 'center-middle');
668
+ attachTaskMarkers(p, element);
669
+ return rect;
670
+ },
671
+
672
+ 'cmmn:HumanTask': function(p, element, attrs) {
673
+ var task = renderer('cmmn:Task')(p, element, attrs);
674
+
675
+ var bo = element.businessObject;
676
+ var definition = bo.definitionRef;
677
+
678
+ if (definition.isBlocking) {
679
+ var x = 15;
680
+ var y = 12;
681
+
682
+ var pathData1 = pathMap.getScaledPath('TASK_TYPE_USER_1', {
683
+ abspos: {
684
+ x: x,
685
+ y: y
686
+ }
687
+ });
688
+
689
+ /* user path */ drawPath(p, pathData1, {
690
+ strokeWidth: 0.5,
691
+ fill: 'none'
692
+ });
693
+
694
+ var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
695
+ abspos: {
696
+ x: x,
697
+ y: y
698
+ }
699
+ });
700
+
701
+ /* user2 path */ drawPath(p, pathData2, {
702
+ strokeWidth: 0.5,
703
+ fill: 'none'
704
+ });
705
+
706
+ var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
707
+ abspos: {
708
+ x: x,
709
+ y: y
710
+ }
711
+ });
712
+
713
+ /* user3 path */ drawPath(p, pathData3, {
714
+ strokeWidth: 0.5,
715
+ fill: 'black'
716
+ });
717
+ }
718
+
719
+ else {
720
+ var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
721
+ abspos: {
722
+ x: 17,
723
+ y: 15
724
+ }
725
+ });
726
+
727
+ /* manual path */ drawPath(p, pathData, {
728
+ strokeWidth: 1.25,
729
+ fill: 'white',
730
+ stroke: 'black'
731
+ });
732
+ }
733
+
734
+ attachPlanningTableMarker(p, element);
735
+
736
+ return task;
737
+ },
738
+
739
+ 'cmmn:CaseTask': function(p, element, attrs) {
740
+ var task = renderer('cmmn:Task')(p, element, attrs);
741
+
742
+ var pathData = pathMap.getScaledPath('TASK_TYPE_FOLDER', {
743
+ abspos: {
744
+ x: 7,
745
+ y: 7
746
+ }
747
+ });
748
+
749
+ /* manual path */ drawPath(p, pathData, {
750
+ strokeWidth: 1.25,
751
+ fill: 'white',
752
+ stroke: 'black'
753
+ });
754
+
755
+ return task;
756
+ },
757
+
758
+ 'cmmn:ProcessTask': function(p, element, attrs) {
759
+ var task = renderer('cmmn:Task')(p, element, attrs);
760
+
761
+ var pathData = pathMap.getScaledPath('TASK_TYPE_CHEVRON', {
762
+ abspos: {
763
+ x: 5,
764
+ y: 5
765
+ }
766
+ });
767
+
768
+ /* manual path */ drawPath(p, pathData, {
769
+ strokeWidth: 1.25,
770
+ fill: 'white',
771
+ stroke: 'black'
772
+ });
773
+
774
+ return task;
775
+ },
776
+
777
+ 'cmmn:DecisionTask': function(p, element, attrs) {
778
+ var task = renderer('cmmn:Task')(p, element, attrs);
779
+
780
+ var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
781
+ abspos: {
782
+ x: 8,
783
+ y: 8
784
+ }
785
+ });
786
+
787
+ drawPath(p, headerPathData, {
788
+ strokeWidth: 1,
789
+ fill: '000'
790
+ });
791
+
792
+ var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
793
+ abspos: {
794
+ x: 8,
795
+ y: 8
796
+ }
797
+ });
798
+
799
+ drawPath(p, headerData, {
800
+ strokeWidth: 1
801
+ });
802
+
803
+ return task;
804
+ },
805
+
806
+ 'cmmn:CaseFileItem': function(p, element, attrs) {
807
+ var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
808
+ xScaleFactor: 1,
809
+ yScaleFactor: 1,
810
+ containerWidth: element.width,
811
+ containerHeight: element.height,
812
+ position: {
813
+ mx: 0.474,
814
+ my: 0.296
815
+ }
816
+ });
817
+
818
+ return drawPath(p, pathData, { fill: 'white' });
819
+ },
820
+
821
+ // ARTIFACTS
822
+ 'cmmn:TextAnnotation': function(p, element) {
823
+ var style = {
824
+ 'fill': 'none',
825
+ 'stroke': 'none'
826
+ };
827
+ var textElement = drawRect(p, element.width, element.height, 0, 0, style);
828
+ var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
829
+ xScaleFactor: 1,
830
+ yScaleFactor: 1,
831
+ containerWidth: element.width,
832
+ containerHeight: element.height,
833
+ position: {
834
+ mx: 0.0,
835
+ my: 0.0
836
+ }
837
+ });
838
+ drawPath(p, textPathData);
839
+
840
+ var text = getBusinessObject(element).text || '';
841
+ renderLabel(p, text, { box: element, align: 'left-middle', padding: 5 });
842
+
843
+ return textElement;
844
+ },
845
+
846
+ 'cmmn:Association': function(p, element, attrs) {
847
+
848
+ var semantic = getBusinessObject(element);
849
+
850
+ attrs = assign({
851
+ strokeDasharray: '0.5, 5',
852
+ strokeLinecap: 'round',
853
+ strokeLinejoin: 'round'
854
+ }, attrs || {});
855
+
856
+ if (semantic.associationDirection === 'One' ||
857
+ semantic.associationDirection === 'Both') {
858
+ attrs.markerEnd = marker('association-end');
859
+ }
860
+
861
+ if (semantic.associationDirection === 'Both') {
862
+ attrs.markerStart = marker('association-start');
863
+ }
864
+
865
+ return drawLine(p, element.waypoints, attrs);
866
+ },
867
+
868
+ // MARKERS
869
+ 'StageMarker': function(p, element) {
870
+ var markerRect = drawRect(p, 14, 14, 0, {
871
+ strokeWidth: 1,
872
+ stroke: 'black'
873
+ });
874
+
875
+ translate(markerRect, element.width / 2 - 7, element.height - 17);
876
+
877
+ var path = isCollapsed(element) ? 'MARKER_STAGE_COLLAPSED' : 'MARKER_STAGE_EXPANDED';
878
+
879
+ var stagePath = pathMap.getScaledPath(path, {
880
+ xScaleFactor: 1.5,
881
+ yScaleFactor: 1.5,
882
+ containerWidth: element.width,
883
+ containerHeight: element.height,
884
+ position: {
885
+ mx: (element.width / 2 - 7) / element.width,
886
+ my: (element.height - 17) / element.height
887
+ }
888
+ });
889
+
890
+ drawPath(p, stagePath);
891
+ },
892
+
893
+ 'RequiredMarker': function(p, element, position) {
894
+ var path = pathMap.getScaledPath('MARKER_REQUIRED', {
895
+ xScaleFactor: 1,
896
+ yScaleFactor: 1,
897
+ containerWidth: element.width,
898
+ containerHeight: element.height,
899
+ position: {
900
+ mx: ((element.width / 2 + position) / element.width),
901
+ my: (element.height - 17) / element.height
902
+ }
903
+ });
904
+
905
+ drawPath(p, path, { strokeWidth: 3 });
906
+ },
907
+
908
+ 'AutoCompleteMarker': function(p, element, position) {
909
+ var markerRect = drawRect(p, 11, 14, 0, {
910
+ strokeWidth: 1,
911
+ stroke: 'black',
912
+ fill: 'black'
913
+ });
914
+
915
+ translate(markerRect, element.width / 2 + position + 2, element.height - 17);
916
+ },
917
+
918
+ 'ManualActivationMarker': function(p, element, position) {
919
+ var path = pathMap.getScaledPath('MARKER_MANUAL_ACTIVATION', {
920
+ xScaleFactor: 1,
921
+ yScaleFactor: 1,
922
+ containerWidth: element.width,
923
+ containerHeight: element.height,
924
+ position: {
925
+ mx: ((element.width / 2 + position) / element.width),
926
+ my: (element.height - 17) / element.height
927
+ }
928
+ });
929
+
930
+ drawPath(p, path, { strokeWidth: 1 });
931
+ },
932
+
933
+ 'RepetitionMarker': function(p, element, position) {
934
+ var path = pathMap.getScaledPath('MARKER_REPEATABLE', {
935
+ xScaleFactor: 1,
936
+ yScaleFactor: 1,
937
+ containerWidth: element.width,
938
+ containerHeight: element.height,
939
+ position: {
940
+ mx: ((element.width / 2 + position) / element.width),
941
+ my: (element.height - 17) / element.height
942
+ }
943
+ });
944
+
945
+ drawPath(p, path);
946
+ },
947
+
948
+ 'PlanningTableMarker': function(p, element, position) {
949
+ var planningTableRect = drawRect(p, 30, 24, 0, {
950
+ strokeWidth: 1.5,
951
+ stroke: 'black'
952
+ });
953
+
954
+ translate(planningTableRect, element.width / 2 - 15, -17);
955
+
956
+ var isCollapsed = isPlanningTableCollapsed(element);
957
+
958
+ var marker = isCollapsed ? 'MARKER_PLANNING_TABLE_COLLAPSED' : 'MARKER_PLANNING_TABLE_EXPANDED';
959
+
960
+ var stagePath = pathMap.getScaledPath(marker, {
961
+ xScaleFactor: 1.5,
962
+ yScaleFactor: 1.5,
963
+ containerWidth: element.width,
964
+ containerHeight: element.height,
965
+ position: {
966
+ mx: (element.width / 2 - 15) / element.width,
967
+ my: (-17) / element.height
968
+ }
969
+ });
970
+
971
+ drawPath(p, stagePath, {
972
+ strokeWidth: 1.5
973
+ });
974
+ },
975
+
976
+ 'cmmn:OnPart': function(p, element) {
977
+ var pathData = createPathFromConnection(element);
978
+
979
+ var path = drawPath(p, pathData, {
980
+ strokeDasharray: '10, 5, 2, 5, 2, 5',
981
+ strokeWidth: 1.5
982
+ });
983
+
984
+ return path;
985
+ },
986
+ 'cmmn:PlanItemOnPart': function(p, element) {
987
+ return renderer('cmmn:OnPart')(p, element);
988
+ },
989
+ 'cmmn:CaseFileItemOnPart': function(p, element) {
990
+ return renderer('cmmn:OnPart')(p, element);
991
+ },
992
+ 'cmmn:EntryCriterion': function(p, element) {
993
+ return drawDiamond(p, element.width, element.height, {
994
+ fill: 'white'
995
+ });
996
+ },
997
+ 'cmmn:ExitCriterion': function(p, element) {
998
+ return drawDiamond(p, element.width, element.height, {
999
+ fill: 'black'
1000
+ });
1001
+ },
1002
+
1003
+ 'cmmndi:CMMNEdge': function(p, element) {
1004
+
1005
+ var bo = getBusinessObject(element);
1006
+
1007
+ if (bo.cmmnElementRef) {
1008
+ return renderer(bo.cmmnElementRef.$type)(p, element);
1009
+ }
1010
+
1011
+ var pathData = createPathFromConnection(element);
1012
+
1013
+ var path = drawPath(p, pathData, {
1014
+ strokeDasharray: '3, 5',
1015
+ strokeWidth: 1
1016
+ });
1017
+
1018
+ return path;
1019
+ },
1020
+
1021
+ 'label': function(parentGfx, element) {
1022
+ // Update external label size and bounds during rendering when
1023
+ // we have the actual rendered bounds anyway.
1024
+
1025
+ var textElement = renderExternalLabel(parentGfx, element);
1026
+
1027
+ var textBBox;
1028
+
1029
+ try {
1030
+ textBBox = textElement.getBBox();
1031
+ } catch (e) {
1032
+ textBBox = { width: 0, height: 0, x: 0 };
1033
+ }
1034
+
1035
+ // update element.x so that the layouted text is still
1036
+ // center alligned (newX = oldMidX - newWidth / 2)
1037
+ element.x = Math.ceil(element.x + element.width / 2) - Math.ceil((textBBox.width / 2));
1038
+
1039
+ // take element width, height from actual bounds
1040
+ element.width = Math.ceil(textBBox.width);
1041
+ element.height = Math.ceil(textBBox.height);
1042
+
1043
+ // compensate bounding box x
1044
+ svgAttr(textElement, {
1045
+ transform: 'translate(' + (-1 * textBBox.x) + ',0)'
1046
+ });
1047
+
1048
+ return textElement;
1049
+ }
1050
+ };
1051
+
1052
+ // attach markers /////////////////////////
1053
+
1054
+ function attachTaskMarkers(p, element) {
1055
+ var obj = getBusinessObject(element);
1056
+ var padding = 6;
1057
+
1058
+ var markers = [];
1059
+
1060
+ if (isRequired(obj)) {
1061
+ markers.push({ marker: 'RequiredMarker', width: 1 });
1062
+ }
1063
+
1064
+ if (isManualActivation(obj)) {
1065
+ markers.push({ marker: 'ManualActivationMarker', width: 14 });
1066
+ }
1067
+
1068
+ if (isRepeatable(obj)) {
1069
+ markers.push({ marker: 'RepetitionMarker', width: 14 });
1070
+ }
1071
+
1072
+ if (markers.length) {
1073
+
1074
+ if (markers.length === 1) {
1075
+ // align marker in the middle of the element
1076
+ drawMarker(markers[0].marker, p, element, (markers[0].width / 2) * (-1));
1077
+ }
1078
+
1079
+ else if (markers.length === 2) {
1080
+ /* align marker:
1081
+ *
1082
+ * | |
1083
+ * +-------------+
1084
+ * ^
1085
+ * |
1086
+ * +-+ +-+
1087
+ * |0| |1| <-- markers
1088
+ * +-+ +-+
1089
+ * (leftMarker) (rightMarker)
1090
+ */
1091
+ drawMarker(markers[0].marker, p, element, (markers[0].width * (-1)) - (padding /2));
1092
+ drawMarker(markers[1].marker, p, element, padding / 2);
1093
+ }
1094
+
1095
+ else if (markers.length === 3) {
1096
+ /* align marker:
1097
+ *
1098
+ * | |
1099
+ * +-------------+
1100
+ * ^
1101
+ * |
1102
+ * +-+ +-+ +-+
1103
+ * |0| |1| |2| <-- markers
1104
+ * +-+ +-+ +-+
1105
+ */
1106
+
1107
+ /* 1 */ drawMarker(markers[1].marker, p, element, markers[1].width / 2 * (-1));
1108
+ /* 0 */ drawMarker(markers[0].marker, p, element, (markers[1].width / 2 * (-1)) - padding - markers[0].width);
1109
+ /* 2 */ drawMarker(markers[2].marker, p, element, (markers[1].width / 2) + padding);
1110
+ }
1111
+ }
1112
+ }
1113
+
1114
+ function attachCasePlanModelMarkers(p, element) {
1115
+ var obj = getBusinessObject(element);
1116
+
1117
+ if (isAutoComplete(obj)) {
1118
+ drawMarker('AutoCompleteMarker', p, element, -7);
1119
+ }
1120
+ }
1121
+
1122
+ function attachStageMarkers(p, element, stage) {
1123
+ var obj = getBusinessObject(element);
1124
+ var padding = 6;
1125
+
1126
+ drawMarker('StageMarker', p, element, -7);
1127
+
1128
+ var leftMarkers = [];
1129
+
1130
+ if (isRequired(obj)) {
1131
+ leftMarkers.push({ marker: 'RequiredMarker', width: 1 });
1132
+ }
1133
+
1134
+ if (isAutoComplete(obj)) {
1135
+ leftMarkers.push({ marker: 'AutoCompleteMarker', width: 14 });
1136
+ }
1137
+
1138
+ if (leftMarkers.length) {
1139
+
1140
+ if (leftMarkers.length === 1) {
1141
+ drawMarker(leftMarkers[0].marker, p, element, (leftMarkers[0].width * (-1) - 7 - padding));
1142
+ }
1143
+
1144
+ else if (leftMarkers.length === 2) {
1145
+ drawMarker(
1146
+ leftMarkers[0].marker,
1147
+ p,
1148
+ element,
1149
+ ((leftMarkers[1].width * (-1)) - 7 - padding) - (leftMarkers[0].width * (-1)) - padding
1150
+ );
1151
+
1152
+ drawMarker(leftMarkers[1].marker, p, element, (leftMarkers[1].width * (-1)) - 7 - padding);
1153
+ }
1154
+
1155
+ }
1156
+
1157
+ var rightMarkers = [];
1158
+
1159
+ if (isManualActivation(obj)) {
1160
+ rightMarkers.push({ marker: 'ManualActivationMarker', width: 14 });
1161
+ }
1162
+
1163
+ if (isRepeatable(obj)) {
1164
+ rightMarkers.push({ marker: 'RepetitionMarker', width: 14 });
1165
+ }
1166
+
1167
+ if (rightMarkers.length) {
1168
+
1169
+ if (rightMarkers.length === 1) {
1170
+ drawMarker(rightMarkers[0].marker, p, element, 7 + padding);
1171
+ }
1172
+
1173
+ else if (rightMarkers.length === 2) {
1174
+ drawMarker(rightMarkers[0].marker, p, element, 7 + padding);
1175
+ drawMarker(rightMarkers[1].marker, p, element, 7 + padding + rightMarkers[0].width + padding);
1176
+ }
1177
+
1178
+ }
1179
+ }
1180
+
1181
+ function attachPlanningTableMarker(p, element) {
1182
+ if (hasPlanningTable(element)) {
1183
+ drawMarker('PlanningTableMarker', p, element);
1184
+ }
1185
+ }
1186
+
1187
+ function drawMarker(marker, parent, element, position) {
1188
+ renderer(marker)(parent, element, position);
1189
+ }
1190
+
1191
+ // draw shape and connection ////////////////////////////////////
1192
+
1193
+ function drawShape(parent, element) {
1194
+ var h = handlers[element.type];
1195
+
1196
+ /* jshint -W040 */
1197
+ if (!h) {
1198
+ return BaseRenderer.prototype.drawShape.apply(this, [ parent, element ]);
1199
+ } else {
1200
+ return h(parent, element);
1201
+ }
1202
+ }
1203
+
1204
+ function drawConnection(parent, element) {
1205
+ var type = element.type;
1206
+ var h = handlers[type];
1207
+
1208
+ /* jshint -W040 */
1209
+ if (!h) {
1210
+ return BaseRenderer.prototype.drawConnection.apply(this, [ parent, element ]);
1211
+ } else {
1212
+ return h(parent, element);
1213
+ }
1214
+ }
1215
+
1216
+ this.canRender = function(element) {
1217
+ return is(element, 'cmmn:CMMNElement') || is(element, 'cmmndi:CMMNEdge');
1218
+ };
1219
+
1220
+ this.drawShape = drawShape;
1221
+ this.drawConnection = drawConnection;
1222
+
1223
+ // hook onto canvas init event to initialize
1224
+ // connection start/end markers on svg
1225
+ eventBus.on('canvas.init', function(event) {
1226
+ initMarkers(event.svg);
1227
+ });
1228
+
1229
+ }
1230
+
1231
+ inherits(CmmnRenderer, BaseRenderer);
1232
+
1233
+ CmmnRenderer.$inject = [ 'eventBus', 'styles', 'pathMap' ];
1234
+
1235
+ module.exports = CmmnRenderer;