1dce143da14fc89f5b2f9391f37a270e79967f81
[sdc/sdc-workflow-designer.git] /
1 import { reduce } from 'min-dash';
2
3 import inherits from 'inherits';
4
5 import { is } from 'bpmn-js/lib/util/ModelUtil';
6
7 import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider';
8
9 var HIGH_PRIORITY = 1500;
10
11 function isCustom(element) {
12     return element && /^custom:/.test(element.type);
13 }
14
15 /**
16  * Specific rules for custom elements
17  */
18 export default function CustomRules(eventBus) {
19     RuleProvider.call(this, eventBus);
20 }
21
22 inherits(CustomRules, RuleProvider);
23
24 CustomRules.$inject = ['eventBus'];
25
26 CustomRules.prototype.init = function() {
27     /**
28      * Can shape be created on target container?
29      */
30     function canCreate(shape, target) {
31         // only judge about custom elements
32         if (!isCustom(shape)) {
33             return;
34         }
35
36         // allow creation on processes
37         return (
38             is(target, 'bpmn:Process') ||
39             is(target, 'bpmn:Participant') ||
40             is(target, 'bpmn:Collaboration')
41         );
42     }
43
44     /**
45      * Can source and target be connected?
46      */
47     function canConnect(source, target) {
48         // only judge about custom elements
49         if (!isCustom(source) && !isCustom(target)) {
50             return;
51         }
52
53         // allow connection between custom shape and task
54         if (isCustom(source)) {
55             if (is(target, 'bpmn:Task')) {
56                 return { type: 'custom:connection' };
57             } else {
58                 return false;
59             }
60         } else if (isCustom(target)) {
61             if (is(source, 'bpmn:Task')) {
62                 return { type: 'custom:connection' };
63             } else {
64                 return false;
65             }
66         }
67     }
68
69     this.addRule('elements.move', HIGH_PRIORITY, function(context) {
70         var target = context.target,
71             shapes = context.shapes;
72
73         var type;
74
75         // do not allow mixed movements of custom / BPMN shapes
76         // if any shape cannot be moved, the group cannot be moved, too
77         var allowed = reduce(
78             shapes,
79             function(result, s) {
80                 if (type === undefined) {
81                     type = isCustom(s);
82                 }
83
84                 if (type !== isCustom(s) || result === false) {
85                     return false;
86                 }
87
88                 return canCreate(s, target);
89             },
90             undefined
91         );
92
93         // reject, if we have at least one
94         // custom element that cannot be moved
95         return allowed;
96     });
97
98     this.addRule('shape.create', HIGH_PRIORITY, function(context) {
99         var target = context.target,
100             shape = context.shape;
101
102         return canCreate(shape, target);
103     });
104
105     this.addRule('shape.resize', HIGH_PRIORITY, function(context) {
106         var shape = context.shape;
107
108         if (isCustom(shape)) {
109             // cannot resize custom elements
110             return false;
111         }
112     });
113
114     this.addRule('connection.create', HIGH_PRIORITY, function(context) {
115         var source = context.source,
116             target = context.target;
117
118         return canConnect(source, target);
119     });
120
121     this.addRule('connection.reconnectStart', HIGH_PRIORITY, function(context) {
122         var connection = context.connection,
123             source = context.hover || context.source,
124             target = connection.target;
125
126         return canConnect(source, target, connection);
127     });
128
129     this.addRule('connection.reconnectEnd', HIGH_PRIORITY, function(context) {
130         var connection = context.connection,
131             source = connection.source,
132             target = context.hover || context.target;
133
134         return canConnect(source, target, connection);
135     });
136 };