@joint/core 4.2.0-alpha.1 → 4.2.0-beta.1
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/dist/geometry.js +1 -1
- package/dist/geometry.min.js +2 -3
- package/dist/joint.d.ts +321 -55
- package/dist/joint.js +2492 -853
- package/dist/joint.min.js +2 -3
- package/dist/joint.nowrap.js +2492 -853
- package/dist/joint.nowrap.min.js +2 -3
- package/dist/vectorizer.js +1 -1
- package/dist/vectorizer.min.js +2 -3
- package/dist/version.mjs +1 -1
- package/package.json +7 -7
- package/src/config/index.mjs +3 -1
- package/src/dia/Cell.mjs +77 -80
- package/src/dia/CellCollection.mjs +136 -0
- package/src/dia/CellView.mjs +1 -2
- package/src/dia/Element.mjs +2 -3
- package/src/dia/Graph.mjs +610 -317
- package/src/dia/GraphLayer.mjs +53 -0
- package/src/dia/GraphLayerCollection.mjs +313 -0
- package/src/dia/GraphLayerView.mjs +128 -0
- package/src/dia/GraphLayersController.mjs +166 -0
- package/src/dia/GraphTopologyIndex.mjs +222 -0
- package/src/dia/{layers/GridLayer.mjs → GridLayerView.mjs} +23 -16
- package/src/dia/{PaperLayer.mjs → LayerView.mjs} +52 -17
- package/src/dia/LegacyGraphLayerView.mjs +14 -0
- package/src/dia/Paper.mjs +756 -423
- package/src/dia/ToolsView.mjs +3 -3
- package/src/dia/index.mjs +6 -1
- package/src/dia/ports.mjs +11 -2
- package/src/dia/symbols.mjs +24 -0
- package/src/mvc/Collection.mjs +19 -19
- package/src/mvc/Model.mjs +13 -10
- package/types/joint.d.ts +320 -54
package/src/dia/Paper.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import V from '../V/index.mjs';
|
|
2
|
+
import * as g from '../g/index.mjs';
|
|
2
3
|
import {
|
|
3
4
|
isNumber,
|
|
4
5
|
assign,
|
|
@@ -12,7 +13,6 @@ import {
|
|
|
12
13
|
isFunction,
|
|
13
14
|
isPlainObject,
|
|
14
15
|
getByPath,
|
|
15
|
-
sortElements,
|
|
16
16
|
isString,
|
|
17
17
|
guid,
|
|
18
18
|
normalizeEvent,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
result,
|
|
24
24
|
camelCase,
|
|
25
25
|
cloneDeep,
|
|
26
|
+
clone,
|
|
26
27
|
invoke,
|
|
27
28
|
hashCode,
|
|
28
29
|
filter as _filter,
|
|
@@ -34,23 +35,37 @@ import {
|
|
|
34
35
|
import { ViewBase } from '../mvc/ViewBase.mjs';
|
|
35
36
|
import { Rect, Point, toRad } from '../g/index.mjs';
|
|
36
37
|
import { View, views as viewsRegistry } from '../mvc/index.mjs';
|
|
37
|
-
import { CellView
|
|
38
|
+
import { CellView } from './CellView.mjs';
|
|
38
39
|
import { ElementView } from './ElementView.mjs';
|
|
39
40
|
import { LinkView } from './LinkView.mjs';
|
|
40
|
-
import { Cell } from './Cell.mjs';
|
|
41
41
|
import { Graph } from './Graph.mjs';
|
|
42
|
-
import {
|
|
42
|
+
import { LayerView } from './LayerView.mjs';
|
|
43
|
+
import { GraphLayerView } from './GraphLayerView.mjs';
|
|
44
|
+
import { LegacyGraphLayerView } from './LegacyGraphLayerView.mjs';
|
|
43
45
|
import { HighlighterView } from './HighlighterView.mjs';
|
|
44
46
|
import { Deque } from '../alg/Deque.mjs';
|
|
47
|
+
import {
|
|
48
|
+
CELL_MARKER, CELL_VIEW_MARKER, LAYER_VIEW_MARKER, GRAPH_LAYER_VIEW_MARKER
|
|
49
|
+
} from './symbols.mjs';
|
|
45
50
|
import * as highlighters from '../highlighters/index.mjs';
|
|
46
51
|
import * as linkAnchors from '../linkAnchors/index.mjs';
|
|
47
52
|
import * as connectionPoints from '../connectionPoints/index.mjs';
|
|
48
53
|
import * as anchors from '../anchors/index.mjs';
|
|
49
54
|
|
|
50
55
|
import $ from '../mvc/Dom/index.mjs';
|
|
51
|
-
import {
|
|
56
|
+
import { GridLayerView } from './GridLayerView.mjs';
|
|
57
|
+
|
|
58
|
+
const paperLayers = {
|
|
59
|
+
GRID: 'grid',
|
|
60
|
+
BACK: 'back',
|
|
61
|
+
/** @deprecated */
|
|
62
|
+
CELLS: 'cells',
|
|
63
|
+
FRONT: 'front',
|
|
64
|
+
TOOLS: 'tools',
|
|
65
|
+
LABELS: 'labels'
|
|
66
|
+
};
|
|
52
67
|
|
|
53
|
-
const sortingTypes = {
|
|
68
|
+
export const sortingTypes = {
|
|
54
69
|
NONE: 'sorting-none',
|
|
55
70
|
APPROX: 'sorting-approximate',
|
|
56
71
|
EXACT: 'sorting-exact'
|
|
@@ -85,24 +100,223 @@ const defaultHighlighting = {
|
|
|
85
100
|
}
|
|
86
101
|
};
|
|
87
102
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
103
|
+
const gridPatterns = {
|
|
104
|
+
|
|
105
|
+
dot: [{
|
|
106
|
+
color: '#AAAAAA',
|
|
107
|
+
thickness: 1,
|
|
108
|
+
markup: 'rect',
|
|
109
|
+
render: function(el, opt) {
|
|
110
|
+
V(el).attr({
|
|
111
|
+
width: opt.thickness,
|
|
112
|
+
height: opt.thickness,
|
|
113
|
+
fill: opt.color
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}],
|
|
117
|
+
|
|
118
|
+
fixedDot: [{
|
|
119
|
+
color: '#AAAAAA',
|
|
120
|
+
thickness: 1,
|
|
121
|
+
markup: 'rect',
|
|
122
|
+
render: function(el, opt) {
|
|
123
|
+
V(el).attr({ fill: opt.color });
|
|
124
|
+
},
|
|
125
|
+
update: function(el, opt, paper) {
|
|
126
|
+
const { sx, sy } = paper.scale();
|
|
127
|
+
const width = sx <= 1 ? opt.thickness : opt.thickness / sx;
|
|
128
|
+
const height = sy <= 1 ? opt.thickness : opt.thickness / sy;
|
|
129
|
+
V(el).attr({ width, height });
|
|
130
|
+
}
|
|
131
|
+
}],
|
|
132
|
+
|
|
133
|
+
mesh: [{
|
|
134
|
+
color: '#AAAAAA',
|
|
135
|
+
thickness: 1,
|
|
136
|
+
markup: 'path',
|
|
137
|
+
render: function(el, opt) {
|
|
138
|
+
|
|
139
|
+
var d;
|
|
140
|
+
var width = opt.width;
|
|
141
|
+
var height = opt.height;
|
|
142
|
+
var thickness = opt.thickness;
|
|
143
|
+
|
|
144
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
145
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
146
|
+
} else {
|
|
147
|
+
d = 'M 0 0 0 0';
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
151
|
+
}
|
|
152
|
+
}],
|
|
153
|
+
|
|
154
|
+
doubleMesh: [{
|
|
155
|
+
color: '#AAAAAA',
|
|
156
|
+
thickness: 1,
|
|
157
|
+
markup: 'path',
|
|
158
|
+
render: function(el, opt) {
|
|
159
|
+
|
|
160
|
+
var d;
|
|
161
|
+
var width = opt.width;
|
|
162
|
+
var height = opt.height;
|
|
163
|
+
var thickness = opt.thickness;
|
|
164
|
+
|
|
165
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
166
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
167
|
+
} else {
|
|
168
|
+
d = 'M 0 0 0 0';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
172
|
+
}
|
|
173
|
+
}, {
|
|
174
|
+
color: '#000000',
|
|
175
|
+
thickness: 3,
|
|
176
|
+
scaleFactor: 4,
|
|
177
|
+
markup: 'path',
|
|
178
|
+
render: function(el, opt) {
|
|
179
|
+
|
|
180
|
+
var d;
|
|
181
|
+
var width = opt.width;
|
|
182
|
+
var height = opt.height;
|
|
183
|
+
var thickness = opt.thickness;
|
|
184
|
+
|
|
185
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
186
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
187
|
+
} else {
|
|
188
|
+
d = 'M 0 0 0 0';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
192
|
+
}
|
|
193
|
+
}]
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const backgroundPatterns = {
|
|
197
|
+
|
|
198
|
+
flipXy: function(img) {
|
|
199
|
+
// d b
|
|
200
|
+
// q p
|
|
201
|
+
|
|
202
|
+
var canvas = document.createElement('canvas');
|
|
203
|
+
var imgWidth = img.width;
|
|
204
|
+
var imgHeight = img.height;
|
|
205
|
+
|
|
206
|
+
canvas.width = 2 * imgWidth;
|
|
207
|
+
canvas.height = 2 * imgHeight;
|
|
208
|
+
|
|
209
|
+
var ctx = canvas.getContext('2d');
|
|
210
|
+
// top-left image
|
|
211
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
212
|
+
// xy-flipped bottom-right image
|
|
213
|
+
ctx.setTransform(-1, 0, 0, -1, canvas.width, canvas.height);
|
|
214
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
215
|
+
// x-flipped top-right image
|
|
216
|
+
ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);
|
|
217
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
218
|
+
// y-flipped bottom-left image
|
|
219
|
+
ctx.setTransform(1, 0, 0, -1, 0, canvas.height);
|
|
220
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
221
|
+
|
|
222
|
+
return canvas;
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
flipX: function(img) {
|
|
226
|
+
// d b
|
|
227
|
+
// d b
|
|
228
|
+
|
|
229
|
+
var canvas = document.createElement('canvas');
|
|
230
|
+
var imgWidth = img.width;
|
|
231
|
+
var imgHeight = img.height;
|
|
232
|
+
|
|
233
|
+
canvas.width = imgWidth * 2;
|
|
234
|
+
canvas.height = imgHeight;
|
|
235
|
+
|
|
236
|
+
var ctx = canvas.getContext('2d');
|
|
237
|
+
// left image
|
|
238
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
239
|
+
// flipped right image
|
|
240
|
+
ctx.translate(2 * imgWidth, 0);
|
|
241
|
+
ctx.scale(-1, 1);
|
|
242
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
243
|
+
|
|
244
|
+
return canvas;
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
flipY: function(img) {
|
|
248
|
+
// d d
|
|
249
|
+
// q q
|
|
250
|
+
|
|
251
|
+
var canvas = document.createElement('canvas');
|
|
252
|
+
var imgWidth = img.width;
|
|
253
|
+
var imgHeight = img.height;
|
|
254
|
+
|
|
255
|
+
canvas.width = imgWidth;
|
|
256
|
+
canvas.height = imgHeight * 2;
|
|
257
|
+
|
|
258
|
+
var ctx = canvas.getContext('2d');
|
|
259
|
+
// top image
|
|
260
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
261
|
+
// flipped bottom image
|
|
262
|
+
ctx.translate(0, 2 * imgHeight);
|
|
263
|
+
ctx.scale(1, -1);
|
|
264
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
265
|
+
|
|
266
|
+
return canvas;
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
watermark: function(img, opt) {
|
|
270
|
+
// d
|
|
271
|
+
// d
|
|
272
|
+
|
|
273
|
+
opt = opt || {};
|
|
274
|
+
|
|
275
|
+
var imgWidth = img.width;
|
|
276
|
+
var imgHeight = img.height;
|
|
277
|
+
|
|
278
|
+
var canvas = document.createElement('canvas');
|
|
279
|
+
canvas.width = imgWidth * 3;
|
|
280
|
+
canvas.height = imgHeight * 3;
|
|
281
|
+
|
|
282
|
+
var ctx = canvas.getContext('2d');
|
|
283
|
+
var angle = isNumber(opt.watermarkAngle) ? -opt.watermarkAngle : -20;
|
|
284
|
+
var radians = toRad(angle);
|
|
285
|
+
var stepX = canvas.width / 4;
|
|
286
|
+
var stepY = canvas.height / 4;
|
|
287
|
+
|
|
288
|
+
for (var i = 0; i < 4; i++) {
|
|
289
|
+
for (var j = 0; j < 4; j++) {
|
|
290
|
+
if ((i + j) % 2 > 0) {
|
|
291
|
+
// reset the current transformations
|
|
292
|
+
ctx.setTransform(1, 0, 0, 1, (2 * i - 1) * stepX, (2 * j - 1) * stepY);
|
|
293
|
+
ctx.rotate(radians);
|
|
294
|
+
ctx.drawImage(img, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return canvas;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const implicitLayers = [{
|
|
304
|
+
id: paperLayers.GRID,
|
|
305
|
+
type: 'GridLayerView',
|
|
306
|
+
patterns: gridPatterns
|
|
92
307
|
}, {
|
|
93
|
-
|
|
308
|
+
id: paperLayers.BACK,
|
|
94
309
|
}, {
|
|
95
|
-
|
|
310
|
+
id: paperLayers.LABELS,
|
|
96
311
|
}, {
|
|
97
|
-
|
|
312
|
+
id: paperLayers.FRONT
|
|
98
313
|
}, {
|
|
99
|
-
|
|
314
|
+
id: paperLayers.TOOLS
|
|
100
315
|
}];
|
|
101
316
|
|
|
102
317
|
const CELL_VIEW_PLACEHOLDER_MARKER = Symbol('joint.cellViewPlaceholderMarker');
|
|
103
318
|
|
|
104
319
|
export const Paper = View.extend({
|
|
105
|
-
|
|
106
320
|
className: 'paper',
|
|
107
321
|
|
|
108
322
|
options: {
|
|
@@ -178,7 +392,7 @@ export const Paper = View.extend({
|
|
|
178
392
|
// }
|
|
179
393
|
defaultLink: function() {
|
|
180
394
|
// Do not create hard dependency on the joint.shapes.standard namespace (by importing the standard.Link model directly)
|
|
181
|
-
const { cellNamespace } = this.model.
|
|
395
|
+
const { cellNamespace } = this.model.layerCollection;
|
|
182
396
|
const ctor = getByPath(cellNamespace, ['standard', 'Link']);
|
|
183
397
|
if (!ctor) throw new Error('dia.Paper: no default link model found. Use `options.defaultLink` to specify a default link model.');
|
|
184
398
|
return new ctor();
|
|
@@ -276,12 +490,24 @@ export const Paper = View.extend({
|
|
|
276
490
|
|
|
277
491
|
// no docs yet
|
|
278
492
|
onViewUpdate: function(view, flag, priority, opt, paper) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
493
|
+
if (opt.mounting || opt.isolate) {
|
|
494
|
+
// Do not update connected links when:
|
|
495
|
+
// - the view was just mounted (added back to the paper by viewport function)
|
|
496
|
+
// - the change was marked as `isolate`.
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// Always update connected links when the view model was replaced with another model
|
|
500
|
+
// with the same id.
|
|
501
|
+
// Note: the removal is done in 2 steps: remove the old model, add the new model.
|
|
502
|
+
// We update connected links on the add step.
|
|
503
|
+
if (!(opt.replace && opt.add)) {
|
|
504
|
+
if ((flag & (paper.FLAG_INSERT | paper.FLAG_REMOVE))) {
|
|
505
|
+
// Do not update connected links when:
|
|
506
|
+
// - the view was just inserted (added to the graph and rendered)
|
|
507
|
+
// - the view model was just removed from the graph
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
285
511
|
paper.requestConnectedLinksUpdate(view, priority, opt);
|
|
286
512
|
},
|
|
287
513
|
|
|
@@ -300,6 +526,8 @@ export const Paper = View.extend({
|
|
|
300
526
|
|
|
301
527
|
cellViewNamespace: null,
|
|
302
528
|
|
|
529
|
+
layerViewNamespace: null,
|
|
530
|
+
|
|
303
531
|
routerNamespace: null,
|
|
304
532
|
|
|
305
533
|
connectorNamespace: null,
|
|
@@ -312,7 +540,7 @@ export const Paper = View.extend({
|
|
|
312
540
|
|
|
313
541
|
connectionPointNamespace: connectionPoints,
|
|
314
542
|
|
|
315
|
-
overflow: false
|
|
543
|
+
overflow: false,
|
|
316
544
|
},
|
|
317
545
|
|
|
318
546
|
events: {
|
|
@@ -356,11 +584,13 @@ export const Paper = View.extend({
|
|
|
356
584
|
`,
|
|
357
585
|
|
|
358
586
|
svg: null,
|
|
359
|
-
viewport: null,
|
|
360
587
|
defs: null,
|
|
361
588
|
tools: null,
|
|
362
589
|
layers: null,
|
|
363
590
|
|
|
591
|
+
// deprecated, use layers element instead
|
|
592
|
+
viewport: null,
|
|
593
|
+
|
|
364
594
|
// For storing the current transformation matrix (CTM) of the paper's viewport.
|
|
365
595
|
_viewportMatrix: null,
|
|
366
596
|
// For verifying whether the CTM is up-to-date. The viewport transform attribute
|
|
@@ -371,7 +601,6 @@ export const Paper = View.extend({
|
|
|
371
601
|
// Paper Layers
|
|
372
602
|
_layers: null,
|
|
373
603
|
|
|
374
|
-
SORT_DELAYING_BATCHES: ['add', 'to-front', 'to-back'],
|
|
375
604
|
UPDATE_DELAYING_BATCHES: ['translate'],
|
|
376
605
|
// If you interact with these elements,
|
|
377
606
|
// the default interaction such as `element move` is prevented.
|
|
@@ -394,14 +623,16 @@ export const Paper = View.extend({
|
|
|
394
623
|
// to mitigate the differences between the model and view geometry.
|
|
395
624
|
DEFAULT_FIND_BUFFER: 200,
|
|
396
625
|
|
|
397
|
-
// Default layer to insert the cell views into.
|
|
398
|
-
DEFAULT_CELL_LAYER: LayersNames.CELLS,
|
|
399
|
-
|
|
400
|
-
// Update flags
|
|
401
626
|
FLAG_INSERT: 1<<30,
|
|
402
627
|
FLAG_REMOVE: 1<<29,
|
|
403
628
|
FLAG_INIT: 1<<28,
|
|
404
629
|
|
|
630
|
+
// Layers that are always present on the paper (e.g. grid, back, front, tools)
|
|
631
|
+
implicitLayers,
|
|
632
|
+
|
|
633
|
+
// Reference layer for inserting new graph layers.
|
|
634
|
+
graphLayerRefId: paperLayers.LABELS,
|
|
635
|
+
|
|
405
636
|
init: function() {
|
|
406
637
|
|
|
407
638
|
const { options } = this;
|
|
@@ -411,6 +642,14 @@ export const Paper = View.extend({
|
|
|
411
642
|
/* eslint-enable no-undef */
|
|
412
643
|
}
|
|
413
644
|
|
|
645
|
+
const defaultLayerViewNamespace = {
|
|
646
|
+
LayerView,
|
|
647
|
+
GraphLayerView,
|
|
648
|
+
GridLayerView,
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
this.layerViewNamespace = defaultsDeep({}, options.layerViewNamespace || {}, defaultLayerViewNamespace);
|
|
652
|
+
|
|
414
653
|
const model = this.model = options.model || new Graph;
|
|
415
654
|
|
|
416
655
|
// This property tells us if we need to keep the compatibility
|
|
@@ -420,20 +659,19 @@ export const Paper = View.extend({
|
|
|
420
659
|
// Layers (SVGGroups)
|
|
421
660
|
this._layers = {
|
|
422
661
|
viewsMap: {},
|
|
423
|
-
namesMap: {},
|
|
424
662
|
order: [],
|
|
425
663
|
};
|
|
426
664
|
|
|
427
|
-
this.cloneOptions();
|
|
428
|
-
this.render();
|
|
429
|
-
this._setDimensions();
|
|
430
|
-
this.startListening();
|
|
431
|
-
|
|
432
665
|
// Hash of all cell views.
|
|
433
666
|
this._views = {};
|
|
434
667
|
this._viewPlaceholders = {};
|
|
435
668
|
this._idToCid = {};
|
|
436
669
|
|
|
670
|
+
this.cloneOptions();
|
|
671
|
+
this.render();
|
|
672
|
+
this._setDimensions();
|
|
673
|
+
this.startListening();
|
|
674
|
+
|
|
437
675
|
// Mouse wheel events buffer
|
|
438
676
|
this._mw_evt_buffer = {
|
|
439
677
|
event: null,
|
|
@@ -441,7 +679,7 @@ export const Paper = View.extend({
|
|
|
441
679
|
};
|
|
442
680
|
|
|
443
681
|
// Render existing cells in the graph
|
|
444
|
-
this.resetViews(model.
|
|
682
|
+
this.resetViews(model.getCells());
|
|
445
683
|
},
|
|
446
684
|
|
|
447
685
|
_resetUpdates: function() {
|
|
@@ -466,10 +704,13 @@ export const Paper = View.extend({
|
|
|
466
704
|
var model = this.model;
|
|
467
705
|
this.listenTo(model, 'add', this.onCellAdded)
|
|
468
706
|
.listenTo(model, 'remove', this.onCellRemoved)
|
|
469
|
-
.listenTo(model, 'change', this.onCellChange)
|
|
470
707
|
.listenTo(model, 'reset', this.onGraphReset)
|
|
471
|
-
.listenTo(model, 'sort', this.onGraphSort)
|
|
472
708
|
.listenTo(model, 'batch:stop', this.onGraphBatchStop);
|
|
709
|
+
|
|
710
|
+
this.listenTo(model, 'layer:add', this.onGraphLayerAdd)
|
|
711
|
+
.listenTo(model, 'layer:remove', this.onGraphLayerRemove)
|
|
712
|
+
.listenTo(model, 'layers:sort', this.onGraphLayerCollectionSort);
|
|
713
|
+
|
|
473
714
|
this.on('cell:highlight', this.onCellHighlight)
|
|
474
715
|
.on('cell:unhighlight', this.onCellUnhighlight)
|
|
475
716
|
.on('transform', this.update);
|
|
@@ -496,27 +737,15 @@ export const Paper = View.extend({
|
|
|
496
737
|
}
|
|
497
738
|
},
|
|
498
739
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
},
|
|
511
|
-
|
|
512
|
-
onGraphReset: function(collection, opt) {
|
|
513
|
-
this.resetLayers();
|
|
514
|
-
this.resetViews(collection.models, opt);
|
|
515
|
-
},
|
|
516
|
-
|
|
517
|
-
onGraphSort: function() {
|
|
518
|
-
if (this.model.hasActiveBatch(this.SORT_DELAYING_BATCHES)) return;
|
|
519
|
-
this.sortViews();
|
|
740
|
+
onGraphReset: function(_collection, opt) {
|
|
741
|
+
// Re-render all graph layer views
|
|
742
|
+
// but keep the implicit layer views.
|
|
743
|
+
this.renderGraphLayerViews();
|
|
744
|
+
this.resetLayerViews();
|
|
745
|
+
// Backward compatibility: reassign the `cells` property
|
|
746
|
+
// with the default layer view.
|
|
747
|
+
this.assertLayerViews();
|
|
748
|
+
this.resetViews(this.model.getCells(), opt);
|
|
520
749
|
},
|
|
521
750
|
|
|
522
751
|
onGraphBatchStop: function(data) {
|
|
@@ -529,10 +758,95 @@ export const Paper = View.extend({
|
|
|
529
758
|
this.updateViews(data);
|
|
530
759
|
}
|
|
531
760
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
761
|
+
},
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* @protected
|
|
765
|
+
* @description When a new layer is added to the graph, we create a new layer view
|
|
766
|
+
**/
|
|
767
|
+
onGraphLayerAdd: function(layer, _, opt) {
|
|
768
|
+
if (this.hasLayerView(layer.id)) return;
|
|
769
|
+
|
|
770
|
+
const layerView = this.createLayerView({
|
|
771
|
+
id: layer.id,
|
|
772
|
+
model: layer
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
const layers = this.model.getLayers();
|
|
776
|
+
let before;
|
|
777
|
+
// Note: There is always at least one graph layer.
|
|
778
|
+
if (layers[layers.length - 1] === layer) {
|
|
779
|
+
// This is the last layer, so insert before the labels layer
|
|
780
|
+
before = paperLayers.LABELS;
|
|
781
|
+
} else {
|
|
782
|
+
// There is a layer after the current one, so insert before that one
|
|
783
|
+
const index = layers.indexOf(layer);
|
|
784
|
+
before = layers[index + 1].id;
|
|
535
785
|
}
|
|
786
|
+
|
|
787
|
+
this.addLayerView(layerView, { before });
|
|
788
|
+
},
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* @protected
|
|
792
|
+
* @description When a layer is removed from the graph, we remove the corresponding layer view
|
|
793
|
+
**/
|
|
794
|
+
onGraphLayerRemove: function(layer, _, opt) {
|
|
795
|
+
if (!this.hasLayerView(layer)) return;
|
|
796
|
+
|
|
797
|
+
// Request layer removal. Since the UPDATE_PRIORITY is lower
|
|
798
|
+
// than cells update priority, the cell views will be removed first.
|
|
799
|
+
this.requestLayerViewRemoval(layer);
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* @protected
|
|
804
|
+
* @description When the graph layer collection is sorted,
|
|
805
|
+
* we reorder all graph layer views.
|
|
806
|
+
**/
|
|
807
|
+
onGraphLayerCollectionSort: function(layerCollection) {
|
|
808
|
+
layerCollection.each(layer => {
|
|
809
|
+
if (!this.hasLayerView(layer)) return;
|
|
810
|
+
|
|
811
|
+
this.moveLayerView(layer, { before: this.graphLayerRefId });
|
|
812
|
+
});
|
|
813
|
+
},
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* @protected
|
|
817
|
+
* @description Resets all graph layer views.
|
|
818
|
+
*/
|
|
819
|
+
renderGraphLayerViews: function() {
|
|
820
|
+
// Remove all existing graph layer views
|
|
821
|
+
// Note: we don't use `getGraphLayerViews()` here because
|
|
822
|
+
// rendered graph layer views could be different from the ones
|
|
823
|
+
// in the graph layer collection (`onResetGraphLayerCollectionReset`).
|
|
824
|
+
this.getLayerViews().forEach(layerView => {
|
|
825
|
+
if (!layerView[GRAPH_LAYER_VIEW_MARKER]) return;
|
|
826
|
+
this._removeLayerView(layerView);
|
|
827
|
+
});
|
|
828
|
+
// Create and insert new graph layer views
|
|
829
|
+
this.model.getLayers().forEach(layer => {
|
|
830
|
+
const layerView = this.createLayerView({
|
|
831
|
+
id: layer.id,
|
|
832
|
+
model: layer
|
|
833
|
+
});
|
|
834
|
+
// Insert the layer view into the paper layers, just before the labels layer.
|
|
835
|
+
// All cell layers are positioned between the "back" and "labels" layers,
|
|
836
|
+
// with the default "cells" layer originally occupying this position.
|
|
837
|
+
this.addLayerView(layerView, { before: this.graphLayerRefId });
|
|
838
|
+
});
|
|
839
|
+
},
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* @protected
|
|
843
|
+
* @description Renders all implicit layer views.
|
|
844
|
+
*/
|
|
845
|
+
renderImplicitLayerViews: function() {
|
|
846
|
+
this.implicitLayers.forEach(layerInit => {
|
|
847
|
+
const layerView = this.createLayerView(layerInit);
|
|
848
|
+
this.addLayerView(layerView);
|
|
849
|
+
});
|
|
536
850
|
},
|
|
537
851
|
|
|
538
852
|
cloneOptions: function() {
|
|
@@ -628,121 +942,301 @@ export const Paper = View.extend({
|
|
|
628
942
|
}];
|
|
629
943
|
},
|
|
630
944
|
|
|
631
|
-
|
|
632
|
-
|
|
945
|
+
/**
|
|
946
|
+
* @public
|
|
947
|
+
* @description Checks whether the layer view exists by the given layer id or layer model.
|
|
948
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
949
|
+
* @return {boolean} True if the layer view exists, false otherwise.
|
|
950
|
+
*/
|
|
951
|
+
hasLayerView(layerRef) {
|
|
952
|
+
let layerId;
|
|
953
|
+
if (isString(layerRef)) {
|
|
954
|
+
layerId = layerRef;
|
|
955
|
+
} else if (layerRef) {
|
|
956
|
+
layerId = layerRef.id;
|
|
957
|
+
} else {
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
return (layerId in this._layers.viewsMap);
|
|
633
961
|
},
|
|
634
962
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
963
|
+
/**
|
|
964
|
+
* @public
|
|
965
|
+
* @description Returns the layer view by the given layer id or layer model.
|
|
966
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
967
|
+
* @return {dia.LayerView} The layer view.
|
|
968
|
+
* @throws {Error} if the layer view is not found
|
|
969
|
+
*/
|
|
970
|
+
getLayerView(layerRef) {
|
|
971
|
+
|
|
972
|
+
let layerId;
|
|
973
|
+
if (isString(layerRef)) {
|
|
974
|
+
layerId = layerRef;
|
|
975
|
+
} else if (layerRef) {
|
|
976
|
+
layerId = layerRef.id;
|
|
977
|
+
} else {
|
|
978
|
+
throw new Error('dia.Paper: No layer provided.');
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const layerView = this._layers.viewsMap[layerId];
|
|
982
|
+
if (!layerView) {
|
|
983
|
+
throw new Error(`dia.Paper: Unknown layer view "${layerId}".`);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
return layerView;
|
|
639
987
|
},
|
|
640
988
|
|
|
641
|
-
|
|
642
|
-
|
|
989
|
+
/**
|
|
990
|
+
* @deprecated use `getLayerView(layerId).el` instead
|
|
991
|
+
*/
|
|
992
|
+
getLayerNode(layerId) {
|
|
993
|
+
return this.getLayerView(layerId).el;
|
|
643
994
|
},
|
|
644
995
|
|
|
645
|
-
|
|
646
|
-
|
|
996
|
+
/**
|
|
997
|
+
* @protected
|
|
998
|
+
* @description Removes the given layer view from the paper.
|
|
999
|
+
* It does not check whether the layer view is empty.
|
|
1000
|
+
* @param {dia.LayerView} layerView - The layer view to remove.
|
|
1001
|
+
*/
|
|
1002
|
+
_removeLayerView(layerView) {
|
|
1003
|
+
this._unregisterLayerView(layerView);
|
|
647
1004
|
layerView.remove();
|
|
648
1005
|
},
|
|
649
1006
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* @protected
|
|
1010
|
+
* @description Removes all layer views from the paper.
|
|
1011
|
+
* It does not check whether the layer views are empty.
|
|
1012
|
+
*/
|
|
1013
|
+
_removeLayerViews: function() {
|
|
1014
|
+
Object.values(this._layers.viewsMap).forEach(layerView => {
|
|
1015
|
+
this._removeLayerView(layerView);
|
|
1016
|
+
});
|
|
656
1017
|
},
|
|
657
1018
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1019
|
+
/**
|
|
1020
|
+
* @protected
|
|
1021
|
+
* @description Unregisters the given layer view from the paper.
|
|
1022
|
+
* @param {dia.LayerView} layerView - The layer view to unregister.
|
|
1023
|
+
*/
|
|
1024
|
+
_unregisterLayerView(layerView) {
|
|
1025
|
+
const { _layers: { viewsMap, order }} = this;
|
|
1026
|
+
const layerId = layerView.id;
|
|
1027
|
+
// Remove the layer id from the order list.
|
|
1028
|
+
const layerIndex = order.indexOf(layerId);
|
|
1029
|
+
if (layerIndex !== -1) {
|
|
1030
|
+
order.splice(layerIndex, 1);
|
|
665
1031
|
}
|
|
666
|
-
|
|
667
|
-
|
|
1032
|
+
// Unlink the layer view from the paper.
|
|
1033
|
+
layerView.unsetPaperReference();
|
|
1034
|
+
// Remove the layer view from the paper's registry.
|
|
1035
|
+
delete viewsMap[layerId];
|
|
668
1036
|
},
|
|
669
1037
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
1038
|
+
/**
|
|
1039
|
+
* @protected
|
|
1040
|
+
* @description Registers the given layer view in the paper.
|
|
1041
|
+
* @param {dia.LayerView} layerView - The layer view to register.
|
|
1042
|
+
* @throws {Error} if the layer view is not an instance of dia.LayerView
|
|
1043
|
+
* @throws {Error} if the layer view already exists in the paper
|
|
1044
|
+
*/
|
|
1045
|
+
_registerLayerView(layerView) {
|
|
1046
|
+
if (!layerView || !layerView[LAYER_VIEW_MARKER]) {
|
|
1047
|
+
throw new Error('dia.Paper: The layer view must be an instance of dia.LayerView.');
|
|
675
1048
|
}
|
|
676
|
-
|
|
677
|
-
|
|
1049
|
+
|
|
1050
|
+
if (this.hasLayerView(layerView.id)) {
|
|
1051
|
+
throw new Error(`dia.Paper: The layer view "${layerView.id}" already exists.`);
|
|
1052
|
+
}
|
|
1053
|
+
// Link the layer view back to the paper.
|
|
1054
|
+
layerView.setPaperReference(this);
|
|
1055
|
+
// Store the layer view in the paper's registry.
|
|
1056
|
+
this._layers.viewsMap[layerView.id] = layerView;
|
|
678
1057
|
},
|
|
679
1058
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
1059
|
+
/**
|
|
1060
|
+
* @public
|
|
1061
|
+
* @description Removes the layer view by the given layer id or layer model.
|
|
1062
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
1063
|
+
* @throws {Error} if the layer view is not empty
|
|
1064
|
+
*/
|
|
1065
|
+
removeLayerView(layerRef) {
|
|
1066
|
+
const layerView = this.getLayerView(layerRef);
|
|
1067
|
+
if (!layerView.isEmpty()) {
|
|
1068
|
+
throw new Error('dia.Paper: The layer view is not empty.');
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
this._removeLayerView(layerView);
|
|
683
1072
|
},
|
|
684
1073
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
1074
|
+
/**
|
|
1075
|
+
* @protected
|
|
1076
|
+
* @description Schedules the layer view removal by the given layer id or layer model.
|
|
1077
|
+
* The actual removal will be performed during the paper update cycle.
|
|
1078
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
1079
|
+
* @param {Object} [opt] - Update options.
|
|
1080
|
+
*/
|
|
1081
|
+
requestLayerViewRemoval(layerRef, opt) {
|
|
1082
|
+
const layerView = this.getLayerView(layerRef);
|
|
1083
|
+
const { FLAG_REMOVE } = this;
|
|
1084
|
+
const { UPDATE_PRIORITY } = layerView;
|
|
1085
|
+
|
|
1086
|
+
this.requestViewUpdate(layerView, FLAG_REMOVE, UPDATE_PRIORITY, opt);
|
|
1087
|
+
},
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* @public
|
|
1091
|
+
* @internal not documented
|
|
1092
|
+
* @description Schedules the cell view insertion into the appropriate layer view.
|
|
1093
|
+
* The actual insertion will be performed during the paper update cycle.
|
|
1094
|
+
* @param {dia.Cell} cell - The cell model whose view should be inserted.
|
|
1095
|
+
* @param {Object} [opt] - Update options.
|
|
1096
|
+
*/
|
|
1097
|
+
requestCellViewInsertion(cell, opt) {
|
|
1098
|
+
const viewLike = this._getCellViewLike(cell);
|
|
1099
|
+
if (!viewLike) return;
|
|
1100
|
+
this.requestViewUpdate(viewLike, this.FLAG_INSERT, viewLike.UPDATE_PRIORITY, opt);
|
|
1101
|
+
},
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* @private
|
|
1105
|
+
* Helper method for addLayerView and moveLayerView methods
|
|
1106
|
+
*/
|
|
1107
|
+
_getBeforeLayerViewFromOptions(layerView, options) {
|
|
1108
|
+
let { before = null, index } = options;
|
|
1109
|
+
|
|
1110
|
+
if (before && index !== undefined) {
|
|
1111
|
+
throw new Error('dia.Paper: Options "before" and "index" are mutually exclusive.');
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
let computedBefore;
|
|
1115
|
+
if (index !== undefined) {
|
|
1116
|
+
const { _layers: { order }} = this;
|
|
1117
|
+
if (index >= order.length) {
|
|
1118
|
+
// If index is greater than the number of layers,
|
|
1119
|
+
// return before as null (move to the end).
|
|
1120
|
+
computedBefore = null;
|
|
1121
|
+
} else if (index < 0) {
|
|
1122
|
+
// If index is negative, move to the beginning.
|
|
1123
|
+
computedBefore = order[0];
|
|
690
1124
|
} else {
|
|
691
|
-
|
|
1125
|
+
const originalIndex = order.indexOf(layerView.id);
|
|
1126
|
+
if (originalIndex !== -1 && index > originalIndex) {
|
|
1127
|
+
// If moving a layer upwards in the stack, we need to adjust the index
|
|
1128
|
+
// to account for the layer being removed from its original position.
|
|
1129
|
+
index += 1;
|
|
1130
|
+
}
|
|
1131
|
+
// Otherwise, get the layer ID at the specified index.
|
|
1132
|
+
computedBefore = order[index] || null;
|
|
692
1133
|
}
|
|
1134
|
+
} else {
|
|
1135
|
+
computedBefore = before;
|
|
693
1136
|
}
|
|
694
|
-
|
|
1137
|
+
|
|
1138
|
+
return computedBefore ? this.getLayerView(computedBefore) : null;
|
|
695
1139
|
},
|
|
696
1140
|
|
|
697
|
-
|
|
698
|
-
|
|
1141
|
+
/**
|
|
1142
|
+
* @public
|
|
1143
|
+
* @description Adds the layer view to the paper.
|
|
1144
|
+
* @param {dia.LayerView} layerView - The layer view to add.
|
|
1145
|
+
* @param {Object} [options] - Adding options.
|
|
1146
|
+
* @param {string|dia.GraphLayer} [options.before] - Layer id or layer model before
|
|
1147
|
+
*/
|
|
1148
|
+
addLayerView(layerView, options = {}) {
|
|
1149
|
+
this._registerLayerView(layerView);
|
|
1150
|
+
|
|
1151
|
+
const beforeLayerView = this._getBeforeLayerViewFromOptions(layerView, options);
|
|
1152
|
+
this.insertLayerView(layerView, beforeLayerView);
|
|
699
1153
|
},
|
|
700
1154
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1155
|
+
/**
|
|
1156
|
+
* @public
|
|
1157
|
+
* @description Moves the layer view.
|
|
1158
|
+
* @param {Paper.LayerRef} layerRef - The layer view reference to move.
|
|
1159
|
+
* @param {Object} [options] - Moving options.
|
|
1160
|
+
* @param {Paper.LayerRef} [options.before] - Layer id or layer model before
|
|
1161
|
+
* @param {number} [options.index] - Zero-based index to which to move the layer view.
|
|
1162
|
+
*/
|
|
1163
|
+
moveLayerView(layerRef, options = {}) {
|
|
1164
|
+
const layerView = this.getLayerView(layerRef);
|
|
1165
|
+
|
|
1166
|
+
const beforeLayerView = this._getBeforeLayerViewFromOptions(layerView, options);
|
|
1167
|
+
this.insertLayerView(layerView, beforeLayerView);
|
|
707
1168
|
},
|
|
708
1169
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
1170
|
+
/**
|
|
1171
|
+
* @protected
|
|
1172
|
+
* @description Inserts the layer view into the paper.
|
|
1173
|
+
* If the layer view already exists in the paper, it is moved to the new position.
|
|
1174
|
+
* @param {dia.LayerView} layerView - The layer view to insert.
|
|
1175
|
+
* @param {dia.LayerView} [before] - Layer view before
|
|
1176
|
+
* which the layer view should be inserted.
|
|
1177
|
+
*/
|
|
1178
|
+
insertLayerView(layerView, beforeLayerView) {
|
|
1179
|
+
const layerId = layerView.id;
|
|
1180
|
+
|
|
1181
|
+
const { _layers: { order }} = this;
|
|
1182
|
+
const currentLayerIndex = order.indexOf(layerId);
|
|
1183
|
+
|
|
1184
|
+
// Should the layer view be inserted before another layer view?
|
|
1185
|
+
if (beforeLayerView) {
|
|
1186
|
+
const beforeLayerViewId = beforeLayerView.id;
|
|
1187
|
+
if (layerId === beforeLayerViewId) {
|
|
1188
|
+
// The layer view is already in the right place.
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
let beforeLayerPosition = order.indexOf(beforeLayerViewId);
|
|
1193
|
+
// Remove from the `order` list if the layer view is already in the order.
|
|
1194
|
+
if (currentLayerIndex !== -1) {
|
|
1195
|
+
if (currentLayerIndex < beforeLayerPosition) {
|
|
1196
|
+
beforeLayerPosition -= 1;
|
|
1197
|
+
}
|
|
1198
|
+
order.splice(currentLayerIndex, 1);
|
|
1199
|
+
}
|
|
1200
|
+
order.splice(beforeLayerPosition, 0, layerId);
|
|
726
1201
|
this.layers.insertBefore(layerView.el, beforeLayerView.el);
|
|
1202
|
+
return;
|
|
727
1203
|
}
|
|
728
|
-
},
|
|
729
1204
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
1205
|
+
// Remove from the `order` list if the layer view is already in the order.
|
|
1206
|
+
// This is needed for the case when the layer view is inserted in the new position.
|
|
1207
|
+
if (currentLayerIndex !== -1) {
|
|
1208
|
+
order.splice(currentLayerIndex, 1);
|
|
1209
|
+
}
|
|
1210
|
+
order.push(layerId);
|
|
1211
|
+
this.layers.appendChild(layerView.el);
|
|
736
1212
|
},
|
|
737
1213
|
|
|
738
|
-
|
|
739
|
-
|
|
1214
|
+
/**
|
|
1215
|
+
* @protected
|
|
1216
|
+
* @description Returns an array of layer view ids in the order they are rendered.
|
|
1217
|
+
* @returns {string[]} An array of layer view ids.
|
|
1218
|
+
*/
|
|
1219
|
+
getLayerViewOrder() {
|
|
740
1220
|
return this._layers.order.slice();
|
|
741
1221
|
},
|
|
742
1222
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1223
|
+
/**
|
|
1224
|
+
* @public
|
|
1225
|
+
* @description Returns an array of layer views in the order they are rendered.
|
|
1226
|
+
* @returns {dia.LayerView[]} An array of layer views.
|
|
1227
|
+
*/
|
|
1228
|
+
getLayerViews() {
|
|
1229
|
+
return this.getLayerViewOrder().map(id => this.getLayerView(id));
|
|
1230
|
+
},
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* @public
|
|
1234
|
+
* @description Returns an array of graph layer views in the order they are rendered.
|
|
1235
|
+
* @returns {dia.GraphLayerView[]} An array of graph layer views.
|
|
1236
|
+
*/
|
|
1237
|
+
getGraphLayerViews() {
|
|
1238
|
+
const { _layers: { viewsMap }} = this;
|
|
1239
|
+
return this.model.getLayers().map(layer => viewsMap[layer.id]);
|
|
746
1240
|
},
|
|
747
1241
|
|
|
748
1242
|
render: function() {
|
|
@@ -758,7 +1252,7 @@ export const Paper = View.extend({
|
|
|
758
1252
|
this.defs = defs;
|
|
759
1253
|
this.layers = layers;
|
|
760
1254
|
|
|
761
|
-
this.
|
|
1255
|
+
this.renderLayerViews();
|
|
762
1256
|
|
|
763
1257
|
V.ensureId(svg);
|
|
764
1258
|
|
|
@@ -780,48 +1274,86 @@ export const Paper = View.extend({
|
|
|
780
1274
|
V(this.svg).prepend(V.createSVGStyle(css));
|
|
781
1275
|
},
|
|
782
1276
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1277
|
+
/**
|
|
1278
|
+
* @protected
|
|
1279
|
+
* @description Creates a layer view instance based on the provided options.
|
|
1280
|
+
* It finds the appropriate layer view constructor from the paper's
|
|
1281
|
+
* `layerViewNamespace` and instantiates it.
|
|
1282
|
+
* @param {*} options See `dia.LayerView` options.
|
|
1283
|
+
* @returns {dia.LayerView}
|
|
1284
|
+
*/
|
|
1285
|
+
createLayerView(options) {
|
|
1286
|
+
if (options == null) {
|
|
1287
|
+
throw new Error('dia.Paper: Layer view options are required.');
|
|
789
1288
|
}
|
|
1289
|
+
|
|
1290
|
+
if (options.id == null) {
|
|
1291
|
+
throw new Error('dia.Paper: Layer view id is required.');
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
const viewOptions = clone(options);
|
|
1295
|
+
|
|
1296
|
+
let viewConstructor;
|
|
1297
|
+
if (viewOptions.model) {
|
|
1298
|
+
const modelType = viewOptions.model.get('type') || viewOptions.model.constructor.name;
|
|
1299
|
+
const type = modelType + 'View';
|
|
1300
|
+
|
|
1301
|
+
// For backward compatibility we use the LegacyGraphLayerView for the default `cells` layer.
|
|
1302
|
+
if (this.model.layersController.legacyMode) {
|
|
1303
|
+
viewConstructor = LegacyGraphLayerView;
|
|
1304
|
+
} else {
|
|
1305
|
+
viewConstructor = this.layerViewNamespace[type] || LayerView;
|
|
1306
|
+
}
|
|
1307
|
+
} else {
|
|
1308
|
+
// Paper layers
|
|
1309
|
+
const type = viewOptions.type;
|
|
1310
|
+
viewConstructor = this.layerViewNamespace[type] || LayerView;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
return new viewConstructor(viewOptions);
|
|
790
1314
|
},
|
|
791
1315
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1316
|
+
/**
|
|
1317
|
+
* @protected
|
|
1318
|
+
* @description Renders all paper layer views and graph layer views.
|
|
1319
|
+
*/
|
|
1320
|
+
renderLayerViews: function() {
|
|
1321
|
+
this._removeLayerViews();
|
|
1322
|
+
// Render the paper layers.
|
|
1323
|
+
this.renderImplicitLayerViews();
|
|
1324
|
+
// Render the layers.
|
|
1325
|
+
this.renderGraphLayerViews();
|
|
1326
|
+
// Ensure that essential layer views are present.
|
|
1327
|
+
this.assertLayerViews();
|
|
796
1328
|
},
|
|
797
1329
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
1330
|
+
/**
|
|
1331
|
+
* @protected
|
|
1332
|
+
* @description Ensures that essential layer views are present on the paper.
|
|
1333
|
+
* @throws {Error} if any of the essential layer views is missing
|
|
1334
|
+
*/
|
|
1335
|
+
assertLayerViews: function() {
|
|
1336
|
+
// Throws an exception if essential layer views are missing.
|
|
1337
|
+
const cellsLayerView = this.getLayerView(this.model.getDefaultLayer().id);
|
|
1338
|
+
const toolsLayerView = this.getLayerView(paperLayers.TOOLS);
|
|
1339
|
+
const labelsLayerView = this.getLayerView(paperLayers.LABELS);
|
|
1340
|
+
|
|
805
1341
|
// backwards compatibility
|
|
806
1342
|
this.tools = toolsLayerView.el;
|
|
807
1343
|
this.cells = this.viewport = cellsLayerView.el;
|
|
808
|
-
//
|
|
809
|
-
|
|
1344
|
+
// Backwards compatibility: same as `LegacyGraphLayerView` we keep
|
|
1345
|
+
// the `viewport` class on the labels layer.
|
|
810
1346
|
labelsLayerView.vel.addClass(addClassNamePrefix('viewport'));
|
|
811
|
-
cellsLayerView.el.style.webkitUserSelect = 'none';
|
|
812
|
-
cellsLayerView.el.style.userSelect = 'none';
|
|
813
1347
|
labelsLayerView.el.style.webkitUserSelect = 'none';
|
|
814
1348
|
labelsLayerView.el.style.userSelect = 'none';
|
|
815
1349
|
},
|
|
816
1350
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
const { _layers: { viewsMap }} = this;
|
|
824
|
-
Object.values(viewsMap).forEach(layerView => layerView.removePivots());
|
|
1351
|
+
/**
|
|
1352
|
+
* @protected
|
|
1353
|
+
* @description Resets all layer views.
|
|
1354
|
+
*/
|
|
1355
|
+
resetLayerViews: function() {
|
|
1356
|
+
this.getLayerViews().forEach(layerView => layerView.reset());
|
|
825
1357
|
},
|
|
826
1358
|
|
|
827
1359
|
update: function() {
|
|
@@ -947,28 +1479,27 @@ export const Paper = View.extend({
|
|
|
947
1479
|
|
|
948
1480
|
clientMatrix: function() {
|
|
949
1481
|
|
|
950
|
-
return V.createSVGMatrix(this.
|
|
1482
|
+
return V.createSVGMatrix(this.layers.getScreenCTM());
|
|
951
1483
|
},
|
|
952
1484
|
|
|
953
1485
|
requestConnectedLinksUpdate: function(view, priority, opt) {
|
|
954
|
-
if (view
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
}
|
|
1486
|
+
if (!view || !view[CELL_VIEW_MARKER]) return;
|
|
1487
|
+
var model = view.model;
|
|
1488
|
+
var links = this.model.getConnectedLinks(model);
|
|
1489
|
+
for (var j = 0, n = links.length; j < n; j++) {
|
|
1490
|
+
var link = links[j];
|
|
1491
|
+
var linkView = this._getCellViewLike(link);
|
|
1492
|
+
if (!linkView) continue;
|
|
1493
|
+
// We do not have to update placeholder views.
|
|
1494
|
+
// They will be updated on initial render.
|
|
1495
|
+
if (linkView[CELL_VIEW_PLACEHOLDER_MARKER]) continue;
|
|
1496
|
+
var nextPriority = Math.max(priority + 1, linkView.UPDATE_PRIORITY);
|
|
1497
|
+
this.scheduleViewUpdate(linkView, linkView.getFlag(LinkView.Flags.UPDATE), nextPriority, opt);
|
|
967
1498
|
}
|
|
968
1499
|
},
|
|
969
1500
|
|
|
970
1501
|
forcePostponedViewUpdate: function(view, flag) {
|
|
971
|
-
if (!view || !
|
|
1502
|
+
if (!view || !view[CELL_VIEW_MARKER]) return false;
|
|
972
1503
|
const model = view.model;
|
|
973
1504
|
if (model.isElement()) return false;
|
|
974
1505
|
const dumpOptions = { silent: true };
|
|
@@ -1070,6 +1601,12 @@ export const Paper = View.extend({
|
|
|
1070
1601
|
if (!view) return 0;
|
|
1071
1602
|
const { FLAG_REMOVE, FLAG_INSERT, FLAG_INIT } = this;
|
|
1072
1603
|
const { model } = view;
|
|
1604
|
+
if (view[GRAPH_LAYER_VIEW_MARKER]) {
|
|
1605
|
+
if (flag & FLAG_REMOVE) {
|
|
1606
|
+
this.removeLayerView(view);
|
|
1607
|
+
return 0;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1073
1610
|
if (view[CELL_VIEW_MARKER]) {
|
|
1074
1611
|
if (flag & FLAG_REMOVE) {
|
|
1075
1612
|
this.removeView(model);
|
|
@@ -1669,7 +2206,7 @@ export const Paper = View.extend({
|
|
|
1669
2206
|
}
|
|
1670
2207
|
this.options.frozen = updates.keyFrozen = false;
|
|
1671
2208
|
if (updates.sort) {
|
|
1672
|
-
this.
|
|
2209
|
+
this.sortLayerViews();
|
|
1673
2210
|
updates.sort = false;
|
|
1674
2211
|
}
|
|
1675
2212
|
},
|
|
@@ -1704,8 +2241,8 @@ export const Paper = View.extend({
|
|
|
1704
2241
|
this.freeze();
|
|
1705
2242
|
this._updates.disabled = true;
|
|
1706
2243
|
//clean up all DOM elements/views to prevent memory leaks
|
|
1707
|
-
this.removeLayers();
|
|
1708
2244
|
this.removeViews();
|
|
2245
|
+
this._removeLayerViews();
|
|
1709
2246
|
},
|
|
1710
2247
|
|
|
1711
2248
|
getComputedSize: function() {
|
|
@@ -1953,7 +2490,17 @@ export const Paper = View.extend({
|
|
|
1953
2490
|
return this.model.getBBox() || new Rect();
|
|
1954
2491
|
}
|
|
1955
2492
|
|
|
1956
|
-
|
|
2493
|
+
const graphLayerViews = this.getGraphLayerViews();
|
|
2494
|
+
// Return an empty rectangle if there are no layers
|
|
2495
|
+
// should not happen in practice
|
|
2496
|
+
if (graphLayerViews.length === 0) {
|
|
2497
|
+
return new Rect();
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// Combine content area rectangles from all layers,
|
|
2501
|
+
// considering only graph layer views to exclude non-cell elements (e.g., grid, tools)
|
|
2502
|
+
const bbox = g.Rect.fromRectUnion(...graphLayerViews.map(view => view.vel.getBBox()));
|
|
2503
|
+
return bbox;
|
|
1957
2504
|
},
|
|
1958
2505
|
|
|
1959
2506
|
// Return the dimensions of the content bbox in the paper units (as it appears on screen).
|
|
@@ -2031,7 +2578,7 @@ export const Paper = View.extend({
|
|
|
2031
2578
|
cid,
|
|
2032
2579
|
model: cell,
|
|
2033
2580
|
interactive,
|
|
2034
|
-
labelsLayer: labelsLayer === true ?
|
|
2581
|
+
labelsLayer: labelsLayer === true ? paperLayers.LABELS : labelsLayer
|
|
2035
2582
|
});
|
|
2036
2583
|
},
|
|
2037
2584
|
|
|
@@ -2184,7 +2731,7 @@ export const Paper = View.extend({
|
|
|
2184
2731
|
this.renderView(cells[i], opt);
|
|
2185
2732
|
}
|
|
2186
2733
|
this.unfreeze({ key });
|
|
2187
|
-
this.
|
|
2734
|
+
this.sortLayerViews();
|
|
2188
2735
|
},
|
|
2189
2736
|
|
|
2190
2737
|
removeViews: function() {
|
|
@@ -2200,8 +2747,7 @@ export const Paper = View.extend({
|
|
|
2200
2747
|
this._idToCid = {};
|
|
2201
2748
|
},
|
|
2202
2749
|
|
|
2203
|
-
|
|
2204
|
-
|
|
2750
|
+
sortLayerViews: function() {
|
|
2205
2751
|
if (!this.isExactSorting()) {
|
|
2206
2752
|
// noop
|
|
2207
2753
|
return;
|
|
@@ -2211,41 +2757,21 @@ export const Paper = View.extend({
|
|
|
2211
2757
|
this._updates.sort = true;
|
|
2212
2758
|
return;
|
|
2213
2759
|
}
|
|
2214
|
-
this.
|
|
2760
|
+
this.sortLayerViewsExact();
|
|
2215
2761
|
},
|
|
2216
2762
|
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
// Run insertion sort algorithm in order to efficiently sort DOM elements according to their
|
|
2220
|
-
// associated model `z` attribute.
|
|
2221
|
-
|
|
2222
|
-
var cellNodes = Array.from(this.cells.childNodes).filter(node => node.getAttribute('model-id'));
|
|
2223
|
-
var cells = this.model.get('cells');
|
|
2224
|
-
|
|
2225
|
-
sortElements(cellNodes, function(a, b) {
|
|
2226
|
-
var cellA = cells.get(a.getAttribute('model-id'));
|
|
2227
|
-
var cellB = cells.get(b.getAttribute('model-id'));
|
|
2228
|
-
var zA = cellA.attributes.z || 0;
|
|
2229
|
-
var zB = cellB.attributes.z || 0;
|
|
2230
|
-
return (zA === zB) ? 0 : (zA < zB) ? -1 : 1;
|
|
2231
|
-
});
|
|
2763
|
+
sortLayerViewsExact: function() {
|
|
2764
|
+
this.getGraphLayerViews().forEach(view => view.sortExact());
|
|
2232
2765
|
},
|
|
2233
2766
|
|
|
2234
2767
|
insertView: function(view, isInitialInsert) {
|
|
2235
|
-
const { el, model } = view;
|
|
2236
2768
|
|
|
2237
|
-
|
|
2238
|
-
const
|
|
2769
|
+
// layer can be null if it is added to the graph with 'dry' option
|
|
2770
|
+
const layerId = this.model.getCellLayerId(view.model);
|
|
2771
|
+
const layerView = this.getLayerView(layerId);
|
|
2772
|
+
|
|
2773
|
+
layerView.insertCellView(view);
|
|
2239
2774
|
|
|
2240
|
-
switch (this.options.sorting) {
|
|
2241
|
-
case sortingTypes.APPROX:
|
|
2242
|
-
layerView.insertSortedNode(el, model.get('z'));
|
|
2243
|
-
break;
|
|
2244
|
-
case sortingTypes.EXACT:
|
|
2245
|
-
default:
|
|
2246
|
-
layerView.insertNode(el);
|
|
2247
|
-
break;
|
|
2248
|
-
}
|
|
2249
2775
|
view.onMount(isInitialInsert);
|
|
2250
2776
|
},
|
|
2251
2777
|
|
|
@@ -2308,7 +2834,7 @@ export const Paper = View.extend({
|
|
|
2308
2834
|
findView: function($el) {
|
|
2309
2835
|
|
|
2310
2836
|
var el = isString($el)
|
|
2311
|
-
? this.
|
|
2837
|
+
? this.layers.querySelector($el)
|
|
2312
2838
|
: $el instanceof $ ? $el[0] : $el;
|
|
2313
2839
|
|
|
2314
2840
|
var id = this.findAttribute('model-id', el);
|
|
@@ -2354,7 +2880,7 @@ export const Paper = View.extend({
|
|
|
2354
2880
|
var views = this.model.getElements().map(this.findViewByModel, this);
|
|
2355
2881
|
|
|
2356
2882
|
return views.filter(function(view) {
|
|
2357
|
-
return view && view.vel.getBBox({ target: this.
|
|
2883
|
+
return view && view.vel.getBBox({ target: this.layers }).containsPoint(p);
|
|
2358
2884
|
}, this);
|
|
2359
2885
|
},
|
|
2360
2886
|
|
|
@@ -2368,7 +2894,7 @@ export const Paper = View.extend({
|
|
|
2368
2894
|
var method = opt.strict ? 'containsRect' : 'intersect';
|
|
2369
2895
|
|
|
2370
2896
|
return views.filter(function(view) {
|
|
2371
|
-
return view && rect[method](view.vel.getBBox({ target: this.
|
|
2897
|
+
return view && rect[method](view.vel.getBBox({ target: this.layers }));
|
|
2372
2898
|
}, this);
|
|
2373
2899
|
},
|
|
2374
2900
|
|
|
@@ -3286,7 +3812,7 @@ export const Paper = View.extend({
|
|
|
3286
3812
|
return true;
|
|
3287
3813
|
}
|
|
3288
3814
|
|
|
3289
|
-
if (view && view.model && (view.model
|
|
3815
|
+
if (view && view.model && (view.model[CELL_MARKER])) {
|
|
3290
3816
|
return false;
|
|
3291
3817
|
}
|
|
3292
3818
|
|
|
@@ -3302,13 +3828,13 @@ export const Paper = View.extend({
|
|
|
3302
3828
|
options.gridSize = gridSize;
|
|
3303
3829
|
if (options.drawGrid && !options.drawGridSize) {
|
|
3304
3830
|
// Do not redraw the grid if the `drawGridSize` is set.
|
|
3305
|
-
this.getLayerView(
|
|
3831
|
+
this.getLayerView(paperLayers.GRID).renderGrid();
|
|
3306
3832
|
}
|
|
3307
3833
|
return this;
|
|
3308
3834
|
},
|
|
3309
3835
|
|
|
3310
3836
|
setGrid: function(drawGrid) {
|
|
3311
|
-
this.getLayerView(
|
|
3837
|
+
this.getLayerView(paperLayers.GRID).setGrid(drawGrid);
|
|
3312
3838
|
return this;
|
|
3313
3839
|
},
|
|
3314
3840
|
|
|
@@ -3657,201 +4183,8 @@ export const Paper = View.extend({
|
|
|
3657
4183
|
|
|
3658
4184
|
sorting: sortingTypes,
|
|
3659
4185
|
|
|
3660
|
-
Layers:
|
|
3661
|
-
|
|
3662
|
-
backgroundPatterns: {
|
|
3663
|
-
|
|
3664
|
-
flipXy: function(img) {
|
|
3665
|
-
// d b
|
|
3666
|
-
// q p
|
|
3667
|
-
|
|
3668
|
-
var canvas = document.createElement('canvas');
|
|
3669
|
-
var imgWidth = img.width;
|
|
3670
|
-
var imgHeight = img.height;
|
|
3671
|
-
|
|
3672
|
-
canvas.width = 2 * imgWidth;
|
|
3673
|
-
canvas.height = 2 * imgHeight;
|
|
3674
|
-
|
|
3675
|
-
var ctx = canvas.getContext('2d');
|
|
3676
|
-
// top-left image
|
|
3677
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3678
|
-
// xy-flipped bottom-right image
|
|
3679
|
-
ctx.setTransform(-1, 0, 0, -1, canvas.width, canvas.height);
|
|
3680
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3681
|
-
// x-flipped top-right image
|
|
3682
|
-
ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);
|
|
3683
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3684
|
-
// y-flipped bottom-left image
|
|
3685
|
-
ctx.setTransform(1, 0, 0, -1, 0, canvas.height);
|
|
3686
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3687
|
-
|
|
3688
|
-
return canvas;
|
|
3689
|
-
},
|
|
3690
|
-
|
|
3691
|
-
flipX: function(img) {
|
|
3692
|
-
// d b
|
|
3693
|
-
// d b
|
|
4186
|
+
Layers: paperLayers,
|
|
3694
4187
|
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
var imgHeight = img.height;
|
|
3698
|
-
|
|
3699
|
-
canvas.width = imgWidth * 2;
|
|
3700
|
-
canvas.height = imgHeight;
|
|
3701
|
-
|
|
3702
|
-
var ctx = canvas.getContext('2d');
|
|
3703
|
-
// left image
|
|
3704
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3705
|
-
// flipped right image
|
|
3706
|
-
ctx.translate(2 * imgWidth, 0);
|
|
3707
|
-
ctx.scale(-1, 1);
|
|
3708
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3709
|
-
|
|
3710
|
-
return canvas;
|
|
3711
|
-
},
|
|
3712
|
-
|
|
3713
|
-
flipY: function(img) {
|
|
3714
|
-
// d d
|
|
3715
|
-
// q q
|
|
3716
|
-
|
|
3717
|
-
var canvas = document.createElement('canvas');
|
|
3718
|
-
var imgWidth = img.width;
|
|
3719
|
-
var imgHeight = img.height;
|
|
3720
|
-
|
|
3721
|
-
canvas.width = imgWidth;
|
|
3722
|
-
canvas.height = imgHeight * 2;
|
|
3723
|
-
|
|
3724
|
-
var ctx = canvas.getContext('2d');
|
|
3725
|
-
// top image
|
|
3726
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3727
|
-
// flipped bottom image
|
|
3728
|
-
ctx.translate(0, 2 * imgHeight);
|
|
3729
|
-
ctx.scale(1, -1);
|
|
3730
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
3731
|
-
|
|
3732
|
-
return canvas;
|
|
3733
|
-
},
|
|
3734
|
-
|
|
3735
|
-
watermark: function(img, opt) {
|
|
3736
|
-
// d
|
|
3737
|
-
// d
|
|
3738
|
-
|
|
3739
|
-
opt = opt || {};
|
|
3740
|
-
|
|
3741
|
-
var imgWidth = img.width;
|
|
3742
|
-
var imgHeight = img.height;
|
|
3743
|
-
|
|
3744
|
-
var canvas = document.createElement('canvas');
|
|
3745
|
-
canvas.width = imgWidth * 3;
|
|
3746
|
-
canvas.height = imgHeight * 3;
|
|
3747
|
-
|
|
3748
|
-
var ctx = canvas.getContext('2d');
|
|
3749
|
-
var angle = isNumber(opt.watermarkAngle) ? -opt.watermarkAngle : -20;
|
|
3750
|
-
var radians = toRad(angle);
|
|
3751
|
-
var stepX = canvas.width / 4;
|
|
3752
|
-
var stepY = canvas.height / 4;
|
|
3753
|
-
|
|
3754
|
-
for (var i = 0; i < 4; i++) {
|
|
3755
|
-
for (var j = 0; j < 4; j++) {
|
|
3756
|
-
if ((i + j) % 2 > 0) {
|
|
3757
|
-
// reset the current transformations
|
|
3758
|
-
ctx.setTransform(1, 0, 0, 1, (2 * i - 1) * stepX, (2 * j - 1) * stepY);
|
|
3759
|
-
ctx.rotate(radians);
|
|
3760
|
-
ctx.drawImage(img, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
|
|
3761
|
-
}
|
|
3762
|
-
}
|
|
3763
|
-
}
|
|
3764
|
-
|
|
3765
|
-
return canvas;
|
|
3766
|
-
}
|
|
3767
|
-
},
|
|
3768
|
-
|
|
3769
|
-
gridPatterns: {
|
|
3770
|
-
dot: [{
|
|
3771
|
-
color: '#AAAAAA',
|
|
3772
|
-
thickness: 1,
|
|
3773
|
-
markup: 'rect',
|
|
3774
|
-
render: function(el, opt) {
|
|
3775
|
-
V(el).attr({
|
|
3776
|
-
width: opt.thickness,
|
|
3777
|
-
height: opt.thickness,
|
|
3778
|
-
fill: opt.color
|
|
3779
|
-
});
|
|
3780
|
-
}
|
|
3781
|
-
}],
|
|
3782
|
-
fixedDot: [{
|
|
3783
|
-
color: '#AAAAAA',
|
|
3784
|
-
thickness: 1,
|
|
3785
|
-
markup: 'rect',
|
|
3786
|
-
render: function(el, opt) {
|
|
3787
|
-
V(el).attr({ fill: opt.color });
|
|
3788
|
-
},
|
|
3789
|
-
update: function(el, opt, paper) {
|
|
3790
|
-
const { sx, sy } = paper.scale();
|
|
3791
|
-
const width = sx <= 1 ? opt.thickness : opt.thickness / sx;
|
|
3792
|
-
const height = sy <= 1 ? opt.thickness : opt.thickness / sy;
|
|
3793
|
-
V(el).attr({ width, height });
|
|
3794
|
-
}
|
|
3795
|
-
}],
|
|
3796
|
-
mesh: [{
|
|
3797
|
-
color: '#AAAAAA',
|
|
3798
|
-
thickness: 1,
|
|
3799
|
-
markup: 'path',
|
|
3800
|
-
render: function(el, opt) {
|
|
3801
|
-
|
|
3802
|
-
var d;
|
|
3803
|
-
var width = opt.width;
|
|
3804
|
-
var height = opt.height;
|
|
3805
|
-
var thickness = opt.thickness;
|
|
3806
|
-
|
|
3807
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
3808
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
3809
|
-
} else {
|
|
3810
|
-
d = 'M 0 0 0 0';
|
|
3811
|
-
}
|
|
3812
|
-
|
|
3813
|
-
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
3814
|
-
}
|
|
3815
|
-
}],
|
|
3816
|
-
doubleMesh: [{
|
|
3817
|
-
color: '#AAAAAA',
|
|
3818
|
-
thickness: 1,
|
|
3819
|
-
markup: 'path',
|
|
3820
|
-
render: function(el, opt) {
|
|
3821
|
-
|
|
3822
|
-
var d;
|
|
3823
|
-
var width = opt.width;
|
|
3824
|
-
var height = opt.height;
|
|
3825
|
-
var thickness = opt.thickness;
|
|
3826
|
-
|
|
3827
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
3828
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
3829
|
-
} else {
|
|
3830
|
-
d = 'M 0 0 0 0';
|
|
3831
|
-
}
|
|
3832
|
-
|
|
3833
|
-
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
3834
|
-
}
|
|
3835
|
-
}, {
|
|
3836
|
-
color: '#000000',
|
|
3837
|
-
thickness: 3,
|
|
3838
|
-
scaleFactor: 4,
|
|
3839
|
-
markup: 'path',
|
|
3840
|
-
render: function(el, opt) {
|
|
3841
|
-
|
|
3842
|
-
var d;
|
|
3843
|
-
var width = opt.width;
|
|
3844
|
-
var height = opt.height;
|
|
3845
|
-
var thickness = opt.thickness;
|
|
3846
|
-
|
|
3847
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
3848
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
3849
|
-
} else {
|
|
3850
|
-
d = 'M 0 0 0 0';
|
|
3851
|
-
}
|
|
3852
|
-
|
|
3853
|
-
V(el).attr({ 'd': d, stroke: opt.color, 'stroke-width': opt.thickness });
|
|
3854
|
-
}
|
|
3855
|
-
}]
|
|
3856
|
-
}
|
|
4188
|
+
backgroundPatterns,
|
|
4189
|
+
gridPatterns,
|
|
3857
4190
|
});
|