bpmn-auto-layout 0.2.0 → 0.3.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.
- package/README.md +8 -4
- package/dist/index.esm.js +578 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +580 -0
- package/dist/index.js.map +1 -0
- package/package.json +20 -8
- package/index.js +0 -1
- package/lib/AutoLayout.js +0 -514
- package/lib/DiFactory.js +0 -152
- package/lib/DiUtil.js +0 -263
- package/lib/Tree.js +0 -335
package/lib/Tree.js
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
This tree is a version of ECOTree.js (by Emilio Cortegoso Lobato), with modifications.
|
|
3
|
-
These modifications include:
|
|
4
|
-
- supporting multiple parents
|
|
5
|
-
- removed all node styling code
|
|
6
|
-
- removed tree orientation code in favour of left to right orientation
|
|
7
|
-
References:
|
|
8
|
-
- ECOTree.js, Emilio Cortegoso Lobato
|
|
9
|
-
- "A Node-Positioning Algorithm for General Trees", Walker II, J. Q.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
function TreeNode(id, dsc, w, h) {
|
|
13
|
-
this.id = id;
|
|
14
|
-
this.dsc = dsc;
|
|
15
|
-
this.w = w;
|
|
16
|
-
this.h = h;
|
|
17
|
-
this.dbIndex = 0;
|
|
18
|
-
this.XPosition = 0;
|
|
19
|
-
this.YPosition = 0;
|
|
20
|
-
this.prelim = 0;
|
|
21
|
-
this.modifier = 0;
|
|
22
|
-
this.leftNeighbor = null;
|
|
23
|
-
this.rightNeighbor = null;
|
|
24
|
-
this.parents = [];
|
|
25
|
-
this.children = [];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
TreeNode.prototype._getLevel = function() {
|
|
29
|
-
if (this.id === -1 || this.parents === undefined || this.parents.length === 0) {
|
|
30
|
-
return 0;
|
|
31
|
-
} else {
|
|
32
|
-
let maxLevel = 0;
|
|
33
|
-
this.parents.forEach(parent => {
|
|
34
|
-
var parentLevel = parent._getLevel();
|
|
35
|
-
maxLevel = (maxLevel < parentLevel) ? parentLevel : maxLevel;
|
|
36
|
-
});
|
|
37
|
-
return maxLevel + 1;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
TreeNode.prototype._getChildrenCount = function() {
|
|
42
|
-
return this.children ? this.children.length : 0;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
TreeNode.prototype._getLeftSibling = function() {
|
|
46
|
-
if (!this.leftNeighbor) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
var haveSameParent = this.leftNeighbor.parents.find(lParent => {
|
|
50
|
-
return this.parents.find(tParent => tParent.id === lParent.id);
|
|
51
|
-
});
|
|
52
|
-
return haveSameParent ? this.leftNeighbor : null;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
TreeNode.prototype._getRightSibling = function() {
|
|
56
|
-
if (!this.rightNeighbor) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
var haveSameParent = this.rightNeighbor.parents.find(rParent => {
|
|
60
|
-
return this.parents.find(tParent => tParent.id === rParent.id);
|
|
61
|
-
});
|
|
62
|
-
return haveSameParent ? this.rightNeighbor : null;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
TreeNode.prototype._getChildAt = function(i) {
|
|
66
|
-
return this.children[i];
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
TreeNode.prototype._getChildrenCenter = function(tree) {
|
|
70
|
-
var first = this._getFirstChild();
|
|
71
|
-
var last = this._getLastChild();
|
|
72
|
-
return first.prelim + ((last.prelim - first.prelim) + tree._getNodeSize(last)) / 2;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
TreeNode.prototype._getFirstChild = function() {
|
|
76
|
-
return this._getChildAt(0);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
TreeNode.prototype._getLastChild = function() {
|
|
80
|
-
return this._getChildAt(this._getChildrenCount() - 1);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export default function Tree() {
|
|
84
|
-
this.config = {
|
|
85
|
-
iMaxDepth: 1000,
|
|
86
|
-
iLevelSeparation: 40,
|
|
87
|
-
iSiblingSeparation: 40,
|
|
88
|
-
iSubtreeSeparation: 60,
|
|
89
|
-
topXAdjustment: 0,
|
|
90
|
-
topYAdjustment: 0
|
|
91
|
-
};
|
|
92
|
-
this.self = this;
|
|
93
|
-
this.maxLevelHeight = [];
|
|
94
|
-
this.maxLevelWidth = [];
|
|
95
|
-
this.previousLevelNode = [];
|
|
96
|
-
this.rootYOffset = 0;
|
|
97
|
-
this.rootXOffset = 0;
|
|
98
|
-
this.nDatabaseNodes = [];
|
|
99
|
-
this.mapIDs = {};
|
|
100
|
-
this.root = new TreeNode(-1, null, null, 2, 2);
|
|
101
|
-
this.iLastSearch = 0;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Layout algorithm
|
|
105
|
-
Tree._firstWalk = function(tree, node, level, prevSiblings = []) {
|
|
106
|
-
|
|
107
|
-
// console.log('_firstWalk()')
|
|
108
|
-
var leftSibling = null;
|
|
109
|
-
node.XPosition = 0;
|
|
110
|
-
node.YPosition = 0;
|
|
111
|
-
node.prelim = 0;
|
|
112
|
-
node.modifier = 0;
|
|
113
|
-
node.leftNeighbor = null;
|
|
114
|
-
node.rightNeighbor = null;
|
|
115
|
-
tree._setLevelHeight(node, level);
|
|
116
|
-
tree._setLevelWidth(node, level);
|
|
117
|
-
tree._setNeighbors(node, level);
|
|
118
|
-
if (node._getChildrenCount() === 0 || level === tree.config.iMaxDepth) {
|
|
119
|
-
leftSibling = node._getLeftSibling();
|
|
120
|
-
if (leftSibling != null) {
|
|
121
|
-
node.prelim = leftSibling.prelim + tree._getNodeSize(leftSibling) + tree.config.iSiblingSeparation;
|
|
122
|
-
} else {
|
|
123
|
-
node.prelim = 0;
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
var n = node._getChildrenCount();
|
|
127
|
-
for (var i = 0; i < n; i++) {
|
|
128
|
-
var iChild = node._getChildAt(i);
|
|
129
|
-
Tree._firstWalk(tree, iChild, level + 1, [ ...prevSiblings, iChild.id ]);
|
|
130
|
-
}
|
|
131
|
-
var midPoint = node._getChildrenCenter(tree);
|
|
132
|
-
midPoint -= tree._getNodeSize(node) / 2;
|
|
133
|
-
leftSibling = node._getLeftSibling();
|
|
134
|
-
if (leftSibling != null && !prevSiblings.includes(leftSibling.id)) {
|
|
135
|
-
node.prelim = leftSibling.prelim + tree._getNodeSize(leftSibling) + tree.config.iSiblingSeparation;
|
|
136
|
-
node.modifier = node.prelim - midPoint;
|
|
137
|
-
Tree._apportion(tree, node, level);
|
|
138
|
-
} else {
|
|
139
|
-
node.prelim = midPoint;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
Tree._apportion = function(tree, node, level) {
|
|
145
|
-
|
|
146
|
-
// console.log('_apportion()')
|
|
147
|
-
var firstChild = node._getFirstChild();
|
|
148
|
-
var firstChildLeftNeighbor = firstChild.leftNeighbor;
|
|
149
|
-
var j = 1;
|
|
150
|
-
for (var k = tree.config.iMaxDepth - level; firstChild != null && firstChildLeftNeighbor != null && j <= k;) {
|
|
151
|
-
var modifierSumRight = 0;
|
|
152
|
-
var modifierSumLeft = 0;
|
|
153
|
-
var rightAncestor = firstChild;
|
|
154
|
-
var leftAncestor = firstChildLeftNeighbor;
|
|
155
|
-
for (var l = 0; l < j; l++) {
|
|
156
|
-
rightAncestor = rightAncestor.parents[0];
|
|
157
|
-
leftAncestor = leftAncestor.parents[0];
|
|
158
|
-
modifierSumRight += rightAncestor.modifier;
|
|
159
|
-
modifierSumLeft += leftAncestor.modifier;
|
|
160
|
-
}
|
|
161
|
-
var totalGap = (firstChildLeftNeighbor.prelim + modifierSumLeft + tree._getNodeSize(firstChildLeftNeighbor) + tree.config.iSubtreeSeparation) - (firstChild.prelim + modifierSumRight);
|
|
162
|
-
if (totalGap > 0) {
|
|
163
|
-
var subtreeAux = node;
|
|
164
|
-
var numSubtrees = 0;
|
|
165
|
-
for (; subtreeAux != null && subtreeAux !== leftAncestor; subtreeAux = subtreeAux._getLeftSibling()) {
|
|
166
|
-
numSubtrees++;
|
|
167
|
-
}
|
|
168
|
-
if (subtreeAux != null) {
|
|
169
|
-
var subtreeMoveAux = node;
|
|
170
|
-
var singleGap = totalGap / numSubtrees;
|
|
171
|
-
for (; subtreeMoveAux !== leftAncestor; subtreeMoveAux = subtreeMoveAux._getLeftSibling()) {
|
|
172
|
-
subtreeMoveAux.prelim += totalGap;
|
|
173
|
-
subtreeMoveAux.modifier += totalGap;
|
|
174
|
-
totalGap -= singleGap;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
j++;
|
|
179
|
-
if (firstChild._getChildrenCount() === 0) {
|
|
180
|
-
firstChild = tree._getLeftmost(node, 0, j);
|
|
181
|
-
} else {
|
|
182
|
-
firstChild = firstChild._getFirstChild();
|
|
183
|
-
}
|
|
184
|
-
if (firstChild != null) {
|
|
185
|
-
firstChildLeftNeighbor = firstChild.leftNeighbor;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
Tree._secondWalk = function(tree, node, level, X, Y, prevSiblings = []) {
|
|
191
|
-
|
|
192
|
-
// console.log('_secondWalk()')
|
|
193
|
-
if (level <= tree.config.iMaxDepth) {
|
|
194
|
-
var xTmp = tree.rootXOffset + node.prelim + X;
|
|
195
|
-
var yTmp = tree.rootYOffset + Y;
|
|
196
|
-
var maxsizeTmp = 0;
|
|
197
|
-
var nodesizeTmp = 0;
|
|
198
|
-
var flag = false;
|
|
199
|
-
|
|
200
|
-
maxsizeTmp = tree.maxLevelWidth[level];
|
|
201
|
-
flag = true;
|
|
202
|
-
nodesizeTmp = node.w;
|
|
203
|
-
|
|
204
|
-
node.XPosition = xTmp;
|
|
205
|
-
node.YPosition = yTmp + (maxsizeTmp - nodesizeTmp) / 2;
|
|
206
|
-
|
|
207
|
-
if (flag) {
|
|
208
|
-
var swapTmp = node.XPosition;
|
|
209
|
-
node.XPosition = node.YPosition;
|
|
210
|
-
node.YPosition = swapTmp;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (node._getChildrenCount() !== 0) {
|
|
214
|
-
Tree._secondWalk(tree, node._getFirstChild(), level + 1, X + node.modifier, Y + maxsizeTmp + tree.config.iLevelSeparation, [ ...prevSiblings, node.id ]);
|
|
215
|
-
}
|
|
216
|
-
var rightSibling = node._getRightSibling();
|
|
217
|
-
if (rightSibling != null && !prevSiblings.includes(rightSibling.id)) { Tree._secondWalk(tree, rightSibling, level, X, Y, [ ...prevSiblings, node.id ]); }
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
Tree.prototype._positionTree = function() {
|
|
222
|
-
|
|
223
|
-
// console.log('_positionTree()')
|
|
224
|
-
this.maxLevelHeight = [];
|
|
225
|
-
this.maxLevelWidth = [];
|
|
226
|
-
this.previousLevelNode = [];
|
|
227
|
-
Tree._firstWalk(this.self, this.root, 0);
|
|
228
|
-
this.rootXOffset = this.config.topXAdjustment + this.root.XPosition;
|
|
229
|
-
this.rootYOffset = this.config.topYAdjustment + this.root.YPosition;
|
|
230
|
-
Tree._secondWalk(this.self, this.root, 0, 0, 0);
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
Tree.prototype._setLevelHeight = function(node, level) {
|
|
234
|
-
if (this.maxLevelHeight[level] == null) { this.maxLevelHeight[level] = 0; }
|
|
235
|
-
if (this.maxLevelHeight[level] < node.h) { this.maxLevelHeight[level] = node.h; }
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
Tree.prototype._setLevelWidth = function(node, level) {
|
|
239
|
-
if (this.maxLevelWidth[level] == null) { this.maxLevelWidth[level] = 0; }
|
|
240
|
-
if (this.maxLevelWidth[level] < node.w) { this.maxLevelWidth[level] = node.w; }
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
Tree.prototype._setNeighbors = function(node, level) {
|
|
244
|
-
var tempNeighbour = this.previousLevelNode[level];
|
|
245
|
-
if (tempNeighbour && tempNeighbour.id !== node.id) {
|
|
246
|
-
node.leftNeighbor = this.previousLevelNode[level];
|
|
247
|
-
if (node.leftNeighbor != null) {
|
|
248
|
-
node.leftNeighbor.rightNeighbor = node;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
this.previousLevelNode[level] = node;
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
Tree.prototype._getNodeSize = function(node) {
|
|
255
|
-
return node.h;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
Tree.prototype._getLeftmost = function(node, level, maxlevel) {
|
|
259
|
-
if (level >= maxlevel) return node;
|
|
260
|
-
if (node._getChildrenCount() === 0) return null;
|
|
261
|
-
|
|
262
|
-
var n = node._getChildrenCount();
|
|
263
|
-
for (var i = 0; i < n; i++) {
|
|
264
|
-
var iChild = node._getChildAt(i);
|
|
265
|
-
var leftmostDescendant = this._getLeftmost(iChild, level + 1, maxlevel);
|
|
266
|
-
if (leftmostDescendant != null) { return leftmostDescendant; }
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return null;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
Tree.prototype.UpdateTree = function() {
|
|
273
|
-
this._positionTree();
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
Tree.prototype.add = function(id, dsc, w, h) {
|
|
277
|
-
var node = new TreeNode(id, dsc, w, h);
|
|
278
|
-
var i = this.nDatabaseNodes.length;
|
|
279
|
-
node.dbIndex = this.mapIDs[id] = i;
|
|
280
|
-
this.nDatabaseNodes[i] = node;
|
|
281
|
-
return node;
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
Tree.prototype.addParentToNode = function(nodeId, parentId) {
|
|
285
|
-
|
|
286
|
-
// retrieve nodes from list
|
|
287
|
-
var node = this.getNodeById(nodeId);
|
|
288
|
-
var parent = (parentId === -1) ? this.root : this.getNodeById(parentId);
|
|
289
|
-
if (node === undefined) {
|
|
290
|
-
throw new Error('Node not found');
|
|
291
|
-
}
|
|
292
|
-
if (parent === undefined) {
|
|
293
|
-
throw new Error('Parent node not found');
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// confirm this parents hasn't already been added to this node
|
|
297
|
-
var found = node.parents.find(parent => parent.id === parentId);
|
|
298
|
-
if (found === undefined) {
|
|
299
|
-
node.parents.push(parent);
|
|
300
|
-
|
|
301
|
-
// confirm that the child hasnt been added to the parents children list
|
|
302
|
-
found = parent.children.find(child => child.id === nodeId);
|
|
303
|
-
|
|
304
|
-
if (found === undefined) {
|
|
305
|
-
parent.children.push(node);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
Tree.prototype.removeParentFromNode = function(nodeId, parentId) {
|
|
311
|
-
|
|
312
|
-
// retrieve nodes from list
|
|
313
|
-
var node = this.getNodeById(nodeId);
|
|
314
|
-
var parent = (parentId === -1) ? this.root : this.getNodeById(parentId);
|
|
315
|
-
if (node === undefined) {
|
|
316
|
-
throw new Error('Node not found');
|
|
317
|
-
}
|
|
318
|
-
if (parent === undefined) {
|
|
319
|
-
throw new Error('Parent node not found');
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// remove the parent node from node parents
|
|
323
|
-
node.parents = node.parents.filter(parent => parent.id !== parentId);
|
|
324
|
-
|
|
325
|
-
// remove the ndoe form the parent children list
|
|
326
|
-
parent.children = parent.children.filter(child => child.id !== nodeId);
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
Tree.prototype.getNodeById = function(id) {
|
|
330
|
-
return this.nDatabaseNodes.find(node => node.id === id);
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
Tree.prototype.getNodeByName = function(name) {
|
|
334
|
-
return this.nDatabaseNodes.find(node => node.dsc === name);
|
|
335
|
-
};
|